src/network/nNetwork.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 "tInitExit.h"
00030 #include "nSimulatePing.h"
00031 #include "nConfig.h"
00032 #include "nNetwork.h"
00033 #include "nServerInfo.h"
00034 #include "tConsole.h"
00035 #include "tDirectories.h"
00036 #include "nSocket.h"
00037 #include "nConfig.h"
00038 #include "nKrawall.h"
00039 #include "tSysTime.h"
00040 #include "tRecorder.h"
00041 #include "tRandom.h"
00042 #include <stdlib.h>
00043 #include <fstream>
00044 #include "tMath.h"
00045 #include <string.h>
00046 
00047 #ifndef WIN32
00048 #include  <netinet/in.h>
00049 #else
00050 #include  <windows.h>
00051 #endif
00052 
00053 #include <deque>
00054 
00055 #ifdef MACOSX_XCODE
00056 #include "version.h"
00057 #endif // MACOSX_XCODE
00058 
00059 #ifdef WIN32
00060 #include "version.h"
00061 #endif // WIN32
00062 
00063 // my IP address. Master server/game server hopefully tell me a correct one.
00064 static tString sn_myAddress ("*.*.*.*:*");
00065 tString const & sn_GetMyAddress()
00066 {
00067     return sn_myAddress;
00068 }
00069 
00071 bool sn_IsLANAddress( tString const & address )
00072 {
00073     if ( address.StartsWith("127.") || address.StartsWith("10.") || address.StartsWith("192.168.") )
00074     {
00075         // easy LANs. Accept the client sent IP, we don't know our own LAN address.
00076         return true;
00077     }
00078 
00079     if( address.StartsWith( "172." ) && address[6] == '.' )
00080     {
00081         // more complicated LAN :)
00082         int second = address.SubStr(4,2).ToInt();
00083         if ( 16 <= second && second < 32 )
00084         {
00085             return true;
00086         }
00087     }
00088 
00089     return false;
00090 }
00091 
00092 // debug watches
00093 #ifdef DEBUG
00094 nMessage* sn_WatchMessage = NULL;
00095 unsigned int sn_WatchMessageID = 76;
00096 #endif
00097 
00098 #define NO_ACK
00099 
00100 tString sn_bigBrotherString;
00101 // tString sn_greeting[5];  //made 4 = 5 (lol i broke the laws of maths. subby),  k's bug fix
00102 
00103 
00104 #ifdef TOP_SOURCE_DIR
00105 #include "nTrueVersion.h"
00106 #endif
00107 
00108 #ifndef TRUE_ARMAGETRONAD_VERSION
00109 #define TRUE_ARMAGETRONAD_VERSION VERSION
00110 #endif
00111 
00112 tString sn_programVersion (TRUE_ARMAGETRONAD_VERSION)    ;
00113 
00114 tString sn_serverName("Unnamed Server");
00115 
00116 const unsigned int sn_defaultPort = 4534;
00117 unsigned int sn_serverPort = 4534;
00118 
00119 tString net_hostip("ANY");
00120 
00121 bool big_brother=true;
00122 static tConfItem<bool> sn_bb("BIG_BROTHER",big_brother);
00123 
00124 static tConfItemLine sn_sn("SERVER_NAME", sn_serverName);
00125 
00126 static tConfItem<int> sn_sport("SERVER_PORT",reinterpret_cast<int&>(sn_serverPort));
00127 
00128 static tConfItemLine sn_sbtip("SERVER_IP", net_hostip);
00129 
00130 void sn_DisconnectUserNoWarn(int i, const tOutput& reason, nServerInfoBase * redirectTo = 0 );
00131 
00132 int sn_defaultDelay=10000;
00133 
00135 void sn_Delay()
00136 {
00137     sn_BasicNetworkSystem.Select( sn_defaultDelay / 1000000.0 );
00138     tAdvanceFrame();
00139 }
00140 
00141 int sn_maxRateIn=8; // maximum data rate in kb/s
00142 int sn_maxRateOut=8; // maximum output data rate in kb/s
00143 
00144 static nConnectError sn_Error = nOK;
00145 
00146 //tArray<unsigned short> send_buffer[MAXCLIENTS+2];
00147 //REAL planned_rate_control[MAXCLIENTS+2];
00148 //REAL rate_control[MAXCLIENTS+2];
00149 //unsigned short  rate[MAXCLIENTS+2];
00150 
00151 // from gGame.C
00152 //extern unsigned short client_gamestate[MAXCLIENTS+2];
00153 
00154 bool deb_net=false;
00155 
00156 static REAL maxTimeout=1;  // the maximal timeout in seconds
00157 static REAL minTimeout=.01;  // the minimal timeout in seconds
00158 static REAL pingTimeout=1; // the normal timeout in multiples of the ping
00159 static REAL pingVarianceTimeout=1; // the normal timeout in multiples of the ping variance
00160 static REAL zeroTimeout=.01; // additional timeout of first packet
00161 
00162 static REAL sn_GetTimeout( int user )
00163 {
00164     tASSERT( user >= 0 && user <= MAXCLIENTS+1 );
00165 
00166     nPingAverager & averager = sn_Connections[ user ].ping;
00167 
00168     REAL timeout = pingTimeout * averager.GetPing() + pingVarianceTimeout * sqrtf( averager.GetSnailAverager().GetAverageVariance() );
00169 
00170     if ( timeout < minTimeout )
00171         timeout = minTimeout;
00172     if ( timeout > maxTimeout )
00173         timeout = maxTimeout;
00174 
00175     return timeout;
00176 }
00177 
00178 #ifndef DEBUG
00179 static REAL killTimeout=30;
00180 #else
00181 static REAL killTimeout=30;
00182 #endif
00183 
00184 static const int kickOnDemandTimeout = 10;
00185 
00186 static bool send_again_warn=false;
00187 
00188 #ifdef DEBUG
00189 static int simulate_loss=0;
00190 #else
00191 //static int simulate_loss=0;
00192 #endif
00193 
00194 int sn_maxNoAck=100; // the maximum number of not ack messages
00195 // before more are send
00196 
00197 //int sn_ackPending[MAXCLIENTS+2];
00198 // int sn_ackAckPending[MAXCLIENTS+2];
00199 
00200 //static nMessage * ack_mess[MAXCLIENTS+2];
00201 
00202 static nNetState current_state;
00203 //int sn_sockets[MAXCLIENTS+2];  // server mode:
00204 // elements 1...MAXCLIENTS are the incoming connections,
00205 // client mode: element 0 connects to the server.
00206 // element MAXCLIENTS+1: currently logging in
00207 
00208 nConnectionInfo sn_Connections[MAXCLIENTS+2];
00209 
00210 static nAddress peers[MAXCLIENTS+2]; // the same logic for the peer adresses.
00211 static int timeouts[MAXCLIENTS+2];
00212 
00213 #define ACKBACK 1000
00214 static unsigned short lastacks[MAXCLIENTS+2][ACKBACK];
00215 static unsigned short lastackPos[MAXCLIENTS+2];
00216 static unsigned short highest_ack[MAXCLIENTS+2];
00217 
00218 
00219 //********************************************************
00220 // Version control
00221 //********************************************************
00222 
00223 static int sn_MaxBackwardsCompatibility = 1000;
00224 static tSettingItem<int> sn_mxc("BACKWARD_COMPATIBILITY",sn_MaxBackwardsCompatibility);
00225 
00226 static int sn_newFeatureDelay = 0;
00227 static tSettingItem<int> sn_nfd("NEW_FEATURE_DELAY",sn_newFeatureDelay);
00228 
00229 // from nConfig.cpp. Adapt version string array there to bump protocol version.
00230 int sn_GetCurrentProtocolVersion();
00231 
00232 static const int sn_currentProtocolVersion              = sn_GetCurrentProtocolVersion(); // the current version number of the network protocol
00233 static const int sn_backwardCompatibleProtocolVersion   = 0;                                                    // the smallest version of the network protocol this program is compatible with
00234 static const nVersion sn_myVersion( sn_backwardCompatibleProtocolVersion, sn_currentProtocolVersion);
00235 static nVersion sn_currentVersion( sn_myVersion );
00236 
00237 const nVersion& sn_MyVersion()                  // the version this progam maximally supports
00238 {
00239     return sn_myVersion;
00240 }
00241 
00242 const nVersion& sn_CurrentVersion()     // the version currently supported
00243 {
00244     return sn_currentVersion;
00245 }
00246 
00247 nVersion::nVersion()
00248 {
00249     min_=0;
00250     max_=0;
00251 }
00252 
00253 nVersion::nVersion( int min, int max )
00254 {
00255     tASSERT( min <= max );
00256     min_=min;
00257     max_=max;
00258 }
00259 
00260 bool nVersion::Supported( int version ) const   // check if a particular version is supported
00261 {
00262     tASSERT( min_ <= max_ );
00263     return version >= min_ && version <= max_;
00264 }
00265 
00266 bool nVersion::Merge( const nVersion& a,
00267                       const nVersion& b)        // merges two versions to one; the new version supports only features both versions understand. false is returned if no common denominator could be found
00268 {
00269     int min = a.min_;
00270     if ( min < b.min_ )
00271     {
00272         min = b.min_;
00273     }
00274 
00275     int max = a.max_;
00276     if ( max > b.max_ )
00277     {
00278         max = b.max_;
00279     }
00280 
00281     if ( min <= max )
00282     {
00283         min_ = min;
00284         max_ = max;
00285         return true;
00286     }
00287     else
00288     {
00289         return false;
00290     }
00291 }
00292 
00293 bool nVersion::operator == ( const nVersion& other )
00294 {
00295     return this->max_ == other.max_ && this->min_ == other.min_;
00296 }
00297 
00298 nVersion& nVersion::operator = ( const nVersion& other )
00299 {
00300     this->min_ = other.min_;
00301     this->max_ = other.max_;
00302 
00303     return *this;
00304 }
00305 
00306 nMessage& operator >> ( nMessage& m, nVersion& ver )
00307 {
00308     int min,max;
00309     m >> min;
00310     m >> max;
00311 
00312     ver = nVersion( min, max );
00313 
00314     return m;
00315 }
00316 
00317 nMessage& operator << ( nMessage& m, const nVersion& ver )
00318 {
00319     m << ver.Min();
00320     m << ver.Max();
00321 
00322     return m;
00323 }
00324 
00325 std::istream& operator >> ( std::istream& s, nVersion& ver )
00326 {
00327     int min,max;
00328     s >> min;
00329     s >> max;
00330 
00331     ver = nVersion( min, max );
00332 
00333     return s;
00334 }
00335 
00336 std::ostream& operator << ( std::ostream& s, const nVersion& ver )
00337 {
00338     s << ver.Min() << " ";
00339     s << ver.Max();
00340 
00341     return s;
00342 }
00343 
00344 nVersionFeature::nVersionFeature( int min, int max ) // creates a feature that is supported from version min to max; values of -1 indicate no border
00345 {
00346     tASSERT( min_ >= sn_MyVersion().Min() );
00347     tASSERT( max < 0 || max <= sn_MyVersion().Max() );
00348 
00349     min_ = min;
00350     max_ = max;
00351 }
00352 
00353 bool nVersionFeature::Supported()
00354 {
00355     return ( min_ < 0 || sn_CurrentVersion().Max() >= min_ ) &&  ( max_ < 0 || sn_CurrentVersion().Min() <= max_ );
00356 }
00357 
00358 bool nVersionFeature::Supported( int client )
00359 {
00360     if ( client < 0 || client > MAXCLIENTS )
00361         return false;
00362 
00363     // the version to check the feature for
00364     const nVersion * version = &sn_CurrentVersion();
00365 
00366     if ( sn_GetNetState() == nCLIENT )
00367     {
00368         // clientside code: override the currently active version with the server version ( if that has been sent )
00369         if ( sn_Connections[0].version.Max() > 0 )
00370             version = &sn_Connections[0].version;
00371     }
00372     else
00373     {
00374         // serverside code: override version to use with the client's version
00375         version = &sn_Connections[ client ].version;
00376     }
00377 
00378     // see if the feature is supported
00379     return ( min_ < 0 || version->Max() >= min_ ) &&  ( max_ < 0 || version->Min() <= max_ );
00380 }
00381 
00382 void handle_version_control( nMessage& m )
00383 {
00384     if ( sn_GetNetState() == nCLIENT )
00385     {
00386         m >> sn_currentVersion;
00387 
00388         // inform configuration of changes
00389         nConfItemVersionWatcher::OnVersionChange( sn_currentVersion );
00390     }
00391 }
00392 
00393 nDescriptor versionControl(10, handle_version_control,"version" );
00394 
00395 void sn_UpdateCurrentVersion()
00396 {
00397     // update the current version from the native version and the versions of all attached clients
00398 
00399     // allow maximally sn_MaxBackwardsCompatibility old versions to connect
00400     int min = sn_myVersion.Max() - sn_MaxBackwardsCompatibility;
00401     if ( min < sn_myVersion.Min() )
00402         min = sn_myVersion.Min();
00403 
00404     // disable features that are too new
00405     int max = sn_myVersion.Max() - sn_newFeatureDelay;
00406     if ( max < min )
00407         max = min;
00408 
00409     nVersion version( min, max );
00410 
00411     // ask configuration if version is OK
00412     nConfItemVersionWatcher::AdaptVersion( version );
00413 
00414     nVersion maxVersion = version;
00415 
00416     if ( sn_GetNetState() == nCLIENT )
00417     {
00418         sn_currentVersion = version;
00419         return;
00420     }
00421 
00422     for ( int i = MAXCLIENTS; i>0; --i )
00423     {
00424         const nConnectionInfo& info = sn_Connections[i];
00425         if ( info.socket )
00426         {
00427             if ( ! version.Merge( version, info.version ) )
00428             {
00429                 // kick user; it has gotten incompatible.
00430                 static bool recurse = true;
00431                 if ( recurse )
00432                 {
00433                     recurse = false;
00434                     sn_DisconnectUser( i, "$network_kill_incompatible" );
00435                     recurse = true;
00436                 }
00437 
00438                 version = maxVersion;
00439             }
00440         }
00441     }
00442 
00443     // inform configuration of changes
00444     nConfItemVersionWatcher::OnVersionChange( version );
00445 
00446     if ( version != sn_currentVersion )
00447     {
00448         sn_currentVersion = version;
00449 
00450         nMessage* m = tNEW( nMessage )( versionControl );
00451         (*m) << version;
00452 
00453         m->BroadCast();
00454     }
00455 }
00456 
00457 //********************************************************
00458 
00459 nConnectError sn_GetLastError()
00460 {
00461     nConnectError ret = sn_Error;
00462     sn_Error = nOK;
00463     return ret;
00464 }
00465 
00466 
00467 
00468 // REAL sn_ping[MAXCLIENTS+2];
00469 
00470 static void reset_last_acks(int i){
00471     for(int j=ACKBACK-1;j>=0;j--)
00472         lastacks[i][j]=0;
00473     lastackPos[i]=0;
00474     highest_ack[i]=0;
00475 }
00476 
00477 
00478 //#ifndef DEBUG
00479 int sn_maxClients=MAXCLIENTS;
00480 
00481 static tSettingItem< int > sn_maxClientsConf( "MAX_CLIENTS", sn_maxClients );
00482 
00483 int sn_allowSameIPCountSoft=4;
00484 static tSettingItem< int > sn_allowSameIPCountSoftConf( "MAX_CLIENTS_SAME_IP_SOFT", sn_allowSameIPCountSoft );
00485 
00486 int sn_allowSameIPCountHard=8;
00487 static tSettingItem< int > sn_allowSameIPCountHardConf( "MAX_CLIENTS_SAME_IP_HARD", sn_allowSameIPCountHard );
00488 
00489 //#else
00490 //int maxclients=1;
00491 //#endif
00492 
00493 int sn_myNetID=0; // our network identification:  0: server
00494 //                                            1..MAXCLIENTS: client
00495 
00496 #define IDS_RESERVED 16          // number of message IDs reserved for special purposes: id 0 is reserved for no-ack messages.
00497 unsigned short current_id=1; // current running network number
00498 
00499 
00500 // the classes that are responsible for the queuing of network send tEvents:
00501 class planned_send:public tHeapElement{
00502 protected:
00503     int peer;
00504 public:
00505     planned_send(REAL priority,int peer);
00506     ~planned_send();
00507 
00508     virtual tHeapBase *Heap() const; // in wich heap are we?
00509 
00510     // change our priority:
00511     void add_to_priority(REAL diff);
00512 
00513     // what is to be done if the sceduled tEvent is executed?
00514     virtual void execute()=0;
00515 };
00516 
00517 class nMessage_planned_send:public planned_send{
00518     tCONTROLLED_PTR(nMessage) m;
00519     bool ack;
00520 
00521 public:
00522     nMessage_planned_send(nMessage *m,REAL priority,bool ack,int peer);
00523     ~nMessage_planned_send();
00524 
00525     virtual void execute();
00526 };
00527 
00528 // *************************************************************
00529 
00530 unsigned short nDescriptor::s_nextID(1);
00531 
00532 #define MAXDESCRIPTORS 400
00533 static nDescriptor* descriptors[MAXDESCRIPTORS];
00534 
00535 static nDescriptor* nDescriptor_anchor;
00536 
00537 nDescriptor::nDescriptor(unsigned short identification,
00538                          nHandler *handle,const char *Name, bool awl)
00539         :tListItem<nDescriptor>(nDescriptor_anchor),
00540         id(identification),handler(handle),name(Name), acceptWithoutLogin(awl)
00541 {
00542 #ifdef DEBUG
00543 #ifndef WIN32
00544     //  con << "Descriptor " << id << ": " << name << '\n';
00545 #endif
00546 #endif
00547     if (MAXDESCRIPTORS<=id || descriptors[id]!=NULL){
00548         con << "Descriptor " << id << " already used!\n";
00549         exit(-1);
00550     }
00551     s_nextID=id+1;
00552     descriptors[id]=this;
00553 }
00554 
00555 /*
00556 nDescriptor::nDescriptor(nHandler *handle,const char *Name)
00557   :id(s_nextID++),handler(handle),name(Name)
00558 {
00559 #ifdef DEBUG
00560   con << "Descriptor " << id << ": " << name << '\n';
00561 #endif
00562 
00563   if (descriptors.Len()>id && descriptors[id]!=NULL){
00564     con << "Descriptor " << id << " already used!\n";
00565     exit(-1);
00566   }
00567   descriptors[id]=this;
00568 }
00569 */
00570 
00571 int nCurrentSenderID::currentSenderID_ = 0;
00572 
00573 void nDescriptor::HandleMessage(nMessage &message){
00574     static tArray<bool> warned;
00575 
00576     // store sender ID for console
00577     nCurrentSenderID currentSender( message.SenderID() );
00578 
00579 #ifdef DEBUG_X
00580     if (message.descriptor>1)
00581         con << "RMT " << message.descriptor << "\n";
00582 #endif
00583 
00584 #ifndef NOEXCEPT
00585     try{
00586 #endif
00587         nDescriptor *nd = 0;
00588 
00589         // z-man: security check ( thanks, Luigi Auriemma! )
00590         if ( message.descriptor  < MAXDESCRIPTORS )
00591             nd=descriptors[message.descriptor];
00592 
00593         if (nd){
00594             if ((message.SenderID() <= MAXCLIENTS) || nd->acceptWithoutLogin)
00595                 nd->handler(message);
00596         }
00597         else
00598             if (!warned[message.Descriptor()]){
00599                 tOutput warn;
00600                 warn.SetTemplateParameter(1, message.Descriptor());
00601                 warn << "$network_warn_unknowndescriptor";
00602                 con << warn;
00603                 warned[message.Descriptor()]=true;
00604             }
00605 #ifndef NOEXCEPT
00606     }
00607     catch(nIgnore const &){
00608         // well, do nothing.
00609     }
00610     catch(nKillHim const &){
00611         // st_Breakpoint();
00612         con << tOutput("$network_error");
00613         sn_DisconnectUser(message.SenderID(), "$network_kill_error" );
00614     }
00615     catch( tGenericException & e )
00616     {
00617         // relay generic errors to sender of message; don't do anything else bad. Especially, we don't
00618         // want a harmless uncaught exception to bring down the server.
00619         sn_ConsoleOut( e.GetName() + ": " + e.GetDescription() + '\n', message.SenderID() );
00620     }
00621 
00622 #endif
00623 }
00624 
00625 // *************************************************************
00626 
00627 
00628 void ack_handler(nMessage &m){
00629     while (!m.End()){
00630         sn_Connections[m.SenderID()].AckReceived();
00631 
00632         unsigned short ack;
00633         m.Read(ack);
00634         //con << "Got ack:" << ack << ":" << m.SenderID() << '\n';
00635         nWaitForAck::Ackt(ack,m.SenderID());
00636     }
00637 }
00638 
00639 static nDescriptor s_Acknowledge(1,ack_handler,"ack");
00640 
00641 
00642 class nWaitForAck;
00643 static tList<nWaitForAck> sn_pendingAcks;
00644 
00645 //static eTimer netTimer;
00646 static nTimeRolling netTime;
00647 
00648 #ifdef NET_DEBUG
00649 static int acks=0;
00650 static int max_acks=0;
00651 #endif
00652 
00653 nWaitForAck::nWaitForAck(nMessage* m,int rec)
00654         :id(-1),message(m),receiver(rec)
00655 {
00656 #ifdef DEBUG
00657     // don't message yourself
00658     if ( rec == 0 && sn_GetNetState() == nSERVER )
00659         st_Breakpoint();
00660 #endif
00661 
00662     if (!message)
00663         tERR_ERROR("Null ack!");
00664 
00665     if (message->Descriptor()!=s_Acknowledge.ID())
00666         sn_Connections[receiver].ackPending++;
00667     else
00668         tERR_ERROR("Should not wait for ack of an ack message itself.");
00669 
00670     //    sn_ackAckPending[receiver]++;
00671 #ifdef NET_DEBUG
00672     acks++;
00673 #endif
00674 
00675     timeFirstSent=::netTime;
00676     timeLastSent=::netTime;
00677 
00678     timeouts=0;
00679 
00680     timeout=sn_GetTimeout( rec );
00681 
00682 #ifdef nSIMULATE_PING
00683     timeSendAgain=::netTime + nSIMULATE_PING;
00684 #ifndef WIN32
00685     tRandomizer & randomizer = tReproducibleRandomizer::GetInstance();
00686     timeSendAgain+= randimizer.Get() * nSIMULATE_PING_VARIANT;
00687     // timeSendAgain+=(nSIMULATE_PING_VARIANT*random())/RAND_MAX;
00688 #endif
00689 #else
00690     const REAL packetLossScale = .003; // packet loss rate that is considered big
00691     const REAL maxTimeoutFactor = 1.2; // maximal stretching of initial timeout value for flawless connections
00692     // factor mutliplied to timeout; 1 if the connection loses a lot of packets, 1.2 for a
00693     // flawless connection
00694     REAL timeoutFactor = 1 + (maxTimeoutFactor-1)*packetLossScale/(sn_Connections[receiver].PacketLoss() + packetLossScale);
00695     timeSendAgain=::netTime + timeout*timeoutFactor + zeroTimeout;
00696 #endif
00697     sn_pendingAcks.Add(this,id);
00698 }
00699 
00700 nWaitForAck::~nWaitForAck(){
00701 #ifdef NET_DEBUG
00702     acks--;
00703     if (acks>max_acks){
00704         max_acks=acks;
00705         // con << "MA=" << max_acks << '\n';
00706     }
00707 #endif
00708 
00709     if (bool(message) && message->Descriptor()!=s_Acknowledge.ID())
00710     {
00711         sn_Connections[receiver].ackPending--;
00712         sn_Connections[receiver].ReliableMessageSent();
00713     }
00714     else
00715     {
00716         tERR_ERROR( "No message." );
00717     }
00718     //    sn_ackAckPending[receiver]--;
00719 
00720     sn_pendingAcks.Remove(this,id);
00721     tCHECK_DEST;
00722 }
00723 
00724 void nWaitForAck::Ackt(unsigned short id,unsigned short peer){
00725     int success=0;
00726     for(int i=sn_pendingAcks.Len()-1;i>=0;i--){
00727         nWaitForAck * ack = sn_pendingAcks(i);
00728         if (ack->message->MessageID()==id &&
00729                 ack->receiver==peer){
00730             success=1;
00731 
00732 #ifdef DEBUG
00733             //      if (sn_pendingAcks(i)->message == sn_WatchMessage)
00734             //  st_Breakpoint();
00735 #endif
00736 
00737 #ifdef DEBUG_X
00738             if (ack->message->descriptor>1)
00739                 con << "AT  " << ack->message->descriptor << '\n';
00740 #endif
00741 
00742             // calculate and average ping
00743             REAL thisping=netTime - ack->timeFirstSent;
00744             sn_Connections[peer].ping.Add( thisping, 1/(1 + 10 * REAL(ack->timeouts * ack->timeouts * ack->timeouts ) ) );
00745 
00746             ack->AckExtraAction();
00747             delete ack;
00748             ::timeouts[peer]=0;
00749             if (i<sn_pendingAcks.Len()-1) i++;
00750         }
00751     }
00752 
00753 #ifdef DEBUG_X
00754     if (!success && peer!=MAXCLIENTS+1)
00755     {
00756         con << "Ack " << id << ':' << peer << " was not asked for.\n";
00757         if (sn_pendingAcks.Len()) con << "Expected:\n";
00758         for(int i=sn_pendingAcks.Len()-1;i>=0;i--){
00759             con << i << "\t:"
00760             << sn_pendingAcks[i]->message->messageIDBig_ << ":"
00761             << sn_pendingAcks[i]->receiver << '\n';
00762         }
00763     }
00764 #endif
00765 }
00766 
00767 void nWaitForAck::AckAllPeer(unsigned short peer){
00768     for(int i=sn_pendingAcks.Len()-1;i>=0;i--){
00769         if (sn_pendingAcks(i)->receiver==peer){
00770             delete sn_pendingAcks(i);
00771             if (i<sn_pendingAcks.Len()-1) i++;
00772         }
00773     }
00774 }
00775 
00776 void nWaitForAck::Resend(){
00777     static tReproducibleRandomizer randomizer;
00778 
00779     for(int i=sn_pendingAcks.Len()-1;i>=0;i--){
00780         nWaitForAck* pendingAck = sn_pendingAcks(i);
00781 
00782         nConnectionInfo & connection = sn_Connections[pendingAck->receiver];
00783 
00784         // don't resend if you can't.
00785         if ( !connection.bandwidthControl_.CanSend() )
00786             continue;
00787 
00788         REAL packetLoss = connection.PacketLoss();
00789         REAL timeout = pendingAck->timeout;
00790 
00791         // should we resend the packet? Certainly it if it is overdue
00792         bool resend = (pendingAck->timeSendAgain + timeout * .1 <=netTime);
00793 
00794         // or if there is already a message waiting...
00795         if ( !resend && connection.sendBuffer_.Len() > 0 )
00796         {
00797             // and we are on time
00798             if ( pendingAck->timeSendAgain <= netTime )
00799                 resend = true;
00800             // or the packet loss is so high that it is advisable to resend every message
00801             // multiple times if bandwidth is available ( we aim for 99% reliability )
00802             else if ( pendingAck->timeouts < 3 && pow( packetLoss, pendingAck->timeouts + 1 ) > .01 &&
00803                       connection.bandwidthControl_.Control( nBandwidthControl::Usage_Planning ) >100 )
00804                 resend = true;
00805 
00806             /* + sn_GetTimeout( pendingAck->receiver ) *
00807                                 ( 3.0 / ( pendingAck->timeouts + 1 ) )
00808                                 ( packetLoss * ( randomizer.Get() + .5 ) ) )
00809             */
00810         }
00811 
00812         if ( resend ){
00813             //con << net_ticks-sn_pendingAcks[i]->ticks_first_sent << '\n';
00814 
00815             // update timeout counters
00816             ::timeouts[pendingAck->receiver]++;
00817             pendingAck->timeouts++;
00818 
00819             if(netTime - pendingAck->timeFirstSent  >  killTimeout &&
00820                     ::timeouts[pendingAck->receiver] > 20){
00821                 // total timeout. Kill connection.
00822                 if (pendingAck->receiver<=MAXCLIENTS){
00823                     tOutput o;
00824                     o.SetTemplateParameter(1, pendingAck->receiver);
00825                     o << "$network_error_timeout";
00826                     con << o;
00827                     sn_DisconnectUser(pendingAck->receiver, "$network_kill_timeout" );
00828 
00829                     sn_Error = nTIMEOUT;
00830 
00831                     if (i>=sn_pendingAcks.Len())
00832                         i=sn_pendingAcks.Len()-1;
00833                 }
00834                 else // it is just in the login slot. Ignore it.
00835                     delete pendingAck;
00836             }
00837             else{
00838 #ifdef DEBUG
00839                 //if (pendingAck->message == sn_WatchMessage)
00840                 //st_Breakpoint();
00841 #endif
00842 
00843                 if (connection.socket){
00844                     //    if(sn_Connections[].rateControlPlanned[pendingAck->receiver]>-1000)
00845                     {
00846                         REAL timeoutFactor = .9 + .1 * pendingAck->timeouts + randomizer.Get() * .1;
00847                         pendingAck->timeSendAgain=netTime+timeout * timeoutFactor;
00848                         pendingAck->timeLastSent=netTime;
00849 
00850                         if (send_again_warn){
00851                             con << "sending packet again: " ;
00852                             deb_net=true;
00853                         }
00854                         connection.ReliableMessageSent();
00855                         pendingAck->message->SendImmediately
00856                         (pendingAck->receiver,false);
00857                         deb_net=false;
00858                     }
00859                 }
00860                 else
00861                     delete pendingAck;
00862             }
00863         }
00864     }
00865 }
00866 
00867 
00868 // defined in netobjec.C
00869 // void ClearKnows(int user);
00870 
00871 
00872 #ifdef NET_DEBUG
00873 static int nMessages=0;
00874 static int max_nMessages=0;
00875 #endif
00876 
00877 #ifdef DEBUG
00878 void BreakOnMessageID( unsigned int messageID )
00879 {
00880     if (messageID == sn_WatchMessageID && messageID != 0 )
00881     {
00882         int x;
00883         x = 0;
00884     }
00885 }
00886 #endif
00887 
00888 class nMessageIDExpander
00889 {
00890     unsigned long quarters[4];
00891 public:
00892     nMessageIDExpander()
00893     {
00894         for (int i=3; i>=0; --i)
00895             quarters[i]=i << 14;
00896     }
00897 
00898     unsigned long ExpandMessageID( unsigned short id )
00899     {
00900         // the current ID is in this quarter
00901         int thisQuarter = ( id >> 14 ) & 3;
00902 
00903         // the following quarter will be this
00904         int nextQuarter = ( thisQuarter + 1 ) & 3;
00905 
00906         // make sure the following quarter has a higher upper ID completion than this
00907         quarters[nextQuarter] = quarters[thisQuarter] + ( 1 << 14 );
00908 
00909         // replace high two bits of incoming ID with the counted up ID
00910         return quarters[thisQuarter] | id;
00911     }
00912 };
00913 
00915 // just received.
00916 static unsigned long int sn_ExpandMessageID( unsigned short id, unsigned short sender )
00917 {
00918 #ifdef DEBUG
00919     BreakOnMessageID( id );
00920 #endif
00921 
00922     static nMessageIDExpander expanders[MAXCLIENTS+2];
00923 
00924     tASSERT( sender <= MAXCLIENTS+2 )
00925     return expanders[sender].ExpandMessageID(id);
00926 }
00927 
00928 nMessage::nMessage(unsigned short*& buffer,short sender, int lenLeft )
00929         :descriptor(ntohs(*(buffer++))),messageIDBig_(sn_ExpandMessageID(ntohs(*(buffer++)),sender)),
00930 senderID(sender),readOut(0){
00931 #ifdef NET_DEBUG
00932     nMessages++;
00933 #endif
00934 
00935     tRecorderSync< unsigned long >::Archive( "_MESSAGE_ID_IN", 3, messageIDBig_ );
00936     tRecorderSync< unsigned short >::Archive( "_MESSAGE_DECL_IN", 3, descriptor );
00937 
00938     unsigned short len=ntohs(*(buffer++));
00939     lenLeft--;
00940     if ( len > lenLeft )
00941     {
00942         len = lenLeft;
00943 #ifndef NOEXCEPT
00944         throw nKillHim();
00945 #endif
00946     }
00947     for(int i=0;i<len;i++)
00948         data[i]=ntohs(*(buffer++));
00949 
00950 #ifdef DEBUG
00951     BreakOnMessageID( messageIDBig_ );
00952 #endif
00953 }
00954 
00955 nMessage::nMessage(const nDescriptor &d)
00956         :descriptor(d.id),
00957 senderID(::sn_myNetID), readOut(0){
00958 #ifdef NET_DEBUG
00959     nMessages++;
00960 #endif
00961 
00962     current_id++;
00963     if (current_id <= IDS_RESERVED)
00964         current_id = IDS_RESERVED + 1;
00965 
00966     messageIDBig_ = current_id;
00967 
00968 #ifdef DEBUG
00969     BreakOnMessageID( messageIDBig_ );
00970 #endif
00971 
00972     tRecorderSync< unsigned long >::Archive( "_MESSAGE_ID_OUT", 3, messageIDBig_ );
00973     tRecorderSync< unsigned short >::Archive( "_MESSAGE_DECL_OUT", 3, descriptor );
00974 }
00975 
00976 
00977 nMessage::~nMessage(){
00978 #ifdef NET_DEBUG
00979     nMessages--;
00980     if (nMessages>max_nMessages){
00981         max_nMessages=nMessages;
00982         con << "MN=" << max_nMessages <<'\n';
00983     }
00984 #endif
00985 
00986 #ifdef DEBUG_X
00987     if (descriptor>1)
00988         con << "DMT " << descriptor << "\n";
00989 #endif
00990 
00991     tCHECK_DEST;
00992 }
00993 
00994 
00995 
00996 
00997 void nMessage::BroadCast(bool ack){
00998     tControlledPTR< nMessage > keep( this );
00999     if (sn_GetNetState()==nCLIENT)
01000         Send(0,ack);
01001 
01002     if (sn_GetNetState()==nSERVER){
01003         for(int i=MAXCLIENTS;i>0;i--){
01004             if (sn_Connections[i].socket)
01005                 Send(i,ack);
01006         }
01007     }
01008 }
01009 
01010 
01011 static nVersionFeature sn_ZeroMessageCrashfix( 1 );
01012 
01013 nMessage& nMessage::operator << (const tString &s){
01014     if ( !sn_ZeroMessageCrashfix.Supported() && s.Len() <= 0 )
01015     {
01016         return this->operator<<( s + " " );
01017     }
01018 
01019     unsigned short len=s.Size()+1;
01020 
01021     // clamp away excess zeroes
01022     while(len > 1 && s(len-2)==0)
01023     {
01024         --len;
01025     }
01026 
01027     Write(len);
01028     int i;
01029 
01030     char const * sRaw = s;
01031 
01032     // write first pairs of bytes
01033     for(i=0;i+1<len;i+=2)
01034         Write(sRaw[i]+(sRaw[i+1] << 8));
01035 
01036     // write last byte
01037     if (i<len)
01038         Write(sRaw[i]);
01039 
01040     return *this;
01041 }
01042 
01043 nMessage& nMessage::operator << (const tColoredString &s){
01044     return *this << static_cast< const tString & >( s );
01045 }
01046 
01047 nMessage& nMessage::operator << ( const tOutput &o ){
01048     return *this << tString( static_cast< const char * >( o ) );
01049 }
01050 
01051 bool sn_filterColorStrings = false;
01052 static tConfItem<bool> cs("FILTER_COLOR_STRINGS",sn_filterColorStrings);
01053 
01054 static void sn_AddToString( tString & s, tString::CHAR c )
01055 {
01056     if ( c )
01057         s += c;
01058 }
01059 
01060 nMessage& nMessage::ReadRaw(tString &s )
01061 {
01062     s.Clear();
01063     unsigned short w,len;
01064     Read(len);
01065     if ( len > 0 )
01066     {
01067         s.reserve(len);
01068         for(int i=0;i<len;i+=2){
01069             Read(w);
01070             tString::CHAR c1 = w & 255;
01071             sn_AddToString( s, c1 );
01072             if (i+1<len)
01073                 sn_AddToString( s, (w-c1) >> 8 );
01074         }
01075     }
01076 
01077     return *this;
01078 }
01079 
01080 nMessage& nMessage::operator >> (tColoredString &s )
01081 {
01082     // read the raw data
01083     ReadRaw( s );
01084 
01085     // filter client string messages
01086     if ( sn_GetNetState() == nSERVER )
01087     {
01088         s.NetFilter();
01089         s.RemoveTrailingColor();
01090     }
01091 
01092     // filter color codes away
01093     if ( sn_filterColorStrings )
01094         s = tColoredString::RemoveColors( s );
01095 
01096     return *this;
01097 }
01098 
01099 nMessage& nMessage::operator >> (tString &s )
01100 {
01101     tColoredString safe;
01102     operator>>( safe );
01103     s = safe;
01104 
01105     return *this;
01106 }
01107 
01108 
01109 #define MANT 26
01110 #define EXP (32-MANT)
01111 #define MS (MANT-1)
01112 
01113 
01114 typedef struct{
01115 int mant:MANT;
01116 unsigned int exp:EXP;
01117 } myfloat;
01118 
01119 
01120 nMessage& nMessage::operator<<(const REAL &x){
01121 
01122 
01123 #ifdef DEBUG
01124     // con << "write x= " << x;
01125 
01126 
01127     if(sizeof(myfloat)!=sizeof(int))
01128         tERR_ERROR_INT("floating ePoint format does not work!");
01129 #endif
01130     /*
01131       REAL nachkomma=x-floor(x);
01132       Write(short(x-nachkomma));
01133       Write(60000*nachkomma);
01134     */
01135     // no fuss. Read and write floats in binary format.
01136     // will likely cause problems for systems other than i386.
01137 
01138     //Write(((short *)&x)[0]);
01139     //Write(((short *)&x)[1]);
01140 
01141     // right. Caused severe problems with the AIX port.
01142 
01143     // new way: own floating ePoint format that is not good with small numbers
01144     // (we do not need them anyway)
01145     REAL y=x;
01146 
01147     unsigned int negative=0;
01148     if (y<0){
01149         y=-y;
01150         negative=1;
01151     }
01152 
01153     unsigned int exp=0;
01154     while ( fabs(y)>=64 && exp < (1<<EXP)-6 )
01155     {
01156         exp +=6;
01157         y/=64;
01158     }
01159     while ( fabs(y)>=1 && exp < (1<<EXP)-1 )
01160     {
01161         exp++;
01162         y/=2;
01163     }
01164     // now x=y*2^exp
01165     unsigned int mant=int(y*(1<<MS));
01166     // now x=mant*2^exp * (1/ (1<<MANT))
01167 
01168     // cutoffs:
01169     if (mant>((1<<MS))-1)
01170         mant=(1<<MS)-1;
01171 
01172     if (exp>(1<<EXP)-1){
01173         exp=(1<<EXP)-1;
01174         if (mant>0)
01175             mant=(1<<MS)-1;
01176     }
01177 
01178     // put them together:
01179 
01180     unsigned int trans=(mant & ((1<<MS)-1)) | (negative << MS) | (exp << MANT);
01181     /*
01182       myfloat trans;
01183       trans.exp=exp;
01184       trans.mant=mant;
01185     */
01186 
01187     operator<<(reinterpret_cast<int &>(trans));
01188 
01189 #ifdef DEBUG
01190     /*
01191       con << "mant: " << mant
01192       << ", exp: " << exp
01193       << ", negative: " << negative;
01194     */
01195 
01196     unsigned int mant2=trans & ((1 << MS)-1);
01197     unsigned int negative2=(trans >> MS) & 1;
01198     unsigned int nt=trans-mant-(negative << MS);
01199     unsigned int exp2=nt >> MANT;
01200 
01201     if (mant2!=mant || negative2!=negative || exp2!=exp)
01202         tERR_ERROR_INT("Floating ePoint tranfer failure!");
01203 
01204     /*
01205       con << ", x: " << x;
01206 
01207       con << ", mant: " << mant
01208       << ", exp: " << exp
01209       << ", negative: " << negative;
01210     */
01211 
01212     // check:
01213 
01214     REAL z=REAL(mant)/(1<<MS);
01215     if (negative)
01216         z=-z;
01217 
01218     while (exp>=6){
01219         exp-=6;
01220         z*=64;
01221     }
01222     while (exp>0){
01223         exp--;
01224         z*=2;
01225     }
01226 
01227     if (fabs(z-x)>(fabs(x)+1)*.001)
01228         tERR_ERROR_INT("Floating ePoint tranfer failure!");
01229 
01230     //con << ", z: " << z << '\n';
01231 #endif
01232 
01233     return *this;
01234 }
01235 
01236 nMessage& nMessage::operator>>(REAL &x){
01237     /*
01238       short vorkomma;
01239       unsigned short nachkomma;
01240       Read((unsigned short &)vorkomma);
01241       Read(nachkomma);
01242       x=vorkomma+nachkomma/60000.0;
01243 
01244       Read(((unsigned short *)&x)[0]);
01245       Read(((unsigned short *)&x)[1]);
01246      */
01247 
01248     unsigned int trans;
01249     operator>>(reinterpret_cast<int &>(trans));
01250 
01251     int mant=trans & ((1 << MS)-1);
01252     unsigned int negative=(trans >> MS) & 1;
01253     unsigned int exp=(trans-mant-(negative << MS)) >> MANT;
01254 
01255     x=REAL(mant)/(1<<MS);
01256     if (negative)
01257         x=-x;
01258 
01259 #ifdef DEBUG
01260     //  con << "read mant: " <<mant << ", exp: " << exp;
01261 #endif
01262 
01263     while (exp>=6){
01264         exp-=6;
01265         x*=64;
01266     }
01267     while (exp>0){
01268         exp--;
01269         x*=2;
01270     }
01271 
01272 #ifdef DEBUG
01273 #ifndef WIN32
01274     if (!finite(x))
01275         st_Breakpoint();
01276     // con << " , x= " << x << '\n';
01277 #endif
01278 #endif
01279     return *this;
01280 }
01281 
01282 nMessage& nMessage::operator<< (const short &x){
01283     Write((reinterpret_cast<const short *>(&x))[0]);
01284 
01285     return *this;
01286 }
01287 
01288 nMessage& nMessage::operator>> (short &x){
01289     Read(reinterpret_cast<unsigned short *>(&x)[0]);
01290 
01291     return *this;
01292 }
01293 
01294 nMessage& nMessage::operator<< (const int &x){
01295     unsigned short a=x & (0xFFFF);
01296     short b=(x-a) >> 16;
01297 
01298     Write(a);
01299     operator<<(b);
01300 
01301     return *this;
01302 }
01303 
01304 nMessage& nMessage::operator>> (int &x){
01305     unsigned short a;
01306     short b;
01307 
01308     Read(a);
01309     operator>>(b);
01310 
01311     x=(b << 16)+a;
01312 
01313     return *this;
01314 }
01315 
01316 nMessage& nMessage::operator<< (const bool &x){
01317     if (x)
01318         Write(1);
01319     else
01320         Write(0);
01321 
01322     return *this;
01323 }
01324 
01325 nMessage& nMessage::operator>> (bool &x){
01326     unsigned short y;
01327     Read(y);
01328     x= (y!=0);
01329 
01330     return *this;
01331 }
01332 
01333 
01334 void nMessage::Read(unsigned short &x){
01335     if (End()){
01336         tOutput o;
01337         st_Breakpoint();
01338         o.SetTemplateParameter(1, senderID);
01339         o << "$network_error_shortmessage";
01340         con << o;
01341         // sn_DisconnectUser(senderID, "$network_kill_error");
01342         nReadError( false );
01343     }
01344     else
01345         x=data(readOut++);
01346 }
01347 
01348 
01349 // **********************************************
01350 //  Basic communication classes: login
01351 // **********************************************
01352 
01353 static bool login_failed=false;
01354 static bool login_succeeded=false;
01355 
01356 // salt value sent as past login tokens. They are returned by
01357 // the server as you sent them, and make sure you only accept
01358 // the right answer.
01359 static nKrawall::nSalt loginSalt;
01360 
01361 static nHandler *real_req_info_handler=NULL;
01362 
01363 void req_info_handler(nMessage &m){
01364     if (real_req_info_handler)
01365         (*real_req_info_handler)(m);
01366     if (m.SenderID()==MAXCLIENTS+1)
01367         sn_DisconnectUser(MAXCLIENTS+1, "$network_kill_logout");
01368 }
01369 
01370 static nDescriptor req_info(2,req_info_handler,"req_info");
01371 
01372 void RequestInfoHandler(nHandler *handle){
01373     real_req_info_handler=handle;
01374 }
01375 
01376 // the server we are redirected to
01377 static std::auto_ptr< nServerInfoBase > sn_redirectTo;
01378 std::auto_ptr< nServerInfoBase > sn_GetRedirectTo()
01379 {
01380     return sn_redirectTo;
01381 }
01382 
01383 nServerInfoBase * sn_PeekRedirectTo()
01384 {
01385     return sn_redirectTo.get();
01386 }
01387 
01388 void login_deny_handler(nMessage &m){
01389     if ( !m.End() )
01390     {
01391         //              tOutput output;
01392         //              m >> output;
01393         //              sn_DenyReason = output;
01394         m >> sn_DenyReason;
01395     }
01396     else
01397     {
01398         sn_DenyReason = tOutput( "$network_kill_unknown" );
01399     }
01400 
01401     if ( !m.End() )
01402     {
01403         // read redirection data from message
01404         tString connectionName;
01405         m >> connectionName;
01406         int port;
01407         m >> port;
01408 
01409         if ( connectionName.Len() > 1 )
01410         {
01411             // create server info and fill it with data
01412             sn_redirectTo = std::auto_ptr< nServerInfoBase>( new nServerInfoRedirect( connectionName, port ) );
01413         }
01414     }
01415 
01416     if (!login_failed)
01417         con << tOutput("$network_login_denial");
01418     if (sn_GetNetState()!=nSERVER){
01419         login_failed=true;
01420         login_succeeded=false;
01421         sn_SetNetState(nSTANDALONE);
01422     }
01423 }
01424 
01425 static nDescriptor login_deny(3,login_deny_handler,"login_deny");
01426 
01427 void login_handler_1( nMessage&m );
01428 void login_handler_2( nMessage&m );
01429 void logout_handler( nMessage&m );
01430 
01431 nDescriptor login(6,login_handler_1,"login1", true);
01432 nDescriptor login_2(11,login_handler_2,"login2", true);
01433 nDescriptor logout(7,logout_handler,"logout");
01434 
01435 tString sn_DenyReason;
01436 
01437 void login_ignore_handler(nMessage &m){
01438     if (sn_GetNetState()!=nSERVER && !login_succeeded){
01439         /*
01440           login_failed=true;
01441           login_succeeded=false;
01442 
01443           // kicking the one who uses our place
01444           // (he is probably timing out anyway..)
01445           nMessage *lo=new nMessage(logout);
01446           lo->Write((unsigned short)sn_myNetID);
01447           lo->Send(0);
01448 
01449           sn_Sync(10);
01450 
01451           (new nMessage(login))->Send(0);
01452         */
01453     }
01454 
01455 
01456 }
01457 
01458 static nDescriptor login_ignore(4,login_ignore_handler,"login_ignore");
01459 
01460 
01461 void first_fill_ids();
01462 
01463 // from nServerInfo.cpp
01464 extern bool sn_AcceptingFromMaster;
01465 
01466 void login_accept_handler(nMessage &m){
01467     if (sn_GetNetState()!=nSERVER && m.SenderID() == 0){
01468         unsigned short id=0;
01469         m.Read(id);
01470 
01471         // read or reset server version info
01472         if ( !m.End() )
01473         {
01474             m >> sn_Connections[0].version;
01475 
01476 #ifdef DEBUG
01477 #define NOEXPIRE
01478 #endif
01479 
01480 #ifndef NOEXPIRE
01481 #ifndef DEDICATED
01482             // expiration for public beta versions
01483             if ( !sn_AcceptingFromMaster &&
01484                     ( strstr( VERSION, "rc" ) || strstr( VERSION, "alpha" ) || strstr( VERSION, "beta" ) ) &&
01485                     sn_Connections[0].version.Max() > sn_currentProtocolVersion + 1 )
01486             {
01487                 throw tGenericException( tOutput("$testing_version_expired"), tOutput("$testing_version_expired_title" ) );
01488             }
01489 #endif
01490 #endif
01491         }
01492         else
01493             sn_Connections[0].version = nVersion( 0, 0);
01494         
01495         // read my public IP
01496         if ( !m.End() )
01497         {
01498             // only accept it if it is not a LAN address
01499             tString address;
01500             m >> address;
01501             if ( !sn_IsLANAddress( address ) )
01502             {
01503                 sn_myAddress = address;
01504             }
01505 
01506             // read salt reply and compare it to what we sent
01507             nKrawall::nSalt replySalt;
01508             nKrawall::ReadScrambledPassword( m, replySalt );
01509 
01510             int compare = memcmp( &loginSalt,&replySalt, sizeof(replySalt) );
01511 
01512             // since we generate a different random salt on playback, record the comparison result
01513             static const char * section = "LOGIN_SALT";
01514             tRecorder::Playback( section, compare );
01515             tRecorder::Record( section, compare );
01516             
01517             if ( compare != 0 )
01518             {
01519                 nReadError( false );
01520             }
01521         }
01522 
01523         // only now, login can be considered a success
01524         login_succeeded=true;
01525         sn_myNetID=id;
01526 
01527         first_fill_ids();
01528     }
01529 }
01530 
01531 static nDescriptor login_accept(5,login_accept_handler,"login_accept", true);
01532 
01533 
01534 
01535 //static short new_id=0;
01536 
01537 // counts the number of logins with the same IP
01538 int CountSameIP( int user, bool reset=false )
01539 {
01540     static int sameIP[ MAXCLIENTS+2 ];
01541     tASSERT( user >= 0 && user <= MAXCLIENTS+1 );
01542 
01543     if ( reset )
01544     {
01545         int count = 0;
01546         for(int user2=1;user2<=MAXCLIENTS;++user2)
01547         {
01548             if(!sn_Connections[user2].socket)
01549                 continue;
01550 
01551             if ( user2 != user && nAddress::Compare( peers[user], peers[user2] ) >=0 )
01552             {
01553                 count++;
01554             }
01555         }
01556 
01557         sameIP[user] = count;
01558     }
01559 
01560     return sameIP[user];
01561 }
01562 
01563 // counts the number of logins with the same Connection
01564 int CountSameConnection( int user )
01565 {
01566     int count = 0;
01567     for(int user2=1;user2<=MAXCLIENTS;++user2)
01568     {
01569         if( NULL == sn_Connections[user2].socket )
01570             continue;
01571 
01572         if ( user2 != user && nAddress::Compare( peers[user], peers[user2] ) == 0 )
01573         {
01574             count++;
01575         }
01576     }
01577 
01578     return count;
01579 }
01580 
01581 // determine a free connection slot or at least one where the user won't be missed
01582 int GetFreeSlot()
01583 {
01584     int user;
01585 
01586     // level 1: look for free slot
01587     if ( sn_NumUsers() < sn_maxClients )
01588     {
01589         for(user=1;user<=sn_maxClients;++user)
01590         {
01591             // look for empty slot
01592             if(!sn_Connections[user].socket)
01593             {
01594                 return user;
01595             }
01596         }
01597     }
01598 
01599     int best = -1;
01600 
01601     // level 2 kicked out users who were timing out and was not a good idea.
01602 
01603     int bestCount = sn_allowSameIPCountSoft-1;
01604 
01605     // level 3: look for dublicate IPs
01606     for(user=1;user<=MAXCLIENTS;++user)
01607     {
01608         int count = CountSameIP( user );
01609         if ( count > bestCount )
01610         {
01611             bestCount = count;
01612             best = user;
01613         }
01614     }
01615     if ( best > 0 )
01616         return best;
01617 
01618     return -1;
01619 }
01620 
01621 static REAL sn_minBan    = 120; // minimal ban time in seconds for trying to connect while you're banned
01622 static tSettingItem< REAL > sn_minBanSetting( "NETWORK_MIN_BAN", sn_minBan );
01623 
01624 // defined in nServerInfo.cpp
01625 extern bool FloodProtection( nMessage const & m );
01626 
01627 // flag to disable 0.2.8 test version lockout
01628 static bool sn_lockOut028tTest = true;
01629 static tSettingItem< bool > sn_lockOut028TestConf( "NETWORK_LOCK_OUT_028_TEST", sn_lockOut028tTest );
01630 
01631 int login_handler( nMessage &m, unsigned short rate ){
01632     nCurrentSenderID senderID;
01633 
01634     // read version and suppored authentication methods
01635     nVersion version;
01636     tString supportedAuthenticationMethods("");
01637     nKrawall::nSalt salt; // it's OK that this may stay uninitialized
01638     if ( !m.End() )
01639     {
01640         // read version
01641         m >> version;
01642 
01643         // ok, clients that send a version do have at lesat basic authentication.
01644         supportedAuthenticationMethods = "bmd5";
01645     }
01646     if ( !m.End() )
01647     {
01648         // read authentication methods
01649         m >> supportedAuthenticationMethods;
01650     }
01651     if ( !m.End() )
01652     {
01653         // also read a login salt, the client expects to get it returned verbatim
01654         nKrawall::ReadScrambledPassword( m, salt );
01655     }
01656 
01657     // don't accept logins in client mode
01658     if (sn_GetNetState() != nSERVER)
01659         return -1;
01660 
01661     // ban users
01662     nMachine & machine = nMachine::GetMachine( m.SenderID() );
01663     REAL banned = machine.IsBanned();
01664     if ( banned > 0 )
01665     {
01666         // the reason for the ban
01667         tString const & reason = machine.GetBanReason();
01668 
01669         // ban user some more so he learns
01670         if ( banned < sn_minBan )
01671         {
01672             machine.Ban( sn_minBan );
01673             banned = sn_minBan;
01674         }
01675         else
01676             con << tOutput( "$network_ban", machine.GetIP() , int(banned/60), reason.Len() > 1 ? reason : tOutput( "$network_ban_noreason" ) );
01677 
01678         sn_DisconnectUser(m.SenderID(), tOutput( "$network_kill_banned", int(banned/60), reason ) );
01679     }
01680 
01681     // ignore multiple logins
01682     if( CountSameConnection( m.SenderID() ) > 0 )
01683         return -1;
01684 
01685     // ignore login floods
01686     if ( FloodProtection( m ) )
01687         return -1;
01688 
01689     bool success=false;
01690 
01691     int new_id = -1;
01692 
01693     // test
01694     //  sn_DisconnectUser(m.SenderID(), "$network_kill_incompatible");
01695     //  return -1;
01696 
01697     nVersion mergedVersion;
01698     if ( !mergedVersion.Merge( version, sn_CurrentVersion() ) )
01699     {
01700         sn_DisconnectUser(m.SenderID(), "$network_kill_incompatible");
01701     }
01702 
01703     // expire 0.2.8 test versions, they have a security flaw
01704     if ( sn_lockOut028tTest && version.Max() >= 5 && version.Max() <= 10 )
01705     {
01706         sn_DisconnectUser(m.SenderID(), "0.2.8_beta and 0.2.8.0_rc versions have a dangerous security flaw and are obsoleted, please upgrade to 0.2.8.2.1.");
01707     }
01708 
01709     if (m.SenderID()!=MAXCLIENTS+1)
01710     {
01711         //con << "Ignoring second login from " << m.SenderID() << ".\n";
01712         (new nMessage(login_ignore))->Send(m.SenderID());
01713     }
01714     else if (sn_Connections[m.SenderID()].socket)
01715     {
01716         if ( sn_maxClients > MAXCLIENTS )
01717             sn_maxClients = MAXCLIENTS;
01718 
01719         // count doublicate IPs
01720         if ( CountSameIP( m.SenderID(), true ) < sn_allowSameIPCountHard )
01721         {
01722             // find new free ( or freeable ) ID
01723             new_id = GetFreeSlot();
01724             if ( new_id > 0 )
01725             {
01726                 if(sn_Connections[new_id].socket)
01727                     sn_DisconnectUser( new_id, "$network_kill_full" );
01728 
01729                 success = true;
01730 
01731                 senderID.SetID( new_id );
01732 
01733                 sn_Connections  [ new_id ].socket       = sn_Connections[MAXCLIENTS+1].socket; // the new connection has number MC+1
01734                 peers                   [ new_id ]                      = peers[MAXCLIENTS+1];
01735                 timeouts                [ new_id ]                      = kickOnDemandTimeout/2;
01736 
01737                 // sn_Connections       [ MAXCLIENTS+1 ].socket         = NULL;
01738                 // peers                        [ MAXCLIENTS+1 ].sa_family      = 0;
01739                 //                              nCallbackLoginLogout::UserLoggedIn(i);
01740 
01741                 sn_Connections  [ new_id ].supportedAuthenticationMethods_ = supportedAuthenticationMethods;
01742 
01743                 // recount doublicate IPs
01744                 CountSameIP( new_id, true );
01745             }
01746         }
01747 
01748         // log login to console
01749         tOutput o;
01750         o.SetTemplateParameter(1, peers[m.SenderID()].ToString() );
01751         o.SetTemplateParameter(2, sn_Connections[m.SenderID()].socket->GetAddress().ToString() );
01752         o << "$network_server_login";
01753         con << o;
01754     }
01755     if (success)
01756     {
01757         tOutput o;
01758         o.SetTemplateParameter(1, new_id);
01759         o << "$network_server_login_success";
01760         con << o;
01761         //      tString s;
01762         // s << "User " << new_id << " logged in.\n";
01763 
01764         sn_Connections[new_id].ping.Reset();
01765         sn_Connections[new_id].bandwidthControl_.Reset();
01766         reset_last_acks(new_id);
01767 
01768         if (rate>sn_maxRateOut)
01769             rate=sn_maxRateOut;
01770 
01771         sn_Connections[new_id].bandwidthControl_.SetRate( rate );
01772         sn_Connections[new_id].version = version;
01773 
01774         nWaitForAck::AckAllPeer(MAXCLIENTS+1);
01775         reset_last_acks(MAXCLIENTS+1);
01776         if (sn_Connections[MAXCLIENTS+1].ackMess)
01777         {
01778             sn_Connections[MAXCLIENTS+1].ackMess=NULL;
01779         }
01780 
01781         // send login accept message with high priority
01782         nMessage *rep=new nMessage(login_accept);
01783         rep->Write(new_id);
01784         (*rep) << sn_myVersion;
01785         (*rep) << peers[m.SenderID()].ToString();
01786         nKrawall::WriteScrambledPassword( salt, *rep );
01787 
01788         rep->Send(new_id, -killTimeout);
01789 
01790         nMessage::SendCollected( new_id );
01791 
01792         nConfItemBase::s_SendConfig(true, new_id);
01793 
01794         // fake activity
01795         nMachine & machine = nMachine::GetMachine( new_id );
01796         machine.AddPlayer();
01797         machine.RemovePlayer();
01798 
01799         nCallbackLoginLogout::UserLoggedIn(new_id);
01800 
01801         //      ANET_Listen(false);
01802         //      ANET_Listen(true);
01803     }
01804     else if (m.SenderID()==MAXCLIENTS+1)
01805     {
01806         sn_DisconnectUser(MAXCLIENTS+1, "$network_kill_full");
01807     }
01808 
01809     sn_UpdateCurrentVersion();
01810 
01811     return new_id;
01812 }
01813 
01814 void login_handler_1(nMessage& m)
01815 {
01816     unsigned short rate;
01817 
01818     m.Read( rate );
01819 
01820     if ( !m.End() ){ // we get a big brother message (ignore it)
01821         tString rem_bb;
01822         m >> rem_bb;
01823     }
01824 
01825     login_handler( m, rate );
01826 }
01827 
01828 void login_handler_2(nMessage& m)
01829 {
01830     unsigned short rate;
01831     unsigned short bb;
01832 
01833     m.Read( rate );
01834     m.Read( bb );
01835     tString rem_bb;
01836 
01837     if ( bb )
01838     { // we get a big brother message
01839         m >> rem_bb;
01840     }
01841 
01842     int new_ID = login_handler( m, rate );
01843 
01844     if ( new_ID > 0 )
01845     {
01846         nMessage* m = tNEW( nMessage )( versionControl );
01847         (*m) << sn_currentVersion;
01848 
01849         m->Send( new_ID );
01850 
01851         if ( bb )
01852         {
01853             std::ofstream s;
01854             if ( tDirectories::Var().Open(s, "big_brother",std::ios::app) )
01855                 s << rem_bb << '\n';
01856         }
01857     }
01858 }
01859 
01860 
01861 void logout_handler(nMessage &m){
01862     unsigned short id = m.SenderID();
01863     //m.Read(id);
01864 
01865     if (sn_Connections[id].socket)
01866     {
01867         tOutput o;
01868         o.SetTemplateParameter(1, id);
01869         o << "$network_logout_server";
01870         con << o;
01871     }
01872     nWaitForAck::AckAllPeer(id);
01873 
01874     if (0<id && id<=MAXCLIENTS)
01875     {
01876         sn_DisconnectUser(id, "$network_kill_logout");
01877     }
01878 }
01879 
01880 
01881 #define MAX_MESS_LEN 300
01882 #define OVERHEAD 32
01883 
01884 static REAL sn_OrderPriority = 0;
01885 
01886 // statistics
01887 int sn_SentBytes        = 0;
01888 int sn_SentPackets      = 0;
01889 int sn_ReceivedBytes    = 0;
01890 int sn_ReceivedPackets  = 0;
01891 nTimeRolling sn_StatsTime               = 0;
01892 
01893 
01894 // adds a message to the buffer
01895 void nSendBuffer::AddMessage    ( nMessage&                     message, nBandwidthControl* control )
01896 {
01897     unsigned long id = message.MessageID();
01898     unsigned short len = message.DataLen();
01899     tRecorderSync< unsigned long >::Archive( "_MESSAGE_ID_SEND", 5, id );
01900 
01901     sendBuffer_[sendBuffer_.Len()]=htons(message.Descriptor());
01902 
01903     sendBuffer_[sendBuffer_.Len()]=htons(message.MessageID());
01904 
01905     sendBuffer_[sendBuffer_.Len()]=htons(message.DataLen());
01906     for(int i=0;i<len;i++)
01907         sendBuffer_[sendBuffer_.Len()]=htons(message.Data(i));
01908 
01909     tRecorderSync< unsigned short >::Archive( "_MESSAGE_SEND_LEN", 5, len );
01910 
01911     if ( control )
01912     {
01913         control->Use( nBandwidthControl::Usage_Planning, len * 2 );
01914     }
01915 }
01916 
01917 // send the contents of the buffer to a specific socket
01918 void nSendBuffer::Send                  ( nSocket const &                               socket
01919                            , const nAddress &   peer
01920                            ,nBandwidthControl* control )
01921 {
01922     if (sendBuffer_.Len()){
01923         sn_SentPackets++;
01924         sn_SentBytes  += sendBuffer_.Len() * 2 + OVERHEAD;
01925 
01926         // store our id
01927         sendBuffer_[sendBuffer_.Len()]=htons(::sn_myNetID);
01928 
01929         socket.Write( reinterpret_cast<int8 *>(&(sendBuffer_[0])),
01930                       2*sendBuffer_.Len(), peer);
01931 
01932         if ( control )
01933         {
01934             control->Use( nBandwidthControl::Usage_Execution, 2*sendBuffer_.Len() + OVERHEAD );
01935         }
01936 
01937         this->Clear();
01938     }
01939 }
01940 
01941 // broadcast the contents of the buffer
01942 void nSendBuffer::Broadcast     ( nSocket const &                               socket
01943                               , int                             port
01944                               , nBandwidthControl* control )
01945 {
01946     if (sendBuffer_.Len()){
01947         sn_SentPackets++;
01948         sn_SentBytes  += sendBuffer_.Len() * 2 + OVERHEAD;
01949 
01950         // store our id
01951         sendBuffer_[sendBuffer_.Len()]=htons(::sn_myNetID);
01952 
01953         socket.Broadcast( reinterpret_cast<int8 *>(&(sendBuffer_[0])),
01954                           2*sendBuffer_.Len(), port);
01955 
01956         Clear();
01957 
01958         if ( control )
01959         {
01960             control->Use( nBandwidthControl::Usage_Execution, 2*sendBuffer_.Len() + OVERHEAD );
01961         }
01962     }
01963 }
01964 
01965 // clears the buffer
01966 void nSendBuffer::Clear()
01967 {
01968     for(int i=sendBuffer_.Len()-1;i>=0;i--)
01969         sendBuffer_(i)=0;
01970 
01971     sendBuffer_.SetLen( 0 );
01972 }
01973 
01974 
01975 nBandwidthControl::nBandwidthControl( nBandwidthControl* parent )
01976 {
01977 #ifdef DEBUG
01978     if ( parent )
01979         parent->numChildren_ ++;
01980     numChildren_ = 0;
01981 #endif
01982 
01983     parent_ = parent;
01984 
01985     Reset();
01986 }
01987 
01988 nBandwidthControl::~nBandwidthControl()
01989 {
01990 #ifdef DEBUG
01991     if ( parent_ )
01992         parent_->numChildren_ --;
01993 
01994     tASSERT( numChildren_ == 0 );
01995 #endif
01996 }
01997 
01998 void nBandwidthControl::Reset()
01999 {
02000     rateControlPlanned_ = rateControl_ = 1000.0f;
02001     rate_ = 8;
02002 }
02003 
02004 void nBandwidthControl::Use( Usage planned, REAL bandwidth )
02005 {
02006     tRecorderSync< REAL >::Archive( "_RATE_CONTROL_USAGE", 4, bandwidth );
02007     ( Usage_Planning == planned ? rateControlPlanned_ : rateControl_ ) -= bandwidth;
02008 }
02009 
02010 void nBandwidthControl::Update( REAL ts)
02011 {
02012     tRecorderSync< REAL >::Archive( "_RATE_CONTROL", 12, rateControl_ );
02013     tRecorderSync< REAL >::Archive( "_RATE_CONTROL_PLANNED", 12, rateControlPlanned_ );
02014 
02015     rateControl_ += ( rate_ * 1000 ) * ts;
02016 
02017     if ( rateControl_ > 1000.0f )
02018     {
02019         rateControl_ = 1000.0f;
02020     }
02021 
02022     rateControlPlanned_ = rateControl_;
02023 }
02024 
02025 void nMessage::SendCollected(int peer)
02026 {
02027     //if ( peer == 7 && sn_Connections[peer].sendBuffer_.Len() > 0 )
02028     //    con << tSysTimeFloat() << "\n";
02029 
02030     sn_OrderPriority = 0;
02031 
02032     if (peer<0 || peer > MAXCLIENTS+1 || !sn_Connections[peer].socket)
02033         tERR_ERROR("Invalid peer!");
02034 
02035     sn_Connections[peer].sendBuffer_.Send( *sn_Connections[peer].socket, peers[peer], &sn_Connections[peer].bandwidthControl_ );
02036 }
02037 
02038 
02039 void nMessage::BroadcastCollected(int peer, unsigned int port){
02040     if (peer<0 || peer > MAXCLIENTS+1 || !sn_Connections[peer].socket)
02041         tERR_ERROR("Invalid peer!");
02042 
02043     sn_Connections[peer].sendBuffer_.Broadcast( *sn_Connections[peer].socket, port, &sn_Connections[peer].bandwidthControl_ );
02044 }
02045 
02046 
02047 // TODO_NOACK
02048 void nMessage::SendImmediately(int peer,bool ack){
02049     if (ack)
02050     {
02051 #ifdef NO_ACK
02052         tASSERT(messageIDBig_);
02053 #endif
02054         new nWaitForAck(this,peer);
02055     }
02056 
02057     // server: messages to yourself are a bit strange...
02058     if ( sn_GetNetState() == nSERVER && peer == 0 && ack )
02059     {
02060         st_Breakpoint();
02061         tJUST_CONTROLLED_PTR< nMessage > bounce(this);
02062         return;
02063     }
02064 
02065 #ifdef DEBUG
02066     /*
02067     if (descriptor>1)
02068       con << "SMT " << descriptor << "\n";
02069     */
02070 
02071     /*
02072       #ifdef DEBUG
02073       if (sn_Connections[].rate_control[peer]<-2000)
02074          tERR_ERROR("Heavy network overflow.");
02075       #endif
02076     */
02077 
02078     // if (peer==0 && sn_GetNetState()==nSERVER)
02079     //      tERR_ERROR("talking to yourself, eh?");
02080 
02081     if (peer==MAXCLIENTS+1){
02082 #ifdef DEBUG
02083         if(descriptor==s_Acknowledge.id)
02084             con << "Sending ack to login slot.\n";
02085 #endif
02086         //      else if (descriptor
02087         //      tERR_ERROR("the last user only should receive denials or acks.");
02088     }
02089 #endif
02090 
02091     if (sn_Connections[peer].sendBuffer_.Len()+data.Len()+3 > MAX_MESS_LEN/2){
02092         SendCollected(peer);
02093         //con << "Overflow packets sent to " << peer << '\n';
02094     }
02095 
02096 
02097     if (sn_Connections[peer].socket)
02098     {
02099         sn_Connections[peer].sendBuffer_.AddMessage( *this, &sn_Connections[peer].bandwidthControl_ );
02100 
02101         /*
02102           if (sn_Connections[].rate_control[peer]>0)
02103           send_collected(peer);
02104 
02105           unsigned short *b=new (unsigned short)[data.Len()+3];
02106 
02107           b[0]=htons(descriptor);
02108           b[1]=htons(messageID);
02109           b[2]=htons(data.Len());
02110           int len=data.Len();
02111           for(int i=0;i<len;i++)
02112           b[3+i]=htons(data(i));
02113 
02114 
02115           ANET_Write(sn_Connections[].socket[peer],(int8 *)b,
02116           2*(data.Len()+3),&peers[peer]);
02117 
02118           //std::cerr << "Sent " << 2*len+6 << " bytes.\n";
02119           sn_Connections[].rate_control[peer]-=2*(len+3)+OVERHEAD;
02120 
02121           delete b;
02122         */
02123 
02124         if (deb_net)
02125             con << "Sent " <<descriptor << ':' << messageIDBig_ << ":"
02126             << peer << '\n';
02127     }
02128 
02129     tControlledPTR< nMessage > bounce( this ); // delete this message if nobody is interested in it any more
02130 }
02131 
02132 REAL sent_per_messid[MAXDESCRIPTORS+100];
02133 
02134 void nMessage::Send(int peer,REAL priority,bool ack){
02135 #ifdef NO_ACK
02136     if (!ack)
02137         messageIDBig_ = 0;
02138 #endif
02139 
02140     // messages to yourself are a bit strange...
02141     if ( sn_GetNetState() == nSERVER && peer == 0 && ack )
02142     {
02143         st_Breakpoint();
02144         tJUST_CONTROLLED_PTR< nMessage > bounce(this);
02145         return;
02146     }
02147 
02148 #ifdef DEBUG
02149 
02150     if (peer==MAXCLIENTS+1){
02151         if(descriptor==s_Acknowledge.id)
02152             con << "Sending ack to login slot.\n";
02153         //      else if (descriptor
02154         //      tERR_ERROR("the last user only should receive denials or acks.");
02155     }
02156 #endif
02157 
02158 #ifdef DEBUG_X
02159     if (descriptor>1)
02160         con << "PMT " << descriptor << "\n";
02161 #endif
02162 
02163     // the next line was redundant; the send buffer handles that part of accounting.
02164     //sn_Connections[peer].bandwidthControl_.Use( nBandwidthControl::Usage_Planning, 2*(data.Len()+3) );
02165 
02166     sent_per_messid[descriptor]+=2*(data.Len()+3);
02167 
02168     tASSERT(Descriptor()!=s_Acknowledge.ID() || !ack);
02169 
02170     new nMessage_planned_send(this,priority+sn_OrderPriority,ack,peer);
02171     sn_OrderPriority += .01; // to roughly keep the relative order of netmessages
02172 }
02173 
02174 // ack messages: don't get an ID
02175 class nAckMessage: public nMessage
02176 {
02177 public:
02178     nAckMessage(): nMessage( s_Acknowledge ){ messageIDBig_ = 0; }
02179 };
02180 
02181 // receive and s_Acknowledge the recently reveived network messages
02182 
02183 typedef std::deque< tJUST_CONTROLLED_PTR< nMessage > > nMessageFifo;
02184 
02185 static void rec_peer(unsigned int peer){
02186     tASSERT( sn_Connections[peer].socket );
02187 
02188     nMachine::Expire();
02189 
02190     // temporary fifo for received messages
02191     //static tArray< tJUST_CONTROLLED_PTR< nMessage > > receivedMessages;
02192     static nMessageFifo receivedMessages;
02193 
02194     // the growing buffer we read messages into
02195     const int serverMaxAcceptedSize=2000;
02196     static tArray< unsigned short > storage(2000);
02197     int maxrec = 0; maxrec = storage.Len();
02198     unsigned short * buff = 0; buff = &storage[0];
02199 
02200     // short buff[maxrec];
02201     if (sn_Connections[peer].socket){
02202         int count=0;
02203         int len=1;
02204         while (len>=0 && sn_Connections[peer].socket)
02205         {
02206             nAddress addrFrom; // the sender of the current packet
02207             len = sn_Connections[peer].socket->Read( reinterpret_cast<int8 *>(buff),maxrec*2, addrFrom);
02208 
02209             if (len>0){
02210                 if ( len >= maxrec*2 )
02211                 {
02212                     // the message was too long to receive. What to do?
02213                     if ( sn_GetNetState() != nSERVER || len < serverMaxAcceptedSize )
02214                     {
02215                         // expand the buffer. The message is lost now, but the
02216                         // peer will certainly resend it. Hopefully, the buffer will be large enough to hold it then.
02217                         storage[maxrec*2-1]=0;
02218                         maxrec = storage.Len();
02219                         buff = &storage[0];
02220 
02221                         tERR_WARN( "Oversized network packet received. Read buffer has been enlargened to catch it the next time.");
02222 
02223                         // no use in processing the truncated packet. Some messages may get lost,
02224                         // but that's better than the inevitable network error and connection
02225                         // termination that expects us if we go on.
02226                         continue;
02227                     }
02228                     else
02229                     {
02230                         // terminate the connection
02231                         sn_DisconnectUser( peer, "$network_kill_error" );
02232                     }
02233                 }
02234 
02235                 unsigned short *b=buff;
02236                 unsigned short *bend=buff+(len/2-1);
02237 
02238                 sn_ReceivedPackets++;
02239                 sn_ReceivedBytes  += len + OVERHEAD;
02240 
02241                 unsigned short claim_id=ntohs(*bend);
02242 
02243                 // z-man: security check ( thanks, Luigi Auriemma! )
02244                 if ( claim_id > MAXCLIENTS+1 )
02245                     continue;   // drop packet, maybe it was just truncated.
02246 
02247                 /*
02248                   std::cerr << "Received " << len << " bytes";
02249                   con << " from user " << claim_id << '\n';
02250                 */
02251                 count ++;
02252 
02253                 unsigned int id=peer;
02254                 //       for(unsigned int i=1;i<=(unsigned int)maxclients;i++)
02255                 int comp=nAddress::Compare( addrFrom, peers[claim_id] );
02256                 if ( comp == 0 ) // || claim_id == MAXCLIENTS+1 )
02257                 {
02258                     // everything seems allright. accept the id.
02259                     id = claim_id;
02260                 }
02261                 else
02262                 {
02263                     // assume it's a new connection
02264                     id = MAXCLIENTS+1;
02265                     peers[ MAXCLIENTS+1 ] = addrFrom;
02266                     sn_Connections[ MAXCLIENTS+1 ].socket = sn_Connections[peer].socket;
02267                 }
02268 
02269                 //       if (peer!=id)
02270                 //  con << "Changed incoming address.\n";
02271                 int lenleft = bend - b;
02272 
02273 #ifndef NOEXCEPT
02274                 try
02275                 {
02276 #endif
02277                     while( lenleft > 0 ){
02278                         tJUST_CONTROLLED_PTR< nMessage > pmess;
02279                         pmess = tNEW( nMessage )(b,id,lenleft);
02280                         nMessage& mess = *pmess;
02281 
02282                         lenleft = bend - b;
02283 
02284                         bool mess_is_new=true;
02285                         // see if we have got this packet before
02286                         unsigned short mess_id=mess.MessageID();
02287 
02288 #ifdef DEBUG
02289                         if ( (simulate_loss && rand()%simulate_loss==0)){
02290                             // simulate packet loss
02291                             con << "Losing packet " << mess_id << ":" << id << ".\n";
02292                         }else
02293 #endif
02294                             if(// (id==MAXCLIENTS+1 && !nCallbackAcceptPackedWithoutConnection::Accept( mess ) ) ||
02295                                 // do not accept normal packages from the login
02296                                 // slot; just login and information packets are allowed.
02297                                 ( sn_GetNetState() != nSERVER && !login_succeeded && !nCallbackAcceptPackedWithoutConnection::Accept( mess ) )
02298                                 // if we are not yet logged in, accept only login and login_deny.
02299                             )
02300                             {
02301                                 //                                                      con << "Ignoring packet " << mess_id << ":" << id << ".\n";
02302                             }
02303                             else
02304                             {
02305                                 if (id <= MAXCLIENTS && mess_id != 0)  // messages with ID 0 are non-ack messages and come really often. they are always new.
02306                                 {
02307                                     unsigned short diff=mess_id-highest_ack[id];
02308                                     if (diff>0 && diff<10000 ||
02309                                             ((
02310                                                  mess.Descriptor() == login_accept.ID() ||
02311                                                  mess.Descriptor() == login_deny.ID()   ||
02312                                                  mess.Descriptor() == login.ID()
02313                                              ) && highest_ack[id] == 0)
02314                                        ){
02315                                         // the message has a more recent id than anything before.
02316                                         // it is surely new.
02317                                         highest_ack[id]=mess_id;
02318                                     }
02319                                     else{
02320                                         // do a better check
02321                                         for(int i=ACKBACK-1;i>=0;i--)
02322                                             if (mess_id==lastacks[id][i])
02323                                                 mess_is_new=false;
02324                                     }
02325                                 }
02326 
02327 
02328                                 // acknowledge the message, even if it was old (the sender
02329                                 // then thinks it got lost the first time)
02330 
02331                                 // special situation: logout. Do not sent ack any more.
02332                                 if ((!sn_Connections[id].socket))
02333                                 {
02334                                     sn_Connections[id].ackMess=NULL;
02335                                 }
02336                                 else if (
02337 #ifdef NO_ACK
02338                                     (mess.MessageID()) &&
02339 #endif
02340                                     (mess.Descriptor()!=login_ignore.ID() ||
02341                                      login_succeeded )){
02342                                     // do not ack the login_ignore packet that did not let you in.
02343 
02344 #ifdef DEBUG
02345                                     if ( id > MAXCLIENTS )
02346                                     {
02347                                         con << "Sending ack to login slot.\n";
02348                                     }
02349 #endif
02350 
02351                                     if(sn_Connections[id].ackMess==NULL)
02352                                     {
02353                                         sn_Connections[id].ackMess=new nAckMessage();
02354                                     }
02355 
02356                                     sn_Connections[id].ackMess->Write(mess.MessageID());
02357                                     if (sn_Connections[id].ackMess->DataLen()>100){
02358                                         sn_Connections[id].ackMess->Send(id, 0, false);
02359                                         sn_Connections[id].ackMess=NULL;
02360                                     }
02361                                 }
02362 
02363                                 if (mess_is_new){
02364                                     // mark the message as old
02365                                     if (mess_id > 0)
02366                                     {
02367                                         lastacks[id][lastackPos[id]]=mess_id;
02368                                         if(++lastackPos[id]>=ACKBACK) lastackPos[id]=0;
02369                                     }
02370 
02371                                     /*
02372                                                                                                 // special situation: login. Change peer number permanently
02373                                                                                                 if (peer==MAXCLIENTS+1 && new_id>0){
02374                                                                                                         id=peer=new_id;
02375                                                                                                 }
02376                                     */
02377 
02378                                     if (sn_GetNetState() != nSTANDALONE)
02379                                     {
02380                                         // store the message for later processing
02381                                         receivedMessages.push_back( pmess );
02382                                     }
02383                                 }
02384                                 //else
02385                                 //con << "Message " << mess_id << ":" << id << " was not new.\n";
02386                             }
02387                     }
02388 #ifndef NOEXCEPT
02389                 }
02390 
02391                 catch(nKillHim)
02392                 {
02393                     con << "nKillHim signal caught.\n";
02394                     sn_DisconnectUser(peer, "$network_kill_error");
02395                 }
02396 #endif
02397             }
02398         #ifndef NOEXCEPT
02399             try
02400             {
02401         #endif
02402                 static int recursionCount = 0;
02403                 ++recursionCount;
02404 
02405                 // handle messages
02406                 while ( receivedMessages.begin() != receivedMessages.end() )
02407                 {
02408                     tJUST_CONTROLLED_PTR< nMessage > mess = receivedMessages.front();
02409                     receivedMessages.pop_front();
02410 
02411                     // perhaps the connection died?
02412                     if ( sn_Connections[ mess->SenderID() ].socket )
02413                         nDescriptor::HandleMessage( *mess );
02414                 }
02415 
02416                 if ( --recursionCount <= 0 )
02417                 {
02418                     nCallbackReceivedComplete::ReceivedComplete();
02419                 }
02420 
02421         #ifndef NOEXCEPT
02422             }
02423 
02424             catch(nKillHim const &)
02425             {
02426                 con << "nKillHim signal caught.\n";
02427                 sn_DisconnectUser(peer, "$network_kill_error");
02428             }
02429         #endif
02430 
02431         }
02432     }
02433 }
02434 
02435 // receives and processes data from control socket
02436 void sn_ReceiveFromControlSocket()
02437 {
02438     rec_peer(0);
02439 }
02440 
02441 // discards data from control socket
02442 void sn_DiscardFromControlSocket()
02443 {
02444     // new facts: pending incoming data on the control socket causes the idle loops
02445     // to use 100% CPU time, we need to fetch and discard the data instead of ignoring it.
02446     if ( sn_Connections[0].socket )
02447     {
02448         int8 buff[2];
02449         nAddress addrFrom;
02450         sn_Connections[0].socket->Read( reinterpret_cast<int8 *>(buff),0, addrFrom);
02451     }
02452 }
02453 
02454 
02455 nNetState sn_GetNetState(){
02456     return current_state;
02457 }
02458 
02459 void clear_owners();
02460 
02461 // tries to open listening sockets according to specification, but falls back to increasing ports
02462 static bool sn_Listen( unsigned int & net_hostport, const tString& net_hostip )
02463 {
02464     unsigned int net_hostport_before = net_hostport;
02465 
02466     try
02467     {
02468         nSocketListener & listener = sn_BasicNetworkSystem.AccessListener();
02469 
02470         listener.SetIpList( net_hostip );
02471 
02472         bool reported = false;
02473 
02474         // try ports in a range
02475         while ( net_hostport < sn_serverPort + 100 )
02476         {
02477             if ( listener.SetPort( net_hostport ).Listen( true ) )
02478                 return true;
02479 
02480             if ( !reported )
02481             {
02482                 con << "sn_SetNetState: Unable to open accept socket on desired port " << net_hostport << ", Trying next ports...\n";
02483                 reported = true;
02484             }
02485 
02486             net_hostport++;
02487         }
02488 
02489         con << "sn_SetNetState: Giving up setting up listening sockets for IP list " << net_hostip << ".\n";
02490     }
02491     catch( const tException & e )
02492     {
02493         con << "sn_SetNetState: can't setup listening sockets. Reason given:\n"
02494         << e.GetName() << ": " << e.GetDescription() << "\n";
02495     }
02496 
02497     // reset host port
02498     net_hostport = net_hostport_before;
02499 
02500     return false;
02501 }
02502 
02503 // save and load machine info
02504 static void sn_SaveMachines();
02505 static void sn_LoadMachines();
02506 
02507 static void sn_DisconnectAll()
02508 {
02509     for(int i=MAXCLIENTS+1;i>=0;i--)
02510     {
02511         if( sn_Connections[i].socket )
02512         {
02513             sn_DisconnectUser(i, "$network_kill_shutdown");
02514             tVERIFY( !sn_Connections[i].socket );
02515         }
02516     }
02517     nCallbackLoginLogout::UserLoggedOut(0);
02518 }
02519 
02520 // flag set as long as the network sockets should not be closed and reopened
02521 static bool sn_noReset = false;
02522 nSocketResetInhibitor::nSocketResetInhibitor()
02523 {
02524     sn_noReset = true;
02525 }
02526 nSocketResetInhibitor::~nSocketResetInhibitor()
02527 {
02528     sn_noReset = false;
02529 }
02530 
02531 void sn_SetNetState(nNetState x){
02532     static bool reentry=false;
02533     if(!reentry && x!=current_state){
02534         sn_UpdateCurrentVersion();
02535 
02536         //if (x == nSERVER)
02537         unsigned int net_hostport = sn_serverPort;
02538 
02539         // save/load machines on entering/leaving server mode
02540         if ( x == nSERVER )
02541             sn_LoadMachines();
02542         else if ( current_state == nSERVER )
02543             if ( !tRecorder::IsPlayingBack() )
02544                 sn_SaveMachines();
02545 
02546         reentry=true;
02547         if (x!=nSTANDALONE)
02548         {
02549             if (x==nCLIENT)
02550             {
02551                 sn_DisconnectAll();
02552             }
02553             else
02554             {
02555                 sn_myNetID=0;
02556             }
02557 
02558             if (!sn_Connections[0].socket)
02559                 sn_Connections[0].socket=sn_BasicNetworkSystem.Init();
02560             // bool success = true;
02561             if (x == nSERVER)
02562             {
02563                 // bool success =
02564                 sn_Listen( net_hostport, net_hostip ) ||    // first try: do it according to user specs
02565                 sn_Listen( net_hostport, tString( "ANY" ) ) ||         // second try: bind to generic IP
02566                 sn_Listen( net_hostport, tString( "ALL" ) );           // last try: bind to all available IPs
02567 
02568 #ifdef DEDICATED
02569                 // save host port that worked, otherwise it may change from the port sent to the master server
02570                 sn_serverPort = net_hostport;
02571 #endif
02572             }
02573         }
02574         else
02575         {
02576             clear_owners();
02577             for(int i=MAXCLIENTS+1;i>=0;i--){
02578                 if(sn_Connections[i].socket){
02579                     if (i==0 && current_state!=nSERVER)
02580                     { // logout: fire and forget
02581                         con << tOutput("$network_logout_process");
02582                         for(int j=3;j>=0;j--){ // just to make sure
02583                             nMessage *lo=new nMessage(logout);
02584                             lo->Write(static_cast<unsigned short>(sn_myNetID));
02585                             lo->ClearMessageID();
02586                             lo->SendImmediately(0, false);
02587                             nMessage::SendCollected(0);
02588                             tDelay(1000);
02589                         }
02590                         con << tOutput("$network_logout_done");
02591 
02592                         sn_myNetID=0; // MAXCLIENTS+1; // reset network id
02593                     }
02594                 }
02595                 sn_DisconnectUserNoWarn(i, "$network_kill_shutdown");
02596             }
02597 
02598             sn_Connections[0].socket = 0;
02599 
02600             // shutdown network system to get new socket
02601             if ( !sn_noReset )
02602                 sn_BasicNetworkSystem.Shutdown();
02603         }
02604 
02605         current_state=x;
02606         reentry=false;
02607     }
02608 
02609     sn_UpdateCurrentVersion();
02610 }
02611 
02612 
02613 
02614 // go to client mode and connect to server
02615 
02616 
02617 void sn_Bend( nAddress const & address )
02618 {
02619     if ((sn_GetNetState() == nSTANDALONE))
02620         sn_SetNetState(nCLIENT);
02621 
02622     peers[0] = address;
02623 }
02624 
02625 void sn_Bend( tString const & server, unsigned int port)
02626 {
02627     // fill address info
02628     nAddress address;
02629     address.SetHostname( server );
02630     address.SetPort( port );
02631 
02632     // delegate
02633     sn_Bend( address );
02634 }
02635 
02636 nConnectError sn_Connect( nAddress const & server, nLoginType loginType, nSocket const * socket ){
02637     sn_DenyReason = "";
02638 
02639     // reset redirection
02640     sn_redirectTo.release();
02641 
02642     // pings in the beginning of the login are not really representative
02643     nPingAverager::SetWeight(.0001);
02644 
02645     // net_hostport = sn_clientPort;
02646 
02647     sn_SetNetState(nSTANDALONE);
02648     sn_SetNetState(nCLIENT);
02649 
02650     // set user requested socket
02651     if ( socket )
02652         sn_Connections[0].socket = socket;
02653 
02654     sn_Connections[0].ping.Reset();
02655 
02656     peers[0] = server;
02657 
02658     reset_last_acks(0);
02659     nCallbackLoginLogout::UserLoggedOut(0);
02660     sn_Connections[0].sendBuffer_.Clear();
02661 
02662     tASSERT( sn_Connections[0].socket );
02663 
02664     // sn_Connections[0].socket->Connect( peers[0] ); // useless
02665     sn_Connections[0].bandwidthControl_.SetRate( sn_maxRateOut );
02666 
02667     sn_myNetID=0; // MAXCLIENTS+1; // reset network id
02668 
02669     // first, get all pending messages
02670     sn_Receive();
02671     sn_Receive();
02672     sn_Receive();
02673 
02674     // reset version control until the true value is given by the server.
02675     sn_currentVersion = nVersion(0,0);
02676 
02677     // Login stuff.....
02678     tJUST_CONTROLLED_PTR< nMessage > mess;
02679     if ( loginType != Login_Pre0252 )
02680     {
02681         mess=new nMessage(login_2);
02682         mess->Write(sn_maxRateIn);
02683 
02684         unsigned short bb = big_brother;
02685         mess->Write( bb );
02686         if ( bb ){
02687             (*mess) << sn_bigBrotherString;
02688             big_brother=false;
02689         }
02690     }
02691     else
02692     {
02693         mess=new nMessage(login);
02694         mess->Write(sn_maxRateIn);
02695 
02696         // send (worthless) big brother string
02697         if (big_brother)
02698         {
02699             (*mess) << sn_bigBrotherString;
02700         }
02701         else
02702         {
02703             (*mess) << tString("");
02704         }
02705 
02706         big_brother=false;
02707     }
02708 
02709     // write our version
02710     (*mess) << sn_MyVersion();
02711     
02712     // write our supported authentication methods
02713     (*mess) << nKrawall::nMethod::SupportedMethods();
02714     
02715     // write a random salt
02716     nKrawall::RandomSalt( loginSalt );
02717     nKrawall::WriteScrambledPassword( loginSalt, *mess );
02718 
02719     mess->ClearMessageID();
02720     mess->SendImmediately(0,false);
02721     nMessage::SendCollected(0);
02722 
02723     con << tOutput("$network_login_process");
02724 
02725     login_failed=false;
02726     login_succeeded=false;
02727 
02728     nTimeRolling timeout=tSysTimeFloat()+5;
02729 
02730     static REAL resend = .25;
02731     nTimeAbsolute nextSend = tSysTimeFloat() + resend/5;
02732     while(sn_GetNetState()==nCLIENT && tSysTimeFloat()<timeout &&
02733             !login_failed && !login_succeeded){
02734         if ( tSysTimeFloat() > nextSend )
02735         {
02736             // con << "retrying...\n";
02737             nextSend = tSysTimeFloat() + resend;
02738             mess->SendImmediately(0,false);
02739             nMessage::SendCollected(0);
02740         }
02741 
02742         tAdvanceFrame(10000);
02743         sn_Receive();
02744         sn_SendPlanned();
02745 
02746         // check for user abort
02747         if ( tConsole::Idle() )
02748         {
02749             con << tOutput("$network_login_failed_abort");
02750             sn_SetNetState(nSTANDALONE);
02751             return nABORT;
02752         }
02753     }
02754     if (login_failed)
02755     {
02756         con << tOutput("$network_login_failed");
02757         sn_SetNetState(nSTANDALONE);
02758         return nDENIED;
02759     }
02760     else if (tSysTimeFloat()>=timeout || sn_GetNetState()!=nCLIENT){
02761         if ( loginType == Login_All )
02762         {
02763             return      sn_Connect( server, Login_Pre0252, socket );
02764         }
02765         else
02766         {
02767             con << tOutput("$network_login_failed_timeout");
02768             sn_SetNetState(nSTANDALONE);
02769             return nTIMEOUT;
02770         }
02771     }
02772     else{
02773         nCallbackLoginLogout::UserLoggedIn(0);
02774 
02775         tOutput mess;
02776         mess.SetTemplateParameter(1, sn_myNetID);
02777         mess << "$network_login_success";
02778         con << mess;
02779         con << tOutput("$network_login_sync");
02780         sn_Sync(40);
02781         con << tOutput("$network_login_relabeling");
02782         con << tOutput("$network_login_sync2");
02783         sn_Sync(40,true);
02784         con << tOutput("$network_login_done");
02785 
02786         // marginalize past ping values
02787         nPingAverager::SetWeight(1);
02788 
02789         return nOK;
02790     }
02791 }
02792 
02793 
02794 void nReadError( bool critical )
02795 {
02796     // st_Breakpoint();
02797 #ifndef NOEXCEPT
02798     if ( critical )
02799         throw nKillHim();
02800     else
02801         throw nIgnore();
02802 #else
02803     con << "\nI told you not to use PGCC! Now we need to leave the\n"
02804     << "system in an undefined state. The progam will crash now.\n"
02805     << "\n\n";
02806 #endif
02807 }
02808 
02809 #ifdef DEDICATED
02810 static short sn_decorateID = true;
02811 static tConfItem< short > sn_decorateIDConf( "CONSOLE_DECORATE_ID", sn_decorateID );
02812 
02813 static short sn_decorateIP = false;
02814 static tConfItem< short > sn_decorateIPConf( "CONSOLE_DECORATE_IP", sn_decorateIP );
02815 
02816 // console with filter for better machine readable log format
02817 class nConsoleFilter:public tConsoleFilter{
02818 private:
02819     virtual void DoFilterLine( tString &line )
02820     {
02821         if ( sn_decorateID )
02822         {
02823             tString orig = line;
02824 
02825             int id = nCurrentSenderID::GetID();
02826             bool printIP = ( id > 0 && sn_decorateIP );
02827 
02828             line = "";
02829             line << "[";
02830             if ( sn_decorateID )
02831                 line << id;
02832             if ( sn_decorateID && printIP )
02833                 line << " ";
02834             if ( printIP )
02835             {
02836                 // get IP from id
02837                 tString IP;
02838                 sn_GetAdr( id,  IP );
02839                 line << "IP=" << IP;
02840             }
02841 
02842             line << "] " << orig;
02843         }
02844     }
02845 };
02846 
02847 static nConsoleFilter sn_consoleFilter;
02848 #endif
02849 
02850 static void sn_ConsoleOut_handler(nMessage &m){
02851     if (sn_GetNetState()!=nSERVER){
02852         tString s;
02853         m >> s;
02854         con << s;
02855     }
02856 }
02857 
02858 
02859 static nDescriptor sn_ConsoleOut_nd(8,sn_ConsoleOut_handler,"sn_ConsoleOut");
02860 
02861 // causes the connected clients to print a message
02862 nMessage* sn_ConsoleOutMessage( const tOutput& o )
02863 {
02864     tString message(o);
02865     message  << "0xffffff";
02866 
02867     // truncate message to 1.4K, a safe size for all UDP packets
02868     static const int maxLen = 1400;
02869     static bool recurse = true;
02870     if ( message.Len() > maxLen && recurse )
02871     {
02872         recurse = false;
02873         tERR_WARN( "Long console message truncated.");
02874 
02875         message.SetLen( maxLen+1 );
02876         message[maxLen]='\0';
02877         recurse = false;
02878     }
02879 
02880     nMessage* m=new nMessage(sn_ConsoleOut_nd);
02881     *m << message;
02882 
02883     return m;
02884 }
02885 
02886 void sn_ConsoleOut(const tOutput& o,int client){
02887     //  tString message(o);
02888 
02889     tJUST_CONTROLLED_PTR< nMessage > m = sn_ConsoleOutMessage( o );
02890 
02891     if (client<0){
02892         m->BroadCast();
02893         con << o;
02894     }
02895     else if (client==sn_myNetID)
02896     {
02897         con << o;
02898     }
02899     else
02900         m->Send(client);
02901 }
02902 
02903 static void client_cen_handler(nMessage &m){
02904     if (sn_GetNetState()!=nSERVER){
02905         tString s;
02906         m >> s;
02907         con.CenterDisplay(s);
02908     }
02909 }
02910 
02911 static nDescriptor client_cen_nd(9,client_cen_handler,"client_cen");
02912 
02913 // causes the connected clients to print a message in the center of the screeen
02914 void sn_CenterMessage(const tOutput &o,int client){
02915     tString message(o);
02916 
02917     tJUST_CONTROLLED_PTR< nMessage > m=new nMessage(client_cen_nd);
02918     *m << message;
02919     if (client<0){
02920         m->BroadCast();
02921         con.CenterDisplay(message);
02922     }
02923     else if (client==sn_myNetID)
02924         con.CenterDisplay(message);
02925     else
02926         m->Send(client);
02927 }
02928 
02929 static void ConsoleOut_conf(std::istream &s)
02930 {
02931     // read the message
02932     tString message;
02933     message.ReadLine( s, true );
02934 
02935     message += "\n";
02936 
02937     // display it
02938     sn_ConsoleOut( message );
02939 }
02940 
02941 static tConfItemFunc ConsoleOut_c("CONSOLE_MESSAGE",&ConsoleOut_conf);
02942 static tAccessLevelSetter sn_ConsoleConfLevel( ConsoleOut_c, tAccessLevel_Moderator );
02943 
02944 static void CeterMessage_conf(std::istream &s)
02945 {
02946     // read the message
02947     tString message;
02948     message.ReadLine( s, true );
02949 
02950     // display it
02951     sn_CenterMessage( message );
02952 }
02953 
02954 static tConfItemFunc CenterMessage_c("CENTER_MESSAGE",&CeterMessage_conf);
02955 static tAccessLevelSetter sn_CenterConfLevel( CenterMessage_c, tAccessLevel_Moderator );
02956 
02957 // ****************************************************************
02958 //                    Send Queue
02959 // ****************************************************************
02960 
02961 // the network stuff planned to send:
02962 tHeap<planned_send> send_queue[MAXCLIENTS+2];
02963 
02964 planned_send::planned_send(REAL priority,int Peer){
02965     peer=Peer;
02966 
02967     SetVal( priority, send_queue[peer] );
02968 }
02969 
02970 planned_send::~planned_send(){
02971     RemoveFromHeap();
02972 }
02973 
02974 tHeapBase *planned_send::Heap() const
02975 {
02976     return &send_queue[peer];
02977 }
02978 
02979 // change our priority:
02980 void planned_send::add_to_priority(REAL diff)
02981 {
02982     SetVal( Val() + diff, send_queue[peer] );
02983 }
02984 
02985 // **********************************************
02986 
02987 nMessage_planned_send::nMessage_planned_send
02988 (nMessage *M,REAL priority,bool Ack,int Peer)
02989         :planned_send(priority,Peer),m(M),ack(Ack){
02990     //if (m)
02991 }
02992 
02993 nMessage_planned_send::~nMessage_planned_send(){
02994 }
02995 
02996 void nMessage_planned_send::execute(){
02997     if ( Val() < -killTimeout-10){
02998         tOutput mess;
02999         mess.SetTemplateParameter(1, peer);
03000         mess << "$network_error_overflow";
03001         con << mess;
03002         st_Breakpoint();
03003         sn_DisconnectUser(peer, "$network_kill_overflow");
03004     }
03005     else if (m)
03006         m->SendImmediately(peer,ack);
03007 }
03008 
03009 
03010 // **********************************************
03011 
03012 static REAL sn_SendPlanned1(){
03013     sn_OrderPriority = 0;
03014 
03015     // if possible, send waiting messages
03016     static double lastTime=-1;
03017     nTimeAbsolute time=tSysTimeFloat();
03018     if (lastTime<0)
03019         lastTime=time;
03020 
03021     if (time<lastTime-.01 || time>lastTime+1000)
03022 #ifdef DEBUG
03023     {
03024         tERR_ERROR("Timer hickup!");
03025     }
03026 #else
03027     {
03028         tERR_WARN("Timer hickup!");
03029         lastTime=time;
03030     }
03031 #endif
03032     REAL dt = time - lastTime;
03033 
03034     //for(int i=MAXCLIENTS+1;i>=0;i--){
03035     for(int i=0;i<=MAXCLIENTS+1;i++){
03036         nConnectionInfo & connection = sn_Connections[i];
03037         if ( !connection.socket )
03038             continue;
03039 
03040         while (connection.ackPending<sn_maxNoAck &&
03041                 connection.bandwidthControl_.CanSend()     &&
03042                 send_queue[i].Len())
03043         {
03044             send_queue[i](0)->execute();
03045             if (send_queue[i].Len())
03046                 delete send_queue[i](0);
03047         }
03048 
03049         // make everything a little more urgent:
03050         for(int j=send_queue[i].Len()-1;j>=0;j--)
03051             send_queue[i](j)->add_to_priority(-dt);
03052     }
03053     lastTime=time;
03054 
03055     return dt;
03056 }
03057 
03058 static void sn_SendPlanned2( REAL dt ){
03059     // empty the send buffers
03060     for(int i=0;i<=MAXCLIENTS+1;i++){
03061         nConnectionInfo & connection = sn_Connections[i];
03062         if ( connection.socket )
03063         {
03064             if (connection.sendBuffer_.Len()>0 && connection.bandwidthControl_.CanSend() )
03065                 nMessage::SendCollected(i);
03066 
03067             // update bandwidth usage and other time related data
03068             connection.Timestep( dt );
03069         }
03070     }
03071 }
03072 
03073 void sn_SendPlanned()
03074 {
03075     // propagate messages to buffers
03076     REAL dt = sn_SendPlanned1();
03077 
03078     // schedule the acks: send them if it's possible (bandwith limit) or if there already is a packet in the pipe.
03079     for(int i=0;i<=MAXCLIENTS+1;i++)
03080         if(sn_Connections[i].socket && sn_Connections[i].ackMess && !sn_Connections[i].ackMess->End()
03081                 //      && sn_ackAckPending[i] <= 1+sn_Connections[].ackMess[i]->DataLen()
03082                 && ( sn_Connections[i].bandwidthControl_.CanSend() || sn_Connections[i].sendBuffer_.Len() > 0 )
03083           ){
03084             sn_Connections[i].ackMess->SendImmediately(i, false);
03085             sn_Connections[i].ackMess=NULL;
03086         }
03087 
03088     // schedule lost messages for resending
03089     nWaitForAck::Resend();
03090 
03091     // send everything out
03092     sn_SendPlanned2( dt );
03093 }
03094 
03095 void sn_Receive(){
03096     /*
03097       static bool reentry=false;
03098       if (reentry)
03099       return;
03100       reentry=true;
03101     */
03102 
03103     netTime=tSysTimeFloat();
03104     //  new_id=0;
03105     sn_Connections[MAXCLIENTS+1].ping.Reset();
03106 
03107     // create the ack messages (not required, is done on demand later)
03108     /*
03109     int i;
03110     for(i=0;i<=MAXCLIENTS+1;i++)
03111         if(sn_Connections[i].ackMess==NULL)
03112             sn_Connections[i].ackMess=new nAckMessage();
03113     */
03114 
03115 
03116     switch (current_state){
03117     case nSERVER:
03118         {
03119             memset( &peers[0], 0, sizeof(sockaddr) );
03120 
03121             // listen on all sockets
03122             nSocketListener const & listener = sn_BasicNetworkSystem.GetListener();
03123             for ( nSocketListener::iterator i = listener.begin(); i != listener.end(); ++i )
03124             {
03125                 // clear peer info used for receiving
03126                 memset( &peers[MAXCLIENTS+1], 0, sizeof(sockaddr) );
03127 
03128                 if((sn_Connections[MAXCLIENTS+1].socket = (*i).CheckNewConnection() ) != NULL)
03129                     rec_peer(MAXCLIENTS+1);
03130             }
03131         }
03132         // z-man: after much thought, the server does also need to listen to the
03133         // network control socket. .... Thinking again, it's only important for the master
03134         // servers, and they call rec_peer(0) separately.
03135         break;
03136 
03137     case nCLIENT:
03138         rec_peer(0);
03139         break;
03140 
03141     case nSTANDALONE:
03142     default:
03143         break;
03144     }
03145 
03146     /*
03147         // scedule regular messages
03148         REAL dt = sn_SendPlanned1();
03149 
03150         // actually resend messages
03151         sn_SendPlanned2( dt );
03152     */
03153 }
03154 
03155 void sn_KickUser(int i, const tOutput& reason, REAL severity, nServerInfoBase * redirectTo )
03156 {
03157     // print it
03158     con << tOutput( "$network_kill_log", i, reason );
03159 
03160     // log it
03161     if ( severity > 0 )
03162     {
03163         nMachine::GetMachine(i).OnKick( severity );
03164     }
03165 
03166     // do it
03167     sn_DisconnectUser( i, reason, redirectTo );
03168 }
03169 
03170 void sn_DisconnectUser(int i, const tOutput& reason, nServerInfoBase * redirectTo )
03171 {
03172     // don't be daft and kill yourself, server!
03173     if ( i == 0 && sn_GetNetState() == nSERVER )
03174     {
03175         tERR_WARN( "Server tried to disconnect from itself." );
03176         return;
03177     }
03178 
03179     // clients can only disconnect from the server
03180     if ( i != 0 && sn_GetNetState() == nCLIENT )
03181     {
03182         tERR_ERROR( "Client tried to disconnect from another client: impossible and a bad idea." );
03183         return;
03184     }
03185 
03186     // anything to do at all?
03187     if (!sn_Connections[i].socket)
03188     {
03189         return;
03190     }
03191 
03192     sn_DisconnectUserNoWarn( i, reason, redirectTo );
03193 }
03194 
03195 void sn_DisconnectUserNoWarn(int i, const tOutput& reason, nServerInfoBase * redirectTo )
03196 {
03197     nCurrentSenderID senderID( i );
03198 
03199     nWaitForAck::AckAllPeer(i);
03200 
03201     static bool reentry=false;
03202     if (reentry)
03203         return;
03204     reentry=true;
03205 
03206     bool printMessage = false; // is it worth printing a message for this event?
03207 
03208     if (sn_Connections[i].socket)
03209     {
03210         nMessage::SendCollected(i);
03211         printMessage = true;
03212 
03213         // to make sure...
03214         if ( i!=0 && i != MAXCLIENTS+2 && sn_GetNetState() == nSERVER ){
03215             for(int j=2;j>=0;j--){
03216                 nMessage* mess = (new nMessage(login_deny));
03217                 *mess << tString( reason );
03218 
03219                 // write redirection
03220                 tString redirection;
03221                 int port;
03222                 if ( redirectTo )
03223                 {
03224                     redirection = redirectTo->GetConnectionName();
03225                     port        = redirectTo->GetPort();
03226                 }
03227                 *mess << redirection;
03228                 *mess << port;
03229 
03230                 mess->SendImmediately(i, false);
03231                 nMessage::SendCollected(i);
03232             }
03233         }
03234     }
03235 
03236     nWaitForAck::AckAllPeer(i);
03237 
03238     sn_Connections[i].ackMess=NULL;
03239 
03240     if (i==0 && sn_GetNetState()==nCLIENT)
03241         sn_SetNetState(nSTANDALONE);
03242 
03243     reset_last_acks(i);
03244 
03245     // peers[i].sa_family=0;
03246 
03247     sn_Connections[i].ackPending=0;
03248     //  sn_ackAckPending[i]=0;
03249 
03250     nCallbackLoginLogout::UserLoggedOut(i);
03251 
03252     if ( printMessage )
03253     {
03254         con << tOutput( "$network_killuser", i, sn_Connections[i].ping.GetPing() );
03255     }
03256 
03257     // clear address, socket and send queue
03258     sn_Connections[i].sendBuffer_.Clear();
03259     sn_Connections[i].socket=NULL;
03260     peers[i] = nAddress();
03261     sn_Connections[i].Clear();
03262     while (send_queue[i].Len())
03263         delete (send_queue[i](0));
03264 
03265     reentry=false;
03266 
03267     sn_UpdateCurrentVersion();
03268 }
03269 
03270 
03271 int sn_QueueLen(int user){
03272     return send_queue[user].Len();
03273 }
03274 
03275 
03276 static tCallback* s_loginoutAnchor=NULL;
03277 int  nCallbackLoginLogout::user;
03278 bool nCallbackLoginLogout::login;
03279 
03280 nCallbackLoginLogout::nCallbackLoginLogout(AA_VOIDFUNC *f)
03281         :tCallback(s_loginoutAnchor,f){}
03282 
03283 void nCallbackLoginLogout::UserLoggedIn(int u){
03284     login = true;
03285     user = u;
03286     Exec(s_loginoutAnchor);
03287 }
03288 
03289 void nCallbackLoginLogout::UserLoggedOut(int u){
03290     login = false;
03291     user = u;
03292     Exec(s_loginoutAnchor);
03293 }
03294 
03295 unsigned short nCallbackAcceptPackedWithoutConnection::descriptor=0;    // the descriptor of the incoming packet
03296 static tCallbackOr* s_AcceptAnchor=NULL;
03297 
03298 nCallbackAcceptPackedWithoutConnection::nCallbackAcceptPackedWithoutConnection(BOOLRETFUNC *f)
03299         : tCallbackOr( s_AcceptAnchor, f )
03300 {
03301 }
03302 
03303 bool nCallbackAcceptPackedWithoutConnection::Accept( const nMessage& m )
03304 {
03305     descriptor=m.Descriptor();
03306     return Exec( s_AcceptAnchor );
03307 }
03308 
03309 static tCallback* s_ReceivedCompleteAnchor=NULL;
03310 
03311 nCallbackReceivedComplete::nCallbackReceivedComplete(AA_VOIDFUNC *f)
03312         : tCallback( s_ReceivedCompleteAnchor, f )
03313 {
03314 }
03315 
03316 void nCallbackReceivedComplete::ReceivedComplete( )
03317 {
03318     Exec( s_ReceivedCompleteAnchor );
03319 }
03320 
03321 static bool net_Accept()
03322 {
03323     return
03324         nCallbackAcceptPackedWithoutConnection::Descriptor()==login_accept.ID() ||
03325         nCallbackAcceptPackedWithoutConnection::Descriptor()==login_deny.ID();
03326 }
03327 
03328 static nCallbackAcceptPackedWithoutConnection net_acc( &net_Accept );
03329 
03330 static void net_exit(){
03331     for (int i=MAXCLIENTS+1;i>=0;i--)
03332     {
03333         sn_Connections[i].ackMess = NULL;
03334         while (send_queue[i].Len())
03335             delete send_queue[i].Remove(0);
03336     }
03337 }
03338 
03339 static tInitExit net_ie(NULL, &net_exit);
03340 
03341 
03342 
03343 void sn_Statistics()
03344 {
03345     nTimeRolling time = tSysTimeFloat();
03346     REAL dt = time - sn_StatsTime;
03347     sn_StatsTime = time;
03348 
03349     if (dt > 0 && (sn_SentPackets || sn_SentBytes))
03350     {
03351         tOutput o;
03352         o.SetTemplateParameter(1,dt);
03353         o.SetTemplateParameter(2,sn_SentBytes);
03354         o.SetTemplateParameter(3,sn_SentPackets);
03355         o.SetTemplateParameter(4,sn_SentBytes/dt);
03356         o.SetTemplateParameter(5,sn_ReceivedBytes);
03357         o.SetTemplateParameter(6,sn_ReceivedPackets);
03358         o.SetTemplateParameter(7,sn_ReceivedBytes/dt);
03359         o << "$network_statistics1";
03360         o << "$network_statistics2";
03361         o << "$network_statistics3";
03362 
03363         con << o;
03364     }
03365 
03366     sn_SentPackets = 0;
03367     sn_SentBytes   = 0;
03368     sn_ReceivedPackets = 0;
03369     sn_ReceivedBytes   = 0;
03370 }
03371 
03372 
03373 
03374 
03375 
03376 
03377 nConnectionInfo::nConnectionInfo(){Clear();}
03378 nConnectionInfo::~nConnectionInfo(){}
03379 
03380 void nConnectionInfo::Clear(){
03381     socket     = NULL;
03382     ackPending = 0;
03383     ping.Reset();
03384     // crypt      = NULL;
03385 
03386     supportedAuthenticationMethods_ = "";
03387 
03388     sendBuffer_.Clear();
03389 
03390     bandwidthControl_.Reset();
03391 
03392     ackMess = NULL;
03393 
03394     // start with 10% packet loss with low statistical weight
03395     packetLoss_.Reset();
03396     packetLoss_.Add(.1,10);
03397 }
03398 
03399 void nConnectionInfo::Timestep( REAL dt )  
03400 {
03401     // update ping
03402     ping.Timestep( dt );
03403 
03404     // update bandwidth control
03405     bandwidthControl_.Update( dt );
03406 
03407     // update packet loss; average about a minute
03408     packetLoss_.Timestep( .02 * dt );
03409 }
03410 
03411 void nConnectionInfo::ReliableMessageSent()  
03412 {
03413     packetLoss_.Add( 1 );
03414 }
03415 
03416 void nConnectionInfo::AckReceived()          
03417 {
03418     packetLoss_.Add( -1 );
03419 }
03420 
03421 REAL nConnectionInfo::PacketLoss() const     
03422 {
03423     REAL ret = packetLoss_.GetAverage();
03424     return ret > 0 ? ret : 0;
03425 }
03426 
03427 void sn_GetAdr(int user,  tString& name)
03428 {
03429     peers[user].ToString( name );
03430 }
03431 
03432 unsigned int sn_GetPort(int user)
03433 {
03434     return peers[user].GetPort();
03435 }
03436 
03437 unsigned int sn_GetServerPort()
03438 {
03439     return sn_serverPort;
03440 }
03441 
03442 int sn_NumUsers( bool all )
03443 {
03444     int ret = 0;
03445     for (int i=MAXCLIENTS; i>0; i--)
03446         if (sn_Connections[i].socket && ( all || ( sn_allowSameIPCountSoft > CountSameIP( i ) ) ) )
03447             ret++;
03448 
03449 #ifndef DEDICATED
03450     ret++;
03451 #endif
03452 
03453     return ret;
03454 }
03455 
03456 int sn_NumUsers()
03457 {
03458     return sn_NumUsers( true );
03459 }
03460 
03461 int sn_NumRealUsers()
03462 {
03463     return sn_NumUsers( false );
03464 }
03465 
03466 int sn_MaxUsers()
03467 {
03468     return sn_maxClients;
03469 }
03470 
03471 int sn_MessagesPending(int user)
03472 {
03473     return sn_Connections[user].ackPending + send_queue[user].Len();
03474 }
03475 
03476 nBasicNetworkSystem sn_BasicNetworkSystem;
03477 
03478 // *******************************************************************************************
03479 // *
03480 // *    nKillHim
03481 // *
03482 // *******************************************************************************************
03485 // *******************************************************************************************
03486 
03487 nKillHim::nKillHim( void )
03488 {
03489 }
03490 
03491 // *******************************************************************************************
03492 // *
03493 // *    ~nKillHim
03494 // *
03495 // *******************************************************************************************
03498 // *******************************************************************************************
03499 
03500 nKillHim::~nKillHim( void )
03501 {
03502 }
03503 
03504 // *******************************************************************************************
03505 // *
03506 // *    DoGetName
03507 // *
03508 // *******************************************************************************************
03512 // *******************************************************************************************
03513 
03514 tString nKillHim::DoGetName( void ) const
03515 {
03516     return tString( "Connektion kill request" );
03517 }
03518 
03519 // *******************************************************************************************
03520 // *
03521 // *    DoGetDescription
03522 // *
03523 // *******************************************************************************************
03527 // *******************************************************************************************
03528 
03529 tString nKillHim::DoGetDescription( void ) const
03530 {
03531     return tString( "The currently handled peer must have done something illegal, so it should be terminated." );
03532 }
03533 
03534 // *******************************************************************************************
03535 // *
03536 // *    nIgnore
03537 // *
03538 // *******************************************************************************************
03541 // *******************************************************************************************
03542 
03543 nIgnore::nIgnore( void )
03544 {
03545 }
03546 
03547 // *******************************************************************************************
03548 // *
03549 // *    ~nIgnore
03550 // *
03551 // *******************************************************************************************
03554 // *******************************************************************************************
03555 
03556 nIgnore::~nIgnore( void )
03557 {
03558 }
03559 
03560 // *******************************************************************************************
03561 // *
03562 // *    DoGetName
03563 // *
03564 // *******************************************************************************************
03568 // *******************************************************************************************
03569 
03570 tString nIgnore::DoGetName( void ) const
03571 {
03572     return tString( "Packet ignore request" );
03573 }
03574 
03575 // *******************************************************************************************
03576 // *
03577 // *    DoGetDescription
03578 // *
03579 // *******************************************************************************************
03583 // *******************************************************************************************
03584 
03585 tString nIgnore::DoGetDescription( void ) const
03586 {
03587     return tString( "An error that should lead to the current message getting ingored was detected." );
03588 }
03589 
03590 // *******************************************************************************************
03591 // *
03592 // *    nAverager
03593 // *
03594 // *******************************************************************************************
03597 // *******************************************************************************************
03598 
03599 nAverager::nAverager( void )
03600         : weight_(0), sum_(0), sumSquared_(0), weightSquared_(0)
03601 {
03602 }
03603 
03604 // *******************************************************************************************
03605 // *
03606 // *    ~nAverager
03607 // *
03608 // *******************************************************************************************
03611 // *******************************************************************************************
03612 
03613 nAverager::~nAverager( void )
03614 {
03615 }
03616 
03617 // *******************************************************************************************
03618 // *
03619 // *    Timestep
03620 // *
03621 // *******************************************************************************************
03625 // *******************************************************************************************
03626 
03627 void nAverager::Timestep( REAL decay )
03628 {
03629     REAL factor = 1/(1+decay);
03630 
03631     // pretend all data so far was collected with a weight of the original weight multiplied by factor
03632     weight_        *= factor;
03633     sum_           *= factor;
03634     sumSquared_    *= factor;
03635     weightSquared_ *= factor * factor;
03636 }
03637 
03638 // *******************************************************************************************
03639 // *
03640 // *    Add
03641 // *
03642 // *******************************************************************************************
03647 // *******************************************************************************************
03648 
03649 void nAverager::Add( REAL value, REAL weight )
03650 {
03651     tASSERT( weight >= 0 );
03652     weight_        += weight;
03653     sum_           += weight * value;
03654     sumSquared_    += weight * value * value;
03655     weightSquared_ += weight * weight;
03656 }
03657 
03658 // *******************************************************************************************
03659 // *
03660 // *    Reset
03661 // *
03662 // *******************************************************************************************
03665 // *******************************************************************************************
03666 
03667 void nAverager::Reset( void )
03668 {
03669     weightSquared_ = weight_ = sum_ = sumSquared_ = 0.0f;
03670 }
03671 
03672 // *******************************************************************************************
03673 // *
03674 // *    GetAverage
03675 // *
03676 // *******************************************************************************************
03680 // *******************************************************************************************
03681 
03682 REAL nAverager::GetAverage( void ) const
03683 {
03684     if ( weight_ > 0 )
03685         return sum_ / weight_;
03686     else
03687         return 0;
03688 }
03689 
03690 // *******************************************************************************************
03691 // *
03692 // *    GetDataVariance
03693 // *
03694 // *******************************************************************************************
03698 // *******************************************************************************************
03699 
03700 REAL nAverager::GetDataVariance( void ) const
03701 {
03702     if ( weight_ > 0 )
03703     {
03704         REAL average       = sum_ / weight_;
03705         REAL averageSquare = sumSquared_ / weight_;
03706         REAL ret = averageSquare - average * average;
03707         if ( ret < 0 )
03708             ret = 0;
03709         return ret;
03710     }
03711     else
03712         return 0;
03713 }
03714 
03715 // *******************************************************************************************
03716 // *
03717 // *    GetAverageVariance
03718 // *
03719 // *******************************************************************************************
03723 // *******************************************************************************************
03724 
03725 REAL nAverager::GetAverageVariance( void ) const
03726 {
03727     if ( weight_ > 0 )
03728     {
03729         REAL square = weight_ * weight_;
03730 
03731         REAL denominator = square - weightSquared_;
03732         REAL numerator = GetDataVariance() * weightSquared_;
03733         if ( denominator > numerator * 1E-30 )
03734         {
03735             return numerator/denominator;
03736         }
03737         else
03738             return 1E+30;
03739     }
03740     else
03741         return 0;
03742 }
03743 
03744 // *******************************************************************************
03745 // *
03746 // *    operator <<
03747 // *
03748 // *******************************************************************************
03753 // *******************************************************************************
03754 
03755 std::istream & nAverager::operator <<( std::istream & stream )
03756 {
03757     char c;
03758     stream >> c;
03759     tASSERT( c == '(' );
03760 
03761     stream >> weight_ >> sum_ >> sumSquared_ >> weightSquared_;
03762 
03763     stream >> c;
03764     tASSERT( c == ')' );
03765 
03766     return stream;
03767 }
03768 
03769 // *******************************************************************************
03770 // *
03771 // *    operator >>
03772 // *
03773 // *******************************************************************************
03778 // *******************************************************************************
03779 
03780 std::ostream & nAverager::operator >>( std::ostream & stream ) const
03781 {
03782     stream << '(' << weight_ << ' ' << sum_  << ' ' << sumSquared_  << ' ' << weightSquared_  << ')';
03783 
03784     return stream;
03785 }
03786 
03787 // *******************************************************************************
03788 // *
03789 // *    operator >>
03790 // *
03791 // *******************************************************************************
03797 // *******************************************************************************
03798 
03799 std::istream & operator >> ( std::istream & stream, nAverager & averager )
03800 {
03801     return averager << stream;
03802 }
03803 
03804 // *******************************************************************************
03805 // *
03806 // *    operator <<
03807 // *
03808 // *******************************************************************************
03814 // *******************************************************************************
03815 
03816 std::ostream & operator << ( std::ostream & stream, nAverager const & averager )
03817 {
03818     return averager >> stream;
03819 }
03820 
03821 
03822 // *******************************************************************************************
03823 // *
03824 // *    nPingAverager
03825 // *
03826 // *******************************************************************************************
03829 // *******************************************************************************************
03830 
03831 nPingAverager::nPingAverager( void )
03832 {
03833     Reset();
03834 }
03835 
03836 // *******************************************************************************************
03837 // *
03838 // *    ~nPingAverager
03839 // *
03840 // *******************************************************************************************
03843 // *******************************************************************************************
03844 
03845 nPingAverager::~nPingAverager( void )
03846 {
03847 }
03848 
03849 // *******************************************************************************************
03850 // *
03851 // *    GetPing
03852 // *
03853 // *******************************************************************************************
03857 // *******************************************************************************************
03858 
03859 REAL nPingAverager::GetPing( void ) const
03860 {
03861     // collect data
03862     // determine the lowest guessed value for variance.
03863     // lag spikes should not contribute here too much.
03864     REAL variance = 1;
03865     {
03866         REAL snailVariance = this->snail_.GetDataVariance();
03867         REAL slowVariance = this->slow_.GetDataVariance();
03868         REAL fastVariance = this->fast_.GetDataVariance();
03869         variance = variance < snailVariance ? variance : snailVariance;
03870         variance = variance < slowVariance ? variance : slowVariance;
03871         variance = variance < fastVariance ? variance : fastVariance;
03872     }
03873 
03874     REAL pingSnail  = this->GetPingSnail();
03875     REAL pingSlow   = this->GetPingSlow();
03876     REAL pingFast   = this->GetPingFast();
03877 
03878     // the proposed return value: defaults to the snail ping, it flucuates the least
03879     REAL pingReturn = pingSnail;
03880 
03881     // return slow average if that differs from the snail one by at least one standard deviation
03882     if ( ( pingSlow - pingReturn ) * ( pingSlow - pingReturn ) > variance )
03883     {
03884         // but clamp it to sane values
03885         if ( pingSlow > pingReturn * 2 )
03886             pingSlow = pingReturn * 2;
03887 
03888         pingReturn = pingSlow;
03889     }
03890 
03891     // same for fast ping
03892     if ( ( pingFast - pingReturn ) * ( pingFast - pingReturn ) > variance )
03893     {
03894         if ( pingFast > pingReturn * 2 )
03895             pingFast = pingReturn * 2;
03896 
03897         pingReturn = pingFast;
03898     }
03899 
03900     // return best estimate plus expected variance with fudge factor. It's better to err to the big ping side.
03901     return pingReturn + sqrtf(variance) * 1.5;
03902 }
03903 
03904 // *******************************************************************************************
03905 // *
03906 // *    operator REAL
03907 // *
03908 // *******************************************************************************************
03912 // *******************************************************************************************
03913 
03914 nPingAverager::operator REAL( void ) const
03915 {
03916     return GetPing();
03917 }
03918 
03919 // *******************************************************************************************
03920 // *
03921 // *    GetPingSlow
03922 // *
03923 // *******************************************************************************************
03927 // *******************************************************************************************
03928 
03929 REAL nPingAverager::GetPingSnail( void ) const
03930 {
03931     return snail_.GetAverage();
03932 }
03933 
03934 // *******************************************************************************************
03935 // *
03936 // *    GetPingSlow
03937 // *
03938 // *******************************************************************************************
03942 // *******************************************************************************************
03943 
03944 REAL nPingAverager::GetPingSlow( void ) const
03945 {
03946     return slow_.GetAverage();
03947 }
03948 
03949 // *******************************************************************************************
03950 // *
03951 // *    GetPingFast
03952 // *
03953 // *******************************************************************************************
03957 // *******************************************************************************************
03958 
03959 REAL nPingAverager::GetPingFast( void ) const
03960 {
03961     return fast_.GetAverage();
03962 }
03963 
03964 // *******************************************************************************************
03965 // *
03966 // *    IsSpiking
03967 // *
03968 // *******************************************************************************************
03972 // *******************************************************************************************
03973 
03974 bool nPingAverager::IsSpiking( void ) const
03975 {
03976     REAL difference = slow_.GetAverage() - fast_.GetAverage();
03977     return slow_.GetAverageVariance() < difference * difference;
03978 }
03979 
03980 // *******************************************************************************************
03981 // *
03982 // *    Timestep
03983 // *
03984 // *******************************************************************************************
03988 // *******************************************************************************************
03989 
03990 void nPingAverager::Timestep( REAL decay )
03991 {
03992     snail_.Timestep( decay * .02 );
03993     slow_.Timestep ( decay * .2 );
03994     fast_.Timestep ( decay * 2 );
03995 }
03996 
03997 // *******************************************************************************************
03998 // *
03999 // *    Add
04000 // *
04001 // *******************************************************************************************
04006 // *******************************************************************************************
04007 
04008 void nPingAverager::Add( REAL value, REAL weight )
04009 {
04010     // add value to both averagers
04011     snail_.Add( value, weight );
04012     slow_.Add ( value, weight );
04013     fast_.Add ( value, weight );
04014 }
04015 
04016 // *******************************************************************************************
04017 // *
04018 // *    Add
04019 // *
04020 // *******************************************************************************************
04024 // *******************************************************************************************
04025 
04026 void nPingAverager::Add( REAL value )
04027 {
04028     // add value to both averagers
04029     Add( value, weight_ );
04030 }
04031 
04032 // *******************************************************************************************
04033 // *
04034 // *    Reset
04035 // *
04036 // *******************************************************************************************
04039 // *******************************************************************************************
04040 
04041 void nPingAverager::Reset( void )
04042 {
04043     snail_.Reset();
04044     slow_. Reset();
04045     fast_. Reset();
04046 
04047     // fill in some low weight values
04048     Add( 1, .000001 );
04049     Add( 0, .000001 );
04050 
04051     // pin snail averager close to zero
04052     // snail_.Add(0,10);
04053     // not such a good idea after all. The above line caused massive resending of packets.
04054 }
04055 
04056 REAL nPingAverager::weight_=1;
04057 
04058 
04059 
04060 
04061 
04062 // *******************************************************************************
04063 // *
04064 // *    nMachine
04065 // *
04066 // *******************************************************************************
04069 // *******************************************************************************
04070 
04071 nMachine::nMachine( void )
04072         : lastUsed_(tSysTimeFloat())
04073         , banned_(-1)
04074         , players_(0)
04075         , decorators_(0)
04076 {
04077     kph_.Add(0,.1666);
04078     lastPlayerAction_ = lastUsed_;
04079 }
04080 
04081 // *******************************************************************************
04082 // *
04083 // *    ~nMachine
04084 // *
04085 // *******************************************************************************
04088 // *******************************************************************************
04089 
04090 nMachine::~nMachine( void )
04091 {
04092     // destroy and remove the decorators
04093     while ( decorators_ )
04094     {
04095         nMachineDecorator * decorator = decorators_;
04096         decorator->Remove();
04097         decorator->Destroy();
04098     }
04099 }
04100 
04101 // *******************************************************************************
04102 // *
04103 // *    operator ==
04104 // *
04105 // *******************************************************************************
04110 // *******************************************************************************
04111 
04112 bool nMachine::operator == ( nMachine const & other ) const
04113 {
04114     return this == &other;
04115 }
04116 
04117 // *******************************************************************************
04118 // *
04119 // *    operator !=
04120 // *
04121 // *******************************************************************************
04126 // *******************************************************************************
04127 
04128 bool nMachine::operator !=( nMachine const & other ) const
04129 {
04130     return this != &other;
04131 }
04132 
04133 // singleton machine map
04134 class nMachinePTR
04135 {
04136 public:
04137     mutable nMachine * machine;
04138     nMachinePTR(): machine(tNEW(nMachine)()){};
04139     ~nMachinePTR(){tDESTROY(machine);}
04140     nMachinePTR(nMachinePTR const & other): machine(other.machine){other.machine=0;}
04141     nMachinePTR & operator=(nMachinePTR const & other){ machine = other.machine; other.machine=0;return *this;}
04142 };
04143 
04144 typedef std::map< tString, nMachinePTR > nMachineMap;
04145 static nMachineMap & sn_GetMachineMap()
04146 {
04147     static nMachineMap map;
04148     return map;
04149 }
04150 
04151 static nMachine & sn_LookupMachine( tString const & address )
04152 {
04153     // get map of all machines and look address up
04154     nMachineMap & map = sn_GetMachineMap();
04155     return map[ address ].machine->SetIP( address );
04156 }
04157 
04158 // *******************************************************************************
04159 // *
04160 // *    GetMachine
04161 // *
04162 // *******************************************************************************
04167 // *******************************************************************************
04168 
04169 nMachine & nMachine::GetMachine( unsigned short userID )
04170 {
04171     // throw out old machines
04172     Expire();
04173 
04174     // hardcoding: the server itself
04175     if ( userID == 0 && sn_GetNetState() != nCLIENT )
04176     {
04177         static nMachine server;
04178         return server;
04179     }
04180 
04181     tASSERT( userID <= MAXCLIENTS+1 );
04182 
04183     if( sn_GetNetState() != nSERVER )
04184     {
04185         // invalid ID, return invalid machine (clients don't track machines)
04186         static nMachine invalid;
04187         return invalid;
04188     }
04189 
04190     // get address
04191     tVERIFY( userID <= MAXCLIENTS+1 );
04192     if( !sn_Connections[userID].socket )
04193     {
04194         // invalid ID, return invalid machine
04195         static nMachine invalid;
04196         return invalid;
04197     }
04198     tString address;
04199     peers[ userID ].GetAddress( address );
04200 
04201 #ifdef DEBUG_X
04202     // add client ID so multiple connects from one machine are distinquished
04203     tString newIP;
04204     newIP << address << " " << userID;
04205     address = newIP;
04206 #endif
04207 
04208     // delegate
04209     return sn_LookupMachine( address );
04210 }
04211 
04212 // safely delete iterator from map
04213 static void sn_Erase( nMachineMap & map, nMachineMap::iterator & iter )
04214 {
04215     if ( iter != map.end() )
04216     {
04217         map.erase( iter );
04218         iter = map.end();
04219     }
04220 }
04221 
04222 // *******************************************************************************
04223 // *
04224 // *    Expire
04225 // *
04226 // *******************************************************************************
04229 // *******************************************************************************
04230 
04231 void nMachine::Expire( void )
04232 {
04233     static double lastTime = tSysTimeFloat();
04234     double time = tSysTimeFloat();
04235     REAL dt = time - lastTime;
04236     if (dt <= 60)
04237         return;
04238     lastTime = time;
04239 
04240     // iterate over known machines
04241     nMachineMap & map = sn_GetMachineMap();
04242     nMachineMap::iterator toErase = map.end();
04243     for( nMachineMap::iterator iter = map.begin(); iter != map.end(); ++iter )
04244     {
04245         // erase last deleted machine
04246         sn_Erase( map, toErase );
04247 
04248         nMachine & machine = *(*iter).second.machine;
04249 
04250         // advance the kick statistics if the user is not banned and has been active
04251         if ( time > machine.banned_ && ( machine.lastUsed_ > time - 300 || machine.players_ > 0 ) )
04252         {
04253             machine.kph_.Add( 0, dt / 3600 );
04254             machine.kph_.Timestep( dt / 3600*24 );
04255         }
04256 
04257         // if the machine is no longer in use, mark it for deletion
04258         if ( machine.players_ == 0 && machine.lastUsed_ < time - 300.0 && machine.banned_ < time && machine.kph_.GetAverage() < 0.5 )
04259             toErase = iter;
04260 
04261     }
04262 
04263     // erase last machine
04264     sn_Erase( map, toErase );
04265 }
04266 
04267 // maximal time a client without players is tolerated
04268 static REAL sn_spectatorTime = 0;
04269 static tSettingItem< REAL > sn_spectatorTimeConf( "NETWORK_SPECTATOR_TIME", sn_spectatorTime );
04270 
04271 // *******************************************************************************
04272 // *
04273 // *    KickSpectators
04274 // *
04275 // *******************************************************************************
04278 // *******************************************************************************
04279 
04280 void nMachine::KickSpectators( void )
04281 {
04282     double time = tSysTimeFloat();
04283 
04284     // kick spectators
04285     if ( sn_GetNetState() == nSERVER && sn_spectatorTime > 0 )
04286     {
04287         for ( int i = MAXCLIENTS; i >= 1; --i )
04288         {
04289             if ( sn_Connections[i].socket )
04290             {
04291                 nMachine & machine = GetMachine( i );
04292                 if ( machine.players_ == 0 && machine.lastPlayerAction_ + sn_spectatorTime < time )
04293                 {
04294                     sn_KickUser( i, tOutput("$network_kill_spectator"), 0 );
04295                 }
04296             }
04297         }
04298     }
04299 }
04300 
04301 // settings for automatic banning
04302 static REAL sn_autobanOffset = 5;  // bias that gets subtracted from the kills per hour
04303 static REAL sn_autobanFactor = 10; // factor that gets multiplied on top of it to determine the ban time in minutes
04304 static REAL sn_autobanMaxKPH = 30; // maximal value of kph
04305 
04306 static tSettingItem< REAL > sn_autobanOffsetSetting( "NETWORK_AUTOBAN_OFFSET", sn_autobanOffset );
04307 static tSettingItem< REAL > sn_autobanFactorSetting( "NETWORK_AUTOBAN_FACTOR", sn_autobanFactor );
04308 static tSettingItem< REAL > sn_autobanMaxKPHSetting( "NETWORK_AUTOBAN_MAX_KPH", sn_autobanMaxKPH );
04309 
04310 // *******************************************************************************
04311 // *
04312 // *    OnKick
04313 // *
04314 // *******************************************************************************
04318 // *******************************************************************************
04319 
04320 void nMachine::OnKick( REAL severity )
04321 {
04322     // if the user is currently banned, don't count
04323     if ( banned_ > tSysTimeFloat() )
04324         return;
04325 
04326     // ban the user a bit, taking the kicks per hour into account
04327     REAL kph = kph_.GetAverage() - sn_autobanOffset;
04328     if ( kph > 0 )
04329     {
04330         // the faster you get kicked when you turn up, the longer you get banned
04331         REAL banTime = 60 * kph * sn_autobanFactor;
04332         Ban( banTime, tString(tOutput( "$network_ban_kick" )) );
04333     }
04334 
04335     // add it to the statistics
04336     if ( sn_autobanMaxKPH > 0 )
04337         kph_.Add( severity * sn_autobanMaxKPH, 2/sn_autobanMaxKPH );
04338 
04339     con << tOutput( "$network_ban_kph", GetIP(), GetKicksPerHour() );
04340 }
04341 
04342 static bool sn_printBans = true;
04343 
04344 // *******************************************************************************
04345 // *
04346 // *    Ban
04347 // *
04348 // *******************************************************************************
04352 // *******************************************************************************
04353 
04354 void nMachine::Ban( REAL time )
04355 {
04356     lastUsed_ = tSysTimeFloat();
04357 
04358     // set the banning timeout to the current time plus the given time
04359     banned_ = tSysTimeFloat() + time;
04360 
04361     if ( sn_printBans )
04362     {
04363         if ( time > 0 )
04364             con << tOutput( "$network_ban", GetIP(), int(time/60), banReason_.Len() > 1 ? banReason_ : tOutput( "$network_ban_noreason" ) );
04365         else
04366             con << tOutput( "$network_noban", GetIP() );
04367     }
04368 }
04369 
04370 // *******************************************************************************
04371 // *
04372 // *    Ban
04373 // *
04374 // *******************************************************************************
04379 // *******************************************************************************
04380 
04381 void nMachine::Ban( REAL time, tString const & reason )
04382 {
04383     banReason_ = tString();
04384     if ( reason.Len() > 2 )
04385         banReason_ = reason;
04386 
04387     Ban( time );
04388 }
04389 
04390 // *******************************************************************************
04391 // *
04392 // *    IsBanned
04393 // *
04394 // *******************************************************************************
04398 // *******************************************************************************
04399 
04400 REAL nMachine::IsBanned( void ) const
04401 {
04402     // test for banning
04403     double time = tSysTimeFloat();
04404     if ( time > banned_ )
04405         return 0;
04406 
04407     return banned_ - time;
04408 }
04409 
04410 // *******************************************************************************
04411 // *
04412 // *    AddPlayer
04413 // *
04414 // *******************************************************************************
04417 // *******************************************************************************
04418 
04419 void nMachine::AddPlayer( void )
04420 {
04421     lastPlayerAction_ = lastUsed_ = tSysTimeFloat();
04422 
04423     players_++;
04424 }
04425 
04426 // *******************************************************************************
04427 // *
04428 // *    RemovePlayer
04429 // *
04430 // *******************************************************************************
04433 // *******************************************************************************
04434 
04435 void nMachine::RemovePlayer( void )
04436 {
04437     lastPlayerAction_ = lastUsed_ = tSysTimeFloat();
04438 
04439     players_--;
04440     if ( players_ < 0 )
04441         players_ = 0;
04442 }
04443 
04444 // *******************************************************************************
04445 // *
04446 // *    GetPlayerCount
04447 // *
04448 // *******************************************************************************
04452 // *******************************************************************************
04453 
04454 int nMachine::GetPlayerCount( void )
04455 {
04456     return players_;
04457 }
04458 
04459 
04460 static char const * sn_machinesFileName = "bans.txt";
04461 
04462 class nMachinePersistor
04463 {
04464 public:
04465     // save ban info of machines
04466     static void SaveMachines()
04467     {
04468         std::ofstream s;
04469         if (tDirectories::Var().Open( s, sn_machinesFileName ) )
04470         {
04471             nMachineMap & map = sn_GetMachineMap();
04472             for( nMachineMap::iterator iter = map.begin(); iter != map.end(); ++iter )
04473             {
04474                 nMachine & machine = *(*iter).second.machine;
04475                 // if ( machine.IsBanned() > 0 )
04476                 {
04477                     s << (*iter).first << " " << machine.IsBanned() << " " << machine.kph_ << " " << machine.GetBanReason() << "\n";
04478                 }
04479             }
04480         }
04481     }
04482 
04483     // load and enter ban info of machines
04484     static void LoadMachines()
04485     {
04486         sn_printBans = false;
04487 
04488         tTextFileRecorder machines( tDirectories::Var(), sn_machinesFileName );
04489         while ( !machines.EndOfFile() )
04490         {
04491             std::stringstream line( machines.GetLine() );
04492 
04493             // address and ban time left
04494             tString address;
04495             REAL banTime;
04496 
04497             // read relevant info
04498             line >> address >> banTime;
04499             std::ws(line);
04500 
04501             // read kph averager
04502             nAverager kph;
04503             char c;
04504             line.get(c);
04505             line.putback(c);
04506             if ( c == '(' )
04507             {
04508                 line >> kph;
04509                 std::ws(line);
04510             }
04511 
04512             // read reason
04513             tString reason;
04514             reason.ReadLine( line );
04515 
04516             if ( address.Len() > 2 )
04517             {
04518                 // ban
04519                 nMachine & machine = sn_LookupMachine( address );
04520                 machine.Ban( banTime, reason );
04521                 machine.kph_ = kph;
04522             }
04523         }
04524 
04525         sn_printBans = true;
04526     }
04527 }
04528 ;
04529 // save ban info of machines
04530 static void sn_SaveMachines()
04531 {
04532     nMachinePersistor::SaveMachines();
04533 }
04534 
04535 // load and enter ban info of machines
04536 static void sn_LoadMachines()
04537 {
04538     nMachinePersistor::LoadMachines();
04539 }
04540 
04541 // *******************************************************************************
04542 // *
04543 // *    GetKicksPerHour
04544 // *
04545 // *******************************************************************************
04549 // *******************************************************************************
04550 
04551 REAL nMachine::GetKicksPerHour( void ) const
04552 {
04553     return this->kph_.GetAverage();
04554 }
04555 
04556 // *******************************************************************************
04557 // *
04558 // *    GetKicksPerHour
04559 // *
04560 // *******************************************************************************
04565 // *******************************************************************************
04566 
04567 nMachine const & nMachine::GetKicksPerHour( REAL & kph ) const
04568 {
04569     kph = this->kph_.GetAverage();
04570     return *this;
04571 }
04572 
04573 // *******************************************************************************
04574 // *
04575 // *    GetIP
04576 // *
04577 // *******************************************************************************
04581 // *******************************************************************************
04582 
04583 tString const & nMachine::GetIP( void ) const
04584 {
04585     return this->IP_;
04586 }
04587 
04588 // *******************************************************************************
04589 // *
04590 // *    GetIP
04591 // *
04592 // *******************************************************************************
04597 // *******************************************************************************
04598 
04599 nMachine const & nMachine::GetIP( tString & IP ) const
04600 {
04601     IP = this->IP_;
04602     return *this;
04603 }
04604 
04605 // *******************************************************************************
04606 // *
04607 // *    SetIP
04608 // *
04609 // *******************************************************************************
04614 // *******************************************************************************
04615 
04616 nMachine & nMachine::SetIP( tString const & IP )
04617 {
04618     lastUsed_ = tSysTimeFloat();
04619 
04620     this->IP_ = IP;
04621     return *this;
04622 }
04623 
04624 // *******************************************************************************
04625 // *
04626 // *    GetBanReason
04627 // *
04628 // *******************************************************************************
04632 // *******************************************************************************
04633 
04634 tString const & nMachine::GetBanReason( void ) const
04635 {
04636     return this->banReason_;
04637 }
04638 
04639 // *******************************************************************************
04640 // *
04641 // *    GetBanReason
04642 // *
04643 // *******************************************************************************
04648 // *******************************************************************************
04649 
04650 nMachine const & nMachine::GetBanReason( tString & reason ) const
04651 {
04652     reason = this->banReason_;
04653     return *this;
04654 }
04655 
04656 // *******************************************************************************
04657 // *
04658 // *    Banning and unbanning
04659 // *
04660 // *******************************************************************************
04661 
04662 // unban IPs
04663 static void sn_UnBanConf(std::istream &s)
04664 {
04665     if ( !s.good() || s.eof() )
04666     {
04667         con << "Usage: UNBAN_IP <ip>\n";
04668         return;
04669     }
04670 
04671     // read IP to unban
04672     tString address;
04673     s >> address;
04674 
04675     if ( address.Len() < 8 )
04676     {
04677         con << "Usage: UNBAN_IP <ip>, no or too short ip given.\n";
04678     }
04679     // and unban
04680     else
04681     {
04682         sn_LookupMachine( address ).Ban( 0 );
04683     }
04684 }
04685 
04686 static tConfItemFunc sn_unBanConf("UNBAN_IP",&sn_UnBanConf);
04687 
04688 // ban IPs
04689 static void sn_BanConf(std::istream &s)
04690 {
04691     // read IP to unban
04692     tString address;
04693     s >> address;
04694 
04695     if ( !s.good() && address.Len() < 7 )
04696     {
04697         con << "Usage: BAN_IP <ip> <time in minutes (defaults to 60)> <reason>\n";
04698         return;
04699     }
04700 
04701     REAL duration = 60;
04702     s >> duration;
04703 
04704     // read reason
04705     tString reason;
04706     std::ws(s);
04707     if ( s.good() )
04708     {
04709         reason.ReadLine(s);
04710     }
04711 
04712     // and ban
04713     if ( address.Len() > 4 )
04714     {
04715         sn_LookupMachine( address ).Ban( duration * 60, reason );
04716     }
04717 }
04718 
04719 static tConfItemFunc sn_banConf("BAN_IP",&sn_BanConf);
04720 
04721 // list bans
04722 static void sn_ListBanConf(std::istream &s)
04723 {
04724     nMachineMap & map = sn_GetMachineMap();
04725     for( nMachineMap::iterator iter = map.begin(); iter != map.end(); ++iter )
04726     {
04727         nMachine & machine = *(*iter).second.machine;
04728         REAL banned = machine.IsBanned();
04729         if ( banned > 0 )
04730         {
04731             con << tOutput( "$network_ban", machine.GetIP(), int(banned/60), machine.GetBanReason() );
04732         }
04733     }
04734 }
04735 
04736 static tConfItemFunc sn_listBanConf("BAN_LIST",&sn_ListBanConf);
04737 
04738 // *******************************************************************************
04739 // *
04740 // *    OnDestroy
04741 // *
04742 // *******************************************************************************
04745 // *******************************************************************************
04746 
04747 void nMachineDecorator::OnDestroy( void )
04748 {
04749 }
04750 
04751 // *******************************************************************************
04752 // *
04753 // *    nMachineDecorator
04754 // *
04755 // *******************************************************************************
04758 // *******************************************************************************
04759 
04760 nMachineDecorator::nMachineDecorator( void )
04761 {
04762 }
04763 
04764 // *******************************************************************************
04765 // *
04766 // *    ~nMachineDecorator
04767 // *
04768 // *******************************************************************************
04771 // *******************************************************************************
04772 
04773 nMachineDecorator::~nMachineDecorator( void )
04774 {
04775     Remove();
04776 }
04777 
04778 // *******************************************************************************
04779 // *
04780 // *    nMachineDecorator
04781 // *
04782 // *******************************************************************************
04786 // *******************************************************************************
04787 
04788 nMachineDecorator::nMachineDecorator( nMachine & machine )
04789 {
04790     Insert( machine.decorators_ );
04791 }
04792 

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