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 #ifndef ArmageTron_NET_H
29 #define ArmageTron_NET_H
30
31 #include "tError.h"
32 #include "tString.h"
33 #include "tHeap.h"
34 #include "tLinkedList.h"
35 #include "tCallback.h"
36 #include "nObserver.h"
37 //#include "tCrypt.h"
38 #include "tException.h"
39 #include <memory>
40
41 class nSocket;
42 class nAddress;
43 class nBasicNetworkSystem;
44 class nServerInfoBase;
45
46 extern nBasicNetworkSystem sn_BasicNetworkSystem;
47
48 class nMessage;
49 class tCrypt;
50 class tOutput;
51
52 typedef double nTimeAbsolute; // typedef for absolute time variables in network code
53 typedef double nTimeRolling; // typedef for time variables in network code that don't have to measure large time differences
54
55 extern tString sn_bigBrotherString; // the string that is sent
56 // to the server for system information
57
58 extern tString sn_programVersion; // our version
59
60 extern tString sn_serverName; // telling name of the server
61
62 extern unsigned int sn_serverPort; // port we listen on when in server mode
63 extern const unsigned int sn_defaultPort; // default port a server listens on
64
65 extern int sn_defaultDelay;
66
67 extern bool sn_decorateTS;
68
69 extern tString sn_DenyReason; // the reason the server gave for sending a login_deny packet
70
71 // rate control
72 extern int sn_maxRateIn,sn_maxRateOut;
73
74 //! exception that is thrown on any unexpected network error;
75 //! causes the owner of the current nNetObject or the sender of
76 //! the currently processed netmessage to be killed.
77 class nKillHim: public tException
78 {
79 public:
80 nKillHim();
81 ~nKillHim();
82
83 private:
84 virtual tString DoGetName() const; //!< returns the name of the exception
85 virtual tString DoGetDescription() const; //!< returns a detailed description
86 };
87
88 //! exception that is thrown on errors where it is safe to just ignore the
89 //! offending packet.
90 class nIgnore: public nKillHim
91 {
92 public:
93 nIgnore();
94 ~nIgnore();
95
96 private:
97 virtual tString DoGetName() const; //!< returns the name of the exception
98 virtual tString DoGetDescription() const; //!< returns a detailed description
99 };
100
101 // call this function on any error occuring while reading a message:
102 void nReadError( bool critical = true );
103
104 #ifndef MAXCLIENTS
105 #ifdef DEDICATED
106 #define MAXCLIENTS 32
107 #else
108 #define MAXCLIENTS 16
109 #endif
110 #endif
111
112 // We can be single player, multiplayer server/client.
113 typedef enum {nSTANDALONE,nSERVER,nCLIENT} nNetState;
114 typedef enum {nOK, nTIMEOUT, nDENIED, nABORT} nConnectError;
115
116
117 // set/get the state
118 nConnectError sn_GetLastError();
119 nNetState sn_GetNetState();
120 void sn_SetNetState(nNetState x);
121 void sn_DisconnectUser(int i, const tOutput& reason, nServerInfoBase * redirectTo = 0 ); //!< terminate connection with user i (peacefully)
122 void sn_KickUser(int i, const tOutput& reason, REAL severity = 1, nServerInfoBase * redirectTo = 0 ); //!< throw out user i (violently)
123
124 void sn_GetAdr(int user, tString& name);
125 unsigned int sn_GetPort(int user);
126 unsigned int sn_GetServerPort();
127 int sn_NumUsers();
128 int sn_MaxUsers();
129 int sn_MessagesPending(int user);
130
131 // information about currently supported versions
132 class nVersion
133 {
134 public:
135 nVersion();
136 nVersion( int min, int max );
137 bool Supported( int version ) const; // check if a particular version is supported
138 bool Merge( const nVersion& a,
139 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
140
Min()141 int Min() const { return min_;}
Max()142 int Max() const { return max_;}
143
144 bool operator != ( const nVersion& other ){ return !operator==(other); }
145 bool operator == ( const nVersion& other );
146 nVersion& operator = ( const nVersion& other );
147 private:
148 int min_, max_;
149 };
150
151 nMessage& operator >> ( nMessage& m, nVersion& ver );
152 nMessage& operator << ( nMessage& m, const nVersion& ver );
153
154 std::istream& operator >> ( std::istream& s, nVersion& ver );
155 std::ostream& operator << ( std::ostream& s, const nVersion& ver );
156
157 const nVersion& sn_MyVersion(); //!< the version this progam maximally supports
158 const nVersion& sn_CurrentVersion(); //!< the version currently supported by all connected players
159 void sn_UpdateCurrentVersion(); //!< updates the sn_CurrentVersion()
160
161 // features that are not available in all currently supported versions
162 class nVersionFeature
163 {
164 public:
165 nVersionFeature( int min, int max = -1 ); // creates a feature that is supported from version min to max; values of -1 indicate no border
166 bool Supported() const; // returns whether this feature is supported by everyone
167 bool Supported( int client ) const; // returns whether this feature is supported by a certain client ( resp. the server in client mode )
168 private:
169 int min_, max_;
170 };
171
172 class nBandwidthControl;
173
174 // send buffer: stores network messages temporarily before really sending them
175 class nSendBuffer
176 {
177 public:
Len()178 int Len () const { return sendBuffer_.Len(); } // returns the length of the buffer
179
180 void AddMessage ( nMessage& message
181 , nBandwidthControl* control ); // adds a message to the buffer
182 void Send ( nSocket const & socket
183 , const nAddress & peer
184 , nBandwidthControl* control ); // send the contents of the buffer to a specific socket
185 void Broadcast ( nSocket const & socket
186 , int port
187 , nBandwidthControl* control ); // broadcast the contents of the buffer
188
189 void Clear(); // clears the buffer
190
191 private:
192 tArray<unsigned short> sendBuffer_;
193 };
194
195 class nBandwidthControl
196 {
197 public:
198 enum Usage
199 {
200 Usage_Planning,
201 Usage_Execution
202 };
203
204 nBandwidthControl( nBandwidthControl* parent = NULL );
205 ~nBandwidthControl();
206 void Reset();
207
SetRate(unsigned short rate)208 void SetRate( unsigned short rate ){ rate_ = rate; }
Rate()209 unsigned short Rate() { return rate_; }
210
Control(Usage planned)211 REAL Control( Usage planned ){ return Usage_Planning == planned ? rateControlPlanned_ : rateControl_;}
212 void Use( Usage planned, REAL bandwidth );
213
CanSend()214 bool CanSend(){ return rateControlPlanned_ > 0; }
Score()215 REAL Score(){ return rateControlPlanned_ / rate_; }
216
217 void Update( REAL ts);
218 private:
219 REAL rateControlPlanned_;
220 REAL rateControl_;
221 unsigned short rate_;
222 nBandwidthControl* parent_;
223 #ifdef DEBUG
224 int numChildren_;
225 #endif
226 };
227
228 //! class responsible for calculating averages
229 class nAverager
230 {
231 public:
232 nAverager(); //!< constructor
233 ~nAverager(); //!< destructor
234 REAL GetAverage() const; //!< returns the average value
235 REAL GetDataVariance() const; //!< returns the variance of the data ( average of (value-average)^2 )
236 REAL GetAverageVariance() const; //!< returns the expected variance of the returned average
237 void Timestep( REAL decay ); //!< lets all values decay, so they can be replaced by new ones
238 void Add( REAL value, REAL weight=1 ); //!< adds a value to the average
239 void Reset(); //!< resets average to zero
240
241 std::istream & operator << ( std::istream & stream ); //!< read operator
242 std::ostream & operator >> ( std::ostream & stream ) const; //!< write operator
243 private:
244 REAL weight_; //!< the total statistical weight
245 REAL sum_; //!< the total sum of value*weight
246 REAL sumSquared_; //!< the total sum of value*value*weight
247 REAL weightSquared_;//!< the sum of all weights, squared
248 };
249
250 //! read operator for nAveragers
251 std::istream & operator >> ( std::istream & stream, nAverager & averager );
252
253 //! write operator for nAveragers
254 std::ostream & operator << ( std::ostream & stream, nAverager const & averager );
255
256 //! averager for pings, detects lag
257 class nPingAverager
258 {
259 public:
260 nPingAverager(); //!< constructor
261 ~nPingAverager(); //!< destructor
262
263 operator REAL() const; //!< conversion to number == GetPing()
264
265 REAL GetPing() const; //!< returns the current best estimate for the ping
266 REAL GetPingSnail() const; //!< returns the extremely longterm average ping
267 REAL GetPingSlow() const; //!< returns the longterm average ping
268 REAL GetPingFast() const; //!< returns the shortterm average ping
269 bool IsSpiking() const ; //!< returns whether a lag spike is currently in process
270 void Timestep( REAL decay ); //!< lets all values decay, so they can be replaced by new ones
271 void Add( REAL value, REAL weight ); //!< adds a value to the average
272 void Add( REAL value ); //!< adds a value to the average
273 void Reset(); //!< resets average to zero
274 private:
275 nAverager snail_; //!< extremely slow averager
276 nAverager slow_; //!< slow, reliable averager
277 nAverager fast_; //!< fast averager for detecting ping spikes
278 static REAL weight_; //!< current default weight
279 public:
280 // accessors
281 inline static void SetWeight( REAL const & weight ); //!< Sets the default statistical weight
282 inline static REAL GetWeight( void ); //!< Gets the default statistical weight
283 inline static void GetWeight( REAL & weight ); //!< Gets the default statistical weight
284 inline nAverager const & GetSnailAverager( void ) const; //!< Gets extremely slow averager
285 inline nPingAverager const & GetSnailAverager( nAverager & snail ) const; //!< Gets extremely slow averager
286 inline nAverager const & GetSlowAverager( void ) const; //!< Gets slow, reliable averager
287 inline nPingAverager const & GetSlowAverager( nAverager & slow ) const; //!< Gets slow, reliable averager
288 inline nAverager const & GetFastAverager( void ) const; //!< Gets fast averager for detecting ping spikes
289 inline nPingAverager const & GetFastAverager( nAverager & fast ) const; //!< Gets fast averager for detecting ping spikes
290 protected:
291 inline nPingAverager & SetSnailAverager( nAverager const & snail ); //!< Sets very slow averager
292 inline nPingAverager & SetSlowAverager( nAverager const & slow ); //!< Sets slow, reliable averager
293 inline nPingAverager & SetFastAverager( nAverager const & fast ); //!< Sets fast averager for detecting ping spikes
294 };
295
296 struct nConnectionInfo // everything that is needed to manage a connection
297 {
298 nSocket const * socket; // the network UDP socket
299 int ackPending;
300
301 nPingAverager ping;
302
303 // tCrypt* crypt;
304
305 // rate control
306 nBandwidthControl bandwidthControl_;
307
308 // send buffer
309 nSendBuffer sendBuffer_;
310
311 // version info
312 nVersion version;
313
314 // ack messages
315 tJUST_CONTROLLED_PTR< nMessage > ackMess;
316
317 // authentication
318 // tString userName;
319
320 // supported authentication methods of the client in a comma separated list
321 tString supportedAuthenticationMethods_;
322
323 nConnectionInfo();
324 ~nConnectionInfo();
325
326 void Clear();
327 void Timestep( REAL dt ); //!< call to update time related information
328
329 void ReliableMessageSent(); //!< call whenever an an reliable message got sent
330 void AckReceived(); //!< call whenever an ackownledgement message arrives
331 REAL PacketLoss() const; //!< returns the average packet loss ratio
332 private:
333 // packet loss measurement
334 nAverager packetLoss_;
335
336 };
337
338 extern nConnectionInfo sn_Connections[MAXCLIENTS+2];
339
340 extern int sn_maxNoAck;
341 //extern int sn_ackPending[MAXCLIENTS+2];
342 //extern int sn_sockets[MAXCLIENTS+2];
343 //extern REAL sn_ping[MAXCLIENTS+2];
344
345 // types of login
346 enum nLoginType
347 {
348 Login_Pre0252, // use the login method known to pre-0.2.5.2 versions
349 Login_Post0252, // use the newer login method
350 Login_All // first attempt the new one, then the old one
351 };
352
353 // go to client mode and connect to server
354 nConnectError sn_Connect(nAddress const & server, nLoginType loginType = Login_All, nSocket const * socket = NULL );
355
356 // let the server connection socket point to a new server (EVIL!)
357 void sn_Bend( nAddress const & server );
358 void sn_Bend( tString const & server, unsigned int port );
359
360 extern int sn_myNetID; // our network identification: 0: server
361 // 1..MAXCLIENTS: client
362
363 // Network messages and functions that know how to handle them:
364
365 class nMessage;
366 typedef void nHandler(nMessage &m);
367
368
369 // types of network messages
370 class nDescriptor:public tListItem<nDescriptor>{
371 friend class nMessage;
372
373 static unsigned short s_nextID;
374
375 unsigned short id; // our id
376 nHandler *handler; // function responsible for our type of message
377
378 const char *name;
379
380 const bool acceptWithoutLogin;
381 public:
382 nDescriptor(unsigned short identification,nHandler *handle
383 ,const char *name, bool acceptEvenIfNotLoggedIn = false);
384 // nDescriptor(nHandler *handle,
385 // const char *name);
386 static void HandleMessage(nMessage &message);
387
ID()388 unsigned short ID(){return id;}
389 };
390
391 // register the routine that gives the peer the server/client information
392 // (game type, number of players online....)
393 void RequestInfoHandler(nHandler *handle);
394
395 // the first sn_myNetID available for external use (give some room!)
396 #define NET_ID_FIRST 100
397
398 // Network messages. Allways to be created with new, get deleted automatically.
399
400 class nMessage: public tReferencable< nMessage >{
401 //friend class nMessage_planned_send;
402 friend class tControlledPTR< nMessage >;
403 friend class tReferencable< nMessage >;
404
405 friend class nDescriptor;
406 friend class nNetObject;
407 friend class nWaitForAck;
408
409 // void AddRef();
410 // void Release();
411
412 protected:
413 unsigned short descriptor; // the network message type id
414 // unsigned short messageID_; // the network message id, every message gets its own (up to overflow)
415 unsigned long messageIDBig_; // uniquified message ID, the last 16 bits are the same as messageID_
416 short senderID; // sender's identification
417 tArray<unsigned short> data; // assuming ints are 32 bit wide...
418
419 unsigned int readOut;
420
421 ~nMessage();
422 public:
Descriptor()423 unsigned short Descriptor() const{
424 return descriptor;
425 }
426
SenderID()427 unsigned short SenderID() const{
428 return senderID;
429 }
430
MessageID()431 unsigned short MessageID() const{
432 return messageIDBig_ & 0xFFFF;
433 }
434
MessageIDBig()435 unsigned long MessageIDBig() const{
436 return messageIDBig_;
437 }
438
DataLen()439 unsigned short DataLen() const{
440 return data.Len();
441 }
442
Data(unsigned short n)443 unsigned short Data(unsigned short n){
444 return data(n);
445 }
446
ClearMessageID()447 void ClearMessageID(){ // clear the message ID so no acks are sent for it
448 messageIDBig_ = 0;
449 }
450
451 nMessage(const nDescriptor &); // create a new message
452 nMessage(unsigned short*& buffer, short sn_myNetID, int lenLeft );
453 // read a message from the network stream
454
455 // immediately send the message WITHOUT the queue; dangerous!
456 void SendImmediately(int peer,bool ack=true);
457
458 // flush the buffers of that peer
459 static void SendCollected(int peer);
460
461 // broadcast the same information across the LAN
462 static void BroadcastCollected(int peer, unsigned int port);
463
464 // send it to anyone who is interested
465 // (the server in client mode, all clients in server mode)
466 void BroadCast(bool ack=true);
467
468 // put the message into the send heap
469 void Send(int peer,REAL priority=0,bool ack=true);
470
Write(const unsigned short & x)471 void Write(const unsigned short &x){
472 data[data.Len()]=x;
473 }
474
475 nMessage& operator<< (const REAL &x);
476 nMessage& operator>> (REAL &x);
477
478 nMessage& operator<< (const unsigned short &x){Write(x);return *this;}
479 nMessage& operator>> (unsigned short &x){Read(x);return *this;}
480
481 nMessage& operator<< (const double &x){
482 return operator<<(REAL(x));
483 }
484
485 nMessage& operator>> (double &x){
486 REAL y;
487 operator>>(y);
488 x=y;
489
490 return *this;
491 }
492
493 // read a string without any kind of filtering
494 nMessage& ReadRaw(tString &s);
495
496 nMessage& operator >> (tString &s);
497 nMessage& operator >> (tColoredString &s);
498 nMessage& operator << (const tString &s);
499 nMessage& operator << (const tColoredString &s);
500 nMessage& operator << (const tOutput &o);
501
BinWrite(const T & x)502 template<class T> void BinWrite (const T &x){
503 for(unsigned int i=0;i<sizeof(T)/2;i++)
504 Write((reinterpret_cast<const unsigned short *>(&x))[i]);
505 }
506
End()507 bool End(){return readOut>=static_cast<unsigned int>(data.Len());}
508
Reset()509 void Reset(){readOut=0;}
510
511 void Read(unsigned short &x);
512
BinRead(const T & x)513 template<class T> void BinRead (const T &x){
514 for(unsigned int i=0;i<sizeof(T)/2;i++)
515 Read(reinterpret_cast<unsigned short *>(&x)[i]);
516 }
517
518
519 nMessage& operator<< (const short &x);
520 nMessage& operator>> (short &x);
521
522 nMessage& operator<< (const int &x);
523 nMessage& operator>> (int &x);
524
525 nMessage& operator<< (const unsigned int &x){operator<<(reinterpret_cast<const int&>(x));return *this;}
526 nMessage& operator>> (unsigned int &x){operator>>(reinterpret_cast<int&>(x));return *this;}
527
528 nMessage& operator<< (const bool &x);
529 nMessage& operator>> (bool &x);
530
531 template <class T> nMessage& operator<<(const tArray<T>& a)
532 {
533 unsigned short len = a.Len();
534 Write(len);
535 for (int i=a.Len()-1; i>=0; i--)
536 operator<< (a(i));
537
538 return *this;
539 }
540
541 template <class T> nMessage& operator>>(tArray<T>& a)
542 {
543 unsigned short len;
544 Read(len);
545 a.SetLen(len);
546 for (int i=a.Len()-1; i>=0; i--)
547 operator >> (a(i));
548
549 return *this;
550 }
551
552 template<class T> nMessage& operator << (const T* p)
553 {
554 if (p)
555 Write( p->ID() );
556 else
557 Write(0);
558
559 return *this;
560 }
561
562 // template<class T> nMessage& operator >> ( T*& p );
563
564 template<class T> nMessage& operator << (const tControlledPTR<T> p)
565 {
566 if (p)
567 Write( p->ID() );
568 else
569 Write(0);
570
571 return *this;
572 }
573
574 // template<class T> nMessage& operator >> ( tControlledPTR<T>& p );
575 };
576
577
578
579 // the class that is responsible for getting acknowleEdgement for
580 // netmessages
581
582 class nWaitForAck{
583 protected:
584 int id;
585 tCONTROLLED_PTR(nMessage) message; // the message
586 int receiver; // the computer who should send the ack
587 REAL timeout; // the time in seconds between send attempts
588 nTimeRolling timeSendAgain; // for timeout
589 nTimeRolling timeFirstSent; // for ping calculation
590 nTimeRolling timeLastSent; // for ping calculation
591 int timeouts;
592
593 public:
594 nWaitForAck(nMessage* m,int rec);
595 virtual ~nWaitForAck();
596
AckExtraAction()597 virtual void AckExtraAction(){}
598
599 static void Ackt(unsigned short id,unsigned short peer);
600
601 static void AckAllPeer(unsigned short peer);
602
603 static void Resend();
604 };
605
606
607 //! pause a bit, abort pause on network activity
608 void sn_Delay();
609
610 // process the messages from all hosts and send acks
611 void sn_Receive();
612
613 // receive and process data from control socket (used on master server to ping servers)
614 extern void sn_ReceiveFromControlSocket();
615
616 // receive and discard data from control socket (used on regular servers to keep the pipe clean)
617 extern void sn_DiscardFromControlSocket();
618
619 // attempts to sync with server/all clients (<=> wait for all acks)
620 // sync_netObjects: if set, network objects are synced as well
621 // otherEnd: if set, the client instructs the server to send all packets and waits for completion.
622 // if unset, the client just sends all packets and hopes for the best.
623 void sn_Sync(REAL timeout,bool sync_sn_netObjects=false, bool otherEnd=true); // defined in nNetObject.C
624
625 // causes the connected clients to print a message
626 void sn_ConsoleOut(const tOutput &message,int client=-1);
627 nMessage* sn_ConsoleOutMessage( tString const & message );
628
629 // causes the connected clients to print a message in the center of the screeen
630 void sn_CenterMessage(const tOutput &message,int client=-1);
631
632
633 // **********************************************
634
635
636 class nCallbackLoginLogout: public tCallback{
637 static int user;
638 static bool login;
639 public:
User()640 static int User(){return user;}
Login()641 static int Login(){return login;}
642
643 nCallbackLoginLogout(VOIDFUNC *f);
644 static void UserLoggedIn(int user);
645 static void UserLoggedOut(int user);
646 };
647
648 class nCallbackAcceptPackedWithoutConnection: public tCallbackOr{
649 static unsigned short descriptor; // the descriptor of the incoming packet
650 public:
Descriptor()651 static unsigned int Descriptor(){return descriptor;}
652
653 nCallbackAcceptPackedWithoutConnection(BOOLRETFUNC *f);
654
655 static bool Accept( const nMessage& m );
656 };
657
658 class nCallbackReceivedComplete: public tCallback
659 {
660 public:
661 nCallbackReceivedComplete(VOIDFUNC *f);
662 static void ReceivedComplete();
663 };
664
665 void sn_SendPlanned();
666 int sn_QueueLen(int user);
667
668 void sn_Statistics();
669
670 //! return the public IP address and port of this machine, or "*.*.*.*:*" if it is unknown..
671 tString const & sn_GetMyAddress();
672
673 //! checks wheter a given address is on the user's LAN (or on loopback).
674 bool sn_IsLANAddress( tString const & address );
675
676 // the SenderID of the currently handled message is stored here for reference
677 class nCurrentSenderID
678 {
679 public:
nCurrentSenderID()680 nCurrentSenderID():lastSenderID_( currentSenderID_ ){}
nCurrentSenderID(int senderID)681 nCurrentSenderID( int senderID ):lastSenderID_( currentSenderID_ ){ SetID( senderID ); }
~nCurrentSenderID()682 ~nCurrentSenderID(){ currentSenderID_ = lastSenderID_; }
683
GetID()684 static int GetID(){ return currentSenderID_; }
SetID(int senderID)685 void SetID( int senderID ){ currentSenderID_ = senderID; }
686 private:
687 int lastSenderID_;
688 static int currentSenderID_;
689 };
690
691 class nMachine;
692
693 //! a decorator for machines for additional information to attach to them
694 class nMachineDecorator: public tListItem< nMachineDecorator >
695 {
696 public:
697 inline void Destroy(); //!< called when machine gets destroyed
698 protected:
699 virtual void OnDestroy(); //!< called when machine gets destroyed
700
701 nMachineDecorator( nMachine & machine ); //!< constructor
702 virtual ~nMachineDecorator(); //!< destructor
703 private:
704 nMachineDecorator(); //!< constructor
705 };
706
707 //! class trying to collect information about a certain client, persistent between connections
708 class nMachine
709 {
710 friend class nMachineDecorator;
711 friend class nMachinePersistor;
712 public:
713 nMachine(); //!< constructor
714 virtual ~nMachine(); //!< destructor
715
716 bool operator == ( nMachine const & other ) const; //!< equality operator
717 bool operator != ( nMachine const & other ) const; //!< inequality operator
718
719 static nMachine & GetMachine( unsigned short userID ); //!< fetches the machine information of a user
720 static void Expire(); //!< expires machine information that is no longer needed
721 static void KickSpectators(); //!< remove clients without players from the server
722
723 // kicking
724 void OnKick( REAL severity = 1 ); //!< call this when you kick a user from this machine, frequent kickees will be banned
725
726 // banning
727 void Ban( REAL time ); //!< ban users from this machine for the given time
728 void Ban( REAL time, tString const & reason ); //!< ban users from this machine for the given time
729 REAL IsBanned() const; //!< returns the number of seconds users from this machine are currently banned for
730
731 // player accounting
732 void AddPlayer(); //!< call when a player joins from this machine
733 void RemovePlayer(); //!< call when a player rom this machine leaves
734 int GetPlayerCount(); //!< returns the number of currently registered players
735 private:
736 nMachine( nMachine const & other ); //!< copy constructor
737 nMachine & operator = ( nMachine const & other ); //!< copy operator
738
739 // variables
740 mutable double lastUsed_; //!< system time where this machine was last used
741 mutable double banned_; //!< system time until that this machine is banned
742 tString banReason_; //!< reason for a ban
743 nAverager kph_; //!< averaged kicks per hour of players from this machine
744 int players_; //!< number of players coming from this machine currently
745 REAL lastPlayerAction_; //!< time of the last player action
746
747 tString IP_; //!< IP address of the machine
748 nMachineDecorator * decorators_; //!< list of decorators
749
750 // accessors
751 public:
752 REAL GetKicksPerHour( void ) const; //!< Gets averaged kicks per hour of players from this machine
753 nMachine const & GetKicksPerHour( REAL & kph ) const; //!< Gets averaged kicks per hour of players from this machine
754 nMachine & SetIP( tString const & IP ); //!< Sets IP address of the machine
755 tString const & GetIP( void ) const; //!< Gets IP address of the machine
756 nMachine const & GetIP( tString & IP ) const; //!< Gets IP address of the machine
757 tString const & GetBanReason( void ) const; //!< Gets the reason of the ban
758 nMachine const & GetBanReason( tString & reason )const;//!< Gets the reason of the ban
759 inline nMachineDecorator * GetDecorators( void ) const; //!< Gets list of decorators
760 inline nMachine const & GetDecorators( nMachineDecorator * & decorators ) const; //!< Gets list of decorators
761
762 //! returns the next machine decorator of a given type
GetNextDecorator(nMachineDecorator * run)763 template< class T > static T * GetNextDecorator( nMachineDecorator * run )
764 {
765 while ( run )
766 {
767 T * ret = dynamic_cast< T * >( run );
768 if ( ret )
769 {
770 return ret;
771 }
772 run = run->Next();
773 }
774
775 return 0;
776 }
777
778 //! returns the first machine decorator of a given type
GetDecorator()779 template< class T > T * GetDecorator()
780 {
781 return GetNextDecorator< T >( GetDecorators() );
782 }
783 protected:
784 private:
785 inline nMachine & SetDecorators( nMachineDecorator * decorators ); //!< Sets list of decorators
786 };
787
788 //! while an object of this class exists, the main network sockets won't get reopened
789 class nSocketResetInhibitor
790 {
791 public:
792 nSocketResetInhibitor();
793 ~nSocketResetInhibitor();
794 };
795
796 // on disconnection, this returns a server we should be redirected to (or NULL if we should not be redirected)
797 std::auto_ptr< nServerInfoBase > sn_GetRedirectTo();
798
799 // take a peek at the same info
800 nServerInfoBase * sn_PeekRedirectTo();
801
802
803 // *******************************************************************************************
804 // *
805 // * GetWeight
806 // *
807 // *******************************************************************************************
808 //!
809 //! @return the default statistical weight
810 //!
811 // *******************************************************************************************
812
GetWeight(void)813 REAL nPingAverager::GetWeight( void )
814 {
815 return weight_;
816 }
817
818 // *******************************************************************************************
819 // *
820 // * GetWeight
821 // *
822 // *******************************************************************************************
823 //!
824 //! @param weight the default statistical weight to fill
825 //!
826 // *******************************************************************************************
827
GetWeight(REAL & weight)828 void nPingAverager::GetWeight( REAL & weight )
829 {
830 weight = weight_;
831 }
832
833 // *******************************************************************************************
834 // *
835 // * SetWeight
836 // *
837 // *******************************************************************************************
838 //!
839 //! @param weight the default statistical weight to set
840 //!
841 // *******************************************************************************************
842
SetWeight(REAL const & weight)843 void nPingAverager::SetWeight( REAL const & weight )
844 {
845 weight_ = weight;
846 }
847
848 // *******************************************************************************************
849 // *
850 // * GetSnailAverager
851 // *
852 // *******************************************************************************************
853 //!
854 //! @return slow, reliable averager
855 //!
856 // *******************************************************************************************
857
GetSnailAverager(void)858 nAverager const & nPingAverager::GetSnailAverager( void ) const
859 {
860 return this->snail_;
861 }
862
863 // *******************************************************************************************
864 // *
865 // * GetSnailAverager
866 // *
867 // *******************************************************************************************
868 //!
869 //! @param snail very slow averager to fill
870 //! @return A reference to this to allow chaining
871 //!
872 // *******************************************************************************************
873
GetSnailAverager(nAverager & snail)874 nPingAverager const & nPingAverager::GetSnailAverager( nAverager & snail ) const
875 {
876 snail = this->snail_;
877 return *this;
878 }
879
880 // *******************************************************************************************
881 // *
882 // * SetSnailAverager
883 // *
884 // *******************************************************************************************
885 //!
886 //! @param snail very slow averager to set
887 //! @return A reference to this to allow chaining
888 //!
889 // *******************************************************************************************
890
SetSnailAverager(nAverager const & snail)891 nPingAverager & nPingAverager::SetSnailAverager( nAverager const & snail )
892 {
893 this->snail_ = snail;
894 return *this;
895 }
896 // *******************************************************************************************
897 // *
898 // * GetSlowAverager
899 // *
900 // *******************************************************************************************
901 //!
902 //! @return slow, reliable averager
903 //!
904 // *******************************************************************************************
905
GetSlowAverager(void)906 nAverager const & nPingAverager::GetSlowAverager( void ) const
907 {
908 return this->slow_;
909 }
910
911 // *******************************************************************************************
912 // *
913 // * GetSlowAverager
914 // *
915 // *******************************************************************************************
916 //!
917 //! @param slow slow, reliable averager to fill
918 //! @return A reference to this to allow chaining
919 //!
920 // *******************************************************************************************
921
GetSlowAverager(nAverager & slow)922 nPingAverager const & nPingAverager::GetSlowAverager( nAverager & slow ) const
923 {
924 slow = this->slow_;
925 return *this;
926 }
927
928 // *******************************************************************************************
929 // *
930 // * SetSlowAverager
931 // *
932 // *******************************************************************************************
933 //!
934 //! @param slow slow, reliable averager to set
935 //! @return A reference to this to allow chaining
936 //!
937 // *******************************************************************************************
938
SetSlowAverager(nAverager const & slow)939 nPingAverager & nPingAverager::SetSlowAverager( nAverager const & slow )
940 {
941 this->slow_ = slow;
942 return *this;
943 }
944
945 // *******************************************************************************************
946 // *
947 // * GetFastAverager
948 // *
949 // *******************************************************************************************
950 //!
951 //! @return fast averager for detecting ping spikes
952 //!
953 // *******************************************************************************************
954
GetFastAverager(void)955 nAverager const & nPingAverager::GetFastAverager( void ) const
956 {
957 return this->fast_;
958 }
959
960 // *******************************************************************************************
961 // *
962 // * GetFastAverager
963 // *
964 // *******************************************************************************************
965 //!
966 //! @param fast fast averager for detecting ping spikes to fill
967 //! @return A reference to this to allow chaining
968 //!
969 // *******************************************************************************************
970
GetFastAverager(nAverager & fast)971 nPingAverager const & nPingAverager::GetFastAverager( nAverager & fast ) const
972 {
973 fast = this->fast_;
974 return *this;
975 }
976
977 // *******************************************************************************************
978 // *
979 // * SetFastAverager
980 // *
981 // *******************************************************************************************
982 //!
983 //! @param fast fast averager for detecting ping spikes to set
984 //! @return A reference to this to allow chaining
985 //!
986 // *******************************************************************************************
987
SetFastAverager(nAverager const & fast)988 nPingAverager & nPingAverager::SetFastAverager( nAverager const & fast )
989 {
990 this->fast_ = fast;
991 return *this;
992 }
993
994 // *******************************************************************************
995 // *
996 // * Destroy
997 // *
998 // *******************************************************************************
999 //!
1000 //!
1001 // *******************************************************************************
1002
Destroy(void)1003 void nMachineDecorator::Destroy( void )
1004 {
1005 this->OnDestroy();
1006 }
1007
1008 // *******************************************************************************
1009 // *
1010 // * GetDecorators
1011 // *
1012 // *******************************************************************************
1013 //!
1014 //! @return list of decorators
1015 //!
1016 // *******************************************************************************
1017
GetDecorators(void)1018 nMachineDecorator * nMachine::GetDecorators( void ) const
1019 {
1020 return this->decorators_;
1021 }
1022
1023 // *******************************************************************************
1024 // *
1025 // * GetDecorators
1026 // *
1027 // *******************************************************************************
1028 //!
1029 //! @param decorators list of decorators to fill
1030 //! @return A reference to this to allow chaining
1031 //!
1032 // *******************************************************************************
1033
GetDecorators(nMachineDecorator * & decorators)1034 nMachine const & nMachine::GetDecorators( nMachineDecorator * & decorators ) const
1035 {
1036 decorators = this->decorators_;
1037 return *this;
1038 }
1039
1040 // *******************************************************************************
1041 // *
1042 // * SetDecorators
1043 // *
1044 // *******************************************************************************
1045 //!
1046 //! @param decorators list of decorators to set
1047 //! @return A reference to this to allow chaining
1048 //!
1049 // *******************************************************************************
1050
SetDecorators(nMachineDecorator * decorators)1051 nMachine & nMachine::SetDecorators( nMachineDecorator * decorators )
1052 {
1053 this->decorators_ = decorators;
1054 return *this;
1055 }
1056
1057 #endif
1058
1059
1060
1061
1062