1 /*
2 
3 *************************************************************************
4 
5 ArmageTron -- Just another Tron Lightcycle Game in 3D.
6 Copyright (C) 2000  Manuel Moos (manuel@moosnet.de)
7 
8 **************************************************************************
9 
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2
13 of the License, or (at your option) any later version.
14 
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23 
24 ***************************************************************************
25 
26 */
27 
28 #include "tMemManager.h"
29 #include "tInitExit.h"
30 #include "nSimulatePing.h"
31 #include "nConfig.h"
32 #include "nNetwork.h"
33 #include "nServerInfo.h"
34 #include "tConsole.h"
35 #include "tDirectories.h"
36 #include "nSocket.h"
37 #include "nConfig.h"
38 #include "nKrawall.h"
39 #include "tSysTime.h"
40 #include "tRecorder.h"
41 #include "tRandom.h"
42 #include <stdlib.h>
43 #include <fstream>
44 #include "tMath.h"
45 #include <string.h>
46 
47 #ifndef WIN32
48 #include  <netinet/in.h>
49 #else
50 #include  <windows.h>
51 #endif
52 
53 #include <deque>
54 
55 // my IP address. Master server/game server hopefully tell me a correct one.
56 static tString sn_myAddress ("*.*.*.*:*");
sn_GetMyAddress()57 tString const & sn_GetMyAddress()
58 {
59     return sn_myAddress;
60 }
61 
62 //! checks wheter a given address is on the user's LAN (or on loopback).
sn_IsLANAddress(tString const & address)63 bool sn_IsLANAddress( tString const & address )
64 {
65     if ( address.StartsWith("127.") || address.StartsWith("10.") || address.StartsWith("192.168.") )
66     {
67         // easy LANs. Accept the client sent IP, we don't know our own LAN address.
68         return true;
69     }
70 
71     if( address.StartsWith( "172." ) && address[6] == '.' )
72     {
73         // more complicated LAN :)
74         int second = address.SubStr(4,2).toInt();
75         if ( 16 <= second && second < 32 )
76         {
77             return true;
78         }
79     }
80 
81     return false;
82 }
83 
84 // debug watches
85 #ifdef DEBUG
86 nMessage* sn_WatchMessage = NULL;
87 unsigned int sn_WatchMessageID = 76;
88 #endif
89 
90 #define NO_ACK
91 
92 tString sn_bigBrotherString;
93 // tString sn_greeting[5];  //made 4 = 5 (lol i broke the laws of maths. subby),  k's bug fix
94 
95 
96 #ifdef TOP_SOURCE_DIR
97 #include "nTrueVersion.h"
98 #endif
99 
100 #ifndef TRUE_ARMAGETRONAD_VERSION
101 #define TRUE_ARMAGETRONAD_VERSION VERSION
102 #endif
103 
104 tString sn_programVersion (TRUE_ARMAGETRONAD_VERSION)    ;
105 
106 tString sn_serverName("Unnamed Server");
107 
108 const unsigned int sn_defaultPort = 4534;
109 unsigned int sn_serverPort = 4534;
110 bool sn_decorateTS = false;
111 
112 tString net_hostip("ANY");
113 
114 bool big_brother=true;
115 static tConfItem<bool> sn_bb("BIG_BROTHER",big_brother);
116 
117 static tConfItemLine sn_sn("SERVER_NAME", sn_serverName);
118 
119 static tConfItem<int> sn_sport("SERVER_PORT",reinterpret_cast<int&>(sn_serverPort));
120 
121 static tConfItemLine sn_sbtip("SERVER_IP", net_hostip);
122 
123 void sn_DisconnectUserNoWarn(int i, const tOutput& reason, nServerInfoBase * redirectTo = 0 );
124 
125 int sn_defaultDelay=10000;
126 
127 //! pause a bit, abort pause on network activity
sn_Delay()128 void sn_Delay()
129 {
130     sn_BasicNetworkSystem.Select( sn_defaultDelay / 1000000.0 );
131     tAdvanceFrame();
132 }
133 
134 int sn_maxRateIn=8; // maximum data rate in kb/s
135 int sn_maxRateOut=8; // maximum output data rate in kb/s
136 
137 static nConnectError sn_Error = nOK;
138 
139 //tArray<unsigned short> send_buffer[MAXCLIENTS+2];
140 //REAL planned_rate_control[MAXCLIENTS+2];
141 //REAL rate_control[MAXCLIENTS+2];
142 //unsigned short  rate[MAXCLIENTS+2];
143 
144 // from gGame.C
145 //extern unsigned short client_gamestate[MAXCLIENTS+2];
146 
147 bool deb_net=false;
148 
149 static REAL maxTimeout=1;  // the maximal timeout in seconds
150 static REAL minTimeout=.01;  // the minimal timeout in seconds
151 static REAL pingTimeout=1; // the normal timeout in multiples of the ping
152 static REAL pingVarianceTimeout=1; // the normal timeout in multiples of the ping variance
153 static REAL zeroTimeout=.01; // additional timeout of first packet
154 
sn_GetTimeout(int user)155 static REAL sn_GetTimeout( int user )
156 {
157     tASSERT( user >= 0 && user <= MAXCLIENTS+1 );
158 
159     nPingAverager & averager = sn_Connections[ user ].ping;
160 
161     REAL timeout = pingTimeout * averager.GetPing() + pingVarianceTimeout * sqrtf( averager.GetSnailAverager().GetAverageVariance() );
162 
163     if ( timeout < minTimeout )
164         timeout = minTimeout;
165     if ( timeout > maxTimeout )
166         timeout = maxTimeout;
167 
168     return timeout;
169 }
170 
171 #ifndef DEBUG
172 static REAL killTimeout=30;
173 #else
174 static REAL killTimeout=30;
175 #endif
176 
177 static const int kickOnDemandTimeout = 10;
178 
179 static bool send_again_warn=false;
180 
181 #ifdef DEBUG
182 static int simulate_loss=0;
183 #else
184 //static int simulate_loss=0;
185 #endif
186 
187 int sn_maxNoAck=100; // the maximum number of not ack messages
188 // before more are send
189 
190 //int sn_ackPending[MAXCLIENTS+2];
191 // int sn_ackAckPending[MAXCLIENTS+2];
192 
193 //static nMessage * ack_mess[MAXCLIENTS+2];
194 
195 static nNetState current_state;
196 //int sn_sockets[MAXCLIENTS+2];  // server mode:
197 // elements 1...MAXCLIENTS are the incoming connections,
198 // client mode: element 0 connects to the server.
199 // element MAXCLIENTS+1: currently logging in
200 
201 nConnectionInfo sn_Connections[MAXCLIENTS+2];
202 
203 static nAddress peers[MAXCLIENTS+2]; // the same logic for the peer adresses.
204 static int timeouts[MAXCLIENTS+2];
205 
206 #define ACKBACK 1000
207 static unsigned short lastacks[MAXCLIENTS+2][ACKBACK];
208 static unsigned short lastackPos[MAXCLIENTS+2];
209 static unsigned short highest_ack[MAXCLIENTS+2];
210 
211 
212 //********************************************************
213 // Version control
214 //********************************************************
215 
216 static int sn_MaxBackwardsCompatibility = 1000;
217 static tSettingItem<int> sn_mxc("BACKWARD_COMPATIBILITY",sn_MaxBackwardsCompatibility);
218 
219 static int sn_newFeatureDelay = 0;
220 static tSettingItem<int> sn_nfd("NEW_FEATURE_DELAY",sn_newFeatureDelay);
221 
222 // from nConfig.cpp. Adapt version string array there to bump protocol version.
223 int sn_GetCurrentProtocolVersion();
224 
225 static const int sn_currentProtocolVersion              = sn_GetCurrentProtocolVersion(); // the current version number of the network protocol
226 static const int sn_backwardCompatibleProtocolVersion 	= 0;							// the smallest version of the network protocol this program is compatible with
227 static const nVersion sn_myVersion( sn_backwardCompatibleProtocolVersion, sn_currentProtocolVersion);
228 static nVersion sn_currentVersion( sn_myVersion );
229 
sn_MyVersion()230 const nVersion& sn_MyVersion()			// the version this progam maximally supports
231 {
232     return sn_myVersion;
233 }
234 
sn_CurrentVersion()235 const nVersion& sn_CurrentVersion() 	// the version currently supported
236 {
237     return sn_currentVersion;
238 }
239 
nVersion()240 nVersion::nVersion()
241 {
242     min_=0;
243     max_=0;
244 }
245 
nVersion(int min,int max)246 nVersion::nVersion( int min, int max )
247 {
248     tASSERT( min <= max );
249     min_=min;
250     max_=max;
251 }
252 
Supported(int version) const253 bool nVersion::Supported( int version ) const	// check if a particular version is supported
254 {
255     tASSERT( min_ <= max_ );
256     return version >= min_ && version <= max_;
257 }
258 
Merge(const nVersion & a,const nVersion & b)259 bool nVersion::Merge( const nVersion& a,
260                       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
261 {
262     int min = a.min_;
263     if ( min < b.min_ )
264     {
265         min = b.min_;
266     }
267 
268     int max = a.max_;
269     if ( max > b.max_ )
270     {
271         max = b.max_;
272     }
273 
274     if ( min <= max )
275     {
276         min_ = min;
277         max_ = max;
278         return true;
279     }
280     else
281     {
282         return false;
283     }
284 }
285 
operator ==(const nVersion & other)286 bool nVersion::operator == ( const nVersion& other )
287 {
288     return this->max_ == other.max_ && this->min_ == other.min_;
289 }
290 
operator =(const nVersion & other)291 nVersion& nVersion::operator = ( const nVersion& other )
292 {
293     this->min_ = other.min_;
294     this->max_ = other.max_;
295 
296     return *this;
297 }
298 
operator >>(nMessage & m,nVersion & ver)299 nMessage& operator >> ( nMessage& m, nVersion& ver )
300 {
301     int min,max;
302     m >> min;
303     m >> max;
304 
305     ver = nVersion( min, max );
306 
307     return m;
308 }
309 
operator <<(nMessage & m,const nVersion & ver)310 nMessage& operator << ( nMessage& m, const nVersion& ver )
311 {
312     m << ver.Min();
313     m << ver.Max();
314 
315     return m;
316 }
317 
operator >>(std::istream & s,nVersion & ver)318 std::istream& operator >> ( std::istream& s, nVersion& ver )
319 {
320     int min,max;
321     s >> min;
322     s >> max;
323 
324     ver = nVersion( min, max );
325 
326     return s;
327 }
328 
operator <<(std::ostream & s,const nVersion & ver)329 std::ostream& operator << ( std::ostream& s, const nVersion& ver )
330 {
331     s << ver.Min() << " ";
332     s << ver.Max();
333 
334     return s;
335 }
336 
nVersionFeature(int min,int max)337 nVersionFeature::nVersionFeature( int min, int max ) // creates a feature that is supported from version min to max; values of -1 indicate no border
338 {
339     tASSERT( min_ >= sn_MyVersion().Min() );
340     tASSERT( max < 0 || max <= sn_MyVersion().Max() );
341 
342     min_ = min;
343     max_ = max;
344 }
345 
Supported() const346 bool nVersionFeature::Supported() const
347 {
348     return ( min_ < 0 || sn_CurrentVersion().Max() >= min_ ) &&  ( max_ < 0 || sn_CurrentVersion().Min() <= max_ );
349 }
350 
Supported(int client) const351 bool nVersionFeature::Supported( int client ) const
352 {
353     if ( client < 0 || client > MAXCLIENTS )
354         return false;
355 
356     // the version to check the feature for
357     const nVersion * version = &sn_CurrentVersion();
358 
359     if ( sn_GetNetState() == nCLIENT )
360     {
361         // clientside code: override the currently active version with the server version ( if that has been sent )
362         if ( sn_Connections[0].version.Max() > 0 )
363             version = &sn_Connections[0].version;
364     }
365     else
366     {
367         // serverside code: override version to use with the client's version
368         version = &sn_Connections[ client ].version;
369     }
370 
371     // see if the feature is supported
372     return ( min_ < 0 || version->Max() >= min_ ) &&  ( max_ < 0 || version->Min() <= max_ );
373 }
374 
handle_version_control(nMessage & m)375 void handle_version_control( nMessage& m )
376 {
377     if ( sn_GetNetState() == nCLIENT )
378     {
379         m >> sn_currentVersion;
380 
381         // inform configuration of changes
382         nConfItemVersionWatcher::OnVersionChange( sn_currentVersion );
383     }
384 }
385 
386 nDescriptor versionControl(10, handle_version_control,"version" );
387 
sn_UpdateCurrentVersion()388 void sn_UpdateCurrentVersion()
389 {
390     // update the current version from the native version and the versions of all attached clients
391 
392     // allow maximally sn_MaxBackwardsCompatibility old versions to connect
393     int min = sn_myVersion.Max() - sn_MaxBackwardsCompatibility;
394     if ( min < sn_myVersion.Min() )
395         min = sn_myVersion.Min();
396 
397     // disable features that are too new
398     int max = sn_myVersion.Max() - sn_newFeatureDelay;
399     if ( max < min )
400         max = min;
401 
402     nVersion version( min, max );
403 
404     // ask configuration if version is OK
405     nConfItemVersionWatcher::AdaptVersion( version );
406 
407     nVersion maxVersion = version;
408 
409     if ( sn_GetNetState() == nCLIENT )
410     {
411         sn_currentVersion = version;
412         return;
413     }
414 
415     for ( int i = MAXCLIENTS; i>0; --i )
416     {
417         const nConnectionInfo& info = sn_Connections[i];
418         if ( info.socket )
419         {
420             if ( ! version.Merge( version, info.version ) )
421             {
422                 // kick user; it has gotten incompatible.
423                 static bool recurse = true;
424                 if ( recurse )
425                 {
426                     recurse = false;
427                     sn_DisconnectUser( i, "$network_kill_incompatible" );
428                     recurse = true;
429                 }
430 
431                 version = maxVersion;
432             }
433         }
434     }
435 
436     // inform configuration of changes
437     nConfItemVersionWatcher::OnVersionChange( version );
438 
439     if ( version != sn_currentVersion )
440     {
441         sn_currentVersion = version;
442 
443         nMessage* m = tNEW( nMessage )( versionControl );
444         (*m) << version;
445 
446         m->BroadCast();
447     }
448 }
449 
450 //********************************************************
451 
sn_GetLastError()452 nConnectError sn_GetLastError()
453 {
454     nConnectError ret = sn_Error;
455     sn_Error = nOK;
456     return ret;
457 }
458 
459 
460 
461 // REAL sn_ping[MAXCLIENTS+2];
462 
reset_last_acks(int i)463 static void reset_last_acks(int i){
464     for(int j=ACKBACK-1;j>=0;j--)
465         lastacks[i][j]=0;
466     lastackPos[i]=0;
467     highest_ack[i]=0;
468 }
469 
470 
471 //#ifndef DEBUG
472 int sn_maxClients=MAXCLIENTS;
473 
restrictMaxClients(int const & newValue)474 bool restrictMaxClients( int const &newValue )
475 {
476     if (newValue > MAXCLIENTS)
477     {
478         tOutput o;
479         o.SetTemplateParameter(1, MAXCLIENTS);
480         o << "$max_clients_limit";
481         con << o << '\n';
482         return false;
483     }
484     return true;
485 }
486 
487 static tSettingItem< int > sn_maxClientsConf( "MAX_CLIENTS", sn_maxClients, &restrictMaxClients );
488 
489 int sn_allowSameIPCountSoft=4;
490 static tSettingItem< int > sn_allowSameIPCountSoftConf( "MAX_CLIENTS_SAME_IP_SOFT", sn_allowSameIPCountSoft );
491 
492 int sn_allowSameIPCountHard=8;
493 static tSettingItem< int > sn_allowSameIPCountHardConf( "MAX_CLIENTS_SAME_IP_HARD", sn_allowSameIPCountHard );
494 
495 //#else
496 //int maxclients=1;
497 //#endif
498 
499 int sn_myNetID=0; // our network identification:  0: server
500 //                                            1..MAXCLIENTS: client
501 
502 #define IDS_RESERVED 16		 // number of message IDs reserved for special purposes: id 0 is reserved for no-ack messages.
503 unsigned short current_id=1; // current running network number
504 
505 
506 // the classes that are responsible for the queuing of network send tEvents:
507 class planned_send:public tHeapElement{
508 protected:
509     int peer;
510 public:
511     planned_send(REAL priority,int peer);
512     ~planned_send();
513 
514     virtual tHeapBase *Heap() const; // in wich heap are we?
515 
516     // change our priority:
517     void add_to_priority(REAL diff);
518 
519     // what is to be done if the sceduled tEvent is executed?
520     virtual void execute()=0;
521 };
522 
523 class nMessage_planned_send:public planned_send{
524     tCONTROLLED_PTR(nMessage) m;
525     bool ack;
526 
527 public:
528     nMessage_planned_send(nMessage *m,REAL priority,bool ack,int peer);
529     ~nMessage_planned_send();
530 
531     virtual void execute();
532 };
533 
534 // *************************************************************
535 
536 unsigned short nDescriptor::s_nextID(1);
537 
538 #define MAXDESCRIPTORS 400
539 static nDescriptor* descriptors[MAXDESCRIPTORS];
540 
541 static nDescriptor* nDescriptor_anchor;
542 
nDescriptor(unsigned short identification,nHandler * handle,const char * Name,bool awl)543 nDescriptor::nDescriptor(unsigned short identification,
544                          nHandler *handle,const char *Name, bool awl)
545         :tListItem<nDescriptor>(nDescriptor_anchor),
546         id(identification),handler(handle),name(Name), acceptWithoutLogin(awl)
547 {
548 #ifdef DEBUG
549 #ifndef WIN32
550     //  con << "Descriptor " << id << ": " << name << '\n';
551 #endif
552 #endif
553     if (MAXDESCRIPTORS<=id || descriptors[id]!=NULL){
554         con << "Descriptor " << id << " already used!\n";
555         exit(-1);
556     }
557     s_nextID=id+1;
558     descriptors[id]=this;
559 }
560 
561 /*
562 nDescriptor::nDescriptor(nHandler *handle,const char *Name)
563   :id(s_nextID++),handler(handle),name(Name)
564 {
565 #ifdef DEBUG
566   con << "Descriptor " << id << ": " << name << '\n';
567 #endif
568 
569   if (descriptors.Len()>id && descriptors[id]!=NULL){
570     con << "Descriptor " << id << " already used!\n";
571     exit(-1);
572   }
573   descriptors[id]=this;
574 }
575 */
576 
577 int nCurrentSenderID::currentSenderID_ = 0;
578 
HandleMessage(nMessage & message)579 void nDescriptor::HandleMessage(nMessage &message){
580     static tArray<bool> warned;
581 
582     // store sender ID for console
583     nCurrentSenderID currentSender( message.SenderID() );
584 
585 #ifdef DEBUG_X
586     if (message.descriptor>1)
587         con << "RMT " << message.descriptor << "\n";
588 #endif
589 
590 #ifndef NOEXCEPT
591     try{
592 #endif
593         nDescriptor *nd = 0;
594 
595         // z-man: security check ( thanks, Luigi Auriemma! )
596         if ( message.descriptor  < MAXDESCRIPTORS )
597             nd=descriptors[message.descriptor];
598 
599         if (nd){
600             if ((message.SenderID() <= MAXCLIENTS) || nd->acceptWithoutLogin)
601                 nd->handler(message);
602         }
603         else
604             if (!warned[message.Descriptor()]){
605                 tOutput warn;
606                 warn.SetTemplateParameter(1, message.Descriptor());
607                 warn << "$network_warn_unknowndescriptor";
608                 con << warn;
609                 warned[message.Descriptor()]=true;
610             }
611 #ifndef NOEXCEPT
612     }
613     catch(nIgnore const &){
614         // well, do nothing.
615     }
616     catch(nKillHim const &){
617         // st_Breakpoint();
618         con << tOutput("$network_error");
619         sn_DisconnectUser(message.SenderID(), "$network_kill_error" );
620     }
621 
622 #endif
623 }
624 
625 // *************************************************************
626 
627 
ack_handler(nMessage & m)628 void ack_handler(nMessage &m){
629     while (!m.End()){
630         sn_Connections[m.SenderID()].AckReceived();
631 
632         unsigned short ack;
633         m.Read(ack);
634         //con << "Got ack:" << ack << ":" << m.SenderID() << '\n';
635         nWaitForAck::Ackt(ack,m.SenderID());
636     }
637 }
638 
639 static nDescriptor s_Acknowledge(1,ack_handler,"ack");
640 
641 
642 class nWaitForAck;
643 static tList<nWaitForAck> sn_pendingAcks;
644 
645 //static eTimer netTimer;
646 static nTimeRolling netTime;
647 
648 #ifdef NET_DEBUG
649 static int acks=0;
650 static int max_acks=0;
651 #endif
652 
nWaitForAck(nMessage * m,int rec)653 nWaitForAck::nWaitForAck(nMessage* m,int rec)
654         :id(-1),message(m),receiver(rec)
655 {
656 #ifdef DEBUG
657     // don't message yourself
658     if ( rec == 0 && sn_GetNetState() == nSERVER )
659         st_Breakpoint();
660 #endif
661 
662     if (!message)
663         tERR_ERROR("Null ack!");
664 
665     if (message->Descriptor()!=s_Acknowledge.ID())
666         sn_Connections[receiver].ackPending++;
667     else
668         tERR_ERROR("Should not wait for ack of an ack message itself.");
669 
670     //    sn_ackAckPending[receiver]++;
671 #ifdef NET_DEBUG
672     acks++;
673 #endif
674 
675     timeFirstSent=::netTime;
676     timeLastSent=::netTime;
677 
678     timeouts=0;
679 
680     timeout=sn_GetTimeout( rec );
681 
682 #ifdef nSIMULATE_PING
683    timeSendAgain=::netTime + nSIMULATE_PING;
684 #ifndef WIN32
685     tRandomizer & randomizer = tReproducibleRandomizer::GetInstance();
686     timeSendAgain+= randomizer.Get() * nSIMULATE_PING_VARIANT;
687     // timeSendAgain+=(nSIMULATE_PING_VARIANT*random())/RAND_MAX;
688 #endif
689 #else
690     const REAL packetLossScale = .003; // packet loss rate that is considered big
691     const REAL maxTimeoutFactor = 1.2; // maximal stretching of initial timeout value for flawless connections
692     // factor mutliplied to timeout; 1 if the connection loses a lot of packets, 1.2 for a
693     // flawless connection
694     REAL timeoutFactor = 1 + (maxTimeoutFactor-1)*packetLossScale/(sn_Connections[receiver].PacketLoss() + packetLossScale);
695     timeSendAgain=::netTime + timeout*timeoutFactor + zeroTimeout;
696 #endif
697     sn_pendingAcks.Add(this,id);
698 }
699 
~nWaitForAck()700 nWaitForAck::~nWaitForAck(){
701 #ifdef NET_DEBUG
702     acks--;
703     if (acks>max_acks){
704         max_acks=acks;
705         // con << "MA=" << max_acks << '\n';
706     }
707 #endif
708 
709     if (bool(message) && message->Descriptor()!=s_Acknowledge.ID())
710     {
711         sn_Connections[receiver].ackPending--;
712         sn_Connections[receiver].ReliableMessageSent();
713     }
714     else
715     {
716         tERR_ERROR( "No message." );
717     }
718     //    sn_ackAckPending[receiver]--;
719 
720     sn_pendingAcks.Remove(this,id);
721     tCHECK_DEST;
722 }
723 
Ackt(unsigned short id,unsigned short peer)724 void nWaitForAck::Ackt(unsigned short id,unsigned short peer){
725 #ifdef DEBUG_X
726     int success=0;
727 #endif
728     for(int i=sn_pendingAcks.Len()-1;i>=0;i--){
729         nWaitForAck * ack = sn_pendingAcks(i);
730         if (ack->message->MessageID()==id &&
731                 ack->receiver==peer){
732 #ifdef DEBUG
733             //      if (sn_pendingAcks(i)->message == sn_WatchMessage)
734             //	st_Breakpoint();
735 #endif
736 
737 #ifdef DEBUG_X
738             success=1;
739 
740             if (ack->message->descriptor>1)
741                 con << "AT  " << ack->message->descriptor << '\n';
742 #endif
743 
744             // calculate and average ping
745             REAL thisping=netTime - ack->timeFirstSent;
746             sn_Connections[peer].ping.Add( thisping, 1/(1 + 10 * REAL(ack->timeouts * ack->timeouts * ack->timeouts ) ) );
747 
748             ack->AckExtraAction();
749             delete ack;
750             ::timeouts[peer]=0;
751             if (i<sn_pendingAcks.Len()-1) i++;
752         }
753     }
754 
755 #ifdef DEBUG_X
756     if (!success && peer!=MAXCLIENTS+1)
757     {
758         con << "Ack " << id << ':' << peer << " was not asked for.\n";
759         if (sn_pendingAcks.Len()) con << "Expected:\n";
760         for(int i=sn_pendingAcks.Len()-1;i>=0;i--){
761             con << i << "\t:"
762             << sn_pendingAcks[i]->message->messageIDBig_ << ":"
763             << sn_pendingAcks[i]->receiver << '\n';
764         }
765     }
766 #endif
767 }
768 
AckAllPeer(unsigned short peer)769 void nWaitForAck::AckAllPeer(unsigned short peer){
770     for(int i=sn_pendingAcks.Len()-1;i>=0;i--){
771         if (sn_pendingAcks(i)->receiver==peer){
772             delete sn_pendingAcks(i);
773             if (i<sn_pendingAcks.Len()-1) i++;
774         }
775     }
776 }
777 
Resend()778 void nWaitForAck::Resend(){
779     static tReproducibleRandomizer randomizer;
780 
781     for(int i=sn_pendingAcks.Len()-1;i>=0;i--){
782         nWaitForAck* pendingAck = sn_pendingAcks(i);
783 
784         nConnectionInfo & connection = sn_Connections[pendingAck->receiver];
785 
786         // don't resend if you can't.
787         if ( !connection.bandwidthControl_.CanSend() )
788             continue;
789 
790         REAL packetLoss = connection.PacketLoss();
791         REAL timeout = pendingAck->timeout;
792 
793         // should we resend the packet? Certainly it if it is overdue
794         bool resend = (pendingAck->timeSendAgain + timeout * .1 <=netTime);
795 
796         // or if there is already a message waiting...
797         if ( !resend && connection.sendBuffer_.Len() > 0 )
798         {
799             // and we are on time
800             if ( pendingAck->timeSendAgain <= netTime )
801                 resend = true;
802             // or the packet loss is so high that it is advisable to resend every message
803             // multiple times if bandwidth is available ( we aim for 99% reliability )
804             else if ( pendingAck->timeouts < 3 && pow( packetLoss, pendingAck->timeouts + 1 ) > .01 &&
805                       connection.bandwidthControl_.Control( nBandwidthControl::Usage_Planning ) >100 )
806                 resend = true;
807 
808             /* + sn_GetTimeout( pendingAck->receiver ) *
809                                 ( 3.0 / ( pendingAck->timeouts + 1 ) )
810                                 ( packetLoss * ( randomizer.Get() + .5 ) ) )
811             */
812         }
813 
814         if ( resend ){
815             //con << net_ticks-sn_pendingAcks[i]->ticks_first_sent << '\n';
816 
817             // update timeout counters
818             ::timeouts[pendingAck->receiver]++;
819             pendingAck->timeouts++;
820 
821             if(netTime - pendingAck->timeFirstSent  >  killTimeout &&
822                     ::timeouts[pendingAck->receiver] > 20){
823                 // total timeout. Kill connection.
824                 if (pendingAck->receiver<=MAXCLIENTS){
825                     tOutput o;
826                     o.SetTemplateParameter(1, pendingAck->receiver);
827                     o << "$network_error_timeout";
828                     con << o;
829                     sn_DisconnectUser(pendingAck->receiver, "$network_kill_timeout" );
830 
831                     sn_Error = nTIMEOUT;
832 
833                     if (i>=sn_pendingAcks.Len())
834                         i=sn_pendingAcks.Len()-1;
835                 }
836                 else // it is just in the login slot. Ignore it.
837                     delete pendingAck;
838             }
839             else{
840 #ifdef DEBUG
841                 //if (pendingAck->message == sn_WatchMessage)
842                 //st_Breakpoint();
843 #endif
844 
845                 if (connection.socket){
846                     //	  if(sn_Connections[].rateControlPlanned[pendingAck->receiver]>-1000)
847                     {
848                         REAL timeoutFactor = .9 + .1 * pendingAck->timeouts + randomizer.Get() * .1;
849                         pendingAck->timeSendAgain=netTime+timeout * timeoutFactor;
850                         pendingAck->timeLastSent=netTime;
851 
852                         if (send_again_warn){
853                             con << "sending packet again: " ;
854                             deb_net=true;
855                         }
856                         connection.ReliableMessageSent();
857                         pendingAck->message->SendImmediately
858                         (pendingAck->receiver,false);
859                         deb_net=false;
860                     }
861                 }
862                 else
863                     delete pendingAck;
864             }
865         }
866     }
867 }
868 
869 
870 // defined in netobjec.C
871 // void ClearKnows(int user);
872 
873 
874 #ifdef NET_DEBUG
875 static int nMessages=0;
876 static int max_nMessages=0;
877 #endif
878 
879 #ifdef DEBUG
BreakOnMessageID(unsigned int messageID)880 void BreakOnMessageID( unsigned int messageID )
881 {
882     if (messageID == sn_WatchMessageID && messageID != 0 )
883     {
884         int x;
885         x = 0;
886     }
887 }
888 #endif
889 
890 class nMessageIDExpander
891 {
892     unsigned long quarters[4];
893 public:
nMessageIDExpander()894     nMessageIDExpander()
895     {
896         for (int i=3; i>=0; --i)
897             quarters[i]=i << 14;
898     }
899 
ExpandMessageID(unsigned short id)900     unsigned long ExpandMessageID( unsigned short id )
901     {
902         // the current ID is in this quarter
903         int thisQuarter = ( id >> 14 ) & 3;
904 
905         // the following quarter will be this
906         int nextQuarter = ( thisQuarter + 1 ) & 3;
907 
908         // make sure the following quarter has a higher upper ID completion than this
909         quarters[nextQuarter] = quarters[thisQuarter] + ( 1 << 14 );
910 
911         // replace high two bits of incoming ID with the counted up ID
912         return quarters[thisQuarter] | id;
913     }
914 };
915 
916 //! expands a short message ID to a full int message ID, assuming it is from a message that was
917 // just received.
sn_ExpandMessageID(unsigned short id,unsigned short sender)918 static unsigned long int sn_ExpandMessageID( unsigned short id, unsigned short sender )
919 {
920 #ifdef DEBUG
921     BreakOnMessageID( id );
922 #endif
923 
924     static nMessageIDExpander expanders[MAXCLIENTS+2];
925 
926     tASSERT( sender <= MAXCLIENTS+2 )
927     return expanders[sender].ExpandMessageID(id);
928 }
929 
nMessage(unsigned short * & buffer,short sender,int lenLeft)930 nMessage::nMessage(unsigned short*& buffer,short sender, int lenLeft )
931         :descriptor(ntohs(*(buffer++))),messageIDBig_(sn_ExpandMessageID(ntohs(*(buffer++)),sender)),
932 senderID(sender),readOut(0){
933 #ifdef NET_DEBUG
934     nMessages++;
935 #endif
936 
937     tRecorderSync< unsigned long >::Archive( "_MESSAGE_ID_IN", 3, messageIDBig_ );
938     tRecorderSync< unsigned short >::Archive( "_MESSAGE_DECL_IN", 3, descriptor );
939 
940     unsigned short len=ntohs(*(buffer++));
941     lenLeft-=3;
942     if ( len > lenLeft )
943     {
944         len = lenLeft;
945 #ifndef NOEXCEPT
946         throw nKillHim();
947 #endif
948     }
949     for(int i=0;i<len;i++)
950         data[i]=ntohs(*(buffer++));
951 
952 #ifdef DEBUG
953     BreakOnMessageID( messageIDBig_ );
954 #endif
955 }
956 
nMessage(const nDescriptor & d)957 nMessage::nMessage(const nDescriptor &d)
958         :descriptor(d.id),
959 senderID(::sn_myNetID), readOut(0){
960 #ifdef NET_DEBUG
961     nMessages++;
962 #endif
963 
964     current_id++;
965     if (current_id <= IDS_RESERVED)
966         current_id = IDS_RESERVED + 1;
967 
968     messageIDBig_ = current_id;
969 
970 #ifdef DEBUG_X
971     con << "Message " << d.id << " " << current_id << "\n";
972 #endif
973 
974 #ifdef DEBUG
975     BreakOnMessageID( messageIDBig_ );
976 #endif
977 
978     tRecorderSync< unsigned long >::Archive( "_MESSAGE_ID_OUT", 3, messageIDBig_ );
979     tRecorderSync< unsigned short >::Archive( "_MESSAGE_DECL_OUT", 3, descriptor );
980 }
981 
982 
~nMessage()983 nMessage::~nMessage(){
984 #ifdef NET_DEBUG
985     nMessages--;
986     if (nMessages>max_nMessages){
987         max_nMessages=nMessages;
988         con << "MN=" << max_nMessages <<'\n';
989     }
990 #endif
991 
992 #ifdef DEBUG_X
993     if (descriptor>1)
994         con << "DMT " << descriptor << "\n";
995 #endif
996 
997     tCHECK_DEST;
998 }
999 
1000 
1001 
1002 
BroadCast(bool ack)1003 void nMessage::BroadCast(bool ack){
1004     tControlledPTR< nMessage > keep( this );
1005     if (sn_GetNetState()==nCLIENT)
1006         Send(0,ack);
1007 
1008     if (sn_GetNetState()==nSERVER){
1009         for(int i=MAXCLIENTS;i>0;i--){
1010             if (sn_Connections[i].socket)
1011                 Send(i,0,ack);
1012         }
1013     }
1014 }
1015 
1016 
1017 static nVersionFeature sn_ZeroMessageCrashfix( 1 );
1018 
operator <<(const tString & s)1019 nMessage& nMessage::operator << (const tString &s){
1020     unsigned short len=s.Len();
1021 
1022     // clamp away excess zeroes
1023     while(len > 1 && s(len-2)==0)
1024     {
1025         --len;
1026     }
1027 
1028     // check whether all clients support zero length strings
1029     if ( !sn_ZeroMessageCrashfix.Supported() )
1030     {
1031         if ( len <= 0 )
1032         {
1033             static tString replacement("");
1034             return this->operator<<( replacement );
1035         }
1036     }
1037     else if ( len == 1 && s(0) == 0 )
1038     {
1039         // do away with the the trailing zero in zero length strings.
1040         len = 0;
1041     }
1042 
1043     Write(len);
1044     int i;
1045 
1046     // write first pairs of bytes
1047     for(i=0;i+1<len;i+=2)
1048     {
1049         // yep. Signed arithmetic. That gives
1050         // nice overflows. By the time we noticed,
1051         // it was too late to change :)
1052         signed char lo = s[i];
1053         signed char hi = s[i+1];
1054 
1055         // combine the two into a single short
1056         Write( short(lo) + (short(hi) << 8) );
1057     }
1058 
1059     // write last byte
1060     if (i<len)
1061         Write( static_cast< signed char >( s[i] ) );
1062 
1063     return *this;
1064 }
1065 
operator <<(const tColoredString & s)1066 nMessage& nMessage::operator << (const tColoredString &s){
1067     return *this << static_cast< const tString & >( s );
1068 }
1069 
operator <<(const tOutput & o)1070 nMessage& nMessage::operator << ( const tOutput &o ){
1071     return *this << tString( static_cast< const char * >( o ) );
1072 }
1073 
ReadRaw(tString & s)1074 nMessage& nMessage::ReadRaw(tString &s )
1075 {
1076     s.Clear();
1077     unsigned short w,len;
1078     Read(len);
1079     if ( len > 0 )
1080     {
1081         s[len-1] = 0;
1082         for(int i=0;i<len;i+=2){
1083             Read(w);
1084 
1085             // carefully reverse the signed
1086             // encoding logic
1087             signed char lo = w & 0xff;
1088             signed short hi = ((short)w) - lo;
1089             hi >>= 8;
1090 
1091             s[i] = lo;
1092             if (i+1<len)
1093                 s[i+1] = hi;
1094         }
1095     }
1096 
1097     return *this;
1098 }
1099 
1100 bool sn_filterColorStrings = false;
1101 static tConfItem<bool> sn_filterColorStringsConf("FILTER_COLOR_STRINGS",sn_filterColorStrings);
1102 bool sn_filterDarkColorStrings = false;
1103 static tConfItem<bool> sn_filterDarkColorStringsConf("FILTER_DARK_COLOR_STRINGS",sn_filterDarkColorStrings);
1104 
operator >>(tColoredString & s)1105 nMessage& nMessage::operator >> (tColoredString &s )
1106 {
1107     // read the raw data
1108     ReadRaw( s );
1109 
1110     // filter client string messages
1111     if ( sn_GetNetState() == nSERVER )
1112     {
1113         s.NetFilter();
1114         s.RemoveTrailingColor();
1115     }
1116 
1117     // filter color codes away
1118     if ( sn_filterColorStrings )
1119         s = tColoredString::RemoveColors( s, false );
1120     else if ( sn_filterDarkColorStrings )
1121         s = tColoredString::RemoveColors( s, true );
1122 
1123     return *this;
1124 }
1125 
operator >>(tString & s)1126 nMessage& nMessage::operator >> (tString &s )
1127 {
1128     tColoredString safe;
1129     operator>>( safe );
1130     s = safe;
1131 
1132     return *this;
1133 }
1134 
1135 
1136 #define MANT 26
1137 #define EXP (32-MANT)
1138 #define MS (MANT-1)
1139 
1140 
1141 typedef struct{
1142 int mant:MANT;
1143 unsigned int exp:EXP;
1144 } myfloat;
1145 
1146 
operator <<(const REAL & x)1147 nMessage& nMessage::operator<<(const REAL &x){
1148 
1149 
1150 #ifdef DEBUG
1151     // con << "write x= " << x;
1152 
1153 
1154     if(sizeof(myfloat)!=sizeof(int))
1155         tERR_ERROR_INT("floating ePoint format does not work!");
1156 #endif
1157     /*
1158       REAL nachkomma=x-floor(x);
1159       Write(short(x-nachkomma));
1160       Write(60000*nachkomma);
1161     */
1162     // no fuss. Read and write floats in binary format.
1163     // will likely cause problems for systems other than i386.
1164 
1165     //Write(((short *)&x)[0]);
1166     //Write(((short *)&x)[1]);
1167 
1168     // right. Caused severe problems with the AIX port.
1169 
1170     // new way: own floating ePoint format that is not good with small numbers
1171     // (we do not need them anyway)
1172     REAL y=x;
1173 
1174     unsigned int negative=0;
1175     if (y<0){
1176         y=-y;
1177         negative=1;
1178     }
1179 
1180     unsigned int exp=0;
1181     while ( fabs(y)>=64 && exp < (1<<EXP)-6 )
1182     {
1183         exp +=6;
1184         y/=64;
1185     }
1186     while ( fabs(y)>=1 && exp < (1<<EXP)-1 )
1187     {
1188         exp++;
1189         y/=2;
1190     }
1191     // now x=y*2^exp
1192     unsigned int mant=int(y*(1<<MS));
1193     // now x=mant*2^exp * (1/ (1<<MANT))
1194 
1195     // cutoffs:
1196     if (mant>((1<<MS))-1)
1197         mant=(1<<MS)-1;
1198 
1199     if (exp>(1<<EXP)-1){
1200         exp=(1<<EXP)-1;
1201         if (mant>0)
1202             mant=(1<<MS)-1;
1203     }
1204 
1205     // put them together:
1206 
1207     unsigned int trans=(mant & ((1<<MS)-1)) | (negative << MS) | (exp << MANT);
1208     /*
1209       myfloat trans;
1210       trans.exp=exp;
1211       trans.mant=mant;
1212     */
1213 
1214     operator<<(reinterpret_cast<int &>(trans));
1215 
1216 #ifdef DEBUG
1217     /*
1218       con << "mant: " << mant
1219       << ", exp: " << exp
1220       << ", negative: " << negative;
1221     */
1222 
1223     unsigned int mant2=trans & ((1 << MS)-1);
1224     unsigned int negative2=(trans >> MS) & 1;
1225     unsigned int nt=trans-mant-(negative << MS);
1226     unsigned int exp2=nt >> MANT;
1227 
1228     if (mant2!=mant || negative2!=negative || exp2!=exp)
1229         tERR_ERROR_INT("Floating ePoint tranfer failure!");
1230 
1231     /*
1232       con << ", x: " << x;
1233 
1234       con << ", mant: " << mant
1235       << ", exp: " << exp
1236       << ", negative: " << negative;
1237     */
1238 
1239     // check:
1240 
1241     REAL z=REAL(mant)/(1<<MS);
1242     if (negative)
1243         z=-z;
1244 
1245     while (exp>=6){
1246         exp-=6;
1247         z*=64;
1248     }
1249     while (exp>0){
1250         exp--;
1251         z*=2;
1252     }
1253 
1254     if (fabs(z-x)>(fabs(x)+1)*.001)
1255         tERR_ERROR_INT("Floating ePoint tranfer failure!");
1256 
1257     //con << ", z: " << z << '\n';
1258 #endif
1259 
1260     return *this;
1261 }
1262 
operator >>(REAL & x)1263 nMessage& nMessage::operator>>(REAL &x){
1264     /*
1265       short vorkomma;
1266       unsigned short nachkomma;
1267       Read((unsigned short &)vorkomma);
1268       Read(nachkomma);
1269       x=vorkomma+nachkomma/60000.0;
1270 
1271       Read(((unsigned short *)&x)[0]);
1272       Read(((unsigned short *)&x)[1]);
1273      */
1274 
1275     unsigned int trans;
1276     operator>>(reinterpret_cast<int &>(trans));
1277 
1278     int mant=trans & ((1 << MS)-1);
1279     unsigned int negative=(trans >> MS) & 1;
1280     unsigned int exp=(trans-mant-(negative << MS)) >> MANT;
1281 
1282     x=REAL(mant)/(1<<MS);
1283     if (negative)
1284         x=-x;
1285 
1286 #ifdef DEBUG
1287     //  con << "read mant: " <<mant << ", exp: " << exp;
1288 #endif
1289 
1290     while (exp>=6){
1291         exp-=6;
1292         x*=64;
1293     }
1294     while (exp>0){
1295         exp--;
1296         x*=2;
1297     }
1298 
1299 #ifdef DEBUG
1300 #ifndef WIN32
1301     if (!finite(x))
1302         st_Breakpoint();
1303     // con << " , x= " << x << '\n';
1304 #endif
1305 #endif
1306     return *this;
1307 }
1308 
operator <<(const short & x)1309 nMessage& nMessage::operator<< (const short &x){
1310     Write((reinterpret_cast<const short *>(&x))[0]);
1311 
1312     return *this;
1313 }
1314 
operator >>(short & x)1315 nMessage& nMessage::operator>> (short &x){
1316     Read(reinterpret_cast<unsigned short *>(&x)[0]);
1317 
1318     return *this;
1319 }
1320 
operator <<(const int & x)1321 nMessage& nMessage::operator<< (const int &x){
1322     unsigned short a=x & (0xFFFF);
1323     short b=(x-a) >> 16;
1324 
1325     Write(a);
1326     operator<<(b);
1327 
1328     return *this;
1329 }
1330 
operator >>(int & x)1331 nMessage& nMessage::operator>> (int &x){
1332     unsigned short a;
1333     short b;
1334 
1335     Read(a);
1336     operator>>(b);
1337 
1338     x=(b << 16)+a;
1339 
1340     return *this;
1341 }
1342 
operator <<(const bool & x)1343 nMessage& nMessage::operator<< (const bool &x){
1344     if (x)
1345         Write(1);
1346     else
1347         Write(0);
1348 
1349     return *this;
1350 }
1351 
operator >>(bool & x)1352 nMessage& nMessage::operator>> (bool &x){
1353     unsigned short y;
1354     Read(y);
1355     x= (y!=0);
1356 
1357     return *this;
1358 }
1359 
1360 
Read(unsigned short & x)1361 void nMessage::Read(unsigned short &x){
1362     if (End()){
1363         tOutput o;
1364         st_Breakpoint();
1365         o.SetTemplateParameter(1, senderID);
1366         o << "$network_error_shortmessage";
1367         con << o;
1368         // sn_DisconnectUser(senderID, "$network_kill_error");
1369         nReadError( false );
1370     }
1371     else
1372         x=data(readOut++);
1373 }
1374 
1375 
1376 // **********************************************
1377 //  Basic communication classes: login
1378 // **********************************************
1379 
1380 static bool login_failed=false;
1381 static bool login_succeeded=false;
1382 
1383 // salt value sent as past login tokens. They are returned by
1384 // the server as you sent them, and make sure you only accept
1385 // the right answer.
1386 static nKrawall::nSalt loginSalt;
1387 
1388 static nHandler *real_req_info_handler=NULL;
1389 
req_info_handler(nMessage & m)1390 void req_info_handler(nMessage &m){
1391     if (real_req_info_handler)
1392         (*real_req_info_handler)(m);
1393     if (m.SenderID()==MAXCLIENTS+1)
1394         sn_DisconnectUser(MAXCLIENTS+1, "$network_kill_logout");
1395 }
1396 
1397 static nDescriptor req_info(2,req_info_handler,"req_info");
1398 
RequestInfoHandler(nHandler * handle)1399 void RequestInfoHandler(nHandler *handle){
1400     real_req_info_handler=handle;
1401 }
1402 
1403 // the server we are redirected to
1404 static std::auto_ptr< nServerInfoBase > sn_redirectTo;
sn_GetRedirectTo()1405 std::auto_ptr< nServerInfoBase > sn_GetRedirectTo()
1406 {
1407     return sn_redirectTo;
1408 }
1409 
sn_PeekRedirectTo()1410 nServerInfoBase * sn_PeekRedirectTo()
1411 {
1412     return sn_redirectTo.get();
1413 }
1414 
login_deny_handler(nMessage & m)1415 void login_deny_handler(nMessage &m){
1416     // only the server is allowed to send this
1417     if(m.SenderID() != 0)
1418         return;
1419 
1420     if ( !m.End() )
1421     {
1422         //		tOutput output;
1423         //		m >> output;
1424         //		sn_DenyReason = output;
1425         m >> sn_DenyReason;
1426     }
1427     else
1428     {
1429         sn_DenyReason = tOutput( "$network_kill_unknown" );
1430     }
1431 
1432     if ( !m.End() )
1433     {
1434         // read redirection data from message
1435         tString connectionName;
1436         m >> connectionName;
1437         int port;
1438         m >> port;
1439 
1440         if ( connectionName.Len() > 1 )
1441         {
1442             // create server info and fill it with data
1443             sn_redirectTo = std::auto_ptr< nServerInfoBase>( new nServerInfoRedirect( connectionName, port ) );
1444         }
1445     }
1446 
1447     if (!login_failed)
1448         con << tOutput("$network_login_denial");
1449     if (sn_GetNetState()!=nSERVER){
1450         login_failed=true;
1451         login_succeeded=false;
1452         sn_SetNetState(nSTANDALONE);
1453     }
1454 }
1455 
1456 static nDescriptor login_deny(3,login_deny_handler,"login_deny");
1457 
1458 void login_handler_1( nMessage&m );
1459 void login_handler_2( nMessage&m );
1460 void logout_handler( nMessage&m );
1461 
1462 nDescriptor login(6,login_handler_1,"login1", true);
1463 nDescriptor login_2(11,login_handler_2,"login2", true);
1464 nDescriptor logout(7,logout_handler,"logout");
1465 
1466 tString sn_DenyReason;
1467 
login_ignore_handler(nMessage & m)1468 void login_ignore_handler(nMessage &m){
1469     if (sn_GetNetState()!=nSERVER && !login_succeeded){
1470         /*
1471           login_failed=true;
1472           login_succeeded=false;
1473 
1474           // kicking the one who uses our place
1475           // (he is probably timing out anyway..)
1476           nMessage *lo=new nMessage(logout);
1477           lo->Write((unsigned short)sn_myNetID);
1478           lo->Send(0);
1479 
1480           sn_Sync(10);
1481 
1482           (new nMessage(login))->Send(0);
1483         */
1484     }
1485 
1486 
1487 }
1488 
1489 static nDescriptor login_ignore(4,login_ignore_handler,"login_ignore");
1490 
1491 
1492 void first_fill_ids();
1493 
1494 // from nServerInfo.cpp
1495 extern bool sn_AcceptingFromMaster;
1496 
login_accept_handler(nMessage & m)1497 void login_accept_handler(nMessage &m){
1498     if (sn_GetNetState()!=nSERVER && m.SenderID() == 0){
1499         unsigned short id=0;
1500         m.Read(id);
1501 
1502         // read or reset server version info
1503         if ( !m.End() )
1504         {
1505             m >> sn_Connections[0].version;
1506 
1507 //#ifdef DEBUG
1508 #define NOEXPIRE
1509 //#endif
1510 
1511 #ifndef NOEXPIRE
1512 #ifndef DEDICATED
1513             // last checked to be compatible with 0.3.1_pb from trunk.
1514             // It's ulikely this branch will introduce more bugs/network code revisions, so we're fine accepting all
1515             int lastCheckedTrunkVersion = 21;
1516 
1517             // start of trunk as seen from this branch
1518             int trunkBegin = 20;
1519 
1520             // maximal allowed version from this branch
1521             int maxVersionThisBranch = sn_currentProtocolVersion + 1;
1522 
1523             // expiration for public beta versions
1524             if ( !sn_AcceptingFromMaster &&
1525                     ( strstr( VERSION, "rc" ) || strstr( VERSION, "alpha" ) || strstr( VERSION, "beta" ) ) &&
1526                  ( sn_Connections[0].version.Max() > lastCheckedTrunkVersion ||
1527                    ( sn_Connections[0].version.Max() > maxVersionThisBranch && sn_Connections[0].version.Max() < trunkBegin )
1528                      )
1529                 )
1530             {
1531                 throw tGenericException( tOutput("$testing_version_expired"), tOutput("$testing_version_expired_title" ) );
1532             }
1533 #endif
1534 #endif
1535         }
1536         else
1537             sn_Connections[0].version = nVersion( 0, 0);
1538 
1539         // read my public IP
1540         if ( !m.End() )
1541         {
1542             // only accept it if it is not a LAN address
1543             tString address;
1544             m >> address;
1545             if ( !sn_IsLANAddress( address ) )
1546             {
1547                 if ( sn_myAddress != address )
1548                 {
1549                     con << "Got address " << address << ".\n";
1550                 }
1551                 sn_myAddress = address;
1552             }
1553 
1554             // read salt reply and compare it to what we sent
1555             nKrawall::nSalt replySalt;
1556             nKrawall::ReadScrambledPassword( m, replySalt );
1557 
1558             int compare = memcmp( &loginSalt,&replySalt, sizeof(replySalt) );
1559 
1560             // since we generate a different random salt on playback, record the comparison result
1561             static const char * section = "LOGIN_SALT";
1562             tRecorder::Playback( section, compare );
1563             tRecorder::Record( section, compare );
1564 
1565             if ( compare != 0 )
1566             {
1567                 nReadError( false );
1568             }
1569         }
1570 
1571         // only now, login can be considered a success
1572         login_succeeded=true;
1573         sn_myNetID=id;
1574 
1575         first_fill_ids();
1576     }
1577 }
1578 
1579 static nDescriptor login_accept(5,login_accept_handler,"login_accept", true);
1580 
1581 
1582 
1583 //static short new_id=0;
1584 
1585 // counts the number of logins with the same IP
CountSameIP(int user,bool reset=false)1586 int CountSameIP( int user, bool reset=false )
1587 {
1588     static int sameIP[ MAXCLIENTS+2 ];
1589     tASSERT( user >= 0 && user <= MAXCLIENTS+1 );
1590 
1591     if ( reset )
1592     {
1593         int count = 0;
1594         for(int user2=1;user2<=MAXCLIENTS;++user2)
1595         {
1596             if(!sn_Connections[user2].socket)
1597                 continue;
1598 
1599             if ( user2 != user && nAddress::Compare( peers[user], peers[user2] ) >=0 )
1600             {
1601                 count++;
1602             }
1603         }
1604 
1605         sameIP[user] = count;
1606     }
1607 
1608     return sameIP[user];
1609 }
1610 
1611 // counts the number of logins with the same Connection
CountSameConnection(int user)1612 int CountSameConnection( int user )
1613 {
1614     int count = 0;
1615     for(int user2=1;user2<=MAXCLIENTS;++user2)
1616     {
1617         if( NULL == sn_Connections[user2].socket )
1618             continue;
1619 
1620         if ( user2 != user && nAddress::Compare( peers[user], peers[user2] ) == 0 )
1621         {
1622             count++;
1623         }
1624     }
1625 
1626     return count;
1627 }
1628 
1629 // determine a free connection slot or at least one where the user won't be missed
GetFreeSlot()1630 int GetFreeSlot()
1631 {
1632     int user;
1633 
1634     // level 1: look for free slot
1635     if ( sn_NumUsers() < sn_maxClients )
1636     {
1637         for(user=1;user<=sn_maxClients;++user)
1638         {
1639             // look for empty slot
1640             if(!sn_Connections[user].socket)
1641             {
1642                 return user;
1643             }
1644         }
1645     }
1646 
1647     int best = -1;
1648 
1649     // level 2 kicked out users who were timing out and was not a good idea.
1650 
1651     int bestCount = sn_allowSameIPCountSoft-1;
1652 
1653     // level 3: look for dublicate IPs
1654     for(user=1;user<=MAXCLIENTS;++user)
1655     {
1656         int count = CountSameIP( user );
1657         if ( count > bestCount )
1658         {
1659             bestCount = count;
1660             best = user;
1661         }
1662     }
1663     if ( best > 0 )
1664         return best;
1665 
1666     return -1;
1667 }
1668 
1669 static REAL sn_minBan    = 120; // minimal ban time in seconds for trying to connect while you're banned
1670 static tSettingItem< REAL > sn_minBanSetting( "NETWORK_MIN_BAN", sn_minBan );
1671 
1672 // defined in nServerInfo.cpp
1673 extern bool FloodProtection( nMessage const & m );
1674 
1675 // flag to disable 0.2.8 test version lockout
1676 static bool sn_lockOut028tTest = true;
1677 static tSettingItem< bool > sn_lockOut028TestConf( "NETWORK_LOCK_OUT_028_TEST", sn_lockOut028tTest );
1678 
login_handler(nMessage & m,unsigned short rate)1679 int login_handler( nMessage &m, unsigned short rate ){
1680     nCurrentSenderID senderID;
1681 
1682     // read version and suppored authentication methods
1683     nVersion version;
1684     tString supportedAuthenticationMethods("");
1685     nKrawall::nSalt salt; // it's OK that this may stay uninitialized
1686     if ( !m.End() )
1687     {
1688         // read version
1689         m >> version;
1690 
1691         // ok, clients that send a version do have at lesat basic authentication.
1692         supportedAuthenticationMethods = "bmd5";
1693     }
1694     if ( !m.End() )
1695     {
1696         // read authentication methods
1697         m >> supportedAuthenticationMethods;
1698     }
1699     if ( !m.End() )
1700     {
1701         // also read a login salt, the client expects to get it returned verbatim
1702         nKrawall::ReadScrambledPassword( m, salt );
1703     }
1704 
1705     // don't accept logins in client mode
1706     if (sn_GetNetState() != nSERVER)
1707         return -1;
1708 
1709     // ban users
1710     nMachine & machine = nMachine::GetMachine( m.SenderID() );
1711     REAL banned = machine.IsBanned();
1712     if ( banned > 0 )
1713     {
1714         // the reason for the ban
1715         tString const & reason = machine.GetBanReason();
1716 
1717         // ban user some more so he learns
1718         if ( banned < sn_minBan )
1719         {
1720             machine.Ban( sn_minBan );
1721             banned = sn_minBan;
1722         }
1723         else
1724             con << tOutput( "$network_ban", machine.GetIP() , int(banned/60), reason.Len() > 1 ? reason : tOutput( "$network_ban_noreason" ) );
1725 
1726         sn_DisconnectUser(m.SenderID(), tOutput( "$network_kill_banned", int(banned/60), reason ) );
1727     }
1728 
1729     // ignore multiple logins
1730     if( CountSameConnection( m.SenderID() ) > 0 )
1731         return -1;
1732 
1733     // ignore login floods
1734     if ( FloodProtection( m ) )
1735         return -1;
1736 
1737     bool success=false;
1738 
1739     int new_id = -1;
1740 
1741     // test
1742     //	sn_DisconnectUser(m.SenderID(), "$network_kill_incompatible");
1743     //	return -1;
1744 
1745     nVersion mergedVersion;
1746     if ( !mergedVersion.Merge( version, sn_CurrentVersion() ) )
1747     {
1748         sn_DisconnectUser(m.SenderID(), "$network_kill_incompatible");
1749     }
1750 
1751     // expire 0.2.8 test versions, they have a security flaw
1752     if ( sn_lockOut028tTest && version.Max() >= 5 && version.Max() <= 10 )
1753     {
1754         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.");
1755     }
1756 
1757     if (m.SenderID()!=MAXCLIENTS+1)
1758     {
1759         //con << "Ignoring second login from " << m.SenderID() << ".\n";
1760         (new nMessage(login_ignore))->Send(m.SenderID());
1761     }
1762     else if (sn_Connections[m.SenderID()].socket)
1763     {
1764         if ( sn_maxClients > MAXCLIENTS )
1765             sn_maxClients = MAXCLIENTS;
1766 
1767         // count doublicate IPs
1768         if ( CountSameIP( m.SenderID(), true ) < sn_allowSameIPCountHard )
1769         {
1770             // find new free ( or freeable ) ID
1771             new_id = GetFreeSlot();
1772             if ( new_id > 0 )
1773             {
1774                 if(sn_Connections[new_id].socket)
1775                     sn_DisconnectUser( new_id, "$network_kill_full" );
1776 
1777                 success = true;
1778 
1779                 senderID.SetID( new_id );
1780 
1781                 sn_Connections	[ new_id ].socket	= sn_Connections[MAXCLIENTS+1].socket; // the new connection has number MC+1
1782                 peers			[ new_id ]			= peers[MAXCLIENTS+1];
1783                 timeouts		[ new_id ]			= kickOnDemandTimeout/2;
1784 
1785                 // sn_Connections	[ MAXCLIENTS+1 ].socket		= NULL;
1786                 // peers			[ MAXCLIENTS+1 ].sa_family	= 0;
1787                 //				nCallbackLoginLogout::UserLoggedIn(i);
1788 
1789                 sn_Connections	[ new_id ].supportedAuthenticationMethods_ = supportedAuthenticationMethods;
1790 
1791                 // recount doublicate IPs
1792                 CountSameIP( new_id, true );
1793             }
1794         }
1795 
1796         // log login to console
1797         tOutput o;
1798         o.SetTemplateParameter(1, peers[m.SenderID()].ToString() );
1799         o.SetTemplateParameter(2, sn_Connections[m.SenderID()].socket->GetAddress().ToString() );
1800         o.SetTemplateParameter(3, sn_GetClientVersionString(version.Max()) );
1801         o.SetTemplateParameter(4, version.Max() );
1802         o << "$network_server_login";
1803         con << o;
1804     }
1805     if (success)
1806     {
1807         tOutput o;
1808         o.SetTemplateParameter(1, new_id);
1809         o << "$network_server_login_success";
1810         con << o;
1811         //      tString s;
1812         // s << "User " << new_id << " logged in.\n";
1813 
1814         sn_Connections[new_id].ping.Reset();
1815         sn_Connections[new_id].bandwidthControl_.Reset();
1816         reset_last_acks(new_id);
1817 
1818         if (rate>sn_maxRateOut)
1819             rate=sn_maxRateOut;
1820 
1821         sn_Connections[new_id].bandwidthControl_.SetRate( rate );
1822         sn_Connections[new_id].version = version;
1823 
1824         nWaitForAck::AckAllPeer(MAXCLIENTS+1);
1825         reset_last_acks(MAXCLIENTS+1);
1826         if (sn_Connections[MAXCLIENTS+1].ackMess)
1827         {
1828             sn_Connections[MAXCLIENTS+1].ackMess=NULL;
1829         }
1830 
1831         // send login accept message with high priority
1832         nMessage *rep=new nMessage(login_accept);
1833         rep->Write(new_id);
1834         (*rep) << sn_myVersion;
1835         (*rep) << peers[m.SenderID()].ToString();
1836         nKrawall::WriteScrambledPassword( salt, *rep );
1837 
1838         rep->Send(new_id, -killTimeout);
1839 
1840         nMessage::SendCollected( new_id );
1841 
1842         nConfItemBase::s_SendConfig(true, new_id);
1843 
1844         // fake activity
1845         nMachine & machine = nMachine::GetMachine( new_id );
1846         machine.AddPlayer();
1847         machine.RemovePlayer();
1848 
1849         nCallbackLoginLogout::UserLoggedIn(new_id);
1850 
1851         //      ANET_Listen(false);
1852         //      ANET_Listen(true);
1853     }
1854     else if (m.SenderID()==MAXCLIENTS+1)
1855     {
1856         sn_DisconnectUser(MAXCLIENTS+1, "$network_kill_full");
1857     }
1858 
1859     sn_UpdateCurrentVersion();
1860 
1861     return new_id;
1862 }
1863 
login_handler_1(nMessage & m)1864 void login_handler_1(nMessage& m)
1865 {
1866     unsigned short rate;
1867 
1868     m.Read( rate );
1869 
1870     if ( !m.End() ){ // we get a big brother message (ignore it)
1871         tString rem_bb;
1872         m >> rem_bb;
1873     }
1874 
1875     login_handler( m, rate );
1876 }
1877 
login_handler_2(nMessage & m)1878 void login_handler_2(nMessage& m)
1879 {
1880     unsigned short rate;
1881     unsigned short bb;
1882 
1883     m.Read( rate );
1884     m.Read( bb );
1885     tString rem_bb;
1886 
1887     if ( bb )
1888     { // we get a big brother message
1889         m >> rem_bb;
1890     }
1891 
1892     int new_ID = login_handler( m, rate );
1893 
1894     if ( new_ID > 0 )
1895     {
1896         nMessage* m = tNEW( nMessage )( versionControl );
1897         (*m) << sn_currentVersion;
1898 
1899         m->Send( new_ID );
1900 
1901         if ( bb )
1902         {
1903             std::ofstream s;
1904             if ( tDirectories::Var().Open(s, "big_brother",std::ios::app) )
1905                 s << rem_bb << '\n';
1906         }
1907     }
1908 }
1909 
1910 
logout_handler(nMessage & m)1911 void logout_handler(nMessage &m){
1912     unsigned short id = m.SenderID();
1913     //m.Read(id);
1914 
1915     // only the server or legal clients are allowed to send this
1916     // (client check comes later)
1917     if(sn_GetNetState() == nCLIENT && id != 0)
1918         return;
1919 
1920     if (sn_Connections[id].socket)
1921     {
1922         tOutput o;
1923         o.SetTemplateParameter(1, id);
1924         o << "$network_logout_server";
1925         con << o;
1926     }
1927     nWaitForAck::AckAllPeer(id);
1928 
1929     if (0<id && id<=MAXCLIENTS)
1930     {
1931         sn_DisconnectUser(id, "$network_kill_logout");
1932     }
1933 }
1934 
1935 
1936 #define MAX_MESS_LEN 300
1937 #define OVERHEAD 32
1938 
1939 static REAL sn_OrderPriority = 0;
1940 
1941 // statistics
1942 int sn_SentBytes        = 0;
1943 int sn_SentPackets      = 0;
1944 int sn_ReceivedBytes    = 0;
1945 int sn_ReceivedPackets  = 0;
1946 nTimeRolling sn_StatsTime		= 0;
1947 
1948 
1949 // adds a message to the buffer
AddMessage(nMessage & message,nBandwidthControl * control)1950 void nSendBuffer::AddMessage	( nMessage&			message, nBandwidthControl* control )
1951 {
1952     unsigned long id = message.MessageID();
1953     unsigned short len = message.DataLen();
1954     tRecorderSync< unsigned long >::Archive( "_MESSAGE_ID_SEND", 5, id );
1955 
1956     sendBuffer_[sendBuffer_.Len()]=htons(message.Descriptor());
1957 
1958     sendBuffer_[sendBuffer_.Len()]=htons(message.MessageID());
1959 
1960     sendBuffer_[sendBuffer_.Len()]=htons(message.DataLen());
1961     for(int i=0;i<len;i++)
1962         sendBuffer_[sendBuffer_.Len()]=htons(message.Data(i));
1963 
1964     tRecorderSync< unsigned short >::Archive( "_MESSAGE_SEND_LEN", 5, len );
1965 
1966     if ( control )
1967     {
1968         control->Use( nBandwidthControl::Usage_Planning, len * 2 );
1969     }
1970 }
1971 
1972 // send the contents of the buffer to a specific socket
Send(nSocket const & socket,const nAddress & peer,nBandwidthControl * control)1973 void nSendBuffer::Send			( nSocket const &				socket
1974                            , const nAddress &	peer
1975                            ,nBandwidthControl* control )
1976 {
1977     if (sendBuffer_.Len()){
1978         sn_SentPackets++;
1979         sn_SentBytes  += sendBuffer_.Len() * 2 + OVERHEAD;
1980 
1981         // store our id
1982         sendBuffer_[sendBuffer_.Len()]=htons(::sn_myNetID);
1983 
1984         socket.Write( reinterpret_cast<int8 *>(&(sendBuffer_[0])),
1985                       2*sendBuffer_.Len(), peer);
1986 
1987         if ( control )
1988         {
1989             control->Use( nBandwidthControl::Usage_Execution, 2*sendBuffer_.Len() + OVERHEAD );
1990         }
1991 
1992         this->Clear();
1993     }
1994 }
1995 
1996 // broadcast the contents of the buffer
Broadcast(nSocket const & socket,int port,nBandwidthControl * control)1997 void nSendBuffer::Broadcast	( nSocket const &				socket
1998                               , int				port
1999                               , nBandwidthControl* control )
2000 {
2001     if (sendBuffer_.Len()){
2002         sn_SentPackets++;
2003         sn_SentBytes  += sendBuffer_.Len() * 2 + OVERHEAD;
2004 
2005         // store our id
2006         sendBuffer_[sendBuffer_.Len()]=htons(::sn_myNetID);
2007 
2008         socket.Broadcast( reinterpret_cast<int8 *>(&(sendBuffer_[0])),
2009                           2*sendBuffer_.Len(), port);
2010 
2011         Clear();
2012 
2013         if ( control )
2014         {
2015             control->Use( nBandwidthControl::Usage_Execution, 2*sendBuffer_.Len() + OVERHEAD );
2016         }
2017     }
2018 }
2019 
2020 // clears the buffer
Clear()2021 void nSendBuffer::Clear()
2022 {
2023     for(int i=sendBuffer_.Len()-1;i>=0;i--)
2024         sendBuffer_(i)=0;
2025 
2026     sendBuffer_.SetLen( 0 );
2027 }
2028 
2029 
nBandwidthControl(nBandwidthControl * parent)2030 nBandwidthControl::nBandwidthControl( nBandwidthControl* parent )
2031 {
2032 #ifdef DEBUG
2033     if ( parent )
2034         parent->numChildren_ ++;
2035     numChildren_ = 0;
2036 #endif
2037 
2038     parent_ = parent;
2039 
2040     Reset();
2041 }
2042 
~nBandwidthControl()2043 nBandwidthControl::~nBandwidthControl()
2044 {
2045 #ifdef DEBUG
2046     if ( parent_ )
2047         parent_->numChildren_ --;
2048 
2049     tASSERT( numChildren_ == 0 );
2050 #endif
2051 }
2052 
Reset()2053 void nBandwidthControl::Reset()
2054 {
2055     rateControlPlanned_ = rateControl_ = 1000.0f;
2056     rate_ = 8;
2057 }
2058 
Use(Usage planned,REAL bandwidth)2059 void nBandwidthControl::Use( Usage planned, REAL bandwidth )
2060 {
2061     tRecorderSync< REAL >::Archive( "_RATE_CONTROL_USAGE", 4, bandwidth );
2062     ( Usage_Planning == planned ? rateControlPlanned_ : rateControl_ ) -= bandwidth;
2063 }
2064 
Update(REAL ts)2065 void nBandwidthControl::Update( REAL ts)
2066 {
2067     tRecorderSync< REAL >::Archive( "_RATE_CONTROL", 12, rateControl_ );
2068     tRecorderSync< REAL >::Archive( "_RATE_CONTROL_PLANNED", 12, rateControlPlanned_ );
2069 
2070     rateControl_ += ( rate_ * 1000 ) * ts;
2071 
2072     if ( rateControl_ > 1000.0f )
2073     {
2074         rateControl_ = 1000.0f;
2075     }
2076 
2077     rateControlPlanned_ = rateControl_;
2078 }
2079 
SendCollected(int peer)2080 void nMessage::SendCollected(int peer)
2081 {
2082     //if ( peer == 7 && sn_Connections[peer].sendBuffer_.Len() > 0 )
2083     //    con << tSysTimeFloat() << "\n";
2084 
2085     sn_OrderPriority = 0;
2086 
2087     if (peer<0 || peer > MAXCLIENTS+1 || !sn_Connections[peer].socket)
2088         tERR_ERROR("Invalid peer!");
2089 
2090     sn_Connections[peer].sendBuffer_.Send( *sn_Connections[peer].socket, peers[peer], &sn_Connections[peer].bandwidthControl_ );
2091 }
2092 
2093 
BroadcastCollected(int peer,unsigned int port)2094 void nMessage::BroadcastCollected(int peer, unsigned int port){
2095     if (peer<0 || peer > MAXCLIENTS+1 || !sn_Connections[peer].socket)
2096         tERR_ERROR("Invalid peer!");
2097 
2098     sn_Connections[peer].sendBuffer_.Broadcast( *sn_Connections[peer].socket, port, &sn_Connections[peer].bandwidthControl_ );
2099 }
2100 
2101 
2102 // TODO_NOACK
SendImmediately(int peer,bool ack)2103 void nMessage::SendImmediately(int peer,bool ack){
2104     if (ack)
2105     {
2106 #ifdef NO_ACK
2107         tASSERT(messageIDBig_);
2108 #endif
2109         new nWaitForAck(this,peer);
2110 
2111 #ifdef nSIMULATE_PING
2112         return;
2113 #endif
2114     }
2115 
2116     // server: messages to yourself are a bit strange...
2117     if ( sn_GetNetState() == nSERVER && peer == 0 && ack )
2118     {
2119         st_Breakpoint();
2120         tJUST_CONTROLLED_PTR< nMessage > bounce(this);
2121         return;
2122     }
2123 
2124 #ifdef DEBUG
2125     /*
2126     if (descriptor>1)
2127       con << "SMT " << descriptor << "\n";
2128     */
2129 
2130     /*
2131       #ifdef DEBUG
2132       if (sn_Connections[].rate_control[peer]<-2000)
2133          tERR_ERROR("Heavy network overflow.");
2134       #endif
2135     */
2136 
2137     // if (peer==0 && sn_GetNetState()==nSERVER)
2138     //      tERR_ERROR("talking to yourself, eh?");
2139 
2140     if (peer==MAXCLIENTS+1){
2141 #ifdef DEBUG
2142         if(descriptor==s_Acknowledge.id)
2143             con << "Sending ack to login slot.\n";
2144 #endif
2145         //      else if (descriptor
2146         //	tERR_ERROR("the last user only should receive denials or acks.");
2147     }
2148 #endif
2149 
2150     if (sn_Connections[peer].sendBuffer_.Len()+data.Len()+3 > MAX_MESS_LEN/2){
2151         SendCollected(peer);
2152         //con << "Overflow packets sent to " << peer << '\n';
2153     }
2154 
2155 
2156     if (sn_Connections[peer].socket)
2157     {
2158         sn_Connections[peer].sendBuffer_.AddMessage( *this, &sn_Connections[peer].bandwidthControl_ );
2159 
2160         /*
2161           if (sn_Connections[].rate_control[peer]>0)
2162           send_collected(peer);
2163 
2164           unsigned short *b=new (unsigned short)[data.Len()+3];
2165 
2166           b[0]=htons(descriptor);
2167           b[1]=htons(messageID);
2168           b[2]=htons(data.Len());
2169           int len=data.Len();
2170           for(int i=0;i<len;i++)
2171           b[3+i]=htons(data(i));
2172 
2173 
2174           ANET_Write(sn_Connections[].socket[peer],(int8 *)b,
2175           2*(data.Len()+3),&peers[peer]);
2176 
2177           //std::cerr << "Sent " << 2*len+6 << " bytes.\n";
2178           sn_Connections[].rate_control[peer]-=2*(len+3)+OVERHEAD;
2179 
2180           delete b;
2181         */
2182 
2183         if (deb_net)
2184             con << "Sent " <<descriptor << ':' << messageIDBig_ << ":"
2185             << peer << '\n';
2186     }
2187 
2188     tControlledPTR< nMessage > bounce( this ); // delete this message if nobody is interested in it any more
2189 }
2190 
2191 REAL sent_per_messid[MAXDESCRIPTORS+100];
2192 
Send(int peer,REAL priority,bool ack)2193 void nMessage::Send(int peer,REAL priority,bool ack){
2194 #ifdef NO_ACK
2195     if (!ack)
2196         messageIDBig_ = 0;
2197 #endif
2198 
2199     // don't send messages to unsupported peers
2200     if( peer > MAXCLIENTS+1 )
2201     {
2202         tJUST_CONTROLLED_PTR< nMessage > bounce(this);
2203         return;
2204     }
2205 
2206 
2207     // messages to yourself are a bit strange...
2208     if ( sn_GetNetState() == nSERVER && peer == 0 && ack )
2209     {
2210         st_Breakpoint();
2211         tJUST_CONTROLLED_PTR< nMessage > bounce(this);
2212         return;
2213     }
2214 
2215 #ifdef DEBUG
2216 
2217     if (peer==MAXCLIENTS+1){
2218         if(descriptor==s_Acknowledge.id)
2219             con << "Sending ack to login slot.\n";
2220         //      else if (descriptor
2221         //	tERR_ERROR("the last user only should receive denials or acks.");
2222     }
2223 #endif
2224 
2225 #ifdef DEBUG_X
2226     if (descriptor>1)
2227         con << "PMT " << descriptor << "\n";
2228 #endif
2229 
2230     // the next line was redundant; the send buffer handles that part of accounting.
2231     //sn_Connections[peer].bandwidthControl_.Use( nBandwidthControl::Usage_Planning, 2*(data.Len()+3) );
2232 
2233     sent_per_messid[descriptor]+=2*(data.Len()+3);
2234 
2235     tASSERT(Descriptor()!=s_Acknowledge.ID() || !ack);
2236 
2237     new nMessage_planned_send(this,priority+sn_OrderPriority,ack,peer);
2238     sn_OrderPriority += .01; // to roughly keep the relative order of netmessages
2239 }
2240 
2241 // ack messages: don't get an ID
2242 class nAckMessage: public nMessage
2243 {
2244 public:
nAckMessage()2245     nAckMessage(): nMessage( s_Acknowledge ){ messageIDBig_ = 0; }
2246 };
2247 
2248 // receive and s_Acknowledge the recently reveived network messages
2249 
2250 typedef std::deque< tJUST_CONTROLLED_PTR< nMessage > > nMessageFifo;
2251 
rec_peer(unsigned int peer)2252 static void rec_peer(unsigned int peer){
2253     tASSERT( sn_Connections[peer].socket );
2254 
2255     nMachine::Expire();
2256 
2257     // temporary fifo for received messages
2258     //static tArray< tJUST_CONTROLLED_PTR< nMessage > > receivedMessages;
2259     static nMessageFifo receivedMessages;
2260 
2261     // the growing buffer we read messages into
2262 #ifndef DEDICATED
2263     const int serverMaxAcceptedSize=2000;
2264 #endif
2265     static tArray< unsigned short > storage(2000);
2266     int maxrec = 0; maxrec = storage.Len();
2267     unsigned short * buff = 0; buff = &storage[0];
2268 
2269     // short buff[maxrec];
2270     if (sn_Connections[peer].socket){
2271         int count=0;
2272         int len=1;
2273         while (len>=0 && sn_Connections[peer].socket)
2274         {
2275             nAddress addrFrom; // the sender of the current packet
2276             len = sn_Connections[peer].socket->Read( reinterpret_cast<int8 *>(buff),maxrec*2, addrFrom);
2277 
2278             if (len>=2){
2279                 if ( len >= maxrec*2 )
2280                 {
2281 #ifndef DEDICATED
2282                     // the message was too long to receive. What to do?
2283                     if ( sn_GetNetState() != nSERVER || len < serverMaxAcceptedSize )
2284                     {
2285                         // expand the buffer. The message is lost now, but the
2286                         // peer will certainly resend it. Hopefully, the buffer will be large enough to hold it then.
2287                         storage[maxrec*2-1]=0;
2288                         maxrec = storage.Len();
2289                         buff = &storage[0];
2290 
2291                         tERR_WARN( "Oversized network packet received. Read buffer has been enlargened to catch it the next time.");
2292 
2293                     }
2294                     else
2295 #endif
2296                     {
2297                         // packet WAAAAY too large.
2298                         static float totalFatsoes = 10;  // number of oversized packages checked
2299                         static float clientFatsoes = 10; // number of oversized pacakges that could be attributed to clients
2300                         static float bother = 5;         // counter that determines whether we bother to check.
2301                         bother+=clientFatsoes;
2302 
2303                         // what follows is work, so we only do it if it payed off in the past
2304                         // if this block is entered not at all by error, no biggie. The clients
2305                         // will time out eventually.
2306                         if(bother>totalFatsoes)
2307                         {
2308                             bother-=totalFatsoes;
2309 
2310                             // increase total stat
2311                             totalFatsoes++;
2312 
2313                             // If it's from a connected client,
2314                             // terminate the connection. If not, it's an attack and
2315                             // we should rather ignore it.
2316                             bool success = false;
2317                             for( int id=MAXCLIENTS; id > 0; --id )
2318                             {
2319                                 if (sn_Connections[id].socket && peers[id] == addrFrom)
2320                                 {
2321                                     sn_DisconnectUser( id, "$network_kill_error" );
2322                                     success=true;
2323                                 }
2324                             }
2325 
2326                             // count the successfully removed client
2327                             if( success )
2328                                 clientFatsoes++;
2329 
2330                             // scale down the stats
2331                             const float factor=.99;
2332                             totalFatsoes*=factor;
2333                             clientFatsoes*=factor;
2334                             bother*=factor;
2335                         }
2336                     }
2337 
2338                     // no use in processing the truncated packet. Some messages may get lost,
2339                     // but that's better than the inevitable network error and connection
2340                     // termination that expects us if we go on.
2341                     continue;
2342                 }
2343 
2344                 unsigned short *b=buff;
2345                 unsigned short *bend=buff+(len/2-1);
2346 
2347                 sn_ReceivedPackets++;
2348                 sn_ReceivedBytes  += len + OVERHEAD;
2349 
2350                 unsigned short claim_id=ntohs(*bend);
2351 
2352                 // z-man: security check ( thanks, Luigi Auriemma! )
2353                 if ( claim_id > MAXCLIENTS+1 )
2354                     continue;	// drop packet, maybe it was just truncated.
2355 
2356                 /*
2357                   std::cerr << "Received " << len << " bytes";
2358                   con << " from user " << claim_id << '\n';
2359                 */
2360                 count ++;
2361 
2362                 unsigned int id=peer;
2363                 //	 for(unsigned int i=1;i<=(unsigned int)maxclients;i++)
2364                 int comp=nAddress::Compare( addrFrom, peers[claim_id] );
2365                 if ( comp == 0 ) // || claim_id == MAXCLIENTS+1 )
2366                 {
2367                     // everything seems allright. accept the id.
2368                     id = claim_id;
2369                 }
2370                 else
2371                 {
2372                     // logged in clients should ignore packets from unknown sources
2373                     if(sn_GetNetState() != nSERVER && sn_myNetID != 0)
2374                         continue;
2375 
2376                     // assume it's a new connection
2377                     id = MAXCLIENTS+1;
2378                     peers[ MAXCLIENTS+1 ] = addrFrom;
2379                     sn_Connections[ MAXCLIENTS+1 ].socket = sn_Connections[peer].socket;
2380                 }
2381 
2382                 //	 if (peer!=id)
2383                 //  con << "Changed incoming address.\n";
2384                 int lenleft = bend - b;
2385 
2386 #ifndef NOEXCEPT
2387                 try
2388                 {
2389 #endif
2390                     while( lenleft >= 3 ){
2391                         tJUST_CONTROLLED_PTR< nMessage > pmess;
2392                         pmess = tNEW( nMessage )(b,id,lenleft);
2393                         nMessage& mess = *pmess;
2394 
2395                         lenleft = bend - b;
2396 
2397                         bool mess_is_new=true;
2398                         // see if we have got this packet before
2399                         unsigned short mess_id=mess.MessageID();
2400 
2401 #ifdef DEBUG
2402                         if ( (simulate_loss && rand()%simulate_loss==0)){
2403                             // simulate packet loss
2404                             con << "Losing packet " << mess_id << ":" << id << ".\n";
2405                         }else
2406 #endif
2407                             if(// (id==MAXCLIENTS+1 && !nCallbackAcceptPackedWithoutConnection::Accept( mess ) ) ||
2408                                 // do not accept normal packages from the login
2409                                 // slot; just login and information packets are allowed.
2410                                 ( sn_GetNetState() != nSERVER && !login_succeeded && !nCallbackAcceptPackedWithoutConnection::Accept( mess ) )
2411                                 // if we are not yet logged in, accept only login and login_deny.
2412                             )
2413                             {
2414                                 //							con << "Ignoring packet " << mess_id << ":" << id << ".\n";
2415                             }
2416                             else
2417                             {
2418                                 if (id <= MAXCLIENTS && mess_id != 0)  // messages with ID 0 are non-ack messages and come really often. they are always new.
2419                                 {
2420                                     unsigned short diff=mess_id-highest_ack[id];
2421                                     if ( ( diff>0 && diff<10000 ) ||
2422                                             ((
2423                                                  mess.Descriptor() == login_accept.ID() ||
2424                                                  mess.Descriptor() == login_deny.ID()   ||
2425                                                  mess.Descriptor() == login.ID()
2426                                              ) && highest_ack[id] == 0)
2427                                        ){
2428                                         // the message has a more recent id than anything before.
2429                                         // it is surely new.
2430                                         highest_ack[id]=mess_id;
2431                                     }
2432                                     else{
2433                                         // do a better check
2434                                         for(int i=ACKBACK-1;i>=0;i--)
2435                                             if (mess_id==lastacks[id][i])
2436                                                 mess_is_new=false;
2437                                     }
2438                                 }
2439 
2440 
2441                                 // acknowledge the message, even if it was old (the sender
2442                                 // then thinks it got lost the first time)
2443 
2444                                 // special situation: logout. Do not sent ack any more.
2445                                 if ((!sn_Connections[id].socket))
2446                                 {
2447                                     sn_Connections[id].ackMess=NULL;
2448                                 }
2449                                 else if (
2450 #ifdef NO_ACK
2451                                     (mess.MessageID()) &&
2452 #endif
2453                                     (mess.Descriptor()!=login_ignore.ID() ||
2454                                      login_succeeded )){
2455                                     // do not ack the login_ignore packet that did not let you in.
2456 
2457 #ifdef DEBUG
2458                                     if ( id > MAXCLIENTS )
2459                                     {
2460                                         con << "Sending ack to login slot.\n";
2461                                     }
2462 #endif
2463 
2464                                     if(sn_Connections[id].ackMess==NULL)
2465                                     {
2466                                         sn_Connections[id].ackMess=new nAckMessage();
2467                                     }
2468 
2469                                     sn_Connections[id].ackMess->Write(mess.MessageID());
2470                                     if (sn_Connections[id].ackMess->DataLen()>100){
2471                                         sn_Connections[id].ackMess->Send(id, 0, false);
2472                                         sn_Connections[id].ackMess=NULL;
2473                                     }
2474                                 }
2475 
2476                                 if (mess_is_new){
2477                                     // mark the message as old
2478                                     if (mess_id > 0)
2479                                     {
2480                                         lastacks[id][lastackPos[id]]=mess_id;
2481                                         if(++lastackPos[id]>=ACKBACK) lastackPos[id]=0;
2482                                     }
2483 
2484                                     /*
2485                                     								// special situation: login. Change peer number permanently
2486                                     								if (peer==MAXCLIENTS+1 && new_id>0){
2487                                     									id=peer=new_id;
2488                                     								}
2489                                     */
2490 
2491                                     if (sn_GetNetState() != nSTANDALONE)
2492                                     {
2493                                         // store the message for later processing
2494                                         receivedMessages.push_back( pmess );
2495                                     }
2496                                 }
2497                                 //else
2498                                 //con << "Message " << mess_id << ":" << id << " was not new.\n";
2499                             }
2500                     }
2501 #ifndef NOEXCEPT
2502                 }
2503 
2504                 catch(nKillHim)
2505                 {
2506                     con << "nKillHim signal caught: ";
2507                     sn_DisconnectUser(id, "$network_kill_error");
2508                 }
2509 #endif
2510             }
2511 	#ifndef NOEXCEPT
2512             try
2513             {
2514 	#endif
2515                 static int recursionCount = 0;
2516                 ++recursionCount;
2517 
2518                 // handle messages
2519                 while ( receivedMessages.begin() != receivedMessages.end() )
2520                 {
2521                     tJUST_CONTROLLED_PTR< nMessage > mess = receivedMessages.front();
2522                     receivedMessages.pop_front();
2523 
2524                     // perhaps the connection died?
2525                     if ( sn_Connections[ mess->SenderID() ].socket )
2526                         nDescriptor::HandleMessage( *mess );
2527                 }
2528 
2529                 if ( --recursionCount <= 0 )
2530                 {
2531                     nCallbackReceivedComplete::ReceivedComplete();
2532                 }
2533 
2534 	#ifndef NOEXCEPT
2535             }
2536 
2537             catch(nKillHim const &)
2538             {
2539                 con << "nKillHim signal caught: ";
2540                 sn_DisconnectUser(peer, "$network_kill_error");
2541             }
2542 	#endif
2543 
2544         }
2545     }
2546 }
2547 
2548 // receives and processes data from control socket
sn_ReceiveFromControlSocket()2549 void sn_ReceiveFromControlSocket()
2550 {
2551     rec_peer(0);
2552 }
2553 
2554 // discards data from control socket
sn_DiscardFromControlSocket()2555 void sn_DiscardFromControlSocket()
2556 {
2557     // new facts: pending incoming data on the control socket causes the idle loops
2558     // to use 100% CPU time, we need to fetch and discard the data instead of ignoring it.
2559     if ( sn_Connections[0].socket )
2560     {
2561         int8 buff[2];
2562         nAddress addrFrom;
2563         sn_Connections[0].socket->Read( reinterpret_cast<int8 *>(buff),0, addrFrom);
2564     }
2565 }
2566 
2567 
sn_GetNetState()2568 nNetState sn_GetNetState(){
2569     return current_state;
2570 }
2571 
2572 void clear_owners();
2573 
2574 // tries to open listening sockets according to specification, but falls back to increasing ports
sn_Listen(unsigned int & net_hostport,const tString & net_hostip)2575 static bool sn_Listen( unsigned int & net_hostport, const tString& net_hostip )
2576 {
2577     unsigned int net_hostport_before = net_hostport;
2578 
2579     try
2580     {
2581         nSocketListener & listener = sn_BasicNetworkSystem.AccessListener();
2582 
2583         listener.SetIpList( net_hostip );
2584 
2585         bool reported = false;
2586 
2587         // try ports in a range
2588         while ( net_hostport < sn_serverPort + 100 )
2589         {
2590             if ( listener.SetPort( net_hostport ).Listen( true ) )
2591                 return true;
2592 
2593             if ( !reported )
2594             {
2595                 con << "sn_SetNetState: Unable to open accept socket on desired port " << net_hostport << ", Trying next ports...\n";
2596                 reported = true;
2597             }
2598 
2599             net_hostport++;
2600         }
2601 
2602         con << "sn_SetNetState: Giving up setting up listening sockets for IP list " << net_hostip << ".\n";
2603     }
2604     catch( const tException & e )
2605     {
2606         con << "sn_SetNetState: can't setup listening sockets. Reason given:\n"
2607         << e.GetName() << ": " << e.GetDescription() << "\n";
2608     }
2609 
2610     // reset host port
2611     net_hostport = net_hostport_before;
2612 
2613     return false;
2614 }
2615 
2616 // save and load machine info
2617 static void sn_SaveMachines();
2618 static void sn_LoadMachines();
2619 
sn_DisconnectAll()2620 static void sn_DisconnectAll()
2621 {
2622     for(int i=MAXCLIENTS+1;i>=0;i--)
2623     {
2624         if( sn_Connections[i].socket )
2625         {
2626             sn_DisconnectUser(i, "$network_kill_shutdown");
2627             tVERIFY( !sn_Connections[i].socket );
2628         }
2629     }
2630     nCallbackLoginLogout::UserLoggedOut(0);
2631 }
2632 
2633 // flag set as long as the network sockets should not be closed and reopened
2634 static bool sn_noReset = false;
nSocketResetInhibitor()2635 nSocketResetInhibitor::nSocketResetInhibitor()
2636 {
2637     sn_noReset = true;
2638 }
~nSocketResetInhibitor()2639 nSocketResetInhibitor::~nSocketResetInhibitor()
2640 {
2641     sn_noReset = false;
2642 }
2643 
sn_SetNetState(nNetState x)2644 void sn_SetNetState(nNetState x){
2645     static bool reentry=false;
2646     if(!reentry && x!=current_state){
2647         sn_UpdateCurrentVersion();
2648 
2649         //if (x == nSERVER)
2650         unsigned int net_hostport = sn_serverPort;
2651 
2652         // save/load machines on entering/leaving server mode
2653         if ( x == nSERVER )
2654             sn_LoadMachines();
2655         else if ( current_state == nSERVER )
2656             if ( !tRecorder::IsPlayingBack() )
2657                 sn_SaveMachines();
2658 
2659         reentry=true;
2660         if (x!=nSTANDALONE)
2661         {
2662             if (x==nCLIENT)
2663             {
2664                 sn_DisconnectAll();
2665             }
2666             else
2667             {
2668                 sn_myNetID=0;
2669             }
2670 
2671             if (!sn_Connections[0].socket)
2672                 sn_Connections[0].socket=sn_BasicNetworkSystem.Init();
2673             // bool success = true;
2674             if (x == nSERVER)
2675             {
2676                 // bool success =
2677                 sn_Listen( net_hostport, net_hostip ) ||    // first try: do it according to user specs
2678                 sn_Listen( net_hostport, tString( "ANY" ) ) ||         // second try: bind to generic IP
2679                 sn_Listen( net_hostport, tString( "ALL" ) );           // last try: bind to all available IPs
2680 
2681 #ifdef DEDICATED
2682                 // save host port that worked, otherwise it may change from the port sent to the master server
2683                 sn_serverPort = net_hostport;
2684 #endif
2685             }
2686         }
2687         else
2688         {
2689             clear_owners();
2690             for(int i=MAXCLIENTS+1;i>=0;i--){
2691                 if(sn_Connections[i].socket){
2692                     if (i==0 && current_state!=nSERVER)
2693                     { // logout: fire and forget
2694                         con << tOutput("$network_logout_process");
2695                         for(int j=3;j>=0;j--){ // just to make sure
2696                             nMessage *lo=new nMessage(logout);
2697                             lo->Write(static_cast<unsigned short>(sn_myNetID));
2698                             lo->ClearMessageID();
2699                             lo->SendImmediately(0, false);
2700                             nMessage::SendCollected(0);
2701                             tDelay(1000);
2702                         }
2703                         con << tOutput("$network_logout_done");
2704 
2705                         sn_myNetID=0; // MAXCLIENTS+1; // reset network id
2706                     }
2707                 }
2708                 sn_DisconnectUserNoWarn(i, "$network_kill_shutdown");
2709             }
2710 
2711             // repeat to clear out pending stuff created during
2712             // the last run (destruction messages, for example)
2713             for(int i=MAXCLIENTS+1;i>=0;i--)
2714             {
2715                 sn_DisconnectUserNoWarn(i, "$network_kill_shutdown");
2716             }
2717 
2718             sn_Connections[0].socket = 0;
2719 
2720             // shutdown network system to get new socket
2721             if ( !sn_noReset )
2722                 sn_BasicNetworkSystem.Shutdown();
2723         }
2724 
2725         current_state=x;
2726         reentry=false;
2727     }
2728 
2729     sn_UpdateCurrentVersion();
2730 }
2731 
2732 
2733 
2734 // go to client mode and connect to server
2735 
2736 
sn_Bend(nAddress const & address)2737 void sn_Bend( nAddress const & address )
2738 {
2739     if ((sn_GetNetState() == nSTANDALONE))
2740         sn_SetNetState(nCLIENT);
2741 
2742     peers[0] = address;
2743 }
2744 
sn_Bend(tString const & server,unsigned int port)2745 void sn_Bend( tString const & server, unsigned int port)
2746 {
2747     // fill address info
2748     nAddress address;
2749     address.SetHostname( server );
2750     address.SetPort( port );
2751 
2752     // delegate
2753     sn_Bend( address );
2754 }
2755 
sn_Connect(nAddress const & server,nLoginType loginType,nSocket const * socket)2756 nConnectError sn_Connect( nAddress const & server, nLoginType loginType, nSocket const * socket ){
2757     sn_DenyReason = "";
2758 
2759     // reset redirection
2760     sn_redirectTo.release();
2761 
2762     // pings in the beginning of the login are not really representative
2763     nPingAverager::SetWeight(.0001);
2764 
2765     // net_hostport = sn_clientPort;
2766 
2767     sn_SetNetState(nSTANDALONE);
2768     sn_SetNetState(nCLIENT);
2769 
2770     // set user requested socket
2771     if ( socket )
2772         sn_Connections[0].socket = socket;
2773 
2774     sn_Connections[0].ping.Reset();
2775 
2776     peers[0] = server;
2777 
2778     reset_last_acks(0);
2779     nCallbackLoginLogout::UserLoggedOut(0);
2780     sn_Connections[0].sendBuffer_.Clear();
2781 
2782     tASSERT( sn_Connections[0].socket );
2783 
2784     // sn_Connections[0].socket->Connect( peers[0] ); // useless
2785     sn_Connections[0].bandwidthControl_.SetRate( sn_maxRateOut );
2786 
2787     sn_myNetID=0; // MAXCLIENTS+1; // reset network id
2788 
2789     // first, get all pending messages
2790     sn_Receive();
2791     sn_Receive();
2792     sn_Receive();
2793 
2794     // reset version control until the true value is given by the server.
2795     sn_currentVersion = nVersion(0,0);
2796 
2797     // Login stuff.....
2798     tJUST_CONTROLLED_PTR< nMessage > mess;
2799     if ( loginType != Login_Pre0252 )
2800     {
2801         mess=new nMessage(login_2);
2802         mess->Write(sn_maxRateIn);
2803 
2804         unsigned short bb = big_brother;
2805         mess->Write( bb );
2806         if ( bb ){
2807             (*mess) << sn_bigBrotherString;
2808             big_brother=false;
2809         }
2810     }
2811     else
2812     {
2813         mess=new nMessage(login);
2814         mess->Write(sn_maxRateIn);
2815 
2816         // send (worthless) big brother string
2817         if (big_brother)
2818         {
2819             (*mess) << sn_bigBrotherString;
2820         }
2821         else
2822         {
2823             (*mess) << tString("");
2824         }
2825 
2826         big_brother=false;
2827     }
2828 
2829     // write our version
2830     (*mess) << sn_MyVersion();
2831 
2832     // write our supported authentication methods
2833     (*mess) << nKrawall::nMethod::SupportedMethods();
2834 
2835     // write a random salt
2836     nKrawall::RandomSalt( loginSalt );
2837     nKrawall::WriteScrambledPassword( loginSalt, *mess );
2838 
2839     mess->ClearMessageID();
2840     mess->SendImmediately(0,false);
2841     nMessage::SendCollected(0);
2842 
2843     con << tOutput("$network_login_process");
2844 
2845     login_failed=false;
2846     login_succeeded=false;
2847 
2848     nTimeRolling timeout=tSysTimeFloat()+5;
2849 
2850     static REAL resend = .25;
2851     nTimeAbsolute nextSend = tSysTimeFloat() + resend/5;
2852     while(sn_GetNetState()==nCLIENT && tSysTimeFloat()<timeout &&
2853             !login_failed && !login_succeeded){
2854         if ( tSysTimeFloat() > nextSend )
2855         {
2856             // con << "retrying...\n";
2857             nextSend = tSysTimeFloat() + resend;
2858             mess->SendImmediately(0,false);
2859             nMessage::SendCollected(0);
2860         }
2861 
2862         tAdvanceFrame(10000);
2863         sn_Receive();
2864         sn_SendPlanned();
2865 
2866         // check for user abort
2867         if ( tConsole::Idle() )
2868         {
2869             con << tOutput("$network_login_failed_abort");
2870             sn_SetNetState(nSTANDALONE);
2871             return nABORT;
2872         }
2873     }
2874     if (login_failed)
2875     {
2876         con << tOutput("$network_login_failed");
2877         sn_SetNetState(nSTANDALONE);
2878         return nDENIED;
2879     }
2880     else if (tSysTimeFloat()>=timeout || sn_GetNetState()!=nCLIENT){
2881         if ( loginType == Login_All )
2882         {
2883             return 	sn_Connect( server, Login_Pre0252, socket );
2884         }
2885         else
2886         {
2887             con << tOutput("$network_login_failed_timeout");
2888             sn_SetNetState(nSTANDALONE);
2889             return nTIMEOUT;
2890         }
2891     }
2892     else{
2893         nCallbackLoginLogout::UserLoggedIn(0);
2894 
2895         tOutput mess;
2896         mess.SetTemplateParameter(1, sn_myNetID);
2897         mess << "$network_login_success";
2898         con << mess;
2899         con << tOutput("$network_login_sync");
2900         sn_Sync(40);
2901         con << tOutput("$network_login_relabeling");
2902         con << tOutput("$network_login_sync2");
2903         sn_Sync(40,true);
2904         con << tOutput("$network_login_done");
2905 
2906         // marginalize past ping values
2907         nPingAverager::SetWeight(1);
2908 
2909         return nOK;
2910     }
2911 }
2912 
2913 
nReadError(bool critical)2914 void nReadError( bool critical )
2915 {
2916     // st_Breakpoint();
2917 #ifndef NOEXCEPT
2918     if ( critical )
2919         throw nKillHim();
2920     else
2921         throw nIgnore();
2922 #else
2923     con << "\nI told you not to use PGCC! Now we need to leave the\n"
2924     << "system in an undefined state. The progam will crash now.\n"
2925     << "\n\n";
2926 #endif
2927 }
2928 
2929 #ifdef DEDICATED
2930 static short sn_decorateID = true;
2931 static tConfItem< short > sn_decorateIDConf( "CONSOLE_DECORATE_ID", sn_decorateID );
2932 
2933 static short sn_decorateIP = false;
2934 static tConfItem< short > sn_decorateIPConf( "CONSOLE_DECORATE_IP", sn_decorateIP );
2935 
2936 static tConfItem< bool > sn_decorateTSConf( "CONSOLE_DECORATE_TIMESTAMP", sn_decorateTS );
2937 
2938 // console with filter for better machine readable log format
2939 class nConsoleFilter:public tConsoleFilter{
2940 private:
DoFilterLine(tString & line)2941     virtual void DoFilterLine( tString &line )
2942     {
2943         if ( sn_decorateID )
2944         {
2945             tString orig = line;
2946 
2947             int id = nCurrentSenderID::GetID();
2948             bool printIP = ( id > 0 && sn_decorateIP );
2949 
2950             line = "";
2951             line << "[";
2952             if ( sn_decorateID )
2953                 line << id;
2954             if ( sn_decorateID && sn_decorateTS )
2955                 line << " ";
2956             if ( sn_decorateTS )
2957                 line << st_GetCurrentTime("TS=%Y/%m/%d-%H:%M:%S");
2958             if ( (sn_decorateID || sn_decorateTS) && printIP )
2959                 line << " ";
2960             if ( printIP )
2961             {
2962                 // get IP from id
2963                 tString IP;
2964                 sn_GetAdr( id,  IP );
2965                 line << "IP=" << IP;
2966             }
2967 
2968             line << "] " << orig;
2969         }
2970     }
2971 };
2972 
2973 static nConsoleFilter sn_consoleFilter;
2974 #endif
2975 
sn_ConsoleOut_handler(nMessage & m)2976 static void sn_ConsoleOut_handler(nMessage &m){
2977     if (sn_GetNetState()!=nSERVER){
2978         tString s;
2979         m >> s;
2980         con << s;
2981     }
2982 }
2983 
2984 
2985 static nDescriptor sn_ConsoleOut_nd(8,sn_ConsoleOut_handler,"sn_ConsoleOut");
2986 
2987 // rough maximal packet size, better send nothig bigger, or it will
2988 // get fragmented.
2989 #define MTU 1400
2990 
2991 // causes the connected clients to print a message
sn_ConsoleOutMessage(tString const & message)2992 nMessage* sn_ConsoleOutMessage( tString const & message )
2993 {
2994     // truncate message to about 1.5K, a safe size for all UDP packets
2995     static const int maxLen = MTU+100;
2996     static bool recurse = true;
2997     if ( message.Len() > maxLen && recurse )
2998     {
2999         recurse = false;
3000         tERR_WARN( "Long console message truncated.");
3001         nMessage * m = sn_ConsoleOutMessage( message.SubStr( 0, MTU ) );
3002         recurse = true;
3003         return m;
3004     }
3005 
3006     nMessage* m=new nMessage(sn_ConsoleOut_nd);
3007     *m << message;
3008 
3009     return m;
3010 }
3011 
sn_ConsoleOutRaw(tString & message,int client)3012 void sn_ConsoleOutRaw( tString & message,int client){
3013     tJUST_CONTROLLED_PTR< nMessage > m = sn_ConsoleOutMessage( message );
3014 
3015     if (client<0){
3016         m->BroadCast();
3017         con << message;
3018     }
3019     else if (client==sn_myNetID)
3020     {
3021         con << message;
3022     }
3023     else
3024     {
3025         m->Send(client);
3026     }
3027 }
3028 
sn_ConsoleOutString(tString & message,int client)3029 void sn_ConsoleOutString( tString & message,int client){
3030     // check if string is too long
3031     if ( message.Len() <= MTU )
3032     {
3033         // no? Fine, just send it in one go.
3034         message  << "0xffffff";
3035         sn_ConsoleOutRaw( message, client );
3036 
3037         return;
3038     }
3039 
3040     // darn, it is too long. Try to find a good spot to cut it
3041     int cut = MTU;
3042     while ( cut > 0 && message(cut) != '\n' )
3043     {
3044         --cut;
3045     }
3046     if ( cut == 0 )
3047     {
3048         // no suitable spot found, just cut anywhere.
3049         cut = MTU;
3050     }
3051 
3052     // split the string
3053     tString beginning = message.SubStr( 0, cut ) + "0xffffff";
3054     tString rest = message.SubStr( cut );
3055 
3056     // and send the bits
3057     sn_ConsoleOutRaw( beginning, client );
3058     sn_ConsoleOutString( rest, client );
3059 }
3060 
sn_ConsoleOut(const tOutput & o,int client)3061 void sn_ConsoleOut(const tOutput& o,int client){
3062     // transform message to string
3063     tString message( o );
3064     sn_ConsoleOutString( message, client );
3065 }
3066 
client_cen_handler(nMessage & m)3067 static void client_cen_handler(nMessage &m){
3068     if (sn_GetNetState()!=nSERVER){
3069         tString s;
3070         m >> s;
3071         con.CenterDisplay(s);
3072     }
3073 }
3074 
3075 static nDescriptor client_cen_nd(9,client_cen_handler,"client_cen");
3076 
3077 // causes the connected clients to print a message in the center of the screeen
sn_CenterMessage(const tOutput & o,int client)3078 void sn_CenterMessage(const tOutput &o,int client){
3079     tString message(o);
3080 
3081     tJUST_CONTROLLED_PTR< nMessage > m=new nMessage(client_cen_nd);
3082     *m << message;
3083     if (client<0){
3084         m->BroadCast();
3085         con.CenterDisplay(message);
3086     }
3087     else if (client==sn_myNetID)
3088         con.CenterDisplay(message);
3089     else
3090         m->Send(client);
3091 }
3092 
ConsoleOut_conf(std::istream & s)3093 static void ConsoleOut_conf(std::istream &s)
3094 {
3095     // read the message
3096     tString message;
3097     message.ReadLine( s, true );
3098 
3099     message += "\n";
3100 
3101     // display it
3102     sn_ConsoleOut( message );
3103 }
3104 
3105 static tConfItemFunc ConsoleOut_c("CONSOLE_MESSAGE",&ConsoleOut_conf);
3106 static tAccessLevelSetter sn_ConsoleConfLevel( ConsoleOut_c, tAccessLevel_Moderator );
3107 
CeterMessage_conf(std::istream & s)3108 static void CeterMessage_conf(std::istream &s)
3109 {
3110     // read the message
3111     tString message;
3112     message.ReadLine( s, true );
3113 
3114     // display it
3115     sn_CenterMessage( message );
3116 }
3117 
3118 static tConfItemFunc CenterMessage_c("CENTER_MESSAGE",&CeterMessage_conf);
3119 static tAccessLevelSetter sn_CenterConfLevel( CenterMessage_c, tAccessLevel_Moderator );
3120 
3121 // ****************************************************************
3122 //                    Send Queue
3123 // ****************************************************************
3124 
3125 // the network stuff planned to send:
3126 tHeap<planned_send> send_queue[MAXCLIENTS+2];
3127 
planned_send(REAL priority,int Peer)3128 planned_send::planned_send(REAL priority,int Peer){
3129     peer=Peer;
3130 
3131     SetVal( priority, send_queue[peer] );
3132 }
3133 
~planned_send()3134 planned_send::~planned_send(){
3135     RemoveFromHeap();
3136 }
3137 
Heap() const3138 tHeapBase *planned_send::Heap() const
3139 {
3140     return &send_queue[peer];
3141 }
3142 
3143 // change our priority:
add_to_priority(REAL diff)3144 void planned_send::add_to_priority(REAL diff)
3145 {
3146     SetVal( Val() + diff, send_queue[peer] );
3147 }
3148 
3149 // **********************************************
3150 
nMessage_planned_send(nMessage * M,REAL priority,bool Ack,int Peer)3151 nMessage_planned_send::nMessage_planned_send
3152 (nMessage *M,REAL priority,bool Ack,int Peer)
3153         :planned_send(priority,Peer),m(M),ack(Ack){
3154     //if (m)
3155 }
3156 
~nMessage_planned_send()3157 nMessage_planned_send::~nMessage_planned_send(){
3158 }
3159 
execute()3160 void nMessage_planned_send::execute(){
3161     if ( Val() < -killTimeout-10){
3162         tOutput mess;
3163         mess.SetTemplateParameter(1, peer);
3164         mess << "$network_error_overflow";
3165         con << mess;
3166         st_Breakpoint();
3167         sn_DisconnectUser(peer, "$network_kill_overflow");
3168     }
3169     else if (m)
3170         m->SendImmediately(peer,ack);
3171 }
3172 
3173 
3174 // **********************************************
3175 
sn_SendPlanned1()3176 static REAL sn_SendPlanned1(){
3177     sn_OrderPriority = 0;
3178 
3179     // if possible, send waiting messages
3180     static double lastTime=-1;
3181     nTimeAbsolute time=tSysTimeFloat();
3182     if (lastTime<0)
3183         lastTime=time;
3184 
3185     if (time<lastTime-.01 || time>lastTime+1000)
3186 #ifdef DEBUG
3187     {
3188         tERR_ERROR("Timer hickup!");
3189     }
3190 #else
3191     {
3192         tERR_WARN("Timer hickup!");
3193         lastTime=time;
3194     }
3195 #endif
3196     REAL dt = time - lastTime;
3197 
3198     //for(int i=MAXCLIENTS+1;i>=0;i--){
3199     for(int i=0;i<=MAXCLIENTS+1;i++){
3200         nConnectionInfo & connection = sn_Connections[i];
3201         if ( !connection.socket )
3202             continue;
3203 
3204         while (connection.ackPending<sn_maxNoAck &&
3205                 connection.bandwidthControl_.CanSend()     &&
3206                 send_queue[i].Len())
3207         {
3208             send_queue[i](0)->execute();
3209             if (send_queue[i].Len())
3210                 delete send_queue[i](0);
3211         }
3212 
3213         // make everything a little more urgent:
3214         for(int j=send_queue[i].Len()-1;j>=0;j--)
3215             send_queue[i](j)->add_to_priority(-dt);
3216     }
3217     lastTime=time;
3218 
3219     return dt;
3220 }
3221 
sn_SendPlanned2(REAL dt)3222 static void sn_SendPlanned2( REAL dt ){
3223     // empty the send buffers
3224     for(int i=0;i<=MAXCLIENTS+1;i++){
3225         nConnectionInfo & connection = sn_Connections[i];
3226         if ( connection.socket )
3227         {
3228             if (connection.sendBuffer_.Len()>0 && connection.bandwidthControl_.CanSend() )
3229                 nMessage::SendCollected(i);
3230 
3231             // update bandwidth usage and other time related data
3232             connection.Timestep( dt );
3233         }
3234     }
3235 }
3236 
sn_SendPlanned()3237 void sn_SendPlanned()
3238 {
3239     // propagate messages to buffers
3240     REAL dt = sn_SendPlanned1();
3241 
3242     // schedule the acks: send them if it's possible (bandwith limit) or if there already is a packet in the pipe.
3243     for(int i=0;i<=MAXCLIENTS+1;i++)
3244         if(sn_Connections[i].socket && sn_Connections[i].ackMess && !sn_Connections[i].ackMess->End()
3245                 //	&& sn_ackAckPending[i] <= 1+sn_Connections[].ackMess[i]->DataLen()
3246                 && ( sn_Connections[i].bandwidthControl_.CanSend() || sn_Connections[i].sendBuffer_.Len() > 0 )
3247           ){
3248             sn_Connections[i].ackMess->SendImmediately(i, false);
3249             sn_Connections[i].ackMess=NULL;
3250         }
3251 
3252     // schedule lost messages for resending
3253     nWaitForAck::Resend();
3254 
3255     // send everything out
3256     sn_SendPlanned2( dt );
3257 }
3258 
sn_Receive()3259 void sn_Receive(){
3260     /*
3261       static bool reentry=false;
3262       if (reentry)
3263       return;
3264       reentry=true;
3265     */
3266 
3267     netTime=tSysTimeFloat();
3268     //	new_id=0;
3269     sn_Connections[MAXCLIENTS+1].ping.Reset();
3270 
3271     // create the ack messages (not required, is done on demand later)
3272     /*
3273     int i;
3274     for(i=0;i<=MAXCLIENTS+1;i++)
3275         if(sn_Connections[i].ackMess==NULL)
3276             sn_Connections[i].ackMess=new nAckMessage();
3277     */
3278 
3279 
3280     switch (current_state){
3281     case nSERVER:
3282         {
3283             memset( &peers[0], 0, sizeof(sockaddr) );
3284 
3285             // listen on all sockets
3286             nSocketListener const & listener = sn_BasicNetworkSystem.GetListener();
3287             for ( nSocketListener::iterator i = listener.begin(); i != listener.end(); ++i )
3288             {
3289                 // clear peer info used for receiving
3290                 memset( &peers[MAXCLIENTS+1], 0, sizeof(sockaddr) );
3291 
3292                 // copy socket info over to [MAXCLIENTS+1] and receive. The copy
3293                 // step is important, nAuthentication.cpp relies on the socket being set.
3294                 if((sn_Connections[MAXCLIENTS+1].socket = (*i).CheckNewConnection() ) != NULL)
3295                 {
3296                     rec_peer(MAXCLIENTS+1);
3297                 }
3298             }
3299         }
3300         // z-man: after much thought, the server does also need to listen to the
3301         // network control socket. .... Thinking again, it's only important for the master
3302         // servers, and they call rec_peer(0) separately.
3303         break;
3304 
3305     case nCLIENT:
3306         rec_peer(0);
3307         break;
3308 
3309     case nSTANDALONE:
3310     default:
3311         break;
3312     }
3313 
3314     /*
3315         // scedule regular messages
3316         REAL dt = sn_SendPlanned1();
3317 
3318         // actually resend messages
3319         sn_SendPlanned2( dt );
3320     */
3321 }
3322 
sn_KickUser(int i,const tOutput & reason,REAL severity,nServerInfoBase * redirectTo)3323 void sn_KickUser(int i, const tOutput& reason, REAL severity, nServerInfoBase * redirectTo )
3324 {
3325     // print it
3326     con << tOutput( "$network_kill_log", i, reason );
3327 
3328     // log it
3329     if ( severity > 0 )
3330     {
3331         nMachine::GetMachine(i).OnKick( severity );
3332     }
3333 
3334     // do it
3335     sn_DisconnectUser( i, reason, redirectTo );
3336 }
3337 
sn_DisconnectUser(int i,const tOutput & reason,nServerInfoBase * redirectTo)3338 void sn_DisconnectUser(int i, const tOutput& reason, nServerInfoBase * redirectTo )
3339 {
3340     // don't be daft and kill yourself, server!
3341     if ( i == 0 && sn_GetNetState() == nSERVER )
3342     {
3343         tERR_WARN( "Server tried to disconnect from itself." );
3344         return;
3345     }
3346 
3347     // clients can only disconnect from the server
3348     if ( i != 0 && i <= MAXCLIENTS && sn_GetNetState() == nCLIENT )
3349     {
3350         tERR_WARN( "Client tried to disconnect from another client: impossible and a bad idea." );
3351         return;
3352     }
3353 
3354     // anything to do at all?
3355     if (!sn_Connections[i].socket)
3356     {
3357         return;
3358     }
3359 
3360     sn_DisconnectUserNoWarn( i, reason, redirectTo );
3361 }
3362 
sn_DisconnectUserNoWarn(int i,const tOutput & reason,nServerInfoBase * redirectTo)3363 void sn_DisconnectUserNoWarn(int i, const tOutput& reason, nServerInfoBase * redirectTo )
3364 {
3365     nCurrentSenderID senderID( i );
3366 
3367     nWaitForAck::AckAllPeer(i);
3368 
3369     static bool reentry=false;
3370     if (reentry)
3371         return;
3372     reentry=true;
3373 
3374     bool printMessage = false; // is it worth printing a message for this event?
3375 
3376     if (sn_Connections[i].socket)
3377     {
3378         nMessage::SendCollected(i);
3379         printMessage = true;
3380 
3381         // to make sure...
3382         if ( i!=0 && i != MAXCLIENTS+2 && sn_GetNetState() == nSERVER ){
3383             for(int j=2;j>=0;j--){
3384                 nMessage* mess = (new nMessage(login_deny));
3385                 *mess << tString( reason );
3386 
3387                 // write redirection
3388                 tString redirection;
3389                 int port;
3390                 if ( redirectTo )
3391                 {
3392                     redirection = redirectTo->GetConnectionName();
3393                     port        = redirectTo->GetPort();
3394                 }
3395                 *mess << redirection;
3396                 *mess << port;
3397 
3398                 mess->SendImmediately(i, false);
3399                 nMessage::SendCollected(i);
3400             }
3401         }
3402     }
3403 
3404     nWaitForAck::AckAllPeer(i);
3405 
3406     sn_Connections[i].ackMess=NULL;
3407 
3408     if (i==0 && sn_GetNetState()==nCLIENT)
3409         sn_SetNetState(nSTANDALONE);
3410 
3411     reset_last_acks(i);
3412 
3413     // peers[i].sa_family=0;
3414 
3415     sn_Connections[i].ackPending=0;
3416     //  sn_ackAckPending[i]=0;
3417 
3418     nCallbackLoginLogout::UserLoggedOut(i);
3419 
3420     if ( printMessage )
3421     {
3422         con << tOutput( "$network_killuser", i, sn_Connections[i].ping.GetPing() );
3423     }
3424 
3425     // clear address, socket and send queue
3426     sn_Connections[i].sendBuffer_.Clear();
3427     sn_Connections[i].socket=NULL;
3428     peers[i] = nAddress();
3429     sn_Connections[i].Clear();
3430     while (send_queue[i].Len())
3431         delete (send_queue[i](0));
3432 
3433     reentry=false;
3434 
3435     sn_UpdateCurrentVersion();
3436 }
3437 
3438 
sn_QueueLen(int user)3439 int sn_QueueLen(int user){
3440     return send_queue[user].Len();
3441 }
3442 
3443 
3444 static tCallback* s_loginoutAnchor=NULL;
3445 int  nCallbackLoginLogout::user;
3446 bool nCallbackLoginLogout::login;
3447 
nCallbackLoginLogout(VOIDFUNC * f)3448 nCallbackLoginLogout::nCallbackLoginLogout(VOIDFUNC *f)
3449         :tCallback(s_loginoutAnchor,f){}
3450 
UserLoggedIn(int u)3451 void nCallbackLoginLogout::UserLoggedIn(int u){
3452     login = true;
3453     user = u;
3454     Exec(s_loginoutAnchor);
3455 }
3456 
UserLoggedOut(int u)3457 void nCallbackLoginLogout::UserLoggedOut(int u){
3458     login = false;
3459     user = u;
3460     Exec(s_loginoutAnchor);
3461 }
3462 
3463 unsigned short nCallbackAcceptPackedWithoutConnection::descriptor=0;	// the descriptor of the incoming packet
3464 static tCallbackOr* s_AcceptAnchor=NULL;
3465 
nCallbackAcceptPackedWithoutConnection(BOOLRETFUNC * f)3466 nCallbackAcceptPackedWithoutConnection::nCallbackAcceptPackedWithoutConnection(BOOLRETFUNC *f)
3467         : tCallbackOr( s_AcceptAnchor, f )
3468 {
3469 }
3470 
Accept(const nMessage & m)3471 bool nCallbackAcceptPackedWithoutConnection::Accept( const nMessage& m )
3472 {
3473     descriptor=m.Descriptor();
3474     return Exec( s_AcceptAnchor );
3475 }
3476 
3477 static tCallback* s_ReceivedCompleteAnchor=NULL;
3478 
nCallbackReceivedComplete(VOIDFUNC * f)3479 nCallbackReceivedComplete::nCallbackReceivedComplete(VOIDFUNC *f)
3480         : tCallback( s_ReceivedCompleteAnchor, f )
3481 {
3482 }
3483 
ReceivedComplete()3484 void nCallbackReceivedComplete::ReceivedComplete( )
3485 {
3486     Exec( s_ReceivedCompleteAnchor );
3487 }
3488 
net_Accept()3489 static bool net_Accept()
3490 {
3491     return
3492         nCallbackAcceptPackedWithoutConnection::Descriptor()==login_accept.ID() ||
3493         nCallbackAcceptPackedWithoutConnection::Descriptor()==login_deny.ID();
3494 }
3495 
3496 static nCallbackAcceptPackedWithoutConnection net_acc( &net_Accept );
3497 
net_exit()3498 static void net_exit(){
3499     for (int i=MAXCLIENTS+1;i>=0;i--)
3500     {
3501         sn_Connections[i].ackMess = NULL;
3502         while (send_queue[i].Len())
3503             delete send_queue[i].Remove(0);
3504     }
3505 }
3506 
3507 static tInitExit net_ie(NULL, &net_exit);
3508 
3509 
3510 
sn_Statistics()3511 void sn_Statistics()
3512 {
3513     nTimeRolling time = tSysTimeFloat();
3514     REAL dt = time - sn_StatsTime;
3515     sn_StatsTime = time;
3516 
3517     if (dt > 0 && (sn_SentPackets || sn_SentBytes))
3518     {
3519         tOutput o;
3520         o.SetTemplateParameter(1,dt);
3521         o.SetTemplateParameter(2,sn_SentBytes);
3522         o.SetTemplateParameter(3,sn_SentPackets);
3523         o.SetTemplateParameter(4,sn_SentBytes/dt);
3524         o.SetTemplateParameter(5,sn_ReceivedBytes);
3525         o.SetTemplateParameter(6,sn_ReceivedPackets);
3526         o.SetTemplateParameter(7,sn_ReceivedBytes/dt);
3527         o << "$network_statistics1";
3528         o << "$network_statistics2";
3529         o << "$network_statistics3";
3530 
3531         con << o;
3532     }
3533 
3534     sn_SentPackets = 0;
3535     sn_SentBytes   = 0;
3536     sn_ReceivedPackets = 0;
3537     sn_ReceivedBytes   = 0;
3538 }
3539 
3540 
3541 
3542 
3543 
3544 
nConnectionInfo()3545 nConnectionInfo::nConnectionInfo(){Clear();}
~nConnectionInfo()3546 nConnectionInfo::~nConnectionInfo(){}
3547 
Clear()3548 void nConnectionInfo::Clear(){
3549     socket     = NULL;
3550     ackPending = 0;
3551     ping.Reset();
3552     // crypt      = NULL;
3553 
3554     supportedAuthenticationMethods_ = "";
3555 
3556     sendBuffer_.Clear();
3557 
3558     bandwidthControl_.Reset();
3559 
3560     ackMess = NULL;
3561 
3562     // userName.SetLen(0);
3563 
3564     // start with 10% packet loss with low statistical weight
3565     packetLoss_.Reset();
3566     packetLoss_.Add(.1,10);
3567 }
3568 
Timestep(REAL dt)3569 void nConnectionInfo::Timestep( REAL dt )  //!< call whenever an an reliable message got sent
3570 {
3571     // update ping
3572     ping.Timestep( dt );
3573 
3574     // update bandwidth control
3575     bandwidthControl_.Update( dt );
3576 
3577     // update packet loss; average about a minute
3578     packetLoss_.Timestep( .02 * dt );
3579 }
3580 
ReliableMessageSent()3581 void nConnectionInfo::ReliableMessageSent()  //!< call whenever an an reliable message got sent
3582 {
3583     packetLoss_.Add( 1 );
3584 }
3585 
AckReceived()3586 void nConnectionInfo::AckReceived()          //!< call whenever an ackownledgement message arrives
3587 {
3588     packetLoss_.Add( -1 );
3589 }
3590 
PacketLoss() const3591 REAL nConnectionInfo::PacketLoss() const     //!< returns the average packet loss ratio
3592 {
3593     REAL ret = packetLoss_.GetAverage();
3594     return ret > 0 ? ret : 0;
3595 }
3596 
sn_GetAdr(int user,tString & name)3597 void sn_GetAdr(int user,  tString& name)
3598 {
3599     peers[user].ToString( name );
3600 }
3601 
sn_GetPort(int user)3602 unsigned int sn_GetPort(int user)
3603 {
3604     return peers[user].GetPort();
3605 }
3606 
sn_GetServerPort()3607 unsigned int sn_GetServerPort()
3608 {
3609     return sn_serverPort;
3610 }
3611 
sn_NumUsers(bool all)3612 int sn_NumUsers( bool all )
3613 {
3614     int ret = 0;
3615     for (int i=MAXCLIENTS; i>0; i--)
3616         if (sn_Connections[i].socket && ( all || ( sn_allowSameIPCountSoft > CountSameIP( i ) ) ) )
3617             ret++;
3618 
3619 #ifndef DEDICATED
3620     ret++;
3621 #endif
3622 
3623     return ret;
3624 }
3625 
sn_NumUsers()3626 int sn_NumUsers()
3627 {
3628     return sn_NumUsers( true );
3629 }
3630 
sn_NumRealUsers()3631 int sn_NumRealUsers()
3632 {
3633     return sn_NumUsers( false );
3634 }
3635 
sn_MaxUsers()3636 int sn_MaxUsers()
3637 {
3638     return sn_maxClients;
3639 }
3640 
sn_MessagesPending(int user)3641 int sn_MessagesPending(int user)
3642 {
3643     return sn_Connections[user].ackPending + send_queue[user].Len();
3644 }
3645 
3646 nBasicNetworkSystem sn_BasicNetworkSystem;
3647 
3648 // *******************************************************************************************
3649 // *
3650 // *	nKillHim
3651 // *
3652 // *******************************************************************************************
3653 //!
3654 //!
3655 // *******************************************************************************************
3656 
nKillHim(void)3657 nKillHim::nKillHim( void )
3658 {
3659 }
3660 
3661 // *******************************************************************************************
3662 // *
3663 // *	~nKillHim
3664 // *
3665 // *******************************************************************************************
3666 //!
3667 //!
3668 // *******************************************************************************************
3669 
~nKillHim(void)3670 nKillHim::~nKillHim( void )
3671 {
3672 }
3673 
3674 // *******************************************************************************************
3675 // *
3676 // *	DoGetName
3677 // *
3678 // *******************************************************************************************
3679 //!
3680 //!		@return		short name
3681 //!
3682 // *******************************************************************************************
3683 
DoGetName(void) const3684 tString nKillHim::DoGetName( void ) const
3685 {
3686     return tString( "Connektion kill request" );
3687 }
3688 
3689 // *******************************************************************************************
3690 // *
3691 // *	DoGetDescription
3692 // *
3693 // *******************************************************************************************
3694 //!
3695 //!		@return		description
3696 //!
3697 // *******************************************************************************************
3698 
DoGetDescription(void) const3699 tString nKillHim::DoGetDescription( void ) const
3700 {
3701     return tString( "The currently handled peer must have done something illegal, so it should be terminated." );
3702 }
3703 
3704 // *******************************************************************************************
3705 // *
3706 // *	nIgnore
3707 // *
3708 // *******************************************************************************************
3709 //!
3710 //!
3711 // *******************************************************************************************
3712 
nIgnore(void)3713 nIgnore::nIgnore( void )
3714 {
3715 }
3716 
3717 // *******************************************************************************************
3718 // *
3719 // *	~nIgnore
3720 // *
3721 // *******************************************************************************************
3722 //!
3723 //!
3724 // *******************************************************************************************
3725 
~nIgnore(void)3726 nIgnore::~nIgnore( void )
3727 {
3728 }
3729 
3730 // *******************************************************************************************
3731 // *
3732 // *	DoGetName
3733 // *
3734 // *******************************************************************************************
3735 //!
3736 //!		@return		short name
3737 //!
3738 // *******************************************************************************************
3739 
DoGetName(void) const3740 tString nIgnore::DoGetName( void ) const
3741 {
3742     return tString( "Packet ignore request" );
3743 }
3744 
3745 // *******************************************************************************************
3746 // *
3747 // *	DoGetDescription
3748 // *
3749 // *******************************************************************************************
3750 //!
3751 //!		@return		description
3752 //!
3753 // *******************************************************************************************
3754 
DoGetDescription(void) const3755 tString nIgnore::DoGetDescription( void ) const
3756 {
3757     return tString( "An error that should lead to the current message getting ingored was detected." );
3758 }
3759 
3760 // *******************************************************************************************
3761 // *
3762 // *	nAverager
3763 // *
3764 // *******************************************************************************************
3765 //!
3766 //!
3767 // *******************************************************************************************
3768 
nAverager(void)3769 nAverager::nAverager( void )
3770         : weight_(0), sum_(0), sumSquared_(0), weightSquared_(0)
3771 {
3772 }
3773 
3774 // *******************************************************************************************
3775 // *
3776 // *	~nAverager
3777 // *
3778 // *******************************************************************************************
3779 //!
3780 //!
3781 // *******************************************************************************************
3782 
~nAverager(void)3783 nAverager::~nAverager( void )
3784 {
3785 }
3786 
3787 // *******************************************************************************************
3788 // *
3789 // *	Timestep
3790 // *
3791 // *******************************************************************************************
3792 //!
3793 //!		@param	decay	decay factor 0 .. infinity; larger values lead to more decay.
3794 //!
3795 // *******************************************************************************************
3796 
Timestep(REAL decay)3797 void nAverager::Timestep( REAL decay )
3798 {
3799     REAL factor = 1/(1+decay);
3800 
3801     // pretend all data so far was collected with a weight of the original weight multiplied by factor
3802     weight_        *= factor;
3803     sum_           *= factor;
3804     sumSquared_    *= factor;
3805     weightSquared_ *= factor * factor;
3806 }
3807 
3808 // *******************************************************************************************
3809 // *
3810 // *	Add
3811 // *
3812 // *******************************************************************************************
3813 //!
3814 //!		@param	value	 the value to add
3815 //!		@param	weight   its statistical weight (importance compared to other values)
3816 //!
3817 // *******************************************************************************************
3818 
Add(REAL value,REAL weight)3819 void nAverager::Add( REAL value, REAL weight )
3820 {
3821     tASSERT( weight >= 0 );
3822     weight_        += weight;
3823     sum_           += weight * value;
3824     sumSquared_    += weight * value * value;
3825     weightSquared_ += weight * weight;
3826 }
3827 
3828 // *******************************************************************************************
3829 // *
3830 // *	Reset
3831 // *
3832 // *******************************************************************************************
3833 //!
3834 //!
3835 // *******************************************************************************************
3836 
Reset(void)3837 void nAverager::Reset( void )
3838 {
3839     weightSquared_ = weight_ = sum_ = sumSquared_ = 0.0f;
3840 }
3841 
3842 // *******************************************************************************************
3843 // *
3844 // *	GetAverage
3845 // *
3846 // *******************************************************************************************
3847 //!
3848 //!		@return		the average value over the last time
3849 //!
3850 // *******************************************************************************************
3851 
GetAverage(void) const3852 REAL nAverager::GetAverage( void ) const
3853 {
3854     if ( weight_ > 0 )
3855         return sum_ / weight_;
3856     else
3857         return 0;
3858 }
3859 
3860 // *******************************************************************************************
3861 // *
3862 // *	GetDataVariance
3863 // *
3864 // *******************************************************************************************
3865 //!
3866 //!		@return		the average recent variance in the incoming data
3867 //!
3868 // *******************************************************************************************
3869 
GetDataVariance(void) const3870 REAL nAverager::GetDataVariance( void ) const
3871 {
3872     if ( weight_ > 0 )
3873     {
3874         REAL average       = sum_ / weight_;
3875         REAL averageSquare = sumSquared_ / weight_;
3876         REAL ret = averageSquare - average * average;
3877         if ( ret < 0 )
3878             ret = 0;
3879         return ret;
3880     }
3881     else
3882         return 0;
3883 }
3884 
3885 // *******************************************************************************************
3886 // *
3887 // *	GetAverageVariance
3888 // *
3889 // *******************************************************************************************
3890 //!
3891 //!		@return		the expected variance of the return value of GetAverage()
3892 //!
3893 // *******************************************************************************************
3894 
GetAverageVariance(void) const3895 REAL nAverager::GetAverageVariance( void ) const
3896 {
3897     if ( weight_ > 0 )
3898     {
3899         REAL square = weight_ * weight_;
3900 
3901         REAL denominator = square - weightSquared_;
3902         REAL numerator = GetDataVariance() * weightSquared_;
3903         if ( denominator > numerator * 1E-30 )
3904         {
3905             return numerator/denominator;
3906         }
3907         else
3908             return 1E+30;
3909     }
3910     else
3911         return 0;
3912 }
3913 
3914 // *******************************************************************************
3915 // *
3916 // *	operator <<
3917 // *
3918 // *******************************************************************************
3919 //!
3920 //!		@param	stream	stream to read from
3921 //!		@return		    stream for chaining
3922 //!
3923 // *******************************************************************************
3924 
operator <<(std::istream & stream)3925 std::istream & nAverager::operator <<( std::istream & stream )
3926 {
3927     char c;
3928     stream >> c;
3929     tASSERT( c == '(' );
3930 
3931     stream >> weight_ >> sum_ >> sumSquared_ >> weightSquared_;
3932 
3933     stream >> c;
3934     tASSERT( c == ')' );
3935 
3936     return stream;
3937 }
3938 
3939 // *******************************************************************************
3940 // *
3941 // *	operator >>
3942 // *
3943 // *******************************************************************************
3944 //!
3945 //!		@param	stream	stream to write to
3946 //!		@return		    stream for chaining
3947 //!
3948 // *******************************************************************************
3949 
operator >>(std::ostream & stream) const3950 std::ostream & nAverager::operator >>( std::ostream & stream ) const
3951 {
3952     stream << '(' << weight_ << ' ' << sum_  << ' ' << sumSquared_  << ' ' << weightSquared_  << ')';
3953 
3954     return stream;
3955 }
3956 
3957 // *******************************************************************************
3958 // *
3959 // *	operator >>
3960 // *
3961 // *******************************************************************************
3962 //!
3963 //!		@param	stream	stream to read to
3964 //!		@param  averager averager to read
3965 //!		@return		    stream for chaining
3966 //!
3967 // *******************************************************************************
3968 
operator >>(std::istream & stream,nAverager & averager)3969 std::istream & operator >> ( std::istream & stream, nAverager & averager )
3970 {
3971     return averager << stream;
3972 }
3973 
3974 // *******************************************************************************
3975 // *
3976 // *	operator <<
3977 // *
3978 // *******************************************************************************
3979 //!
3980 //!		@param	stream	stream to write to
3981 //!		@param  averager averager to write
3982 //!		@return		    stream for chaining
3983 //!
3984 // *******************************************************************************
3985 
operator <<(std::ostream & stream,nAverager const & averager)3986 std::ostream & operator << ( std::ostream & stream, nAverager const & averager )
3987 {
3988     return averager >> stream;
3989 }
3990 
3991 
3992 // *******************************************************************************************
3993 // *
3994 // *	nPingAverager
3995 // *
3996 // *******************************************************************************************
3997 //!
3998 //!
3999 // *******************************************************************************************
4000 
nPingAverager(void)4001 nPingAverager::nPingAverager( void )
4002 {
4003     Reset();
4004 }
4005 
4006 // *******************************************************************************************
4007 // *
4008 // *	~nPingAverager
4009 // *
4010 // *******************************************************************************************
4011 //!
4012 //!
4013 // *******************************************************************************************
4014 
~nPingAverager(void)4015 nPingAverager::~nPingAverager( void )
4016 {
4017 }
4018 
4019 // *******************************************************************************************
4020 // *
4021 // *	GetPing
4022 // *
4023 // *******************************************************************************************
4024 //!
4025 //!		@return		our best estimate for the ping
4026 //!
4027 // *******************************************************************************************
4028 
GetPing(void) const4029 REAL nPingAverager::GetPing( void ) const
4030 {
4031     // collect data
4032     // determine the lowest guessed value for variance.
4033     // lag spikes should not contribute here too much.
4034     REAL variance = 1;
4035     {
4036         REAL snailVariance = this->snail_.GetDataVariance();
4037         REAL slowVariance = this->slow_.GetDataVariance();
4038         REAL fastVariance = this->fast_.GetDataVariance();
4039         variance = variance < snailVariance ? variance : snailVariance;
4040         variance = variance < slowVariance ? variance : slowVariance;
4041         variance = variance < fastVariance ? variance : fastVariance;
4042     }
4043 
4044     REAL pingSnail  = this->GetPingSnail();
4045     REAL pingSlow   = this->GetPingSlow();
4046     REAL pingFast   = this->GetPingFast();
4047 
4048     // the proposed return value: defaults to the snail ping, it flucuates the least
4049     REAL pingReturn = pingSnail;
4050 
4051     // return slow average if that differs from the snail one by at least one standard deviation
4052     if ( ( pingSlow - pingReturn ) * ( pingSlow - pingReturn ) > variance )
4053     {
4054         // but clamp it to sane values
4055         if ( pingSlow > pingReturn * 2 )
4056             pingSlow = pingReturn * 2;
4057 
4058         pingReturn = pingSlow;
4059     }
4060 
4061     // same for fast ping
4062     if ( ( pingFast - pingReturn ) * ( pingFast - pingReturn ) > variance )
4063     {
4064         if ( pingFast > pingReturn * 2 )
4065             pingFast = pingReturn * 2;
4066 
4067         pingReturn = pingFast;
4068     }
4069 
4070     // return best estimate plus expected variance with fudge factor. It's better to err to the big ping side.
4071     return pingReturn + sqrtf(variance) * 1.5;
4072 }
4073 
4074 // *******************************************************************************************
4075 // *
4076 // *	operator REAL
4077 // *
4078 // *******************************************************************************************
4079 //!
4080 //!		@return		our best estimate for the ping
4081 //!
4082 // *******************************************************************************************
4083 
operator REAL(void) const4084 nPingAverager::operator REAL( void ) const
4085 {
4086     return GetPing();
4087 }
4088 
4089 // *******************************************************************************************
4090 // *
4091 // *	GetPingSlow
4092 // *
4093 // *******************************************************************************************
4094 //!
4095 //!		@return		extremely longterm ping average
4096 //!
4097 // *******************************************************************************************
4098 
GetPingSnail(void) const4099 REAL nPingAverager::GetPingSnail( void ) const
4100 {
4101     return snail_.GetAverage();
4102 }
4103 
4104 // *******************************************************************************************
4105 // *
4106 // *	GetPingSlow
4107 // *
4108 // *******************************************************************************************
4109 //!
4110 //!		@return		longterm ping average
4111 //!
4112 // *******************************************************************************************
4113 
GetPingSlow(void) const4114 REAL nPingAverager::GetPingSlow( void ) const
4115 {
4116     return slow_.GetAverage();
4117 }
4118 
4119 // *******************************************************************************************
4120 // *
4121 // *	GetPingFast
4122 // *
4123 // *******************************************************************************************
4124 //!
4125 //!		@return		shortterm ping average
4126 //!
4127 // *******************************************************************************************
4128 
GetPingFast(void) const4129 REAL nPingAverager::GetPingFast( void ) const
4130 {
4131     return fast_.GetAverage();
4132 }
4133 
4134 // *******************************************************************************************
4135 // *
4136 // *	IsSpiking
4137 // *
4138 // *******************************************************************************************
4139 //!
4140 //!		@return		true if unusual high fluctuations exist in the ping
4141 //!
4142 // *******************************************************************************************
4143 
IsSpiking(void) const4144 bool nPingAverager::IsSpiking( void ) const
4145 {
4146     REAL difference = slow_.GetAverage() - fast_.GetAverage();
4147     return slow_.GetAverageVariance() < difference * difference;
4148 }
4149 
4150 // *******************************************************************************************
4151 // *
4152 // *	Timestep
4153 // *
4154 // *******************************************************************************************
4155 //!
4156 //!		@param	decay	time since last timestep
4157 //!
4158 // *******************************************************************************************
4159 
Timestep(REAL decay)4160 void nPingAverager::Timestep( REAL decay )
4161 {
4162     snail_.Timestep( decay * .02 );
4163     slow_.Timestep ( decay * .2 );
4164     fast_.Timestep ( decay * 2 );
4165 }
4166 
4167 // *******************************************************************************************
4168 // *
4169 // *	Add
4170 // *
4171 // *******************************************************************************************
4172 //!
4173 //!		@param	value	the value to add
4174 //!		@param	weight	the value's statistical weight
4175 //!
4176 // *******************************************************************************************
4177 
Add(REAL value,REAL weight)4178 void nPingAverager::Add( REAL value, REAL weight )
4179 {
4180     // add value to both averagers
4181     snail_.Add( value, weight );
4182     slow_.Add ( value, weight );
4183     fast_.Add ( value, weight );
4184 }
4185 
4186 // *******************************************************************************************
4187 // *
4188 // *	Add
4189 // *
4190 // *******************************************************************************************
4191 //!
4192 //!		@param	value	the value to add with default weight
4193 //!
4194 // *******************************************************************************************
4195 
Add(REAL value)4196 void nPingAverager::Add( REAL value )
4197 {
4198     // add value to both averagers
4199     Add( value, weight_ );
4200 }
4201 
4202 // *******************************************************************************************
4203 // *
4204 // *	Reset
4205 // *
4206 // *******************************************************************************************
4207 //!
4208 //!
4209 // *******************************************************************************************
4210 
Reset(void)4211 void nPingAverager::Reset( void )
4212 {
4213     snail_.Reset();
4214     slow_. Reset();
4215     fast_. Reset();
4216 
4217     // fill in some low weight values
4218     Add( 1, .000001 );
4219     Add( 0, .000001 );
4220 
4221     // pin snail averager close to zero
4222     // snail_.Add(0,10);
4223     // not such a good idea after all. The above line caused massive resending of packets.
4224 }
4225 
4226 REAL nPingAverager::weight_=1;
4227 
4228 
4229 
4230 
4231 
4232 // *******************************************************************************
4233 // *
4234 // *	nMachine
4235 // *
4236 // *******************************************************************************
4237 //!
4238 //!
4239 // *******************************************************************************
4240 
nMachine(void)4241 nMachine::nMachine( void )
4242         : lastUsed_(tSysTimeFloat())
4243         , banned_(-1)
4244         , players_(0)
4245         , decorators_(0)
4246 {
4247     kph_.Add(0,.1666);
4248     lastPlayerAction_ = lastUsed_;
4249 }
4250 
4251 // *******************************************************************************
4252 // *
4253 // *	~nMachine
4254 // *
4255 // *******************************************************************************
4256 //!
4257 //!
4258 // *******************************************************************************
4259 
~nMachine(void)4260 nMachine::~nMachine( void )
4261 {
4262     // destroy and remove the decorators
4263     while ( decorators_ )
4264     {
4265         nMachineDecorator * decorator = decorators_;
4266         decorator->Remove();
4267         decorator->Destroy();
4268     }
4269 }
4270 
4271 // *******************************************************************************
4272 // *
4273 // *	operator ==
4274 // *
4275 // *******************************************************************************
4276 //!
4277 //!		@param	other	the machine to compare with
4278 //!		@return		    true if they are equal
4279 //!
4280 // *******************************************************************************
4281 
operator ==(nMachine const & other) const4282 bool nMachine::operator == ( nMachine const & other ) const
4283 {
4284     return this == &other;
4285 }
4286 
4287 // *******************************************************************************
4288 // *
4289 // *	operator !=
4290 // *
4291 // *******************************************************************************
4292 //!
4293 //!		@param	other	the machine to compare with
4294 //!		@return		    false if they are equal
4295 //!
4296 // *******************************************************************************
4297 
operator !=(nMachine const & other) const4298 bool nMachine::operator !=( nMachine const & other ) const
4299 {
4300     return this != &other;
4301 }
4302 
4303 // singleton machine map
4304 class nMachinePTR
4305 {
4306 public:
4307     mutable nMachine * machine;
nMachinePTR()4308     nMachinePTR(): machine(tNEW(nMachine)()){}
~nMachinePTR()4309     ~nMachinePTR(){tDESTROY(machine);}
nMachinePTR(nMachinePTR const & other)4310     nMachinePTR(nMachinePTR const & other): machine(other.machine){other.machine=0;}
operator =(nMachinePTR const & other)4311     nMachinePTR & operator=(nMachinePTR const & other){ machine = other.machine; other.machine=0;return *this;}
4312 };
4313 
4314 typedef std::map< tString, nMachinePTR > nMachineMap;
sn_GetMachineMap()4315 static nMachineMap & sn_GetMachineMap()
4316 {
4317     static nMachineMap map;
4318     return map;
4319 }
4320 
sn_LookupMachine(tString const & address)4321 static nMachine & sn_LookupMachine( tString const & address )
4322 {
4323     // get map of all machines and look address up
4324     nMachineMap & map = sn_GetMachineMap();
4325     return map[ address ].machine->SetIP( address );
4326 }
4327 
4328 // *******************************************************************************
4329 // *
4330 // *	GetMachine
4331 // *
4332 // *******************************************************************************
4333 //!
4334 //!		@param	userID	the user ID to fetch the machine for
4335 //!		@return		    the machine the user ID belongs to
4336 //!
4337 // *******************************************************************************
4338 
GetMachine(unsigned short userID)4339 nMachine & nMachine::GetMachine( unsigned short userID )
4340 {
4341     // throw out old machines
4342     Expire();
4343 
4344     // hardcoding: the server itself
4345     if ( userID == 0 && sn_GetNetState() != nCLIENT )
4346     {
4347         static nMachine server;
4348         return server;
4349     }
4350 
4351     tASSERT( userID <= MAXCLIENTS+1 );
4352 
4353     if( sn_GetNetState() != nSERVER )
4354     {
4355         // invalid ID, return invalid machine (clients don't track machines)
4356         static nMachine invalid;
4357         return invalid;
4358     }
4359 
4360     // get address
4361     tVERIFY( userID <= MAXCLIENTS+1 );
4362     if( !sn_Connections[userID].socket )
4363     {
4364         // invalid ID, return invalid machine
4365         static nMachine invalid;
4366         return invalid;
4367     }
4368     tString address;
4369     peers[ userID ].GetAddress( address );
4370 
4371 #ifdef DEBUG_X
4372     // add client ID so multiple connects from one machine are distinguished
4373     tString newIP;
4374     newIP << address << " " << userID;
4375     address = newIP;
4376 #endif
4377 
4378     // delegate
4379     return sn_LookupMachine( address );
4380 }
4381 
4382 // safely delete iterator from map
sn_Erase(nMachineMap & map,nMachineMap::iterator & iter)4383 static void sn_Erase( nMachineMap & map, nMachineMap::iterator & iter )
4384 {
4385     if ( iter != map.end() )
4386     {
4387         map.erase( iter );
4388         iter = map.end();
4389     }
4390 }
4391 
4392 // *******************************************************************************
4393 // *
4394 // *	Expire
4395 // *
4396 // *******************************************************************************
4397 //!
4398 //!
4399 // *******************************************************************************
4400 
Expire(void)4401 void nMachine::Expire( void )
4402 {
4403     static double lastTime = tSysTimeFloat();
4404     double time = tSysTimeFloat();
4405     REAL dt = time - lastTime;
4406     if (dt <= 60)
4407         return;
4408     lastTime = time;
4409 
4410     // iterate over known machines
4411     nMachineMap & map = sn_GetMachineMap();
4412     nMachineMap::iterator toErase = map.end();
4413     for( nMachineMap::iterator iter = map.begin(); iter != map.end(); ++iter )
4414     {
4415         // erase last deleted machine
4416         sn_Erase( map, toErase );
4417 
4418         nMachine & machine = *(*iter).second.machine;
4419 
4420         // advance the kick statistics if the user is not banned and has been active
4421         if ( time > machine.banned_ && ( machine.lastUsed_ > time - 300 || machine.players_ > 0 ) )
4422         {
4423             machine.kph_.Add( 0, dt / 3600 );
4424             machine.kph_.Timestep( dt / 3600*24 );
4425         }
4426 
4427         // if the machine is no longer in use, mark it for deletion
4428         if ( machine.players_ == 0 && machine.lastUsed_ < time - 300.0 && machine.banned_ < time && machine.kph_.GetAverage() < 0.5 )
4429             toErase = iter;
4430 
4431     }
4432 
4433     // erase last machine
4434     sn_Erase( map, toErase );
4435 }
4436 
4437 // maximal time a client without players is tolerated
4438 static REAL sn_spectatorTime = 0;
4439 static tSettingItem< REAL > sn_spectatorTimeConf( "NETWORK_SPECTATOR_TIME", sn_spectatorTime );
4440 
4441 // *******************************************************************************
4442 // *
4443 // *	KickSpectators
4444 // *
4445 // *******************************************************************************
4446 //!
4447 //!
4448 // *******************************************************************************
4449 
KickSpectators(void)4450 void nMachine::KickSpectators( void )
4451 {
4452     double time = tSysTimeFloat();
4453 
4454     // kick spectators
4455     if ( sn_GetNetState() == nSERVER && sn_spectatorTime > 0 )
4456     {
4457         for ( int i = MAXCLIENTS; i >= 1; --i )
4458         {
4459             if ( sn_Connections[i].socket )
4460             {
4461                 nMachine & machine = GetMachine( i );
4462                 if ( machine.players_ == 0 && machine.lastPlayerAction_ + sn_spectatorTime < time )
4463                 {
4464                     sn_KickUser( i, tOutput("$network_kill_spectator"), 0 );
4465                 }
4466             }
4467         }
4468     }
4469 }
4470 
4471 // settings for automatic banning
4472 static REAL sn_autobanOffset = 5;  // bias that gets subtracted from the kills per hour
4473 static REAL sn_autobanFactor = 10; // factor that gets multiplied on top of it to determine the ban time in minutes
4474 static REAL sn_autobanMaxKPH = 30; // maximal value of kph
4475 
4476 static tSettingItem< REAL > sn_autobanOffsetSetting( "NETWORK_AUTOBAN_OFFSET", sn_autobanOffset );
4477 static tSettingItem< REAL > sn_autobanFactorSetting( "NETWORK_AUTOBAN_FACTOR", sn_autobanFactor );
4478 static tSettingItem< REAL > sn_autobanMaxKPHSetting( "NETWORK_AUTOBAN_MAX_KPH", sn_autobanMaxKPH );
4479 
4480 // *******************************************************************************
4481 // *
4482 // *	OnKick
4483 // *
4484 // *******************************************************************************
4485 //!
4486 //! @param severity the severity of the offense; 1 is standard.
4487 //!
4488 // *******************************************************************************
4489 
OnKick(REAL severity)4490 void nMachine::OnKick( REAL severity )
4491 {
4492     // if the user is currently banned, don't count
4493     if ( banned_ > tSysTimeFloat() )
4494         return;
4495 
4496     // ban the user a bit, taking the kicks per hour into account
4497     REAL kph = kph_.GetAverage() - sn_autobanOffset;
4498     if ( kph > 0 )
4499     {
4500         // the faster you get kicked when you turn up, the longer you get banned
4501         REAL banTime = 60 * kph * sn_autobanFactor;
4502         Ban( banTime, tString(tOutput( "$network_ban_kick" )) );
4503     }
4504 
4505     // add it to the statistics
4506     if ( sn_autobanMaxKPH > 0 )
4507         kph_.Add( severity * sn_autobanMaxKPH, 2/sn_autobanMaxKPH );
4508 
4509     con << tOutput( "$network_ban_kph", GetIP(), GetKicksPerHour() );
4510 }
4511 
4512 static bool sn_printBans = true;
4513 
4514 // *******************************************************************************
4515 // *
4516 // *	Ban
4517 // *
4518 // *******************************************************************************
4519 //!
4520 //!		@param	time	time in seconds the ban should be in effect
4521 //!
4522 // *******************************************************************************
4523 
Ban(REAL time)4524 void nMachine::Ban( REAL time )
4525 {
4526     lastUsed_ = tSysTimeFloat();
4527 
4528     // set the banning timeout to the current time plus the given time
4529     banned_ = tSysTimeFloat() + time;
4530 
4531     if ( sn_printBans )
4532     {
4533         if ( time > 0 )
4534             con << tOutput( "$network_ban", GetIP(), int(time/60), banReason_.Len() > 1 ? banReason_ : tOutput( "$network_ban_noreason" ) );
4535         else
4536             con << tOutput( "$network_noban", GetIP() );
4537     }
4538 }
4539 
4540 // *******************************************************************************
4541 // *
4542 // *	Ban
4543 // *
4544 // *******************************************************************************
4545 //!
4546 //!		@param	time	time in seconds the ban should be in effect
4547 //!		@param	reason	the reason for the ban
4548 //!
4549 // *******************************************************************************
4550 
Ban(REAL time,tString const & reason)4551 void nMachine::Ban( REAL time, tString const & reason )
4552 {
4553     banReason_ = tString();
4554     if ( reason.Len() > 2 )
4555         banReason_ = reason;
4556 
4557     Ban( time );
4558 }
4559 
4560 // *******************************************************************************
4561 // *
4562 // *	IsBanned
4563 // *
4564 // *******************************************************************************
4565 //!
4566 //!		@return		kick time left
4567 //!
4568 // *******************************************************************************
4569 
IsBanned(void) const4570 REAL nMachine::IsBanned( void ) const
4571 {
4572     // test for banning
4573     double time = tSysTimeFloat();
4574     if ( time > banned_ )
4575         return 0;
4576 
4577     return banned_ - time;
4578 }
4579 
4580 // *******************************************************************************
4581 // *
4582 // *	AddPlayer
4583 // *
4584 // *******************************************************************************
4585 //!
4586 //!
4587 // *******************************************************************************
4588 
AddPlayer(void)4589 void nMachine::AddPlayer( void )
4590 {
4591     lastPlayerAction_ = lastUsed_ = tSysTimeFloat();
4592 
4593     players_++;
4594 }
4595 
4596 // *******************************************************************************
4597 // *
4598 // *	RemovePlayer
4599 // *
4600 // *******************************************************************************
4601 //!
4602 //!
4603 // *******************************************************************************
4604 
RemovePlayer(void)4605 void nMachine::RemovePlayer( void )
4606 {
4607     lastPlayerAction_ = lastUsed_ = tSysTimeFloat();
4608 
4609     players_--;
4610     if ( players_ < 0 )
4611         players_ = 0;
4612 }
4613 
4614 // *******************************************************************************
4615 // *
4616 // *	GetPlayerCount
4617 // *
4618 // *******************************************************************************
4619 //!
4620 //!		@return		the number of currently connected players
4621 //!
4622 // *******************************************************************************
4623 
GetPlayerCount(void)4624 int nMachine::GetPlayerCount( void )
4625 {
4626     return players_;
4627 }
4628 
4629 
4630 static char const * sn_machinesFileName = "bans.txt";
4631 
4632 class nMachinePersistor
4633 {
4634 public:
4635     // save ban info of machines
SaveMachines()4636     static void SaveMachines()
4637     {
4638         std::ofstream s;
4639         if (tDirectories::Var().Open( s, sn_machinesFileName ) )
4640         {
4641             nMachineMap & map = sn_GetMachineMap();
4642             for( nMachineMap::iterator iter = map.begin(); iter != map.end(); ++iter )
4643             {
4644                 nMachine & machine = *(*iter).second.machine;
4645                 // if ( machine.IsBanned() > 0 )
4646                 {
4647                     s << (*iter).first << " " << machine.IsBanned() << " " << machine.kph_ << " " << machine.GetBanReason() << "\n";
4648                 }
4649             }
4650         }
4651     }
4652 
4653     // load and enter ban info of machines
LoadMachines()4654     static void LoadMachines()
4655     {
4656         sn_printBans = false;
4657 
4658         tTextFileRecorder machines( tDirectories::Var(), sn_machinesFileName );
4659         while ( !machines.EndOfFile() )
4660         {
4661             std::stringstream line( machines.GetLine() );
4662 
4663             // address and ban time left
4664             tString address;
4665             REAL banTime;
4666 
4667             // read relevant info
4668             line >> address >> banTime;
4669             std::ws(line);
4670 
4671             // read kph averager
4672             nAverager kph;
4673             char c;
4674             line.get(c);
4675             line.putback(c);
4676             if ( c == '(' )
4677             {
4678                 line >> kph;
4679                 std::ws(line);
4680             }
4681 
4682             // read reason
4683             tString reason;
4684             reason.ReadLine( line );
4685 
4686             if ( address.Len() > 2 )
4687             {
4688                 // ban
4689                 nMachine & machine = sn_LookupMachine( address );
4690                 machine.Ban( banTime, reason );
4691                 machine.kph_ = kph;
4692             }
4693         }
4694 
4695         sn_printBans = true;
4696     }
4697 }
4698 ;
4699 // save ban info of machines
sn_SaveMachines()4700 static void sn_SaveMachines()
4701 {
4702     nMachinePersistor::SaveMachines();
4703 }
4704 
4705 // load and enter ban info of machines
sn_LoadMachines()4706 static void sn_LoadMachines()
4707 {
4708     nMachinePersistor::LoadMachines();
4709 }
4710 
4711 // *******************************************************************************
4712 // *
4713 // *	GetKicksPerHour
4714 // *
4715 // *******************************************************************************
4716 //!
4717 //!		@return		averaged kicks per hour of players from this machine
4718 //!
4719 // *******************************************************************************
4720 
GetKicksPerHour(void) const4721 REAL nMachine::GetKicksPerHour( void ) const
4722 {
4723     return this->kph_.GetAverage();
4724 }
4725 
4726 // *******************************************************************************
4727 // *
4728 // *	GetKicksPerHour
4729 // *
4730 // *******************************************************************************
4731 //!
4732 //!		@param	kph	averaged kicks per hour of players from this machine to fill
4733 //!		@return		A reference to this to allow chaining
4734 //!
4735 // *******************************************************************************
4736 
GetKicksPerHour(REAL & kph) const4737 nMachine const & nMachine::GetKicksPerHour( REAL & kph ) const
4738 {
4739     kph = this->kph_.GetAverage();
4740     return *this;
4741 }
4742 
4743 // *******************************************************************************
4744 // *
4745 // *	GetIP
4746 // *
4747 // *******************************************************************************
4748 //!
4749 //!		@return		IP address of the machine
4750 //!
4751 // *******************************************************************************
4752 
GetIP(void) const4753 tString const & nMachine::GetIP( void ) const
4754 {
4755     return this->IP_;
4756 }
4757 
4758 // *******************************************************************************
4759 // *
4760 // *	GetIP
4761 // *
4762 // *******************************************************************************
4763 //!
4764 //!		@param	IP	IP address of the machine to fill
4765 //!		@return		A reference to this to allow chaining
4766 //!
4767 // *******************************************************************************
4768 
GetIP(tString & IP) const4769 nMachine const & nMachine::GetIP( tString & IP ) const
4770 {
4771     IP = this->IP_;
4772     return *this;
4773 }
4774 
4775 // *******************************************************************************
4776 // *
4777 // *	SetIP
4778 // *
4779 // *******************************************************************************
4780 //!
4781 //!		@param	IP	IP address of the machine to set
4782 //!		@return		A reference to this to allow chaining
4783 //!
4784 // *******************************************************************************
4785 
SetIP(tString const & IP)4786 nMachine & nMachine::SetIP( tString const & IP )
4787 {
4788     lastUsed_ = tSysTimeFloat();
4789 
4790     this->IP_ = IP;
4791     return *this;
4792 }
4793 
4794 // *******************************************************************************
4795 // *
4796 // *	GetBanReason
4797 // *
4798 // *******************************************************************************
4799 //!
4800 //!		@return		Reason of the ban
4801 //!
4802 // *******************************************************************************
4803 
GetBanReason(void) const4804 tString const & nMachine::GetBanReason( void ) const
4805 {
4806     return this->banReason_;
4807 }
4808 
4809 // *******************************************************************************
4810 // *
4811 // *	GetBanReason
4812 // *
4813 // *******************************************************************************
4814 //!
4815 //!		@param	reason	Reason of the ban to fill
4816 //!		@return		A reference to this to allow chaining
4817 //!
4818 // *******************************************************************************
4819 
GetBanReason(tString & reason) const4820 nMachine const & nMachine::GetBanReason( tString & reason ) const
4821 {
4822     reason = this->banReason_;
4823     return *this;
4824 }
4825 
4826 // *******************************************************************************
4827 // *
4828 // *	Banning and unbanning
4829 // *
4830 // *******************************************************************************
4831 
4832 // unban IPs
sn_UnBanConf(std::istream & s)4833 static void sn_UnBanConf(std::istream &s)
4834 {
4835     if ( !s.good() || s.eof() )
4836     {
4837         con << "Usage: UNBAN_IP <ip>\n";
4838         return;
4839     }
4840 
4841     // read IP to unban
4842     tString address;
4843     s >> address;
4844 
4845     if ( address.Len() < 8 )
4846     {
4847         con << "Usage: UNBAN_IP <ip>, no or too short ip given.\n";
4848     }
4849     // and unban
4850     else
4851     {
4852         sn_LookupMachine( address ).Ban( 0 );
4853     }
4854 }
4855 
4856 static tConfItemFunc sn_unBanConf("UNBAN_IP",&sn_UnBanConf);
4857 
4858 // ban IPs
sn_BanConf(std::istream & s)4859 static void sn_BanConf(std::istream &s)
4860 {
4861     // read IP to unban
4862     tString address;
4863     s >> address;
4864 
4865     if ( !s.good() && address.Len() < 7 )
4866     {
4867         con << "Usage: BAN_IP <ip> <time in minutes (defaults to 60)> <reason>\n";
4868         return;
4869     }
4870 
4871     REAL duration = 60;
4872     s >> duration;
4873 
4874     // read reason
4875     tString reason;
4876     std::ws(s);
4877     if ( s.good() )
4878     {
4879         reason.ReadLine(s);
4880     }
4881 
4882     // and ban
4883     if ( address.Len() > 4 )
4884     {
4885         sn_LookupMachine( address ).Ban( duration * 60, reason );
4886     }
4887 }
4888 
4889 static tConfItemFunc sn_banConf("BAN_IP",&sn_BanConf);
4890 
4891 // list bans
sn_ListBanConf(std::istream & s)4892 static void sn_ListBanConf(std::istream &s)
4893 {
4894     nMachineMap & map = sn_GetMachineMap();
4895     for( nMachineMap::iterator iter = map.begin(); iter != map.end(); ++iter )
4896     {
4897         nMachine & machine = *(*iter).second.machine;
4898         REAL banned = machine.IsBanned();
4899         if ( banned > 0 )
4900         {
4901             con << tOutput( "$network_ban", machine.GetIP(), int(banned/60), machine.GetBanReason() );
4902         }
4903     }
4904 }
4905 
4906 static tConfItemFunc sn_listBanConf("BAN_LIST",&sn_ListBanConf);
4907 
4908 // *******************************************************************************
4909 // *
4910 // *	OnDestroy
4911 // *
4912 // *******************************************************************************
4913 //!
4914 //!
4915 // *******************************************************************************
4916 
OnDestroy(void)4917 void nMachineDecorator::OnDestroy( void )
4918 {
4919 }
4920 
4921 // *******************************************************************************
4922 // *
4923 // *	nMachineDecorator
4924 // *
4925 // *******************************************************************************
4926 //!
4927 //!
4928 // *******************************************************************************
4929 
nMachineDecorator(void)4930 nMachineDecorator::nMachineDecorator( void )
4931 {
4932 }
4933 
4934 // *******************************************************************************
4935 // *
4936 // *	~nMachineDecorator
4937 // *
4938 // *******************************************************************************
4939 //!
4940 //!
4941 // *******************************************************************************
4942 
~nMachineDecorator(void)4943 nMachineDecorator::~nMachineDecorator( void )
4944 {
4945     Remove();
4946 }
4947 
4948 // *******************************************************************************
4949 // *
4950 // *	nMachineDecorator
4951 // *
4952 // *******************************************************************************
4953 //!
4954 //!		@param	machine
4955 //!
4956 // *******************************************************************************
4957 
nMachineDecorator(nMachine & machine)4958 nMachineDecorator::nMachineDecorator( nMachine & machine )
4959 {
4960     Insert( machine.decorators_ );
4961 }
4962 
4963