~swag/armagetronad/0.2.9-sty+ct+ap-fork

« back to all changes in this revision

Viewing changes to src/network/nNetwork.cpp

  • Committer: Voodoo
  • Date: 2011-07-28 18:46:18 UTC
  • mfrom: (563.24.161 merge)
  • Revision ID: voodoo-20110728184618-0djbrm75ftd07c4v
merge -r 1285..1297 lp:armagetronad/0.2.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
201
201
nConnectionInfo sn_Connections[MAXCLIENTS+2];
202
202
 
203
203
static nAddress peers[MAXCLIENTS+2]; // the same logic for the peer adresses.
 
204
static nAddress lastPeers[MAXCLIENTS+2]; // the peers last connected to each slot
204
205
static int timeouts[MAXCLIENTS+2];
205
206
 
206
207
#define ACKBACK 1000
628
629
 
629
630
// *************************************************************
630
631
 
 
632
// random offset
 
633
static int sn_GetRandomOffset()
 
634
{
 
635
    static tReproducibleRandomizer rand;
 
636
    return rand.Get(0x7fffffff);
 
637
}
 
638
 
 
639
// syn cookie
 
640
static int sn_SynTimestamp()
 
641
{
 
642
    static int offset = sn_GetRandomOffset();
 
643
 
 
644
    return offset + tSysTimeFloat()/16;
 
645
}
 
646
 
 
647
// a cookie consists of two shorts, each transmitted as MessageID
 
648
// of two consecutive fake login accept packets. They'll be sent back
 
649
// to the server inside ONE ack message by a real, non-spoofed client.
 
650
struct nCookie
 
651
{
 
652
    unsigned short first; 
 
653
    unsigned short second;
 
654
 
 
655
    nCookie(): first(0), second(0){}
 
656
};
 
657
 
 
658
static void sn_SynGenerateCookie(int stamp, nAddress const & sender, nCookie & ret)
 
659
{
 
660
    // just some random modulus.
 
661
    static const unsigned int modulo = 0x7f71fa35;
 
662
    stamp %= modulo;
 
663
 
 
664
    // calculate just some random checksum. Doesn't need to be any good,
 
665
    // we can change it any time should someone be able to predict it.
 
666
    int checksum = stamp;
 
667
    int mul = ( stamp & 0x7fff ) + 3;
 
668
    sockaddr const * sock = sender;
 
669
    for(int i = sender.GetAddressLength()-1; i >= 0; --i )
 
670
    {
 
671
        ++mul;
 
672
        checksum += (checksum >> 16) * mul;
 
673
        checksum += reinterpret_cast< char const * >( sock )[i];
 
674
        checksum %= modulo;
 
675
    }
 
676
 
 
677
    // message IDs must not be 0, so we need to add a 1 offset and can't
 
678
    // do the usual &0xffff / >>16 split.
 
679
    ret.first = ( checksum % 0xfffe ) + 1;
 
680
    ret.second = (checksum + 1 - ret.first)/0xfffe + 1;
 
681
}
 
682
 
 
683
static void sn_SynGenerateCookie(int stamp, nMessage const &m, nCookie & ret)
 
684
{
 
685
    sn_SynGenerateCookie( stamp, peers[m.SenderID()], ret );
 
686
}
 
687
 
 
688
 
 
689
// *************************************************************
 
690
 
631
691
 
632
692
void ack_handler(nMessage &m){
633
 
    while (!m.End()){
 
693
    if( m.SenderID() == MAXCLIENTS+1 )
 
694
    {
 
695
    // check for syn cookie response
 
696
        nCookie cookie;
 
697
        if(m.End())
 
698
        {
 
699
            return;
 
700
        }
 
701
        m.Read(cookie.first);
 
702
        if(m.End())
 
703
        {
 
704
            return;
 
705
        }
 
706
        m.Read(cookie.second);
 
707
        if(!m.End())
 
708
        {
 
709
            return;
 
710
        }
 
711
 
 
712
        int stamp = sn_SynTimestamp();
 
713
        for(int offset=0; offset >= -1; --offset)
 
714
        {
 
715
            nCookie correct;
 
716
            sn_SynGenerateCookie( stamp+offset , m, correct );
 
717
            if( correct.first == cookie.first && correct.second == cookie.second )
 
718
            {
 
719
                nMachine::GetMachine( m.SenderID() ).Validate();
 
720
            }
 
721
        }
 
722
            
 
723
        return;
 
724
    }
 
725
 
 
726
    while (!m.End())
 
727
    {
634
728
        sn_Connections[m.SenderID()].AckReceived();
635
729
 
636
730
        unsigned short ack;
640
734
    }
641
735
}
642
736
 
643
 
static nDescriptor s_Acknowledge(1,ack_handler,"ack");
 
737
static nDescriptor s_Acknowledge(1,ack_handler,"ack",true);
644
738
 
645
739
 
646
740
class nWaitForAck;
940
1034
    tRecorderSync< unsigned short >::Archive( "_MESSAGE_DECL_IN", 3, descriptor );
941
1035
 
942
1036
    unsigned short len=ntohs(*(buffer++));
943
 
    lenLeft--;
 
1037
    lenLeft-=3;
944
1038
    if ( len > lenLeft )
945
1039
    {
946
1040
        len = lenLeft;
1494
1588
 
1495
1589
void login_accept_handler(nMessage &m){
1496
1590
    if (sn_GetNetState()!=nSERVER && m.SenderID() == 0){
 
1591
        if(m.End())
 
1592
        {
 
1593
            // fake login accept sent only for cookie ack response. ignore.
 
1594
            return;
 
1595
        }
 
1596
 
1497
1597
        unsigned short id=0;
1498
1598
        m.Read(id);
1499
1599
 
1667
1767
static REAL sn_minBan    = 120; // minimal ban time in seconds for trying to connect while you're banned
1668
1768
static tSettingItem< REAL > sn_minBanSetting( "NETWORK_MIN_BAN", sn_minBan );
1669
1769
 
1670
 
// defined in nServerInfo.cpp
1671
 
extern bool FloodProtection( nMessage const & m );
1672
1770
 
1673
1771
// flag to disable 0.2.8 test version lockout
1674
1772
static bool sn_lockOut028tTest = true;
1677
1775
// the network stuff planned to send:
1678
1776
tHeap<planned_send> send_queue[MAXCLIENTS+2];
1679
1777
 
 
1778
// defined in nServerInfo.cpp
 
1779
extern bool FloodProtection( nMachine & machine, REAL timeFactor=1.0 );
 
1780
 
 
1781
// time factor for incoming connections, lower makes turtle mode kick in later
 
1782
static REAL sn_minConnectionTimeGlobalFactor = 0.1;
 
1783
static tSettingItem< REAL > sn_minPingTimeGlobal( "CONNECTION_FLOOD_SENSITIVITY", sn_minConnectionTimeGlobalFactor );
 
1784
 
 
1785
// enforce turtle mode
 
1786
static bool sn_forceTurtleMode = false;
 
1787
static tSettingItem< bool > sn_forceTurtleModeConf( "FORCE_TURTLE_MODE", sn_forceTurtleMode );
 
1788
 
 
1789
// keep recording even in turtle mode
 
1790
static bool sn_recordTurtleMode = false;
 
1791
static tSettingItem< bool > sn_recordTurtleModeConf( "RECORD_TURTLE_MODE", sn_recordTurtleMode );
 
1792
 
 
1793
// enforce the anti-spoof login part of turtle mode at all times
 
1794
static bool sn_synCookie = false;
 
1795
static tSettingItem< bool > sn_synCookieConf( "ANTI_SPOOF", sn_synCookie );
 
1796
 
 
1797
 
 
1798
// number of packets from unknown sources to process each call to rec_peer
 
1799
static int sn_connectionLimit = 100;
 
1800
static tSettingItem< int > sn_connectionLimitConf( "CONNECTION_LIMIT", sn_connectionLimit );
 
1801
 
 
1802
// turtle mode control
 
1803
class nTurtleControl
 
1804
{
 
1805
    REAL lastTurtleModeTime; // last time turtle mode was activated
 
1806
    bool setThisFrame;
 
1807
 
 
1808
    // true while we're turtling from a flood
 
1809
    bool turtleMode;
 
1810
public:
 
1811
    nTurtleControl()
 
1812
    : lastTurtleModeTime(-700)
 
1813
    , setThisFrame(false)
 
1814
    , turtleMode(false)
 
1815
    {
 
1816
    }
 
1817
 
 
1818
    operator bool() const
 
1819
    {
 
1820
        return turtleMode;
 
1821
    }
 
1822
 
 
1823
    // activates turtle mode. It will persist for at least 60 seconds.
 
1824
    void SetTurtleMode()
 
1825
    {
 
1826
        if( !setThisFrame )
 
1827
        {
 
1828
            if( !turtleMode )
 
1829
            {
 
1830
                // report
 
1831
                sn_ConsoleOut( tOutput("$turtle_mode_activated") ); 
 
1832
 
 
1833
                // stop recording
 
1834
                if( !sn_recordTurtleMode && tRecorder::IsRecording() )
 
1835
                {
 
1836
                    tRecorder::StopRecording();
 
1837
                }
 
1838
            }
 
1839
 
 
1840
            turtleMode = true;
 
1841
            setThisFrame = true;
 
1842
            lastTurtleModeTime = tSysTimeFloat();
 
1843
            
 
1844
        }
 
1845
    }
 
1846
 
 
1847
    void Update()
 
1848
    {
 
1849
        setThisFrame = false;
 
1850
        if( lastTurtleModeTime + 60 < tSysTimeFloat() )
 
1851
        {
 
1852
            if( turtleMode && !sn_forceTurtleMode )
 
1853
            {
 
1854
                // report
 
1855
                sn_ConsoleOut( tOutput("$turtle_mode_deactivated") ); 
 
1856
            }
 
1857
 
 
1858
            turtleMode = sn_forceTurtleMode;
 
1859
        }
 
1860
    }
 
1861
};
 
1862
static nTurtleControl sn_turtleMode;
 
1863
 
 
1864
// checks for global flood events
 
1865
static inline bool GlobalConnectionFloodProtection( REAL extraFactor = 1.0f )
 
1866
{
 
1867
    static nMachine server;
 
1868
 
 
1869
    if( sn_minConnectionTimeGlobalFactor > 0 && FloodProtection( server, sn_minConnectionTimeGlobalFactor*extraFactor ) )
 
1870
    {
 
1871
        sn_turtleMode.SetTurtleMode();
 
1872
    }
 
1873
    
 
1874
    return sn_turtleMode;
 
1875
}
 
1876
 
 
1877
// checks for individual flood events
 
1878
bool IndividualConnectionFloodProtection( nMachine * machine, int peer,  REAL extraFactor = 1.0f )
 
1879
{
 
1880
    // IP is not spoofed or there is no
 
1881
    // current spoof heavy attack. Really look up the machine.
 
1882
    if( !machine )
 
1883
    {
 
1884
        machine = &nMachine::GetMachine( peer );
 
1885
    }
 
1886
    
 
1887
    // check individual flood protection (be lenient in turtle mode, login responses may have trouble getting through an attack)
 
1888
    return FloodProtection( *machine, ( sn_turtleMode ? .2 : 1 ) * extraFactor );
 
1889
}
 
1890
 
 
1891
// report login failure. Or don't if we're flooded.
 
1892
int sn_ReportFailure(nMessage &m, char const * reason)
 
1893
{
 
1894
    if( !sn_turtleMode )
 
1895
    {
 
1896
        sn_DisconnectUser(m.SenderID(), reason);
 
1897
    }
 
1898
 
 
1899
    return -1;
 
1900
}
 
1901
 
1680
1902
int login_handler( nMessage &m, unsigned short rate ){
1681
1903
    nCurrentSenderID senderID;
1682
1904
 
1725
1947
            con << tOutput( "$network_ban", machine.GetIP() , int(banned/60), reason.Len() > 1 ? reason : tOutput( "$network_ban_noreason" ) );
1726
1948
 
1727
1949
        sn_DisconnectUser(m.SenderID(), tOutput( "$network_kill_banned", int(banned/60), reason ) );
 
1950
 
 
1951
        return -1;
1728
1952
    }
1729
1953
 
1730
1954
    // ignore multiple logins
1731
1955
    if( CountSameConnection( m.SenderID() ) > 0 )
1732
1956
        return -1;
1733
1957
 
1734
 
    // ignore login floods
1735
 
    if ( FloodProtection( m ) )
1736
 
        return -1;
1737
 
 
1738
1958
    bool success=false;
1739
1959
 
1740
1960
    int new_id = -1;
1746
1966
    nVersion mergedVersion;
1747
1967
    if ( !mergedVersion.Merge( version, sn_CurrentVersion() ) )
1748
1968
    {
1749
 
        sn_DisconnectUser(m.SenderID(), "$network_kill_incompatible");
 
1969
        return sn_ReportFailure(m, "$network_kill_incompatible");
1750
1970
    }
1751
1971
 
1752
1972
    // expire 0.2.8 test versions, they have a security flaw
1753
1973
    if ( sn_lockOut028tTest && version.Max() >= 5 && version.Max() <= 10 )
1754
1974
    {
1755
 
        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.");
 
1975
        return sn_ReportFailure(m, "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.");
1756
1976
    }
1757
1977
 
1758
1978
    if (m.SenderID()!=MAXCLIENTS+1)
1773
1993
            if ( new_id > 0 )
1774
1994
            {
1775
1995
                if(sn_Connections[new_id].socket)
 
1996
                {
1776
1997
                    sn_DisconnectUser( new_id, "$network_kill_full" );
 
1998
                }
1777
1999
 
1778
2000
                success = true;
1779
2001
 
1858
2080
    }
1859
2081
    else if (m.SenderID()==MAXCLIENTS+1)
1860
2082
    {
1861
 
        sn_DisconnectUser(MAXCLIENTS+1, "$network_kill_full");
 
2083
        return sn_ReportFailure(m, "$network_kill_full");
1862
2084
    }
1863
2085
 
1864
2086
    sn_UpdateCurrentVersion();
2249
2471
 
2250
2472
typedef std::deque< tJUST_CONTROLLED_PTR< nMessage > > nMessageFifo;
2251
2473
 
 
2474
// from nServerInfo.cpp
 
2475
extern nDescriptor RequestSmallServerInfoDescriptor, RequestBigServerInfoDescriptor;
 
2476
 
2252
2477
static void rec_peer(unsigned int peer){
2253
2478
    tASSERT( sn_Connections[peer].socket );
2254
2479
 
 
2480
    sn_turtleMode.Update();
2255
2481
    nMachine::Expire();
2256
2482
 
2257
2483
    // temporary fifo for received messages
2259
2485
    static nMessageFifo receivedMessages;
2260
2486
 
2261
2487
    // the growing buffer we read messages into
 
2488
#ifndef DEDICATED
2262
2489
    const int serverMaxAcceptedSize=2000;
 
2490
#endif
2263
2491
    static tArray< unsigned short > storage(2000);
2264
2492
    int maxrec = 0; maxrec = storage.Len();
2265
2493
    unsigned short * buff = 0; buff = &storage[0];
2276
2504
            if (len>0){
2277
2505
                if ( len >= maxrec*2 )
2278
2506
                {
 
2507
#ifndef DEDICATED
2279
2508
                    // the message was too long to receive. What to do?
2280
2509
                    if ( sn_GetNetState() != nSERVER || len < serverMaxAcceptedSize )
2281
2510
                    {
2287
2516
 
2288
2517
                        tERR_WARN( "Oversized network packet received. Read buffer has been enlargened to catch it the next time.");
2289
2518
 
2290
 
                        // no use in processing the truncated packet. Some messages may get lost,
2291
 
                        // but that's better than the inevitable network error and connection
2292
 
                        // termination that expects us if we go on.
2293
 
                        continue;
2294
2519
                    }
2295
2520
                    else
 
2521
#endif
2296
2522
                    {
2297
 
                        // terminate the connection
2298
 
                        sn_DisconnectUser( peer, "$network_kill_error" );
 
2523
                        // packet WAAAAY too large.
 
2524
                        static float totalFatsoes = 10;  // number of oversized packages checked
 
2525
                        static float clientFatsoes = 10; // number of oversized pacakges that could be attributed to clients
 
2526
                        static float bother = 5;         // counter that determines whether we bother to check.
 
2527
                        bother+=clientFatsoes;
 
2528
 
 
2529
                        // what follows is work, so we only do it if it payed off in the past
 
2530
                        // if this block is entered not at all by error, no biggie. The clients
 
2531
                        // will time out eventually.
 
2532
                        bool success = false;
 
2533
                        if(bother>totalFatsoes)
 
2534
                        {
 
2535
                            bother-=totalFatsoes;
 
2536
 
 
2537
                            // increase total stat
 
2538
                            totalFatsoes++;
 
2539
 
 
2540
                            // If it's from a connected client,
 
2541
                            // terminate the connection. If not, it's an attack and
 
2542
                            // we should rather ignore it.
 
2543
                            for( int id=MAXCLIENTS; id > 0; --id )
 
2544
                            {
 
2545
                                if (sn_Connections[id].socket && peers[id] == addrFrom)
 
2546
                                {
 
2547
                                    sn_DisconnectUser( id, "$network_kill_error" );
 
2548
                                    success=true;
 
2549
                                }
 
2550
                            }
 
2551
 
 
2552
                            // count the successfully removed client
 
2553
                            if( success )
 
2554
                            {
 
2555
                                clientFatsoes++;
 
2556
                            }
 
2557
 
 
2558
                            // scale down the stats
 
2559
                            const float factor=.99;
 
2560
                            totalFatsoes*=factor;
 
2561
                            clientFatsoes*=factor;
 
2562
                            bother*=factor;
 
2563
                        }
 
2564
 
 
2565
                        if( !success )
 
2566
                        {
 
2567
                            // check for global and local spam (just for reporting, the packet
 
2568
                            // is going to get blocked either way)
 
2569
                            REAL severity = len*.5/MAX_MESS_LEN;
 
2570
                            if( !GlobalConnectionFloodProtection( severity ) )
 
2571
                            {
 
2572
                                peers[ MAXCLIENTS+1] = addrFrom;
 
2573
                                IndividualConnectionFloodProtection( NULL, MAXCLIENTS+1, severity );
 
2574
                            }
 
2575
                        }
2299
2576
                    }
 
2577
 
 
2578
                    // no use in processing the truncated packet. Some messages may get lost,
 
2579
                    // but that's better than the inevitable network error and connection
 
2580
                    // termination that expects us if we go on.
 
2581
                    continue;
2300
2582
                }
2301
2583
 
2302
2584
                unsigned short *b=buff;
2317
2599
                */
2318
2600
                count ++;
2319
2601
 
 
2602
                // set if only the first message of the packet is to be processed.
 
2603
                bool onlyReadFirstMessage = false;
 
2604
 
2320
2605
                unsigned int id=peer;
2321
2606
                //       for(unsigned int i=1;i<=(unsigned int)maxclients;i++)
2322
2607
                int comp=nAddress::Compare( addrFrom, peers[claim_id] );
2327
2612
                }
2328
2613
                else
2329
2614
                {
 
2615
                    // check for communication from last partner
 
2616
                    if( claim_id > 0 && 0 == nAddress::Compare( addrFrom, lastPeers[claim_id] ) )
 
2617
                    {
 
2618
                        // ignore. The peer think it's still a client, but it's wrong.
 
2619
                        // new login packets, pings etc. all come with claim_id == 0.
 
2620
                        continue;
 
2621
                    }
 
2622
 
2330
2623
                    // assume it's a new connection
2331
2624
                    id = MAXCLIENTS+1;
2332
2625
                    peers[ MAXCLIENTS+1 ] = addrFrom;
2333
2626
                    sn_Connections[ MAXCLIENTS+1 ].socket = sn_Connections[peer].socket;
 
2627
 
 
2628
// #define NO_GLOBAL_FLOODPROTECTION
 
2629
#ifndef NO_GLOBAL_FLOODPROTECTION
 
2630
                    // flood check for pings, logins and other potential nasties; as early as possible
 
2631
                    if( sn_turtleMode && count > sn_connectionLimit*10 )
 
2632
                    {
 
2633
                        continue;
 
2634
                    }
 
2635
 
 
2636
                    nMachine * machine = nMachine::PeekMachine( peer );
 
2637
 
 
2638
                    if( sn_GetNetState() == nSERVER )
 
2639
                    {
 
2640
                        // check whether we're currently getting flooded
 
2641
                        GlobalConnectionFloodProtection();
 
2642
 
 
2643
                        if( sn_turtleMode || sn_synCookie )
 
2644
                        {
 
2645
                            // peek at descriptor
 
2646
                            unsigned short descriptor = ntohs(*b);
 
2647
 
 
2648
                            // do some extra checks
 
2649
                            if( descriptor == s_Acknowledge.ID() )
 
2650
                            {
 
2651
                                // this must be the cookie response triggered by the code below.
 
2652
                                // allow it, but be careful to only read the first message.
 
2653
                                onlyReadFirstMessage = true;
 
2654
                            }
 
2655
                            else if( descriptor == login_accept.ID() )
 
2656
                            {
 
2657
                                // Hah. Nice trick. Won't work, though.
 
2658
                            }
 
2659
                            else if( !sn_turtleMode && 
 
2660
                                     ( descriptor == RequestSmallServerInfoDescriptor.ID() || 
 
2661
                                       descriptor == RequestBigServerInfoDescriptor.ID() ) )
 
2662
                            {
 
2663
                                // Pings. Let them in unless we're under real attack.
 
2664
                                onlyReadFirstMessage = true;
 
2665
                            }
 
2666
                            else if( !machine || !machine->IsValidated() )
 
2667
                            {
 
2668
                                if( count > sn_connectionLimit )
 
2669
                                {
 
2670
                                    continue;
 
2671
                                }
 
2672
 
 
2673
                                // send fake login accept messages; the ack response whitelists the IP
 
2674
                                nCookie cookie;
 
2675
                                sn_SynGenerateCookie( sn_SynTimestamp(), peers[peer], cookie );
 
2676
                                tJUST_CONTROLLED_PTR<nMessage> r = tNEW(nMessage)(login_accept);
 
2677
                                r->BendMessageID( cookie.first );
 
2678
                                r->SendImmediately(peer,false);
 
2679
                                r = tNEW(nMessage)(login_accept);
 
2680
                                r->BendMessageID( cookie.second );
 
2681
                                r->SendImmediately(peer,false);
 
2682
                                int idback = ::sn_myNetID;
 
2683
                                sn_myNetID = 1; // set a fake ID so the client doesn't consider the packet as a response from the server and messes up its ack data
 
2684
                                nMessage::SendCollected(peer);
 
2685
                                ::sn_myNetID = idback;
 
2686
 
 
2687
                                // and ignore for now
 
2688
                                continue;
 
2689
                            }
 
2690
                        }
 
2691
 
 
2692
                        // IP is not spoofed or there is no
 
2693
                        // current spoof heavy attack. Check closer.
 
2694
                        if( IndividualConnectionFloodProtection( machine, peer ) )
 
2695
                        {
 
2696
                            continue;
 
2697
                        }
 
2698
                    }
 
2699
#endif
2334
2700
                }
2335
2701
 
 
2702
 
2336
2703
                //       if (peer!=id)
2337
2704
                //  con << "Changed incoming address.\n";
2338
2705
                int lenleft = bend - b;
2341
2708
                try
2342
2709
                {
2343
2710
#endif
2344
 
                    while( lenleft > 0 ){
 
2711
                    while( lenleft >= 3 ){
2345
2712
                        tJUST_CONTROLLED_PTR< nMessage > pmess;
2346
2713
                        pmess = tNEW( nMessage )(b,id,lenleft);
2347
2714
                        nMessage& mess = *pmess;
2409
2776
                                    // do not ack the login_ignore packet that did not let you in.
2410
2777
 
2411
2778
#ifdef DEBUG
2412
 
                                    if ( id > MAXCLIENTS )
 
2779
                                    if ( id > MAXCLIENTS && mess.Descriptor() != login_accept.ID() )
2413
2780
                                    {
2414
2781
                                        con << "Sending ack to login slot.\n";
2415
2782
                                    }
2451
2818
                                //else
2452
2819
                                //con << "Message " << mess_id << ":" << id << " was not new.\n";
2453
2820
                            }
 
2821
 
 
2822
                        // abort if we're only supoosed to process the first message
 
2823
                        if( onlyReadFirstMessage )
 
2824
                        {
 
2825
                            break;
 
2826
                        }
2454
2827
                    }
2455
2828
#ifndef NOEXCEPT
2456
2829
                }
2457
2830
 
2458
2831
                catch(nKillHim)
2459
2832
                {
2460
 
                    con << "nKillHim signal caught.\n";
 
2833
                    con << "nKillHim signal caught: ";
2461
2834
                    sn_DisconnectUser(peer, "$network_kill_error");
2462
2835
                }
2463
2836
#endif
2490
2863
 
2491
2864
            catch(nKillHim const &)
2492
2865
            {
2493
 
                con << "nKillHim signal caught.\n";
 
2866
                con << "nKillHim signal caught: ";
2494
2867
                sn_DisconnectUser(peer, "$network_kill_error");
2495
2868
            }
2496
2869
        #endif
2615
2988
        {
2616
2989
            if (x==nCLIENT)
2617
2990
            {
 
2991
                // sn_Connections[MAXCLIENTS+1].socket = NULL;
2618
2992
                sn_DisconnectAll();
2619
2993
            }
2620
2994
            else
3259
3633
                if((sn_Connections[MAXCLIENTS+1].socket = (*i).CheckNewConnection() ) != NULL)
3260
3634
                {
3261
3635
                    rec_peer(MAXCLIENTS+1);
 
3636
                    sn_Connections[MAXCLIENTS+1].socket = NULL;
3262
3637
                }
3263
3638
            }
3264
3639
        }
3338
3713
 
3339
3714
    bool printMessage = false; // is it worth printing a message for this event?
3340
3715
 
 
3716
    tString reasonString( reason );
 
3717
 
3341
3718
    if (sn_Connections[i].socket)
3342
3719
    {
 
3720
        // store IP:port for later
 
3721
        lastPeers[i] = peers[i];
 
3722
 
3343
3723
        nMessage::SendCollected(i);
3344
3724
 
3345
3725
        // to make sure...
3348
3728
            for(int j=2;j>=0;j--){
3349
3729
                nMessage* mess = (new nMessage(login_deny));
3350
3730
                mess->ClearMessageID();
3351
 
                *mess << tString( reason );
 
3731
                *mess << reasonString;
3352
3732
 
3353
3733
                // write redirection
3354
3734
                tString redirection;
3385
3765
 
3386
3766
    if ( printMessage )
3387
3767
    {
3388
 
        con << tOutput( "$network_killuser", i, sn_Connections[i].ping.GetPing() );
 
3768
        con << tOutput( "$network_killuser", i, sn_Connections[i].ping.GetPing(), peers[i].ToString(), reasonString );
3389
3769
    }
3390
3770
 
3391
3771
    // clear address, socket and send queue
3889
4269
        return 0;
3890
4270
}
3891
4271
 
 
4272
// *******************************************************************************************
 
4273
// *
 
4274
// *    GetWeight
 
4275
// *
 
4276
// *******************************************************************************************
 
4277
//!
 
4278
//!             @return         the current total weight
 
4279
//!
 
4280
// *******************************************************************************************
 
4281
 
 
4282
REAL nAverager::GetWeight( void ) const
 
4283
{
 
4284
    return weight_;
 
4285
}
 
4286
 
3892
4287
// *******************************************************************************
3893
4288
// *
3894
4289
// *    operator <<
4137
4532
 
4138
4533
void nPingAverager::Timestep( REAL decay )
4139
4534
{
4140
 
    snail_.Timestep( decay * .02 );
4141
 
    slow_.Timestep ( decay * .2 );
4142
 
    fast_.Timestep ( decay * 2 );
 
4535
    if( snail_.GetWeight() > 100 )
 
4536
        snail_.Timestep( decay * .02 );
 
4537
    if( slow_.GetWeight() > 30 )
 
4538
        slow_.Timestep ( decay * .2 );
 
4539
    if( fast_.GetWeight() > 10 )
 
4540
        fast_.Timestep ( decay * 2 );
4143
4541
}
4144
4542
 
4145
4543
// *******************************************************************************************
4220
4618
        : lastUsed_(tSysTimeFloat())
4221
4619
        , banned_(-1)
4222
4620
        , players_(0)
 
4621
        , validated_(false)
4223
4622
        , decorators_(0)
4224
4623
{
4225
4624
    kph_.Add(0,.1666);
4289
4688
    nMachinePTR & operator=(nMachinePTR const & other){ machine = other.machine; other.machine=0;return *this;}
4290
4689
};
4291
4690
 
4292
 
typedef std::map< tString, nMachinePTR > nMachineMap;
 
4691
typedef sockaddr nMachineKey;
 
4692
 
 
4693
bool operator < ( nMachineKey const & a, nMachineKey const & b )
 
4694
{
 
4695
    return reinterpret_cast< sockaddr_in const & >( a ).sin_addr.s_addr < reinterpret_cast< sockaddr_in const & >( b ).sin_addr.s_addr;
 
4696
}
 
4697
 
 
4698
typedef std::map< nMachineKey, nMachinePTR > nMachineMap;
4293
4699
static nMachineMap & sn_GetMachineMap()
4294
4700
{
4295
4701
    static nMachineMap map;
4296
4702
    return map;
4297
4703
}
4298
4704
 
 
4705
static nMachine & sn_LookupMachine( nMachineKey const * address )
 
4706
{
 
4707
    // get map of all machines and look address up
 
4708
    nMachineMap & map = sn_GetMachineMap();
 
4709
    nMachine & ret = *map[ *address ].machine;
 
4710
    if( ret.GetIP().Len() <= 2 )
 
4711
    {
 
4712
        nAddress addr;
 
4713
        sockaddr * target = addr;
 
4714
        *target = *address;
 
4715
        ret.SetIP( addr.GetAddress() );
 
4716
    }
 
4717
    return ret;
 
4718
}
 
4719
 
 
4720
static nMachine * sn_PeekMachine( nMachineKey const * address )
 
4721
{
 
4722
    // get map of all machines and look address up
 
4723
    nMachineMap & map = sn_GetMachineMap();
 
4724
    nMachineMap::const_iterator i = map.find( *address );
 
4725
    if( i != map.end() )
 
4726
    {
 
4727
        return (*i).second.machine;
 
4728
    }
 
4729
    else
 
4730
    {
 
4731
        return NULL;
 
4732
    }
 
4733
}
 
4734
 
4299
4735
static nMachine & sn_LookupMachine( tString const & address )
4300
4736
{
4301
 
    // get map of all machines and look address up
4302
 
    nMachineMap & map = sn_GetMachineMap();
4303
 
    return map[ address ].machine->SetIP( address );
 
4737
    nAddress addr;
 
4738
    addr.SetAddress( address );
 
4739
    return sn_LookupMachine( addr );
4304
4740
}
4305
4741
 
4306
4742
// *******************************************************************************
4343
4779
        static nMachine invalid;
4344
4780
        return invalid;
4345
4781
    }
4346
 
    tString address;
4347
 
    peers[ userID ].GetAddress( address );
4348
 
 
4349
 
#ifdef DEBUG_X
4350
 
    // add client ID so multiple connects from one machine are distinguished
4351
 
    tString newIP;
4352
 
    newIP << address << " " << userID;
4353
 
    address = newIP;
4354
 
#endif
4355
 
 
4356
 
    // delegate
4357
 
    return sn_LookupMachine( address );
 
4782
 
 
4783
    // delegate
 
4784
    return sn_LookupMachine( peers[userID] );
 
4785
}
 
4786
 
 
4787
// *******************************************************************************
 
4788
// *
 
4789
// *    PeekMachine
 
4790
// *
 
4791
// *******************************************************************************
 
4792
//!
 
4793
//!             @param  userID  the user ID to fetch the machine for
 
4794
//!             @return             the machine the user ID belongs to
 
4795
//!
 
4796
// *******************************************************************************
 
4797
 
 
4798
nMachine * nMachine::PeekMachine( unsigned short userID )
 
4799
{
 
4800
    // hardcoding: the server itself
 
4801
    if ( userID == 0 && sn_GetNetState() != nCLIENT )
 
4802
    {
 
4803
        return &GetMachine( userID );
 
4804
    }
 
4805
 
 
4806
    tASSERT( userID <= MAXCLIENTS+1 );
 
4807
 
 
4808
    if( sn_GetNetState() != nSERVER )
 
4809
    {
 
4810
        // invalid ID, return invalid machine (clients don't track machines)
 
4811
        return &GetMachine( userID );
 
4812
    }
 
4813
 
 
4814
    // get address
 
4815
    tVERIFY( userID <= MAXCLIENTS+1 );
 
4816
    if( !sn_Connections[userID].socket )
 
4817
    {
 
4818
        // invalid ID, return invalid machine
 
4819
        return &GetMachine( userID );
 
4820
    }
 
4821
 
 
4822
    // delegate
 
4823
    return sn_PeekMachine( peers[userID] );
4358
4824
}
4359
4825
 
4360
4826
// safely delete iterator from map
4622
5088
                nMachine & machine = *(*iter).second.machine;
4623
5089
                // if ( machine.IsBanned() > 0 )
4624
5090
                {
4625
 
                    s << (*iter).first << " " << machine.IsBanned() << " " << machine.kph_ << " " << machine.GetBanReason() << "\n";
 
5091
                    s << machine.GetIP() << " " << machine.IsBanned() << " " << machine.kph_ << " " << machine.GetBanReason() << "\n";
4626
5092
                }
4627
5093
            }
4628
5094
        }