00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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;
00074 static REAL sn_queryDelayGlobal = 0.1f;
00075 static int sn_numQueries = 3;
00076 static int sn_TNALostContact = 4;
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;
00101
00102
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
00116 tString ToString( const nServerInfoBase & info )
00117 {
00118 tString ret;
00119 ret << info.GetConnectionName() << ":" << info.GetPort();
00120 return ret;
00121 }
00122
00123
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
00198 void nServerInfo::CalcScore()
00199 {
00200 static int userScore[8] = { -100, 0, 100, 250, 300, 300, 250, 100 };
00201
00202
00203 if ( !this->advancedInfoSet && this->advancedInfoSetEver )
00204 {
00205
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
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
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;
00373
00374
00375
00376 return reinterpret_cast<nServerInfo *>
00377 ( reinterpret_cast<char*> (anchor) +
00378 ( reinterpret_cast<char*>( &info ) - reinterpret_cast<char*> (&info.next) )
00379 );
00380 }
00381
00382
00383 void nServerInfo::Sort( PrimaryKey key )
00384 {
00385
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
00401 if (!prev)
00402 break;
00403
00404
00405
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
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()
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)
00473 {
00474 if (autosave)
00475 {
00476 Save();
00477 }
00478 sn_LastLoaded.Clear();
00479
00480 while (GetFirstServer())
00481 delete GetFirstServer();
00482 }
00483
00484
00485
00486
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)
00506 {
00507
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
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
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
00557 server->GetAddress();
00558
00559 tRecorder::Record( section, *server );
00560 server = CreateServerInfo();
00561 }
00562 delete server;
00563
00564
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
00584 tRecorder::Record( section, *server );
00585
00586
00587 server->GetAddress();
00588
00589
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
00608 tRecorder::Record( sectionEnd );
00609 }
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621 static nDescriptor SmallServerDescriptor(50,nServerInfo::GetSmallServerInfo,"small_server", true);
00622
00623
00624
00625 static nDescriptor BigServerDescriptor(51,nServerInfo::GetBigServerInfo,"big_server", true);
00626 static nDescriptor BigServerMasterDescriptor(54,nServerInfo::GetBigServerInfoMaster,"big_server_master", true);
00627
00628
00629 static nDescriptor RequestSmallServerInfoDescriptor(52,nServerInfo::GiveSmallServerInfo,"small_request", true);
00630
00631
00632 static nDescriptor RequestBigServerInfoDescriptor(53,nServerInfo::GiveBigServerInfo,"big_request", true);
00633 static nDescriptor RequestBigServerInfoMasterDescriptor(55,nServerInfo::GiveBigServerInfoMaster,"big_request_master", true);
00634
00635
00636
00637
00638
00639
00640
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
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
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
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773 void nServerInfo::Alive()
00774 {
00775
00776 if ( sn_IsMaster && TimesNotAnswered() >= sn_TNALostContact )
00777 {
00778 transactionNr = sn_NextTransactionNr++;
00779 if (!sn_NextTransactionNr)
00780 sn_NextTransactionNr++;
00781 }
00782 }
00783
00784
00785 static const int sn_minPingCount=4;
00786
00787 static const int sn_minPingCounts[sn_minPingCount] = { 10,20,50,100 };
00788
00789 static REAL sn_minPingTimes[sn_minPingCount] = { 1,4,20,100 };
00790
00791
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
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_;
00816 double lastTime_[MAX];
00817 int lastTimeIndex_;
00818 bool warned_;
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
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
00855
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
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
00883 for ( i = sn_minPingCount-1; i >= 0; --i )
00884 {
00885
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
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
00919 nQueryMessageStats & GetQueryMessageStats( nMachine & machine )
00920 {
00921
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
00933 return *stats;
00934 }
00935
00936
00937 bool FloodProtection( nMachine & machine, REAL timeFactor=1.0 )
00938 {
00939
00940 return GetQueryMessageStats( machine ).FloodProtection( timeFactor );
00941 }
00942
00943
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
00954 bool FloodProtection( nMessage const & m )
00955 {
00956
00957 nMachine & server = nMachine::GetMachine( 0 );
00958 nMachine & peer = nMachine::GetMachine( m.SenderID() );
00959
00960
00961 if ( !sn_firstInPacket )
00962 {
00963 GetQueryMessageStats( peer ).Block();
00964
00965 return true;
00966 }
00967
00968
00969 sn_firstInPacket = false;
00970
00971 if ( sn_minPingTimes[sn_minPingCount - 1] <= 0 )
00972 return false;
00973
00974
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
00983
00984
00985
00986
00987
00988
00989
00990
00991 sn_ServerCount++;
00992
00993 nServerInfo *n = NULL;
00994
00995
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
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
01042 n->queried = 0;
01043
01044 if (!sn_IsMaster)
01045 m >> n->transactionNr;
01046 else
01047 {
01048
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
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
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
01111
01112 sn_SendAll[m.SenderID()] = true;
01113 }
01114
01115 else
01116 {
01117 if ( FloodProtection( m ) )
01118 return;
01119
01120
01121 tJUST_CONTROLLED_PTR< nMessage > ret = tNEW(nMessage)(SmallServerDescriptor);
01122
01123
01124 nServerInfoBase info;
01125 info.GetFrom( sn_Connections[m.SenderID()].socket );
01126
01127
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
01140 int sn_NumRealUsers();
01141
01142 nServerInfo* nServerInfo::GetBigServerInfoCommon(nMessage &m)
01143 {
01144
01145 nServerInfoBase baseInfo;
01146 baseInfo.NetRead( m );
01147
01148
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
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
01188 nMessage *ret = tNEW(nMessage)( descriptor );
01189
01190
01191 info.NetWrite( *ret );
01192
01193
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
01216 nServerInfo me;
01217 me.GetFrom( sn_Connections[m.SenderID()].socket );
01218
01219
01220 GiveBigServerInfoCommon(m, me, BigServerDescriptor );
01221 }
01222
01223 void nServerInfo::SetFromMaster()
01224 {
01225
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
01256 nServerInfoBase baseInfo;
01257 baseInfo.NetRead( m );
01258
01259
01260 nServerInfo *server = GetFirstServer();
01261 while( server && *server != baseInfo )
01262 server = server->Next();
01263
01264 if (!server)
01265 return;
01266
01267
01268 GiveBigServerInfoCommon(m, *server, BigServerMasterDescriptor );
01269 }
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
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
01405 Load( tDirectories::Var(), MasterFile( fileSuffix ) );
01406
01407
01408 DeleteUnreachable();
01409
01410
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
01426 con << tOutput("$network_master_connecting", masterInfo->GetName() );
01427
01428 nConnectError error = nTIMEOUT;
01429
01430 {
01431 error = masterInfo->Connect( Login_Post0252 );
01432 }
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451 switch( error )
01452 {
01453 case nOK:
01454 break;
01455 case nABORT:
01456 {
01457 return;
01458 }
01459 case nTIMEOUT:
01460
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
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
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
01526 run = GetFirstServer();
01527 while (run)
01528 {
01529 nServerInfo * next = run->Next();
01530 if ( !run->stillOnMasterServer )
01531 {
01532
01533 if ( run->scoreBias_ > 0 )
01534 {
01535 run->scoreBias_ -= 10;
01536 }
01537 else
01538 {
01539
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
01562 if (sn_GetNetState() != nCLIENT)
01563 sn_SetNetState(nCLIENT);
01564
01565
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
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
01614 if (sn_GetNetState() != nCLIENT)
01615 sn_SetNetState(nCLIENT);
01616
01617
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
01638 nSocketResetInhibitor inhibitor;
01639
01640 static unsigned int lastPort = 0;
01641
01642
01643 sn_SetNetState(nSERVER);
01644 unsigned int port = sn_GetServerPort();
01645
01646
01647
01648 lastPort = port;
01649
01650
01651
01652 if (!masterInfo)
01653 {
01654
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
01672 nSocket const * connection = NULL;
01673
01674
01675 {
01676 nConnectError result = nDENIED;
01677
01678
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
01691 if ( result != nOK )
01692 {
01693
01694 connection = NULL;
01695 result = masterInfo->Connect( Login_Post0252 );
01696 }
01697
01698
01699 if ( result != nOK )
01700 return;
01701 }
01702
01703
01704 nServerInfoBase info;
01705 info.GetFrom( connection );
01706
01707
01708 nMessage *m=tNEW(nMessage)(SmallServerDescriptor);
01709 info.NetWrite(*m);
01710 unsigned int dummy = 0;
01711 *m << dummy;
01712
01713
01714 con << tOutput("$network_master_send");
01715 m->BroadCast();
01716 sn_Receive();
01717 sn_SendPlanned();
01718
01719
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()
01732 {
01733
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
01752 if ( !queryDirectly )
01753 {
01754
01755 if ( name != ToString( *this ) )
01756 {
01757 advancedInfoSetEver = true;
01758 }
01759
01760 if( advancedInfoSetEver )
01761 {
01762
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
01784
01785
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
01810
01811
01812
01813 if (best)
01814 {
01815
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
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
01843 sn_Bend( GetMasters()->GetAddress() );
01844
01845 tJUST_CONTROLLED_PTR< nMessage > req = tNEW(nMessage)(RequestBigServerInfoMasterDescriptor);
01846 req->ClearMessageID();
01847
01848
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
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
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
01926
01927 int TNA = run->TimesNotAnswered();
01928
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
01951 return;
01952 }
01953
01954
01955 if ( kickOut && ( ( totalTNA > totalTNAMax && maxTNA >= sn_TNALostContact ) || unreachableCount > maxUnreachable ) )
01956 {
01957
01958 delete kickOut;
01959
01960 }
01961 }
01962 }
01963
01964 void nServerInfo::StartQueryAll( QueryType queryType )
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
01976 run->SetQueryType( queryType );
01977
01978
01979 run->ClearAddress();
01980 run->GetAddress();
01981
01982 run->queried = 0;
01983 run->advancedInfoSet = 0;
01984
01985 int TNA = run->TimesNotAnswered();
01986
01987
01988 if ( TNA > 0 )
01989 {
01990 run->advancedInfoSetEver = false;
01991 }
01992 else
01993 {
01994
01995 }
01996
01997 run = run->Next();
01998 }
01999 }
02000
02001 bool nServerInfo::DoQueryAll(int simultaneous)
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
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
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
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
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
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
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 );
02215 }
02216
02217
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231
02232
02233
02234
02235
02236
02237
02238
02239
02240 nServerInfo *nServerInfo::GetMasters()
02241 {
02242
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
02256 nServerInfo * oldFirstServer = sn_FirstServer;
02257 sn_FirstServer = NULL;
02258
02259
02260 Load( tDirectories::Config(), "master.srv" );
02261
02262
02263 while ( sn_FirstServer )
02264 {
02265 nServerInfo * server = sn_FirstServer;
02266 server->Remove();
02267 server->Insert( sn_masterList );
02268 }
02269
02270
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
02292 nServerInfo * masterInfo = GetMasters();
02293
02294
02295 int count = 0;
02296 while( masterInfo )
02297 {
02298 masterInfo = masterInfo->Next();
02299 ++count;
02300 }
02301
02302
02303 static tReproducibleRandomizer randomizer;
02304 REAL ran = randomizer.Get();
02305
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
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
02361
02362
02365
02366
02367 nServerInfoBase::nServerInfoBase()
02368 : connectionName_(""),
02369 port_(0)
02370 {
02371 }
02372
02373
02374
02375
02376
02377
02380
02381
02382 nServerInfoBase::~nServerInfoBase()
02383 {
02384 }
02385
02386
02387
02388
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
02403
02404
02407
02408
02409 bool nServerInfoBase::operator !=( const nServerInfoBase & other ) const
02410 {
02411 return ! operator == ( other );
02412 }
02413
02414
02415
02416
02417
02418
02422
02423
02424 nConnectError nServerInfoBase::Connect( nLoginType loginType, const nSocket * socket )
02425 {
02426
02427 if ( !GetAddress().IsSet() )
02428 {
02429
02430 return nTIMEOUT;
02431 }
02432
02433
02434
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
02442
02443 return error;
02444 }
02445
02446
02447
02448
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
02465
02466
02471
02472
02473 nServerInfoBase & nServerInfoBase::operator =( const nServerInfoBase & other )
02474 {
02475 CopyFrom( other );
02476 return *this;
02477 }
02478
02479
02480
02481
02482
02483
02487
02488
02489 void nServerInfoBase::DoNetWrite( nMessage & m ) const
02490 {
02491 NetWriteThis( m );
02492 }
02493
02494
02495
02496
02497
02498
02502
02503
02504 void nServerInfoBase::DoNetRead( nMessage & m )
02505 {
02506 NetReadThis( m );
02507 }
02508
02509
02510
02511
02512
02513
02517
02518
02519 void nServerInfoBase::NetWriteThis( nMessage & m ) const
02520 {
02521 m << port_;
02522 m << connectionName_;
02523 }
02524
02525
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
02537
02538
02542
02543
02544 void nServerInfoBase::NetReadThis( nMessage & m )
02545 {
02546 m >> port_;
02547 sn_ReadFiltered( m, connectionName_ );
02548
02549 if ( ( sn_IsMaster || sn_AcceptingFromBroadcast || sn_AcceptingFromMaster ) && connectionName_.Len()>1 )
02550 {
02551
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
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
02577
02578 static tString net_dns("");
02579
02580 static tConfItemLine sn_sbtip_official("SERVER_DNS", net_dns);
02581
02582
02583
02584
02585
02586
02590
02591
02592 void nServerInfoBase::DoGetFrom( nSocket const * socket )
02593 {
02594
02595 connectionName_ = net_dns;
02596
02597 if ( ! socket )
02598 {
02599 port_ = sn_GetServerPort();
02600 }
02601 else
02602 {
02603
02604 nAddress const & address = socket->GetAddress();
02605 port_ = address.GetPort();
02606 }
02607 }
02608
02609
02610
02611
02612
02613
02617
02618
02619 void nServerInfo::DoNetWrite( nMessage & m ) const
02620 {
02621 nServerInfoBase::DoNetWrite( m );
02622 NetWriteThis( m );
02623 }
02624
02625
02626
02627
02628
02629
02633
02634
02635 void nServerInfo::DoNetRead( nMessage & m )
02636 {
02637 nServerInfoBase::DoNetRead( m );
02638 NetReadThis( m );
02639 }
02640
02641
02642
02643
02644
02645
02649
02650
02651 void nServerInfo::DoGetFrom( nSocket const * socket )
02652 {
02653
02654 nServerInfoBase::DoGetFrom( socket );
02655
02656
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
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
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
02729
02730
02734
02735
02736 void nServerInfo::NetReadThis( nMessage & m )
02737 {
02738 tString oldName = name;
02739
02740 sn_ReadFiltered( m, name );
02741 m >> 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
02808 nServerInfo * master = GetMasters();
02809 while( master )
02810 {
02811 tJUST_CONTROLLED_PTR< nMessage > ret = tNEW(nMessage)(SmallServerDescriptor);
02812
02813
02814 nServerInfoBase::NetWriteThis(*ret);
02815 unsigned int notrans = 0;
02816 *ret << notrans;
02817 ret->ClearMessageID();
02818
02819
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
02838 sn_Polling.Remove(this, pollID);
02839 }
02840
02841
02842
02843
02844
02845
02849
02850
02851 nAddress const & nServerInfoBase::GetAddress( void ) const
02852 {
02853 return this->AccessAddress();
02854 }
02855
02856
02857
02858
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
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
02893
02894
02899
02900
02901 nServerInfoBase & nServerInfoBase::SetAddress( nAddress const & address )
02902 {
02903 AccessAddress() = address;
02904 return *this;
02905 }
02906
02907
02908
02909
02910
02911
02912
02916
02917
02918 nAddress & nServerInfoBase::AccessAddress( void ) const
02919 {
02920
02921 if ( !this->address_.get() )
02922 {
02923 std::auto_ptr< nAddress > address( tNEW( nAddress ) );
02924
02925
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
02945
02946
02950
02951
02952 const tString & nServerInfoBase::DoGetName( void ) const
02953 {
02954 return connectionName_;
02955 }
02956
02957
02958
02959
02960
02961
02965
02966
02967 const tString & nServerInfo::DoGetName( void ) const
02968 {
02969 return name;
02970 }
02971
02972