~evan-nelson/armagetronad/armagetronad+pcm

« back to all changes in this revision

Viewing changes to src/network/nNetwork.cpp

Attempting to create a timeout for PLAYER_CENTER_MESSAGE.

Show diffs side-by-side

added added

removed removed

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