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