src/network/nServerInfo.cpp

Go to the documentation of this file.
00001 /*
00002 
00003 *************************************************************************
00004 
00005 ArmageTron -- Just another Tron Lightcycle Game in 3D.
00006 Copyright (C) 2000  Manuel Moos (manuel@moosnet.de)
00007 
00008 **************************************************************************
00009 
00010 This program is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU General Public License
00012 as published by the Free Software Foundation; either version 2
00013 of the License, or (at your option) any later version.
00014 
00015 This program is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00023   
00024 ***************************************************************************
00025 
00026 */
00027 
00028 #include "tMemManager.h"
00029 #include "tSysTime.h"
00030 #include "tConsole.h"
00031 #include "tList.h"
00032 #include "tLocale.h"
00033 #include "tToDo.h"
00034 #include "tDirectories.h"
00035 #include "tConfiguration.h"
00036 #include "tRandom.h"
00037 #include "tRecorder.h"
00038 
00039 #include "nSocket.h"
00040 
00041 #include "nServerInfo.h"
00042 #include "nNetObject.h"
00043 #ifdef KRAWALL_SERVER
00044 #include "nAuthentication.h"
00045 #endif
00046 
00047 #include <fstream>
00048 
00049 static nServerInfo*          sn_masterList  = NULL;
00050 static nServerInfo*          sn_FirstServer = NULL;
00051 static sn_ServerInfoCreator* sn_Creator     = NULL;
00052 
00053 static nServerInfo*          sn_Transmitting[MAXCLIENTS+2];
00054 static unsigned int          sn_LastKnown   [MAXCLIENTS+2];
00055 static bool                  sn_SendAll     [MAXCLIENTS+2];
00056 static bool                  sn_Requested   [MAXCLIENTS+2];
00057 static REAL                  sn_Timeout     [MAXCLIENTS+2];
00058 
00059 #ifdef KRAWALL_SERVER
00060 static bool                  sn_Auth        [MAXCLIENTS+2];
00061 #endif
00062 
00063 static nServerInfo*          sn_Requesting=NULL;
00064 static unsigned int          sn_NextTransactionNr = 0;
00065 
00066 static bool sn_AcceptingFromBroadcast = false;
00067 bool sn_AcceptingFromMaster    = false;
00068 static bool sn_IsMaster               = false;
00069 
00070 static nServerInfo*           sn_QuerySoon =NULL;
00071 static nTimeRolling           sn_QueryTimeout = 0;
00072 
00073 static REAL sn_queryDelay = 1.5f;       // time delay between queries of the same server
00074 static REAL sn_queryDelayGlobal = 0.1f; // time delay between all queries
00075 static int sn_numQueries = 3;   // number of queries per try
00076 static int sn_TNALostContact = 4;  // minimum TNA value to be considered contact loss
00077 
00078 static tSettingItem< REAL > sn_queryDelayConf( "BROWSER_QUERY_DELAY_SINGLE", sn_queryDelay );
00079 static tSettingItem< REAL > sn_queryDelayGlobalConf( "BROWSER_QUERY_DELAY_GLOBAL", sn_queryDelayGlobal );
00080 static tSettingItem< int > sn_numQueriesConf( "BROWSER_NUM_QUERIES", sn_numQueries );
00081 static tSettingItem< int > sn_TNALostContactConf( "BROWSER_CONTACTLOSS", sn_TNALostContact );
00082 
00083 static int sn_MaxUnreachable()
00084 {
00085     return sn_IsMaster ? 10 : 5;
00086 }
00087 
00088 static int sn_MaxTNA()
00089 {
00090     return sn_IsMaster ? 30 : 10;
00091 }
00092 
00093 static int sn_MaxTNATotal()
00094 {
00095     return sn_IsMaster ? 300 : 50;
00096 }
00097 
00098 static tList<nServerInfo>       sn_Polling;
00099 
00100 static tString sn_LastLoaded;  // stores the filename of the last loaded server list
00101 
00102 // make sure every new client gets a new server list
00103 static void login_callback(){
00104     sn_Transmitting[nCallbackLoginLogout::User()] = NULL;
00105     sn_LastKnown   [nCallbackLoginLogout::User()] = 0;
00106     sn_SendAll     [nCallbackLoginLogout::User()] = true;
00107     sn_Requested   [nCallbackLoginLogout::User()] = false;
00108     sn_Timeout     [nCallbackLoginLogout::User()] = tSysTimeFloat() + 70;
00109 #ifdef KRAWALL_SERVER
00110     sn_Auth        [nCallbackLoginLogout::User()] = false;
00111 #endif
00112 
00113 }
00114 
00115 // helper function: server info to string
00116 tString ToString( const nServerInfoBase & info )
00117 {
00118     tString ret;
00119     ret << info.GetConnectionName() << ":" << info.GetPort();
00120     return ret;
00121 }
00122 
00123 // authentification stuff
00124 #ifdef KRAWALL_SERVER_LEAGUE
00125 void ResultCallback(const tString& username,
00126                     const tString& origUsername,
00127                     int user, bool success)
00128 {
00129     if (success)
00130     {
00131         sn_Auth[user] = true;
00132         sn_Transmitting[user] = nServerInfo::GetFirstServer();
00133     }
00134     else
00135         nAuthentication::RequestLogin(username, user, tOutput("$login_request_failed"), true);
00136 }
00137 #endif // KRAWALL_SERVER_LEAGUE
00138 
00139 
00140 
00141 static nCallbackLoginLogout nlc(&login_callback);
00142 
00143 static nServerInfo *CreateServerInfo()
00144 {
00145     if (sn_Creator)
00146         return (*sn_Creator)();
00147     else
00148         return tNEW(nServerInfo());
00149 }
00150 
00151 nServerInfo::nServerInfo()
00152         :tListItem<nServerInfo>(sn_FirstServer),
00153         pollID(-1),
00154         transactionNr(sn_NextTransactionNr),
00155         method(0),
00156         key(0),
00157         advancedInfoSet(false),
00158         advancedInfoSetEver(false),
00159         queried(0),
00160         timeQuerySent(0),
00161         ping(10),
00162         release_("pre_0.2.5"),
00163         login2_(true),
00164         timesNotAnswered(5),
00165         stillOnMasterServer(false),
00166         name(""),
00167         users(0),
00168         maxUsers_(MAXCLIENTS),
00169         score(-10000),
00170         scoreBias_(0),
00171         queryType_( QUERY_ALL )
00172 {
00173     if (sn_IsMaster)
00174     {
00175         sn_NextTransactionNr++;
00176         if (0 == sn_NextTransactionNr)
00177             sn_NextTransactionNr++;
00178     }
00179 }
00180 
00181 nServerInfo::~nServerInfo()
00182 {
00183     sn_Polling.Remove(this, pollID);
00184 
00185     for (int i = MAXCLIENTS+1; i>=0; i--)
00186         if (sn_Transmitting[i] == this)
00187             sn_Transmitting[i] = sn_Transmitting[i]->Next();
00188 
00189     if (sn_Requesting == this)
00190         sn_Requesting = sn_Requesting->Next();
00191 
00192     if (sn_QuerySoon == this)
00193         sn_Requesting = NULL;
00194 }
00195 
00196 
00197 // calculates the score from other data
00198 void nServerInfo::CalcScore()
00199 {
00200     static int userScore[8] = { -100, 0, 100, 250, 300, 300, 250, 100 };
00201 
00202     // do nothing if we are requerying
00203     if ( !this->advancedInfoSet && this->advancedInfoSetEver )
00204     {
00205         // score = scoreBias_;
00206 
00207         return;
00208     }
00209 
00210     score  = 100;
00211     if (ping > .1)
00212         score  -= (ping - .1) * 300;
00213 
00214     if (users < 8 && users >= 0)
00215         score += userScore[users];
00216 
00217     if (users >= maxUsers_ )
00218         score -= 200;
00219 
00220     if ( Compat_Ok != this->Compatibility() )
00221     {
00222         score -= 400;
00223     }
00224 
00225     score -= fabsf( this->Version().Max() - sn_MyVersion().Max() ) * 10;
00226 
00227     score += scoreBias_;
00228 }
00229 
00230 
00231 // read/write all the information a normal server will broadcast
00232 /*
00233   void nServerInfo::NetWrite(nMessage &m)
00234   {
00235   m << name;
00236   m << users;
00237   }
00238 */
00239 
00240 
00241 // the same for the information the master server is responsible for
00242 /*
00243 void nServerInfo::MasterNetWrite(nMessage &m)
00244 {
00245     m << transactionNr;
00246     m << connectionName;
00247     m << port;
00248     m << method;
00249     m << key;
00250 }
00251 */
00252 
00253 /*
00254 void nServerInfo::MasterNetRead (nMessage &m)
00255 {
00256   m >> transactionNr;
00257   m >> connectionName;
00258   m >> port;
00259   m >> method;
00260   m >> key;
00261 }
00262 */
00263 
00264 static const tString TRANSACTION("transaction");
00265 static const tString CONNECTION ("connection");
00266 static const tString PORT       ("port");
00267 static const tString METHOD     ("method");
00268 static const tString KEY        ("key");
00269 static const tString TNA        ("tna");
00270 static const tString NAME       ("name");
00271 static const tString VERSION_TAG    ("version");
00272 static const tString RELEASE    ("release");
00273 static const tString SCOREBIAS  ("scorebias");
00274 static const tString URL                ("url");
00275 static const tString END        ("ServerEnd");
00276 static const tString START      ("ServerBegin");
00277 
00278 void nServerInfo::Save(std::ostream &s) const
00279 {
00280     s << CONNECTION << "\t" << GetConnectionName() << "\n";
00281     s << PORT       << "\t" << GetPort()           << "\n";
00282     s << METHOD     << "\t" << method         << "\n";
00283 
00284     s << KEY  << "\t" << key.Len()      << "  ";
00285     for (int i = key.Len()-1; i>=0; i--)
00286         s << "\t" << key(i);
00287     s << "\n";
00288 
00289     s << TRANSACTION << "\t" << transactionNr << "\n";
00290     s << VERSION_TAG    << "\t" << version_ << "\n";
00291     s << RELEASE        << "\t" << release_ << "\n";
00292 
00293     s << URL            << "\t" << url_ << "\n";
00294 
00295     s << SCOREBIAS  << "\t" << scoreBias_ << "\n";
00296     s << NAME  << "\t" << name             << "\n";
00297     s << TNA  << "\t" << timesNotAnswered  << "\n";
00298     s << END   << "\t" << "\n\n";
00299 }
00300 
00301 void nServerInfo::Load(std::istream &s)
00302 {
00303     bool end = false;
00304     while (!end && s.good() && !s.eof())
00305     {
00306         tString id;
00307         s >> id;
00308         int dummy;
00309 
00310         if (id == START)
00311             continue;
00312         else if (id == END)
00313             end = true;
00314         else if (id == METHOD)
00315             s >> dummy;
00316         else if (id == TRANSACTION)
00317             s >> transactionNr;
00318         else if ( id == VERSION_TAG )
00319             s >> version_;
00320         else if ( id == SCOREBIAS )
00321             s >> scoreBias_;
00322         else if ( id == RELEASE )
00323             release_.ReadLine( s );
00324         else if ( id == URL )
00325             url_.ReadLine( s );
00326         else if (id == CONNECTION)
00327         {
00328             tString connectionName;
00329             connectionName.ReadLine( s );
00330             SetConnectionName( connectionName );
00331         }
00332         else if (id == PORT)
00333         {
00334             unsigned int port;
00335             s >> port;
00336             SetPort( port );
00337         }
00338         else if (id == KEY)
00339         {
00340             int len;
00341             s >> len;
00342             key.SetLen(len);
00343             for (int i=len-1; i>=0; i--)
00344                 s >> key(i);
00345         }
00346         else if(id == TNA)
00347             s >> timesNotAnswered;
00348         else if (id == NAME)
00349             name.ReadLine(s);
00350         else
00351             con << "Warning: unknown tag " << id << " found in server config file.\n";
00352     }
00353 
00354     queried = 0;
00355     advancedInfoSet = false;
00356     advancedInfoSetEver =false;
00357 
00358     score = scoreBias_;
00359 }
00360 
00361 nServerInfo *nServerInfo::GetFirstServer()
00362 {
00363     return sn_FirstServer;
00364 }
00365 
00366 
00367 nServerInfo *nServerInfo::Prev()
00368 {
00369     if (reinterpret_cast<nServerInfo **>(anchor) == &sn_FirstServer)
00370         return NULL;
00371 
00372     static nServerInfo& info = *this; // will not cause recursion since it is called only once.
00373 
00374     // uaaa. Pointer magic...
00375     // TODO: perhaps there is a better way using member pointers?
00376     return reinterpret_cast<nServerInfo *>
00377            ( reinterpret_cast<char*> (anchor) +
00378              ( reinterpret_cast<char*>( &info ) - reinterpret_cast<char*> (&info.next) )
00379            );
00380 }
00381 
00382 // Sort server list
00383 void nServerInfo::Sort( PrimaryKey key )
00384 {
00385     // insertion sort
00386     nServerInfo *run = GetFirstServer();
00387     while (run)
00388     {
00389         nServerInfo* ascend = run;
00390         run = run->Next();
00391 
00392         while (1)
00393         {
00394             if ( ascend == GetFirstServer() )
00395                 break;
00396 
00397             nServerInfo *prev = ascend->Prev();
00398 
00399 
00400             // check if ascend is well in place
00401             if (!prev)
00402                 break;
00403 
00404             //    if (prev->queried > ascend->queried)
00405             //      break;
00406             int compare = 0;
00407             bool previousPolling = prev->Polling();
00408             bool previousUnreachable  = !prev->Reachable() && !previousPolling;
00409             bool ascendPolling = ascend->Polling();
00410             bool ascendUnreachable  = !ascend->Reachable() && !ascendPolling;
00411 
00412             switch ( key )
00413             {
00414 
00415             case KEY_NAME:
00416                 // Unreachable servers should be displayed at the end of the list
00417                 if ( !previousUnreachable && !ascendUnreachable ) {
00418                     compare = tColoredString::RemoveColors(prev->name).Compare( tColoredString::RemoveColors(ascend->name), true );
00419                 }
00420 
00421                 break;
00422             case KEY_PING:
00423                 if ( ascend->ping > prev->ping )
00424                     compare = -1;
00425                 else if ( ascend->ping < prev->ping )
00426                     compare = 1;
00427                 break;
00428             case KEY_USERS:
00429                 compare = ascend->users - prev->users;
00430                 break;
00431             case KEY_SCORE:
00432                 if ( previousUnreachable )
00433                     compare ++;
00434                 if ( ascendUnreachable )
00435                     compare --;
00436                 if ( ascend->score > prev->score )
00437                     compare = 1;
00438                 else if ( ascend->score < prev->score )
00439                     compare = -1;
00440                 break;
00441             case KEY_MAX:
00442                 break;
00443             }
00444 
00445             if (0 == compare)
00446             {
00447                 if ( previousPolling )
00448                     compare++;
00449                 if ( ascendPolling )
00450                     compare--;
00451             }
00452 
00453             if ( compare <= 0 )
00454                 break;
00455 
00456             prev->Remove();
00457             prev->Insert( ascend->next );
00458         }
00459     }
00460 }
00461 
00462 void nServerInfo::CalcScoreAll()        // calculate the score for all servers
00463 {
00464     nServerInfo *run = GetFirstServer();
00465     while (run)
00466     {
00467         run->CalcScore();
00468         run = run->Next();
00469     }
00470 }
00471 
00472 void nServerInfo::DeleteAll(bool autosave)               // delete all server infos
00473 {
00474     if (autosave)
00475     {
00476         Save();
00477     }
00478     sn_LastLoaded.Clear();
00479 
00480     while (GetFirstServer())
00481         delete GetFirstServer();
00482 }
00483 
00484 // set the function that creates new server infos (so the server infos
00485 // generated by calls from the master server can be of a derived class).
00486 // returns the old function, so you can resore it later.
00487 sn_ServerInfoCreator* nServerInfo::SetCreator(sn_ServerInfoCreator* creator)
00488 {
00489     sn_ServerInfoCreator* ret = sn_Creator;
00490     sn_Creator = creator;
00491     return ret;
00492 }
00493 
00494 
00495 void nServerInfo::Save()
00496 {
00497     if ( sn_LastLoaded.Len() <= 1 )
00498     {
00499         return;
00500     }
00501 
00502     Save( tDirectories::Var(), sn_LastLoaded );
00503 }
00504 
00505 void nServerInfo::Save(const tPath& path, const char *filename)      // save/load all server infos
00506 {
00507     // don't save on playback
00508     if ( tRecorder::IsPlayingBack() )
00509         return;
00510 
00511     std::ofstream s;
00512     if ( path.Open( s, filename ) )
00513     {
00514         nServerInfo *run = GetFirstServer();
00515         while (run && run->Next())
00516         {
00517             run = run->Next();
00518         }
00519 
00520         while (run)
00521         {
00522             s << START << "\n";
00523             run->Save(s);
00524             run = run->Prev();
00525         }
00526     }
00527 }
00528 
00529 // streaming operators
00530 std::istream & operator >> ( std::istream & s, nServerInfo & info )
00531 {
00532     info.Load( s );
00533 
00534     return s;
00535 }
00536 
00537 std::ostream & operator << ( std::ostream & s, nServerInfo const & info )
00538 {
00539     info.Save( s );
00540 
00541     return s;
00542 }
00543 
00544 void nServerInfo::Load(const tPath& path, const char *filename)
00545 {
00546     sn_LastLoaded = filename;
00547 
00548     // read server info from archive
00549     static char const * section = "SERVERINFO";
00550     static char const * sectionEnd = "SERVERINFOEND";
00551     if ( tRecorder::IsPlayingBack() )
00552     {
00553         nServerInfo *server = CreateServerInfo();
00554         while ( tRecorder::Playback( section, *server ) )
00555         {
00556             // preemptively resolve DNS
00557             server->GetAddress();
00558 
00559             tRecorder::Record( section, *server );
00560             server = CreateServerInfo();
00561         }
00562         delete server;
00563 
00564         // acknowledge end of playback
00565         tRecorder::PlaybackStrict( sectionEnd );
00566         tRecorder::Record( sectionEnd );
00567         return;
00568     }
00569 
00570 
00571     std::ifstream s;
00572     path.Open( s, filename );
00573 
00574     while (s.good() && !s.eof())
00575     {
00576         tString id;
00577         s >> id;
00578         if (id == START)
00579         {
00580             nServerInfo *server = CreateServerInfo();
00581             server->Load(s);
00582 
00583             // record server
00584             tRecorder::Record( section, *server );
00585 
00586             // preemptively resolve DNS
00587             server->GetAddress();
00588 
00589             // remove double servers
00590             bool IsDouble = 0;
00591             nServerInfo *run = GetFirstServer();
00592             while(!IsDouble && run)
00593             {
00594                 if (run != server && *run == *server )
00595                     IsDouble = true;
00596 
00597                 run = run->Next();
00598             }
00599 
00600             if (IsDouble)
00601                 delete server;
00602         }
00603         else
00604             break;
00605     }
00606 
00607     // mark end of recording
00608     tRecorder::Record( sectionEnd );
00609 }
00610 
00611 
00612 
00613 // **********************************
00614 // now the real network protocol part
00615 // **********************************
00616 
00617 // the network handlers and descriptors used by the master protocol
00618 
00619 // used to transfer small server information (adress, port, public key)
00620 // from the master server or response to a broadcast to the client
00621 static nDescriptor SmallServerDescriptor(50,nServerInfo::GetSmallServerInfo,"small_server", true);
00622 
00623 // used to transfer the rest of the server info (name, number of players, etc)
00624 // from the server directly to the client
00625 static nDescriptor BigServerDescriptor(51,nServerInfo::GetBigServerInfo,"big_server", true);
00626 static nDescriptor BigServerMasterDescriptor(54,nServerInfo::GetBigServerInfoMaster,"big_server_master", true);
00627 
00628 // request small server information from master server/broadcast
00629 static nDescriptor RequestSmallServerInfoDescriptor(52,nServerInfo::GiveSmallServerInfo,"small_request", true);
00630 
00631 // request big server information from master server/broadcast
00632 static nDescriptor RequestBigServerInfoDescriptor(53,nServerInfo::GiveBigServerInfo,"big_request", true);
00633 static nDescriptor RequestBigServerInfoMasterDescriptor(55,nServerInfo::GiveBigServerInfoMaster,"big_request_master", true);
00634 
00635 // used to transfer the rest of the server info (name, number of players, etc)
00636 // from the server directly to the client
00637 //atic nDescriptor ExtraServerDescriptor(54,nServerInfo::GetExtraServerInfo,"extra_server", true);
00638 
00639 // request big server information from master server/broadcast
00640 //atic nDescriptor RequestExtraServerInfoDescriptor(55,nServerInfo::GiveExtraServerInfo,"extra_request", true);
00641 
00642 static bool net_Accept()
00643 {
00644     return
00645         nCallbackAcceptPackedWithoutConnection::Descriptor()==SmallServerDescriptor.ID() ||
00646         nCallbackAcceptPackedWithoutConnection::Descriptor()==BigServerDescriptor.ID() ||
00647         nCallbackAcceptPackedWithoutConnection::Descriptor()==BigServerMasterDescriptor.ID();
00648 }
00649 
00650 static nCallbackAcceptPackedWithoutConnection net_acc( &net_Accept );
00651 
00652 static int sn_ServerCount = 0;
00653 
00654 /*
00655 static void ReadServerInfo(nMessage &m, unsigned int& port, tString& connectionName, bool acceptDirect, bool acceptMaster)
00656 {
00657     m >> port;            // get the port
00658     m >> connectionName;  // and the name
00659     if (connectionName.Len()<=1) // no valid name (must come directly from the server who does not know his own address)
00660     {
00661         sn_GetAdr(m.SenderID(), connectionName);
00662 
00663         // remove the port
00664         for (int i=connectionName.Len(); i>=0; i--)
00665             if (':' == connectionName[i])
00666             {
00667                 connectionName[i] = '\0';
00668                 connectionName.SetLen(i+1);
00669             }
00670 
00671         if (!acceptDirect && !acceptMaster)
00672         {
00673             //    Cheater(m.SenderID());
00674             return;
00675         }
00676     }
00677     else
00678     {
00679         if (!acceptMaster)
00680         {
00681             //    Cheater(m.SenderID());
00682             return;
00683         }
00684     }
00685 }
00686 
00687 static void WriteServerInfo(nMessage &m, unsigned int port, const tString connectionName)
00688 {
00689     m << port;
00690     if (connectionName.Len() > 3 && connectionName[0] == '1' && connectionName[1] == '2' &&  connectionName[2] == '7')
00691         m << tString("");
00692     else
00693         m << connectionName;
00694 }
00695 
00696 static void WriteMyInfo(nMessage &m)
00697 {
00698     m << sn_GetServerPort();
00699     m << tString("");
00700 }
00701 */
00702 
00703 
00704 // TODO: make these dynamic
00705 /*
00706 static tString sn_localName("127.0.0.1");
00707 static tString sn_globalName("armagetron.kicks-ass.net");
00708 
00709 static tSettingItem< tString > sn_localNameSetting( "LOCAL_NETNAME", sn_localName );
00710 static tSettingItem< tString > sn_globalNameSetting( "GLOBAL_NETNAME", sn_globalName );
00711 
00712 static const tString s_LocalName("127.0.0.2");
00713 static const tString s_GlobalName("armagetron.kicks-ass.net");
00714 
00715 static void S_GlobalizeName(tString &connectionName)
00716 {
00717     if ( sn_IsMaster )
00718     {
00719         if ( connectionName == sn_localName )
00720         {
00721             connectionName = sn_globalName;
00722         }
00723     }
00724 }
00725 
00726 static tString S_LocalizeName(const tString &connectionName)
00727 {
00728     if ( !sn_IsMaster )
00729     {
00730         if ( connectionName[0] < '0' || connectionName[0] > '9' )
00731         {
00732             // get the IP adress
00733             struct sockaddr temp;
00734             ANET_GetAddrFromName (connectionName, &temp);
00735             tString connectionNameTemp( ANET_AddrToString (&temp) );
00736             // remove the port part
00737             for(int pos = connectionNameTemp.Len()-1; pos>=0; pos--)
00738                 if (':' == connectionNameTemp[pos])
00739                 {
00740                     connectionNameTemp[pos]='\0';
00741                     connectionNameTemp.SetLen(pos+1);
00742                 }
00743 
00744             return connectionNameTemp;
00745         }
00746     }
00747 
00748     return connectionName;
00749 }
00750 */
00751 
00752 // dummy functions
00753 static void S_GlobalizeName(tString &connectionName)
00754 {
00755 }
00756 
00757 static const tString & S_LocalizeName(const tString &connectionName)
00758 {
00759     return connectionName;
00760 }
00761 
00762 static tString sn_connectionName("");
00763 //static tSettingItem< tString > sn_connectionNameSetting( "CONNECTION_NAME", sn_connectionName );
00764 
00765 /*
00766 static void WriteMyInfo(nMessage &m)
00767 {
00768     m << sn_GetServerPort();
00769     m << sn_connectionName;
00770 }
00771 */
00772 
00773 void nServerInfo::Alive()
00774 {
00775     // give it a new transaction number if it was down temporarily
00776     if ( sn_IsMaster && TimesNotAnswered() >= sn_TNALostContact )
00777     {
00778         transactionNr = sn_NextTransactionNr++;
00779         if (!sn_NextTransactionNr)
00780             sn_NextTransactionNr++;
00781     }
00782 }
00783 
00784 // size of flood protection array
00785 static const int sn_minPingCount=4;
00786 // number of consecutive pings that get tracked
00787 static const int sn_minPingCounts[sn_minPingCount] = { 10,20,50,100 };
00788 // time limits for pings to come in
00789 static REAL sn_minPingTimes[sn_minPingCount] = { 1,4,20,100 };
00790 
00791 // setting items to make flood protection configurable
00792 static tSettingItem< REAL > sn_minPingTime10 ( "PING_FLOOD_TIME_10" , sn_minPingTimes[0] );
00793 static tSettingItem< REAL > sn_minPingTime20 ( "PING_FLOOD_TIME_20" , sn_minPingTimes[1] );
00794 static tSettingItem< REAL > sn_minPingTime50 ( "PING_FLOOD_TIME_50" , sn_minPingTimes[2] );
00795 static tSettingItem< REAL > sn_minPingTime100( "PING_FLOOD_TIME_100", sn_minPingTimes[3] );
00796 
00797 // machine decorator to store ping statistics from individual clients
00798 class nQueryMessageStats: public nMachineDecorator
00799 {
00800 public:
00801     nQueryMessageStats( nMachine & machine )
00802             : nMachineDecorator( machine )
00803             , machine_( machine )
00804             , warned_(false)
00805     {
00806         tASSERT( MAX > sn_minPingCounts[ sn_minPingCount-1 ] );
00807 
00808         for ( int i = 0; i < MAX; ++i )
00809             lastTime_[i] = -1E10;
00810 
00811         lastTimeIndex_ = 0;
00812     }
00813 
00814     enum{ MAX=101 };
00815     nMachine & machine_;     // the machine this belongs to
00816     double lastTime_[MAX];   // log of the last times the server was pinged by this client
00817     int lastTimeIndex_;      // the current index in the array
00818     bool warned_;            // flag to avoid warning spam in the log file
00819 
00820     tString GetIP()
00821     {
00822         tString ret = machine_.GetIP();
00823         if ( ret.Len() < 4 )
00824             ret = "everyone";
00825 
00826         return ret;
00827     }
00828 
00829     // determine whether a warning should be printed now
00830     bool PrintWarning()
00831     {
00832         if ( warned_ )
00833             return false;
00834 
00835         double time = tSysTimeFloat();
00836         static double lastTime = time-10;
00837         if ( time < lastTime + 5 )
00838             return false;
00839 
00840         warned_ = true;
00841         return true;
00842     }
00843 
00844     virtual void OnDestroy()
00845     {
00846         if ( warned_ )
00847             con << "Flood protection ban of " << GetIP() << " removed because machine is discarded.\n";
00848 
00849         delete this;
00850     }
00851 
00852     void Block()
00853     {
00854         // block a DOS attacker for a while so he thinks his attack
00855         // brought the server down
00856         double time = tSysTimeFloat();
00857 
00858         if ( lastTime_[0] < time )
00859         {
00860             for ( int i = 0; i < MAX; ++i )
00861             {
00862                 lastTime_[i] = time+10;
00863             }
00864         }
00865 
00866         if ( PrintWarning() )
00867         {
00868             con << "Flood protection bans " << GetIP() << " for sending multiple querty messages with one packet.\n";
00869         }
00870     }
00871 
00872     // determines whether this client should be considered flooding
00873     bool FloodProtection( REAL timeFactor )
00874     {
00875         int i;
00876         double now = tSysTimeFloat();
00877 
00878         bool protect = false;
00879         REAL diff = 0;
00880         int count = 0;
00881 
00882         // go through the different levels
00883         for ( i = sn_minPingCount-1; i >= 0; --i )
00884         {
00885             // this many pings should be tracked
00886             count = sn_minPingCounts[i];
00887             diff = now - lastTime_[(lastTimeIndex_ + MAX - count) % MAX];
00888             REAL tolerance = sn_minPingTimes[i]*timeFactor;
00889             if ( tolerance > 0 && diff < tolerance )
00890             {
00891                 protect = true;
00892                 break;
00893             }
00894         }
00895 
00896         lastTimeIndex_ = (lastTimeIndex_ + 1) % MAX;
00897         lastTime_[lastTimeIndex_] = now;
00898 
00899         if ( protect )
00900         {
00901             if ( PrintWarning() )
00902                 con << "Flood protection bans " << GetIP() << " after " << count << " pings in " << int((diff)*100)/100.0 << " seconds.\n";
00903 
00904             return true;
00905         }
00906 
00907         // reset warning flag
00908         if ( warned_ && now - lastTime_[(lastTimeIndex_ + MAX-2 ) % MAX] > sn_minPingTimes[ sn_minPingCount-1 ] )
00909         {
00910             con << "Flood protection ban of " << GetIP() << " removed.\n";
00911             warned_ = false;
00912         }
00913 
00914         return false;
00915     }
00916 };
00917 
00918 // finds the query message stats for a machine
00919 nQueryMessageStats & GetQueryMessageStats( nMachine & machine )
00920 {
00921     // get the decorator
00922     nQueryMessageStats * stats = NULL;
00923     nMachineDecorator * decorator = machine.GetDecorators();
00924     while ( decorator && !stats )
00925     {
00926         stats = dynamic_cast< nQueryMessageStats * >( decorator );
00927         decorator = decorator->Next();
00928     }
00929     if ( !stats )
00930         stats = tNEW( nQueryMessageStats )( machine );
00931 
00932     // and delegate
00933     return *stats;
00934 }
00935 
00936 // determines wheter the machine is causing a flood attack
00937 bool FloodProtection( nMachine & machine, REAL timeFactor=1.0 )
00938 {
00939     // get the decorator and delegate
00940     return GetQueryMessageStats( machine ).FloodProtection( timeFactor );
00941 }
00942 
00943 // flag reset after each packet was received
00944 static bool sn_firstInPacket = true;
00945 static void sn_ResetFirstInPacket()
00946 {
00947     sn_firstInPacket = true;
00948 }
00949 static nCallbackReceivedComplete sn_resetFirstInPacket( sn_ResetFirstInPacket );
00950 static REAL sn_minPingTimeGlobalFactor = 0.1;
00951 static tSettingItem< REAL > sn_minPingTimeGlobal( "PING_FLOOD_GLOBAL", sn_minPingTimeGlobalFactor );
00952 
00953 // determines wheter the message comes from a flood attack; if so, reject it (return true)
00954 bool FloodProtection( nMessage const & m )
00955 {
00956     // get the machine infos
00957     nMachine & server = nMachine::GetMachine( 0 );
00958     nMachine & peer   = nMachine::GetMachine( m.SenderID() );
00959 
00960     // only accept one ping per packet
00961     if ( !sn_firstInPacket )
00962     {
00963         GetQueryMessageStats( peer ).Block();
00964 
00965         return true;
00966     }
00967 
00968     // don't accept further queries from this packet
00969     sn_firstInPacket = false;
00970 
00971     if ( sn_minPingTimes[sn_minPingCount - 1] <= 0 )
00972         return false;
00973 
00974     // and delegate
00975     return FloodProtection( peer ) || ( sn_minPingTimeGlobalFactor > 0 && FloodProtection( server, sn_minPingTimeGlobalFactor ) );
00976 }
00977 
00978 void nServerInfo::GetSmallServerInfo(nMessage &m){
00979     nServerInfoBase baseInfo;
00980     baseInfo.NetRead( m );
00981 
00982     // ReadServerInfo(m, port, connectionName, sn_AcceptingFromBroadcast, sn_AcceptingFromMaster);
00983 
00984     // master server should not listen to LAN games
00985     //if ( sn_IsMaster && baseInfo.GetConnectionName().Len() >= 3 && 0 == strncmp( baseInfo.GetConnectionName(), "192", 3 ) )
00986     //{
00987     //    return;
00988     //}
00989 
00990     // S_GlobalizeName( connectionName );
00991     sn_ServerCount++;
00992 
00993     nServerInfo *n = NULL;
00994 
00995     // check if we already have that server lised
00996     nServerInfo *run = GetFirstServer();
00997     int countSameAdr = 0;
00998     while(run)
00999     {
01000         if (run->GetConnectionName() == baseInfo.GetConnectionName() )
01001         {
01002             if (countSameAdr++ > 32)
01003                 n = run;
01004 
01005             if ( run->GetPort() == baseInfo.GetPort() )
01006                 n = run;
01007         }
01008         run = run->Next();
01009     }
01010 
01011     if (m.End())
01012         return;
01013 
01014     if (!n)
01015     {
01016         // so far no objections have been found; create the new server info.
01017         n = CreateServerInfo();
01018         n->timesNotAnswered = 0;
01019         if ( sn_IsMaster )
01020         {
01021             con << "Received new server: " << ToString( baseInfo ) << "\n";
01022             n->timesNotAnswered = 5;
01023         }
01024     }
01025     else
01026     {
01027         n->Alive();
01028 
01029         if ( sn_IsMaster )
01030         {
01031             con << "Updated server: " <<  ToString( baseInfo ) << "\n";
01032         }
01033     }
01034 
01035     n->nServerInfoBase::CopyFrom( baseInfo );
01036     n->stillOnMasterServer = true;
01037 
01038     if (n->name.Len() <= 1)
01039         n->name <<  ToString( baseInfo );
01040 
01041     //  n->advancedInfoSet = false;
01042     n->queried         = 0;
01043 
01044     if (!sn_IsMaster)
01045         m >> n->transactionNr;
01046     else
01047     {
01048         // n->timesNotAnswered = 5;
01049 
01050         if ( n->timesNotAnswered >= 1 )
01051         {
01052             if (sn_QuerySoon)
01053                 sn_QuerySoon->QueryServer();
01054 
01055             sn_QuerySoon = n;
01056             sn_QueryTimeout = tSysTimeFloat() + 5.0f;
01057         }
01058 
01059         unsigned int dummy;
01060         m >> dummy;
01061     }
01062 
01063     if (sn_IsMaster)
01064     {
01065         Save();
01066     }
01067 }
01068 
01069 static bool TransIsNewer(unsigned int newTrans, unsigned int oldTrans)
01070 {
01071     int diff = newTrans - oldTrans;
01072     return (diff > 0);
01073 }
01074 
01075 void nServerInfo::GiveSmallServerInfo(nMessage &m)
01076 {
01077     // start transmitting the server list in master server mode
01078     if (sn_IsMaster)
01079     {
01080         con << "Giving server info to user " << m.SenderID() << "\n";
01081 
01082         sn_Requested[m.SenderID()] = true;
01083 #ifdef KRAWALL_SERVER_LEAGUE
01084         // one moment! check if we need authentification
01085         tString adr;
01086         unsigned int port = sn_GetPort(m.SenderID());
01087         sn_GetAdr(m.SenderID(), adr);
01088         if (nKrawall::RequireMasterLogin(adr, port))
01089         {
01090             nAuthentication::SetLoginResultCallback(&ResultCallback);
01091             nAuthentication::RequestLogin(tString(""), m.SenderID(), tOutput("$login_request_master"));
01092         }
01093         else
01094         {
01095             sn_Transmitting[m.SenderID()] = GetFirstServer();
01096             sn_Auth[m.SenderID()]         = true;
01097         }
01098 #else
01099         sn_Transmitting[m.SenderID()] = GetFirstServer();
01100 #endif
01101 
01102         if (m.End())
01103             sn_SendAll[m.SenderID()] = true;
01104         else
01105         {
01106             sn_SendAll[m.SenderID()] = false;
01107             m >> sn_LastKnown[m.SenderID()];
01108         }
01109 
01110         // give out all server info if there is a disagreement
01111         // if ( static_cast< unsigned int > ( sn_NextTransactionNr - sn_lastKnown[m.SenderID] ) < 1000 )
01112         sn_SendAll[m.SenderID()] = true;
01113     }
01114 
01115     else
01116     {
01117         if ( FloodProtection( m ) )
01118             return;
01119 
01120         // immediately respond with a small info
01121         tJUST_CONTROLLED_PTR< nMessage > ret = tNEW(nMessage)(SmallServerDescriptor);
01122 
01123         // get small server info
01124         nServerInfoBase info;
01125         info.GetFrom( sn_Connections[m.SenderID()].socket );
01126 
01127         // fill it in
01128         info.NetWrite(*ret);
01129 
01130         unsigned int notrans = 0;
01131         *ret << notrans;
01132 
01133         ret->ClearMessageID();
01134         ret->SendImmediately(m.SenderID(), false);
01135         nMessage::SendCollected(m.SenderID());
01136     }
01137 }
01138 
01139 // from nNetwork.cpp
01140 int sn_NumRealUsers();
01141 
01142 nServerInfo* nServerInfo::GetBigServerInfoCommon(nMessage &m)
01143 {
01144     // read server info
01145     nServerInfoBase baseInfo;
01146     baseInfo.NetRead( m );
01147 
01148     // find the server
01149     nServerInfo *server = GetFirstServer();
01150     while( server && *server != baseInfo )
01151         server = server->Next();
01152 
01153     if ( server )
01154     {
01155         server->NetReadThis( m );
01156         server->Alive();
01157         server->CalcScore();
01158     }
01159     else
01160     {
01161         if ( sn_IsMaster )
01162         {
01163             tOutput message;
01164             message.SetTemplateParameter(1, ToString( baseInfo ) );
01165             message.SetTemplateParameter(2, sn_Connections[m.MessageID()].socket->GetAddress().ToString() );
01166             message << "$network_browser_unidentified";
01167             con << message;
01168         }
01169         else
01170         {
01171             // add the server, but ping it again
01172             nServerInfo * n = CreateServerInfo();
01173             n->CopyFrom( baseInfo );
01174             n->name = ToString( baseInfo );
01175             n->QueryServer();
01176 #ifdef DEBUG
01177             con << "Recevied unknown server " << n->name << ".\n";
01178 #endif
01179         }
01180     }
01181 
01182     return server;
01183 }
01184 
01185 void nServerInfo::GiveBigServerInfoCommon(nMessage &m, const nServerInfo & info, nDescriptor& descriptor )
01186 {
01187     // create message
01188     nMessage *ret = tNEW(nMessage)( descriptor );
01189 
01190     // write info
01191     info.NetWrite( *ret );
01192 
01193     // send info
01194     ret->ClearMessageID();
01195     ret->SendImmediately(m.SenderID(), false);
01196     nMessage::SendCollected(m.SenderID());
01197 }
01198 
01199 void nServerInfo::GetBigServerInfo(nMessage &m)
01200 {
01201     nServerInfo * server = GetBigServerInfoCommon( m );
01202 
01203     if (!server)
01204         return;
01205 }
01206 
01207 void nServerInfo::GiveBigServerInfo(nMessage &m)
01208 {
01209     if ( FloodProtection( m ) )
01210         return;
01211 
01212     if (sn_IsMaster)
01213         return;
01214 
01215     // collect info
01216     nServerInfo me;
01217     me.GetFrom( sn_Connections[m.SenderID()].socket );
01218 
01219     // delegate
01220     GiveBigServerInfoCommon(m, me, BigServerDescriptor );
01221 }
01222 
01223 void nServerInfo::SetFromMaster()
01224 {
01225     // no information about ping
01226     ping = .999;
01227     users = 0;
01228     userNames_ = userNamesOneLine_ = "Sever polled over master server, no reliable user data available.";
01229     advancedInfoSet = true;
01230 
01231     CalcScore();
01232 }
01233 
01234 void nServerInfo::GetBigServerInfoMaster(nMessage &m)
01235 {
01236     if ( sn_GetNetState() == nSERVER && FloodProtection( m ) )
01237         return;
01238 
01239     nServerInfo *server = GetBigServerInfoCommon( m );
01240 
01241     if (!server)
01242         return;
01243 
01244     server->SetFromMaster();
01245 }
01246 
01247 void nServerInfo::GiveBigServerInfoMaster(nMessage &m)
01248 {
01249     if ( FloodProtection( m ) )
01250         return;
01251 
01252     if ( !sn_IsMaster )
01253         return;
01254 
01255     // read info of desired server from message
01256     nServerInfoBase baseInfo;
01257     baseInfo.NetRead( m );
01258 
01259     // find the server
01260     nServerInfo *server = GetFirstServer();
01261     while( server && *server != baseInfo )
01262         server = server->Next();
01263 
01264     if (!server)
01265         return;
01266 
01267     // delegate
01268     GiveBigServerInfoCommon(m, *server, BigServerMasterDescriptor );
01269 }
01270 
01271 /*
01272 #define nUSERNAMES 0
01273 #define nOPTIONS 1
01274 #define nURL 2
01275 
01276 
01277 void nServerInfo::GiveExtraServerInfo(nMessage &m)
01278 {
01279         if (sn_IsMaster)
01280                 Cheater(m.SenderID());
01281   
01282         unsigned short extraType;
01283         WriteMyInfo(m);
01284         m >> extraType;
01285 
01286         tJUST_CONTROLLED_PTR< nMessage > pm = tNEW( nMessage( ExtraServerDescriptor ) );
01287         nMessage& mRet = *pm;
01288 
01289         mRet << extraType;
01290 
01291         tString ret="UNKNOWN";
01292 
01293         if ( nServerInfoAdmin::GetAdmin() )
01294         {
01295                 switch ( extraType )
01296                 {
01297                         case nUSERNAMES:
01298                                 ret = nServerInfoAdmin::GetAdmin()->GetUsers();
01299                                 break;
01300                         case nOPTIONS:
01301                                 ret = nServerInfoAdmin::GetAdmin()->GetOptions();
01302                                 break;
01303                         case nURL:
01304                                 ret = nServerInfoAdmin::GetAdmin()->GetUrl();
01305                                 break;
01306                 }
01307         }
01308 
01309         mRet << ret;
01310         mRet.Send( m.SenderID() );
01311         mRet.ClearMessageID();
01312         mRet.SendImmediately(m.SenderID(), false);
01313         nMessage::SendCollected(m.SenderID());
01314 }
01315 
01316 void nServerInfo::GetExtraServerInfo(nMessage &m)
01317 {
01318         unsigned int port;
01319         tString connectionName;
01320 
01321         ReadServerInfo(m, port, connectionName, true, false);
01322 
01323         //  S_GlobalizeName( connectionName );
01324 
01325         // find the server
01326         nServerInfo *server = GetFirstServer();
01327         while(server && !(server->port == port && S_LocalizeName(server->connectionName) == connectionName))
01328                 server = server->Next();
01329 
01330         if (!server)
01331                 return;
01332 
01333         unsigned short extraType;
01334         m >> extraType;
01335 
01336         tString value;
01337         m >> value;
01338 
01339         switch ( extraType )
01340         {
01341                 case nUSERNAMES:
01342                         server->userNames_ = value;
01343                         break;
01344                 case nOPTIONS:
01345                         server->options_ = value;
01346                         break;
01347                 case nURL:
01348                         server->url_ = value;
01349                         break;
01350         }
01351 
01352         server->Alive();
01353         server->CalcScore();
01354 }
01355 
01356 // queries extra informationn
01357 bool nServerInfo::QueryExtraInfo()
01358 {
01359         static float lastTime = 0.0f;
01360         static const float Interval     
01361 }
01362 
01363 RequestExtraServerInfoDescriptor
01364 
01365 nConnectError nServerInfo::Connect( nLoginType loginType, const nSocket * socket )
01366 {
01367     unsigned int portBack = sn_clientPort;
01368     sn_clientPort = port;
01369     nConnectError error = sn_Connect( connectionName, login2_, socket );
01370     sn_clientPort = portBack;
01371 
01372     return error;
01373 }
01374 */
01375 
01376 tString MasterFile( char const * suffix )
01377 {
01378     std::ostringstream filename;
01379     filename << "frommaster" << suffix << ".srv";
01380     return tString( filename.str().c_str() );
01381 }
01382 
01383 void nServerInfo::GetFromMaster(nServerInfoBase *masterInfo, char const * fileSuffix )
01384 {
01385     sn_AcceptingFromMaster = true;
01386 
01387     if ( !fileSuffix )
01388     {
01389         fileSuffix = "";
01390     }
01391 
01392     bool multiMaster = false;
01393     if (!masterInfo)
01394     {
01395         multiMaster = true;
01396         masterInfo = GetRandomMaster();
01397     }
01398 
01399     if (!masterInfo)
01400         return;
01401 
01402     DeleteAll();
01403 
01404     // load all the servers we know
01405     Load( tDirectories::Var(), MasterFile( fileSuffix ) );
01406 
01407     // delete unreachable servers
01408     DeleteUnreachable();
01409 
01410     // find the latest server we know about
01411     unsigned int latest=0;
01412     nServerInfo *run = GetFirstServer();
01413     if (run)
01414     {
01415         latest = run->TransactionNr();
01416         run = run->Next();
01417         while (run)
01418         {
01419             if (TransIsNewer(run->TransactionNr(), latest))
01420                 latest = run->TransactionNr();
01421             run = run->Next();
01422         }
01423     }
01424 
01425     // connect to the master server
01426     con << tOutput("$network_master_connecting", masterInfo->GetName() );
01427 
01428     nConnectError error = nTIMEOUT;
01429     //try
01430     {
01431         error = masterInfo->Connect( Login_Post0252 );
01432     }
01433     /*
01434         catch( tException const & )
01435         {
01436             if ( !masterInfo->Next() )
01437                 throw;
01438         }
01439     #ifdef _MSC_VER
01440     #pragma warning ( disable : 4286 )
01441         // GRR. Visual C++ dones not handle generic exceptions with the above general statement.
01442         // A specialized version is needed. The best part: it warns about the code below being redundant.
01443         catch( tGenericException const & )
01444         {
01445             if ( !masterInfo->Next() )
01446                 throw;
01447         }
01448     #endif // _MSC_VER
01449     */
01450 
01451     switch( error )
01452     {
01453     case nOK:
01454         break;
01455     case nABORT:
01456     {
01457         return;
01458     }
01459     case nTIMEOUT:
01460         // delete the master and select a new one
01461         if ( multiMaster )
01462         {
01463             delete masterInfo;
01464             masterInfo = sn_masterList;
01465         }
01466         else
01467         {
01468             masterInfo = 0;
01469         }
01470 
01471         if ( masterInfo )
01472         {
01473             con << tOutput( "$network_master_timeout_retry" );
01474             GetFromMaster( masterInfo );
01475         }
01476         else
01477         {
01478             tConsole::Message("$network_master_timeout_title", "$network_master_timeout_inter", 3600);
01479         }
01480         return;
01481         break;
01482 
01483     case nDENIED:
01484         tConsole::Message("$network_master_denied_title", "$network_master_denied_inter", 20);
01485         return;
01486         break;
01487 
01488     }
01489 
01490 
01491     // send the server list request message
01492     con << tOutput("$network_master_reqlist");
01493 
01494     nMessage *m=tNEW(nMessage)(RequestSmallServerInfoDescriptor);
01495     if (GetFirstServer())
01496         *m << latest;
01497     m->BroadCast();
01498 
01499     sn_ServerCount = 0;
01500     int lastReported = 10;
01501 
01502     // just wait for the data to pour in
01503     REAL timeout = tSysTimeFloat() + 60;
01504     while(sn_GetNetState() == nCLIENT && timeout > tSysTimeFloat())
01505     {
01506         sn_Receive();
01507         sn_SendPlanned();
01508         tAdvanceFrame(100000);
01509         st_DoToDo();
01510         if (sn_ServerCount > lastReported + 9)
01511         {
01512             tOutput o;
01513             o.SetTemplateParameter(1, lastReported);
01514             o << "$network_master_status";
01515             con << o;
01516             lastReported = (sn_ServerCount/10) * 10;
01517         }
01518     }
01519 
01520     tOutput o;
01521     o.SetTemplateParameter(1, sn_ServerCount);
01522     o << "$network_master_finish";
01523     con << o;
01524 
01525     // remove servers that are no longer listed on the master
01526     run = GetFirstServer();
01527     while (run)
01528     {
01529         nServerInfo * next = run->Next();
01530         if ( !run->stillOnMasterServer )
01531         {
01532             // if the server has still positive score bias, just reduce that
01533             if ( run->scoreBias_ > 0 )
01534             {
01535                 run->scoreBias_ -= 10;
01536             }
01537             else
01538             {
01539                 // kill it
01540                 delete run;
01541             }
01542         }
01543         run = next;
01544     }
01545 
01546     Save(tDirectories::Var(), MasterFile( fileSuffix ));
01547 
01548     sn_SetNetState(nSTANDALONE);
01549 
01550     sn_AcceptingFromMaster = false;
01551 
01552     tAdvanceFrame();
01553 }
01554 
01555 void nServerInfo::GetFromLAN(unsigned int pollBeginPort, unsigned int pollEndPort)
01556 {
01557     sn_AcceptingFromBroadcast = true;
01558 
01559     sn_LastLoaded.Clear();
01560 
01561     // enter client state
01562     if (sn_GetNetState() != nCLIENT)
01563         sn_SetNetState(nCLIENT);
01564 
01565     // prepare the request message and broadcast is
01566     con << tOutput("$network_master_reqlist");
01567     for (unsigned int port = pollBeginPort; port <= pollEndPort; port++)
01568     {
01569         nMessage *m=tNEW(nMessage)(RequestSmallServerInfoDescriptor);
01570         m->ClearMessageID();
01571         m->SendImmediately(0, false);
01572         nMessage::BroadcastCollected(0, port);
01573         tDelay(1000);
01574     }
01575 
01576     sn_ServerCount = 0;
01577     int lastReported = 10;
01578 
01579     // and just wait a bit for the answers to arrive
01580     REAL timeout = tSysTimeFloat() + 1.5f;
01581     while(sn_GetNetState() == nCLIENT && timeout > tSysTimeFloat())
01582     {
01583         tAdvanceFrame();
01584         sn_Receive();
01585         sn_SendPlanned();
01586         tAdvanceFrame(10000);
01587         if (sn_ServerCount > lastReported)
01588         {
01589             tOutput o;
01590             o.SetTemplateParameter(1, lastReported);
01591             o << "$network_master_status";
01592             con << 0;
01593             lastReported = (sn_ServerCount/10) * 10;
01594         }
01595     }
01596 
01597     tOutput o;
01598     o.SetTemplateParameter(1, sn_ServerCount);
01599     o << "$network_master_finish";
01600     con << o;
01601 
01602     sn_AcceptingFromBroadcast = false;
01603 
01604     sn_SetNetState(nSTANDALONE);
01605 }
01606 
01607 void nServerInfo::GetFromLANContinuously(unsigned int pollBeginPort, unsigned int pollEndPort)
01608 {
01609     sn_AcceptingFromBroadcast = true;
01610 
01611     sn_LastLoaded.Clear();
01612 
01613     // enter client state
01614     if (sn_GetNetState() != nCLIENT)
01615         sn_SetNetState(nCLIENT);
01616 
01617     // prepare the request message and broadcast it
01618     for (unsigned int port = pollBeginPort; port <= pollEndPort; port++)
01619     {
01620         nMessage *m=tNEW(nMessage)(RequestSmallServerInfoDescriptor);
01621         m->ClearMessageID();
01622         m->SendImmediately(0, false);
01623         nMessage::BroadcastCollected(0, port);
01624         tDelay(1000);
01625     }
01626 }
01627 
01628 void nServerInfo::GetFromLANContinuouslyStop()
01629 {
01630     sn_AcceptingFromBroadcast = false;
01631 
01632     sn_SetNetState(nSTANDALONE);
01633 }
01634 
01635 void nServerInfo::TellMasterAboutMe(nServerInfoBase *masterInfo)
01636 {
01637     // don't reinitialize the network system
01638     nSocketResetInhibitor inhibitor;
01639 
01640     static unsigned int lastPort = 0;
01641 
01642     // enter server state so we know our true port number
01643     sn_SetNetState(nSERVER);
01644     unsigned int port = sn_GetServerPort();
01645     //if (port == lastPort)
01646     //    return; // the master already knows about us
01647 
01648     lastPort = port;
01649 
01650     //    sn_SetNetState(nSTANDALONE);
01651 
01652     if (!masterInfo)
01653     {
01654         // recurse, logging in to all masters
01655         nServerInfo * run = GetMasters();
01656 
01657         while ( run )
01658         {
01659             if ( run->GetAddress().IsSet() )
01660             {
01661                 TellMasterAboutMe( run );
01662             }
01663             run = run->Next();
01664         }
01665 
01666         return;
01667     }
01668 
01669     con << tOutput("$network_master_connecting", masterInfo->GetName() );
01670 
01671     // the socket that the master server connection runs on
01672     nSocket const * connection = NULL;
01673 
01674     // connect to the master server; try the listening sockets first
01675     {
01676         nConnectError result = nDENIED;
01677 
01678         // iterate through listening sockets
01679         const nSocketListener & listener = sn_BasicNetworkSystem.GetListener();
01680         for ( nSocketListener::iterator i = listener.begin(); i != listener.end(); ++i )
01681         {
01682             result = masterInfo->Connect( Login_Post0252, &(*i) );
01683             if ( nOK == result )
01684             {
01685                 connection = &(*i);
01686                 break;
01687             }
01688         }
01689 
01690         // try a generic socket next ( a shot in the dark, but worth a try )
01691         if ( result != nOK )
01692         {
01693             // leave connection at NULL so the server info will be filled with generic info
01694             connection = NULL;
01695             result = masterInfo->Connect( Login_Post0252 );
01696         }
01697 
01698         // give up
01699         if ( result != nOK )
01700             return;
01701     }
01702 
01703     // collect the server information of this system
01704     nServerInfoBase info;
01705     info.GetFrom( connection );
01706 
01707     // write it to a network message message
01708     nMessage *m=tNEW(nMessage)(SmallServerDescriptor);
01709     info.NetWrite(*m);
01710     unsigned int dummy = 0;
01711     *m << dummy;
01712 
01713     // send it
01714     con << tOutput("$network_master_send");
01715     m->BroadCast();
01716     sn_Receive();
01717     sn_SendPlanned();
01718 
01719     // wait for the data to be accepted
01720     nTimeRolling timeout = tSysTimeFloat() + 20;
01721     while(sn_GetNetState() == nCLIENT && timeout > tSysTimeFloat() && sn_Connections[0].ackPending > 0)
01722     {
01723         sn_Receive();
01724         sn_SendPlanned();
01725         tAdvanceFrame(10000);
01726     }
01727 
01728     sn_SetNetState(nSTANDALONE);
01729 }
01730 
01731 void nServerInfo::QueryServer()                                  // start to get advanced info from this server itself
01732 {
01733     // determine whether we should query directly or via the master
01734     bool queryDirectly = false;
01735     switch( queryType_ )
01736     {
01737     case QUERY_ALL:
01738         queryDirectly = true;
01739         break;
01740     case QUERY_OPTOUT:
01741         queryDirectly = ( scoreBias_ >= 0 );
01742         break;
01743     case QUERY_OPTIN:
01744         queryDirectly = ( scoreBias_ > 0 );
01745         break;
01746     case QUERY_NONE:
01747         queryDirectly = false;
01748         break;
01749     }
01750 
01751     // early exit if there is nothing to poll
01752     if ( !queryDirectly )
01753     {
01754         // see if the server name is just IP:port; if no, we already successfully polled it
01755         if ( name != ToString( *this ) )
01756         {
01757             advancedInfoSetEver = true;
01758         }
01759 
01760         if( advancedInfoSetEver )
01761         {
01762             // but only 90% of the time, we want to know if the server goes down sometime.
01763             static tReproducibleRandomizer randomizer;
01764             if ( randomizer.Get() > .1 && timesNotAnswered == 0 )
01765             {
01766                 SetFromMaster();
01767                 return;
01768             }
01769         }
01770     }
01771 
01772     sn_Polling.Add(this, pollID);
01773 
01774 #ifdef DEBUG
01775     if ( sn_IsMaster )
01776     {
01777         con << "Querying server " <<  ToString( *this ) << "\n";
01778     }
01779 #endif
01780 
01781     if (timesNotAnswered > sn_MaxTNA() )
01782     {
01783         // server was inactive too long. Delete it if possible.
01784 
01785         // check if this server is the one with the highest TAN
01786         unsigned int latest=0;
01787         nServerInfo *run = GetFirstServer();
01788         nServerInfo *best = NULL;
01789         while (run == this)
01790             run = run->Next();
01791 
01792         if (run)
01793         {
01794             latest  = run->TransactionNr();
01795             best    = run;
01796             run     = run->Next();
01797 
01798             while (run)
01799             {
01800                 if ((run != this) && TransIsNewer(run->TransactionNr(), latest))
01801                 {
01802                     latest = run->TransactionNr();
01803                     best   = run;
01804                 }
01805                 run = run->Next();
01806             }
01807         }
01808 
01809         // now, best points to the latest (except this) server and
01810         // latest is its TAN.
01811 
01812         // continue if this server is the only one available
01813         if (best)
01814         {
01815             // if THIS server has the latest TAN, simpy transfer it to the second latest.
01816             if (TransIsNewer(TransactionNr(), latest))
01817                 best->transactionNr = TransactionNr();
01818 
01819             timesNotAnswered = 1000;
01820             if ( sn_IsMaster )
01821             {
01822                 con << "Deleted unreachable server: " <<  ToString( *this ) << "\n";
01823 
01824                 delete this;
01825             }
01826             return;
01827         }
01828     }
01829 
01830     if ( queryDirectly )
01831     {
01832         // send information query directly to server
01833         sn_Bend( GetAddress() );
01834 
01835         tJUST_CONTROLLED_PTR< nMessage > req = tNEW(nMessage)(RequestBigServerInfoDescriptor);
01836         req->ClearMessageID();
01837         req->SendImmediately(0, false);
01838         nMessage::SendCollected(0);
01839     }
01840     else
01841     {
01842         // send information query to master
01843         sn_Bend( GetMasters()->GetAddress() );
01844 
01845         tJUST_CONTROLLED_PTR< nMessage > req = tNEW(nMessage)(RequestBigServerInfoMasterDescriptor);
01846         req->ClearMessageID();
01847 
01848         // write server info into request packet
01849         nServerInfoBase::NetWriteThis( *req );
01850 
01851         req->SendImmediately(0, false);
01852         nMessage::SendCollected(0);
01853     }
01854 
01855     timeQuerySent = tSysTimeFloat();
01856     if ( queried == 0 )
01857     {
01858         if ( ++timesNotAnswered == sn_TNALostContact && sn_IsMaster )
01859         {
01860             con << "Lost contact with server: " <<  ToString( *this ) << "\n";
01861         }
01862         else if ( sn_IsMaster && timesNotAnswered == 2 )
01863         {
01864             con << "Starting to lose contact with server: " <<  ToString( *this ) << ", name \"" << tColoredString::RemoveColors(name) << "\"\n";
01865         }
01866     }
01867 
01868     queried++;
01869 
01870     if ( !this->advancedInfoSetEver )
01871     {
01872         score = -1E+32f;
01873     }
01874 }
01875 
01876 void nServerInfo::SetQueryType( QueryType queryType )
01877 {
01878     queryType_ = queryType;
01879 }
01880 
01881 // make it appear that we never queried the server (but keep the information)
01882 void nServerInfo::ClearInfoFlags()
01883 {
01884     advancedInfoSetEver = advancedInfoSet = false;
01885     ping = 10;
01886 }
01887 
01888 void GetSenderData(const nMessage &m,tString& name, int& port)
01889 {
01890     sn_GetAdr(m.SenderID(),name);
01891     port = sn_GetPort(m.SenderID());
01892 }
01893 
01894 // *******************************************************************************
01895 // *
01896 // *    DeleteUnreachable
01897 // *
01898 // *******************************************************************************
01901 // *******************************************************************************
01902 
01903 void nServerInfo::DeleteUnreachable( void )
01904 {
01905     int totalTNAMax = sn_MaxTNATotal();
01906     int maxUnreachable = sn_MaxUnreachable();
01907     int totalTNA = totalTNAMax + 1;
01908     int lastTNA = totalTNA + 1;
01909     int unreachableCount = 0;
01910 
01911     while ( ( totalTNA > totalTNAMax || unreachableCount > maxUnreachable ) && lastTNA != totalTNA  )
01912     {
01913         lastTNA = totalTNA;
01914         totalTNA = 0;
01915         unreachableCount = 0;
01916 
01917         nServerInfo *kickOut = NULL;
01918         int maxTNA = 0;
01919         int minTNA = 100;
01920 
01921         nServerInfo * run = GetFirstServer();
01922 
01923         while(run)
01924         {
01925             // run->score = run->scoreBias_;
01926 
01927             int TNA = run->TimesNotAnswered();
01928             // sum up TNAs and determine server with maximum TNA
01929             if ( TNA > 0 && TNA <= sn_MaxTNA() )
01930             {
01931                 unreachableCount++;
01932                 totalTNA += TNA;
01933                 if ( TNA > maxTNA )
01934                 {
01935                     maxTNA = TNA;
01936                     kickOut = run;
01937                 }
01938             }
01939 
01940             if ( TNA < minTNA  )
01941             {
01942                 minTNA = TNA;
01943             }
01944 
01945             run = run->Next();
01946         }
01947 
01948         if ( minTNA > 0 )
01949         {
01950             // no server was reachable at all! Ehternet cable is probably pulled.
01951             return;
01952         }
01953 
01954         // mark worst server for kickout if total TNA is too high
01955         if ( kickOut && ( ( totalTNA > totalTNAMax && maxTNA >= sn_TNALostContact ) || unreachableCount > maxUnreachable ) )
01956         {
01957             // just delete the bastard!
01958             delete kickOut;
01959             //                  kickOut->timesNotAnswered = sn_MaxTNA() + 100;
01960         }
01961     }
01962 }
01963 
01964 void nServerInfo::StartQueryAll( QueryType queryType )                         // start querying the advanced info of each of the servers in our list
01965 {
01966     sn_Requesting     = GetFirstServer();
01967 
01968     while (sn_Polling.Len())
01969         sn_Polling.Remove(sn_Polling(0), sn_Polling(0)->pollID);
01970 
01971     nServerInfo *run = GetFirstServer();
01972 
01973     while(run)
01974     {
01975         // set the query type
01976         run->SetQueryType( queryType );
01977 
01978         // do a DNS query of the server
01979         run->ClearAddress();
01980         run->GetAddress();
01981 
01982         run->queried         = 0;
01983         run->advancedInfoSet = 0;
01984 
01985         int TNA = run->TimesNotAnswered();
01986 
01987         // remove known status
01988         if ( TNA > 0 )
01989         {
01990             run->advancedInfoSetEver = false;
01991         }
01992         else
01993         {
01994             // run->advancedInfoSetEver = true;
01995         }
01996 
01997         run = run->Next();
01998     }
01999 }
02000 
02001 bool nServerInfo::DoQueryAll(int simultaneous)         // continue querying the advanced info of each of the servers in our list; return value: do we need to go on with this?
02002 {
02003     REAL time = tSysTimeFloat();
02004 
02005     static REAL globalTimeout = time;
02006     if ( time < globalTimeout )
02007     {
02008         return true;
02009     }
02010 
02011     globalTimeout = time + sn_queryDelayGlobal;
02012 
02013     for (int i=sn_Polling.Len()-1; i>=0; i--)
02014     {
02015         nServerInfo* poll = sn_Polling(i);
02016         if (poll->timeQuerySent + sn_queryDelay < time)
02017             sn_Polling.Remove(poll, poll->pollID);
02018     }
02019 
02020     if (sn_Requesting && sn_Polling.Len() < simultaneous)
02021     {
02022         nServerInfo* next = sn_Requesting->Next();
02023 
02024         if (!sn_Requesting->advancedInfoSet && sn_Requesting->pollID < 0 && sn_Requesting->queried <= sn_numQueries)
02025         {
02026             sn_Requesting->QueryServer();
02027         }
02028 #ifdef DEBUG
02029         else
02030         {
02031             int x;
02032             x = 1;
02033         }
02034 #endif
02035 
02036         sn_Requesting = next;
02037     }
02038 
02039     sn_Receive();
02040     sn_SendPlanned();
02041 
02042     if (sn_Requesting)
02043         return true;
02044     else
02045     {
02046         bool ret = false;
02047 
02048         nServerInfo *run = GetFirstServer();
02049         while(run && !ret)
02050         {
02051             if (!run->advancedInfoSet && (run->queried <= sn_numQueries-1 || run->pollID >= 0))
02052                 ret = true;
02053 
02054             run = run->Next();
02055         }
02056 
02057         if (ret)
02058         {
02059             sn_Requesting = GetFirstServer();
02060             Save();
02061         }
02062         else
02063             Save();
02064 
02065         return ret;
02066     }
02067 }
02068 
02069 
02070 
02071 
02072 
02073 
02074 
02075 
02076 
02077 
02078 
02079 
02080 
02081 
02082 
02083 
02084 
02085 
02086 
02087 
02088 
02089 
02090 
02091 
02092 
02093 
02094 
02095 
02096 
02097 
02098 
02099 
02100 
02101 
02102 
02103 void nServerInfo::RunMaster()
02104 {
02105     sn_IsMaster               = true;
02106     sn_AcceptingFromBroadcast = true;
02107 
02108     DeleteUnreachable();
02109 
02110     nTimeRolling time = tSysTimeFloat();
02111     if (time > sn_QueryTimeout && sn_QuerySoon)
02112     {
02113         sn_QuerySoon->QueryServer();
02114         sn_QuerySoon = NULL;
02115         std::cout.flush();
02116         std::cerr.flush();
02117     }
02118 
02119     if (sn_NextTransactionNr == 0)
02120         // find the latest server we know about
02121     {
02122         unsigned int latest=0;
02123         nServerInfo *run = GetFirstServer();
02124         if (run)
02125         {
02126             latest = run->TransactionNr();
02127             run = run->Next();
02128             while (run)
02129             {
02130                 if (TransIsNewer(run->TransactionNr(), latest))
02131                     latest = run->TransactionNr();
02132                 run = run->Next();
02133             }
02134         }
02135 
02136         latest++;
02137         if (latest == 0)
02138             latest ++;
02139 
02140         sn_NextTransactionNr = latest;
02141     }
02142 
02143     // start with random transaction number
02144     if (sn_NextTransactionNr == 0)
02145     {
02146         sn_NextTransactionNr = rand();
02147     }
02148 
02149     for (int i=MAXCLIENTS; i>0; i--)
02150     {
02151         if(sn_Connections[i].socket)
02152         {
02153             // kick the user soon when the transfer is completed
02154             if ((sn_Requested[i] && !sn_Transmitting[i]
02155 #ifdef KRAWALL_SERVER
02156                     && sn_Auth[i]
02157 #endif
02158                     && sn_MessagesPending(i) == 0))
02159             {
02160                 if (sn_Timeout[i] > tSysTimeFloat() + .2f)
02161                     sn_Timeout[i] = tSysTimeFloat() + .2f;
02162             }
02163 
02164             // defend against DOS attacks: Kill idle clients
02165             if(sn_Timeout[i] < tSysTimeFloat())
02166                 sn_DisconnectUser(i, "$network_kill_timeout");
02167 
02168             if (!sn_Requested[i] && sn_Timeout[i] < tSysTimeFloat() + 60.0f)
02169                 sn_DisconnectUser(i, "$network_kill_timeout");
02170 
02171         }
02172 
02173         if (sn_Transmitting[i] && sn_MessagesPending(i) < 3)
02174         {
02175 
02176             for (int j = 10-sn_MessagesPending(i); j>=0 && sn_Transmitting[i]; j--)
02177             {
02178                 // skip known servers
02179                 if (!sn_SendAll[i])
02180                 {
02181                     while (sn_Transmitting[i] && !TransIsNewer(sn_Transmitting[i]->TransactionNr(), sn_LastKnown[i]))
02182                         sn_Transmitting[i] = sn_Transmitting[i]->Next();
02183                 }
02184 
02185                 if (!sn_Transmitting[i])
02186                     continue;
02187 
02188                 if (sn_Transmitting[i]->TimesNotAnswered() < sn_TNALostContact )
02189                 {
02190                     // tell user i about server sn_Transmitting[i]
02191                     nMessage *m = tNEW(nMessage)(SmallServerDescriptor);
02192                     sn_Transmitting[i]->nServerInfoBase::NetWriteThis( *m );
02193                     *m << sn_Transmitting[i]->TransactionNr();
02194                     m->Send(i);
02195                 }
02196 
02197                 sn_Transmitting[i] = sn_Transmitting[i]->Next();
02198             }
02199         }
02200 
02201     }
02202 
02203     sn_Receive();
02204     sn_SendPlanned();
02205 }
02206 
02207 bool nServerInfo::Reachable() const
02208 {
02209     return advancedInfoSetEver && TimesNotAnswered() < sn_TNALostContact;
02210 }
02211 
02212 bool nServerInfo::Polling() const
02213 {
02214     return (!advancedInfoSetEver && queried <= 3 && TimesNotAnswered() < sn_TNALostContact );// || ( !advancedInfoSet && queried > 1 && queried <= 3 );
02215 }
02216 
02217 
02218 
02219 
02220 /*
02221 class nMasterServerInfo: public nServerInfo
02222 {
02223 public:
02224     nMasterServerInfo()
02225     {
02226         Remove();  // the master server should not appear on any list
02227 
02228         // automatically load the master server config file
02229         tString f;
02230 
02231         std::ifstream s;
02232 
02233         tDirectories::Config().Open( s, "master.srv" );
02234 
02235         Load(s);
02236     }
02237 };
02238 */
02239 
02240 nServerInfo *nServerInfo::GetMasters()
02241 {
02242     // reload master list at least once per minute
02243     double time = tSysTimeFloat();
02244     static double deleteTime = time;
02245     if ( time > deleteTime )
02246     {
02247         deleteTime = time + 60.0;
02248 
02249         while (sn_masterList)
02250             delete sn_masterList;
02251     }
02252 
02253     if (!sn_masterList)
02254     {
02255         // back up the regular server list
02256         nServerInfo * oldFirstServer = sn_FirstServer;
02257         sn_FirstServer = NULL;
02258 
02259         // load the master server list cleanly
02260         Load( tDirectories::Config(), "master.srv" );
02261 
02262         // transfer list
02263         while ( sn_FirstServer )
02264         {
02265             nServerInfo * server = sn_FirstServer;
02266             server->Remove();
02267             server->Insert( sn_masterList );
02268         }
02269 
02270         // restore up the regular server list
02271         sn_FirstServer = oldFirstServer;
02272     }
02273 
02274     return sn_masterList;
02275 }
02276 
02277 class DeleteMaster
02278 {
02279 public:
02280     ~DeleteMaster()
02281     {
02282         while (sn_masterList)
02283             delete sn_masterList;
02284     }
02285 };
02286 
02287 static DeleteMaster sn_delm;
02288 
02289 nServerInfo* nServerInfo::GetRandomMaster()
02290 {
02291     // select a random master server
02292     nServerInfo * masterInfo = GetMasters();
02293 
02294     // count masters
02295     int count = 0;
02296     while( masterInfo )
02297     {
02298         masterInfo = masterInfo->Next();
02299         ++count;
02300     }
02301 
02302     // select randomly
02303     static tReproducibleRandomizer randomizer;
02304     REAL ran = randomizer.Get();
02305     // REAL ran = rand()/REAL(RAND_MAX);
02306     int r = 1;
02307 
02308     masterInfo = GetMasters();
02309     while( masterInfo && masterInfo->Next() && r < ran * count )
02310     {
02311         masterInfo = masterInfo->Next();
02312         ++r;
02313     }
02314 
02315     tASSERT( masterInfo );
02316 
02317     // store and return
02318     masterInfo->Remove();
02319     masterInfo->Insert( sn_masterList );
02320 
02321     return masterInfo;
02322 }
02323 
02324 nServerInfo::Compat     nServerInfo::Compatibility() const
02325 {
02326     if ( sn_MyVersion().Min() > version_.Max() )
02327     {
02328         return Compat_Downgrade;
02329     }
02330 
02331     if ( sn_MyVersion().Max() < version_.Min() )
02332     {
02333         return Compat_Upgrade;
02334     }
02335 
02336     return Compat_Ok;
02337 }
02338 
02339 
02340 static nServerInfoAdmin* sn_serverInfoAdmin = NULL;
02341 
02342 nServerInfoAdmin::nServerInfoAdmin()
02343 {
02344     tASSERT( NULL == sn_serverInfoAdmin );
02345     sn_serverInfoAdmin = this;
02346 }
02347 
02348 nServerInfoAdmin::~nServerInfoAdmin()
02349 {
02350     sn_serverInfoAdmin = NULL;
02351 }
02352 
02353 nServerInfoAdmin* nServerInfoAdmin::GetAdmin()
02354 {
02355     return sn_serverInfoAdmin;
02356 }
02357 
02358 // *******************************************************************************************
02359 // *
02360 // *   nServerInfoBase
02361 // *
02362 // *******************************************************************************************
02365 // *******************************************************************************************
02366 
02367 nServerInfoBase::nServerInfoBase()
02368         : connectionName_(""),
02369           port_(0)
02370 {
02371 }
02372 
02373 // *******************************************************************************************
02374 // *
02375 // *   ~nServerInfoBase
02376 // *
02377 // *******************************************************************************************
02380 // *******************************************************************************************
02381 
02382 nServerInfoBase::~nServerInfoBase()
02383 {
02384 }
02385 
02386 // *******************************************************************************************
02387 // *
02388 // *   operator ==
02389 // *
02390 // *******************************************************************************************
02393 // *******************************************************************************************
02394 
02395 bool nServerInfoBase::operator ==( const nServerInfoBase & other ) const
02396 {
02397     return GetAddress() == other.GetAddress() && port_ == other.port_;
02398 }
02399 
02400 // *******************************************************************************************
02401 // *
02402 // *   operator !=
02403 // *
02404 // *******************************************************************************************
02407 // *******************************************************************************************
02408 
02409 bool nServerInfoBase::operator !=( const nServerInfoBase & other ) const
02410 {
02411     return ! operator == ( other );
02412 }
02413 
02414 // *******************************************************************************************
02415 // *
02416 // *   Connect
02417 // *
02418 // *******************************************************************************************
02422 // *******************************************************************************************
02423 
02424 nConnectError nServerInfoBase::Connect( nLoginType loginType, const nSocket * socket )
02425 {
02426     // refuse to connect without address
02427     if ( !GetAddress().IsSet() )
02428     {
02429         // well, not really a timeout. But we would timeout if we tried to connect.
02430         return nTIMEOUT;
02431     }
02432 
02433     //unsigned int portBack = sn_clientPort;
02434     //sn_clientPort = port_;
02435     if ( GetAddress().ToString().StartsWith( "*.*.*.*" ) )
02436     {
02437         throw tGenericException( tOutput("$network_message_dns_error_inter"),tOutput("$network_message_dns_error_title"));
02438     }
02439 
02440     nConnectError error = sn_Connect( GetAddress(), loginType, socket );
02441     //sn_clientPort = portBack;
02442 
02443     return error;
02444 }
02445 
02446 // *******************************************************************************************
02447 // *
02448 // *   CopyFrom
02449 // *
02450 // *******************************************************************************************
02454 // *******************************************************************************************
02455 
02456 void nServerInfoBase::CopyFrom( const nServerInfoBase & other )
02457 {
02458     port_               = other.port_;
02459     connectionName_     = other.connectionName_;
02460 }
02461 
02462 // *******************************************************************************************
02463 // *
02464 // *   operator =
02465 // *
02466 // *******************************************************************************************
02471 // *******************************************************************************************
02472 
02473 nServerInfoBase & nServerInfoBase::operator =( const nServerInfoBase & other )
02474 {
02475     CopyFrom( other );
02476     return *this;
02477 }
02478 
02479 // *******************************************************************************************
02480 // *
02481 // *   DoNetWrite
02482 // *
02483 // *******************************************************************************************
02487 // *******************************************************************************************
02488 
02489 void nServerInfoBase::DoNetWrite( nMessage & m ) const
02490 {
02491     NetWriteThis( m );
02492 }
02493 
02494 // *******************************************************************************************
02495 // *
02496 // *   DoNetRead
02497 // *
02498 // *******************************************************************************************
02502 // *******************************************************************************************
02503 
02504 void nServerInfoBase::DoNetRead( nMessage & m )
02505 {
02506     NetReadThis( m );
02507 }
02508 
02509 // *******************************************************************************************
02510 // *
02511 // *    NetWriteThis
02512 // *
02513 // *******************************************************************************************
02517 // *******************************************************************************************
02518 
02519 void nServerInfoBase::NetWriteThis( nMessage & m ) const
02520 {
02521     m << port_;            // write the port
02522     m << connectionName_;  // and the name
02523 }
02524 
02525 // reads a string, filtering out unwanted characters regardless of the network mode
02526 static void sn_ReadFiltered( nMessage & m, tString & s )
02527 {
02528     tColoredString raw;
02529     m >> raw;
02530     raw.NetFilter();
02531     s = raw;
02532 }
02533 
02534 // *******************************************************************************************
02535 // *
02536 // *    NetReadThis
02537 // *
02538 // *******************************************************************************************
02542 // *******************************************************************************************
02543 
02544 void nServerInfoBase::NetReadThis( nMessage & m )
02545 {
02546     m >> port_;                            // get the port
02547     sn_ReadFiltered( m, connectionName_ ); // get the connection name
02548 
02549     if ( ( sn_IsMaster || sn_AcceptingFromBroadcast || sn_AcceptingFromMaster ) && connectionName_.Len()>1 ) // no valid name (must come directly from the server who does not know his own address)
02550     {
02551         // resolve DNS
02552         connectionName_ = S_LocalizeName( connectionName_ );
02553     }
02554     else
02555     {
02556 #ifdef DEBUG_X
02557         if ( connectionName_.Len() > 1 )
02558         {
02559             std::cout << "Overwriting source from " << connectionName_ << ".\n";
02560         }
02561 #endif
02562 
02563         sn_GetAdr( m.SenderID(), connectionName_ );
02564 
02565         // remove the port
02566         for (int i=connectionName_.Size()-1; i>=0; i--)
02567             if (':' == connectionName_[i])
02568             {
02569                 connectionName_ = connectionName_.SubStr( 0, i );
02570             }
02571 
02572         S_GlobalizeName( connectionName_ );
02573     }
02574 }
02575 
02576 // the official IP address or DNS hostname of this server. If left blank, the recipient of the
02577 // message will figure the IP out on its own.
02578 static tString net_dns("");
02579 
02580 static tConfItemLine sn_sbtip_official("SERVER_DNS", net_dns);
02581 
02582 // *******************************************************************************************
02583 // *
02584 // *    DoGetFrom
02585 // *
02586 // *******************************************************************************************
02590 // *******************************************************************************************
02591 
02592 void nServerInfoBase::DoGetFrom( nSocket const * socket )
02593 {
02594     // better not set connection name, the message recipient can figure it out more reliably
02595     connectionName_ = net_dns;
02596 
02597     if ( ! socket )
02598     {
02599         port_ = sn_GetServerPort();
02600     }
02601     else
02602     {
02603         // fill port information from socket
02604         nAddress const & address = socket->GetAddress();
02605         port_ = address.GetPort();
02606     }
02607 }
02608 
02609 // *******************************************************************************************
02610 // *
02611 // *   DoNetWrite
02612 // *
02613 // *******************************************************************************************
02617 // *******************************************************************************************
02618 
02619 void nServerInfo::DoNetWrite( nMessage & m ) const
02620 {
02621     nServerInfoBase::DoNetWrite( m );
02622     NetWriteThis( m );
02623 }
02624 
02625 // *******************************************************************************************
02626 // *
02627 // *   DoNetRead
02628 // *
02629 // *******************************************************************************************
02633 // *******************************************************************************************
02634 
02635 void nServerInfo::DoNetRead( nMessage & m )
02636 {
02637     nServerInfoBase::DoNetRead( m );
02638     NetReadThis( m );
02639 }
02640 
02641 // *******************************************************************************************
02642 // *
02643 // * DoGetFrom
02644 // *
02645 // *******************************************************************************************
02649 // *******************************************************************************************
02650 
02651 void nServerInfo::DoGetFrom( nSocket const * socket )
02652 {
02653     // delegate
02654     nServerInfoBase::DoGetFrom( socket );
02655 
02656     // fill
02657 
02658     users           = sn_NumRealUsers();
02659     version_        = sn_CurrentVersion();
02660     release_        = sn_programVersion;
02661 
02662 #ifdef WIN32
02663     release_ += " win";
02664 #else
02665 #ifdef MACOSX
02666     release_ += " mac";
02667 #else
02668 #endif
02669     release_ += " unix";
02670 #endif
02671 
02672 #ifdef DEDICATED
02673     release_ += " dedicated";
02674 #else
02675     release_ += " hybrid";
02676 #endif
02677 
02678     maxUsers_       = sn_MaxUsers();
02679 
02680     // filter newlines and stuff from the server name
02681     tColoredString filteredName( sn_serverName );
02682     filteredName.NetFilter();
02683     name            = filteredName;
02684 
02685     if ( nServerInfoAdmin::GetAdmin() )
02686     {
02687         userNames_  = nServerInfoAdmin::GetAdmin()->GetUsers();
02688         options_    = nServerInfoAdmin::GetAdmin()->GetOptions();
02689         url_        = nServerInfoAdmin::GetAdmin()->GetUrl();
02690     }
02691     else
02692     {
02693         tString str("UNKNOWN");
02694 
02695         userNames_  = str;
02696         options_    = str;
02697         url_        = str;
02698     }
02699 }
02700 
02701 // *******************************************************************************************
02702 // *
02703 // *    NetWriteThis
02704 // *
02705 // *******************************************************************************************
02709 // *******************************************************************************************
02710 
02711 void nServerInfo::NetWriteThis( nMessage & m ) const
02712 {
02713     m << name;
02714     m << users;
02715 
02716     m << version_;
02717     m << release_;
02718 
02719     m << maxUsers_;
02720 
02721     m << userNames_;
02722     m << options_;
02723     m << url_;
02724 }
02725 
02726 // *******************************************************************************************
02727 // *
02728 // *    NetReadThis
02729 // *
02730 // *******************************************************************************************
02734 // *******************************************************************************************
02735 
02736 void nServerInfo::NetReadThis( nMessage & m )
02737 {
02738     tString oldName = name;
02739 
02740     sn_ReadFiltered( m, name  ); // get the server name
02741     m >> users;                 // get the playing users
02742 
02743     if ( !m.End() )
02744     {
02745         m >> version_;
02746         sn_ReadFiltered( m, release_ );
02747         login2_ = true;
02748     }
02749     else
02750     {
02751         login2_ = false;
02752     }
02753 
02754     if ( !m.End() )
02755     {
02756         m >> maxUsers_;
02757     }
02758 
02759     if ( !m.End() )
02760     {
02761         m >> userNames_;
02762         m >> options_;
02763         sn_ReadFiltered( m, url_ );
02764 
02765         if (options_.Len() > 240)
02766             options_.SetPos( 240, true );
02767 
02768         if (url_.Len() > 75)
02769             url_.SetPos( 75, true );
02770     }
02771     else
02772     {
02773         userNames_ = "No Info\n";
02774         options_ = "No Info\n";
02775         url_ = "No Info\n";
02776     }
02777 
02778     userNamesOneLine_.Clear();
02779     for ( int i = 0; i < userNames_.Len()-2 ; ++i )
02780     {
02781         char c = userNames_[i];
02782         if ( c == '\n' )
02783             userNamesOneLine_ << "0xffffff, ";
02784         else
02785             userNamesOneLine_ << c;
02786     }
02787 
02788     timesNotAnswered = 0;
02789 
02790     if (!advancedInfoSet)
02791     {
02792         if ( sn_IsMaster )
02793         {
02794             if ( !advancedInfoSetEver )
02795             {
02796                 con << "Acknowledged server: " <<  ToString( *this ) << ", name: \"" << tColoredString::RemoveColors(name) << "\"\n";
02797                 con << "\n";
02798                 Save();
02799             }
02800             else if ( name != oldName )
02801             {
02802                 con << "Name of server " <<  ToString( *this )
02803                 << " changed from \"" << tColoredString::RemoveColors(oldName)
02804                 << "\" to \"" << tColoredString::RemoveColors(name) << "\"\n";
02805             }
02806 
02807             // broadcast the server to the other master servers
02808             nServerInfo * master = GetMasters();
02809             while( master )
02810             {
02811                 tJUST_CONTROLLED_PTR< nMessage > ret = tNEW(nMessage)(SmallServerDescriptor);
02812 
02813                 // get small server info
02814                 nServerInfoBase::NetWriteThis(*ret);
02815                 unsigned int notrans = 0;
02816                 *ret << notrans;
02817                 ret->ClearMessageID();
02818 
02819                 // send message
02820                 sn_Bend( master->GetAddress() );
02821                 ret->SendImmediately(0, false);
02822                 nMessage::SendCollected(0);
02823 
02824                 master = master->Next();
02825             }
02826         }
02827 
02828         advancedInfoSet = true;
02829         advancedInfoSetEver = true;
02830         ping = tSysTimeFloat() - timeQuerySent;
02831 
02832         CalcScore();
02833     }
02834 
02835     queried = 0;
02836 
02837     //  queried = true;
02838     sn_Polling.Remove(this, pollID);
02839 }
02840 
02841 // *******************************************************************************************
02842 // *
02843 // *    GetAddress
02844 // *
02845 // *******************************************************************************************
02849 // *******************************************************************************************
02850 
02851 nAddress const & nServerInfoBase::GetAddress( void ) const
02852 {
02853     return this->AccessAddress();
02854 }
02855 
02856 // *******************************************************************************************
02857 // *
02858 // *    GetAddress
02859 // *
02860 // *******************************************************************************************
02865 // *******************************************************************************************
02866 
02867 nServerInfoBase const & nServerInfoBase::GetAddress( nAddress & address ) const
02868 {
02869     address = this->AccessAddress();
02870     return *this;
02871 }
02872 
02873 // *******************************************************************************************
02874 // *
02875 // *    ClearAddress
02876 // *
02877 // *******************************************************************************************
02881 // *******************************************************************************************
02882 
02883 nServerInfoBase const & nServerInfoBase::ClearAddress() const
02884 {
02885     std::auto_ptr< nAddress > clearedAddress;
02886     address_ = clearedAddress;
02887     return *this;
02888 }
02889 
02890 // *******************************************************************************************
02891 // *
02892 // *    SetAddress
02893 // *
02894 // *******************************************************************************************
02899 // *******************************************************************************************
02900 
02901 nServerInfoBase & nServerInfoBase::SetAddress( nAddress const & address )
02902 {
02903     AccessAddress() = address;
02904     return *this;
02905 }
02906 
02907 // *******************************************************************************************
02908 // *
02909 // *    AccessAddress
02910 // *    This function is dangerous; use only if you absolutely have to and do not store the returned reference longer than required.
02911 // *
02912 // *******************************************************************************************
02916 // *******************************************************************************************
02917 
02918 nAddress & nServerInfoBase::AccessAddress( void ) const
02919 {
02920     // create address if it is not already there
02921     if ( !this->address_.get() )
02922     {
02923         std::auto_ptr< nAddress > address( tNEW( nAddress ) );
02924 
02925         // fill it with hostname and port
02926         address->SetHostname( this->GetConnectionName() );
02927         address->SetPort( this->GetPort() );
02928 
02929         this->address_ = address;
02930 
02931 #ifdef DEBUG
02932         tString unresolved = ToString( *this );
02933         tString resolved = this->address_->ToString();
02934         if ( unresolved != resolved )
02935             con << "Address of server " << unresolved << " determined to be " << resolved << "\n";
02936 #endif
02937     }
02938 
02939     return *this->address_;
02940 }
02941 
02942 // *******************************************************************************************
02943 // *
02944 // *    DoGetName
02945 // *
02946 // *******************************************************************************************
02950 // *******************************************************************************************
02951 
02952 const tString & nServerInfoBase::DoGetName( void ) const
02953 {
02954     return connectionName_;
02955 }
02956 
02957 // *******************************************************************************************
02958 // *
02959 // *    DoGetName
02960 // *
02961 // *******************************************************************************************
02965 // *******************************************************************************************
02966 
02967 const tString & nServerInfo::DoGetName( void ) const
02968 {
02969     return name;
02970 }
02971 
02972 

Generated on Sat Mar 15 22:55:51 2008 for Armagetron Advanced by  doxygen 1.5.4