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