nWaitForAck Class Reference

#include <nNetwork.h>

Inheritance diagram for nWaitForAck:

Inheritance graph
[legend]

List of all members.

Public Member Functions

 nWaitForAck (nMessage *m, int rec)
virtual ~nWaitForAck ()
virtual void AckExtraAction ()

Static Public Member Functions

static void Ackt (unsigned short id, unsigned short peer)
static void AckAllPeer (unsigned short peer)
static void Resend ()

Protected Member Functions

 tCONTROLLED_PTR (nMessage) message

Protected Attributes

int id
int receiver
REAL timeout
nTimeRolling timeSendAgain
nTimeRolling timeFirstSent
nTimeRolling timeLastSent
int timeouts


Detailed Description

Definition at line 618 of file nNetwork.h.


Constructor & Destructor Documentation

nWaitForAck::nWaitForAck ( nMessage m,
int  rec 
)

Definition at line 651 of file nNetwork.cpp.

References tList< T, MALLOC, REFERENCE >::Add(), tReproducibleRandomizer::GetInstance(), nDescriptor::ID(), netTime, nSERVER, nSIMULATE_PING_VARIANT, REAL, receiver, s_Acknowledge, sn_GetNetState(), sn_GetTimeout(), st_Breakpoint(), tERR_ERROR, timeFirstSent, timeLastSent, timeout, and timeSendAgain.

00654         :id(-1),message(m),receiver(rec)
00655 {
00656 #ifdef DEBUG
00657     // don't message yourself
00658     if ( rec == 0 && sn_GetNetState() == nSERVER )
00659         st_Breakpoint();
00660 #endif
00661 
00662     if (!message)
00663         tERR_ERROR("Null ack!");
00664 
00665     if (message->Descriptor()!=s_Acknowledge.ID())
00666         sn_Connections[receiver].ackPending++;
00667     else
00668         tERR_ERROR("Should not wait for ack of an ack message itself.");
00669 
00670     //    sn_ackAckPending[receiver]++;
00671 #ifdef NET_DEBUG
00672     acks++;
00673 #endif
00674 
00675     timeFirstSent=::netTime;
00676     timeLastSent=::netTime;
00677 
00678     timeouts=0;
00679 
00680     timeout=sn_GetTimeout( rec );
00681 
00682 #ifdef nSIMULATE_PING
00683     timeSendAgain=::netTime + nSIMULATE_PING;
00684 #ifndef WIN32
00685     tRandomizer & randomizer = tReproducibleRandomizer::GetInstance();
00686     timeSendAgain+= randimizer.Get() * nSIMULATE_PING_VARIANT;
00687     // timeSendAgain+=(nSIMULATE_PING_VARIANT*random())/RAND_MAX;
00688 #endif
00689 #else
00690     const REAL packetLossScale = .003; // packet loss rate that is considered big
00691     const REAL maxTimeoutFactor = 1.2; // maximal stretching of initial timeout value for flawless connections
00692     // factor mutliplied to timeout; 1 if the connection loses a lot of packets, 1.2 for a
00693     // flawless connection
00694     REAL timeoutFactor = 1 + (maxTimeoutFactor-1)*packetLossScale/(sn_Connections[receiver].PacketLoss() + packetLossScale);
00695     timeSendAgain=::netTime + timeout*timeoutFactor + zeroTimeout;
00696 #endif

Here is the call graph for this function:

nWaitForAck::~nWaitForAck (  )  [virtual]

Definition at line 698 of file nNetwork.cpp.

00700                          {
00701 #ifdef NET_DEBUG
00702     acks--;
00703     if (acks>max_acks){
00704         max_acks=acks;
00705         // con << "MA=" << max_acks << '\n';
00706     }
00707 #endif
00708 
00709     if (bool(message) && message->Descriptor()!=s_Acknowledge.ID())
00710     {
00711         sn_Connections[receiver].ackPending--;
00712         sn_Connections[receiver].ReliableMessageSent();
00713     }
00714     else
00715     {
00716         tERR_ERROR( "No message." );
00717     }
00718     //    sn_ackAckPending[receiver]--;
00719 
00720     sn_pendingAcks.Remove(this,id);


Member Function Documentation

nWaitForAck::tCONTROLLED_PTR ( nMessage   )  [protected]

virtual void nWaitForAck::AckExtraAction (  )  [inline, virtual]

Reimplemented in nWaitForAckSync.

Definition at line 633 of file nNetwork.h.

00633 {};

void nWaitForAck::Ackt ( unsigned short  id,
unsigned short  peer 
) [static]

Definition at line 722 of file nNetwork.cpp.

Referenced by ack_handler().

00724                                                            {
00725     int success=0;
00726     for(int i=sn_pendingAcks.Len()-1;i>=0;i--){
00727         nWaitForAck * ack = sn_pendingAcks(i);
00728         if (ack->message->MessageID()==id &&
00729                 ack->receiver==peer){
00730             success=1;
00731 
00732 #ifdef DEBUG
00733             //      if (sn_pendingAcks(i)->message == sn_WatchMessage)
00734             //  st_Breakpoint();
00735 #endif
00736 
00737 #ifdef DEBUG_X
00738             if (ack->message->descriptor>1)
00739                 con << "AT  " << ack->message->descriptor << '\n';
00740 #endif
00741 
00742             // calculate and average ping
00743             REAL thisping=netTime - ack->timeFirstSent;
00744             sn_Connections[peer].ping.Add( thisping, 1/(1 + 10 * REAL(ack->timeouts * ack->timeouts * ack->timeouts ) ) );
00745 
00746             ack->AckExtraAction();
00747             delete ack;
00748             ::timeouts[peer]=0;
00749             if (i<sn_pendingAcks.Len()-1) i++;
00750         }
00751     }
00752 
00753 #ifdef DEBUG_X
00754     if (!success && peer!=MAXCLIENTS+1)
00755     {
00756         con << "Ack " << id << ':' << peer << " was not asked for.\n";
00757         if (sn_pendingAcks.Len()) con << "Expected:\n";
00758         for(int i=sn_pendingAcks.Len()-1;i>=0;i--){
00759             con << i << "\t:"
00760             << sn_pendingAcks[i]->message->messageIDBig_ << ":"
00761             << sn_pendingAcks[i]->receiver << '\n';
00762         }
00763     }

Here is the caller graph for this function:

void nWaitForAck::AckAllPeer ( unsigned short  peer  )  [static]

Definition at line 765 of file nNetwork.cpp.

Referenced by logout_handler().

00767                                                {
00768     for(int i=sn_pendingAcks.Len()-1;i>=0;i--){
00769         if (sn_pendingAcks(i)->receiver==peer){
00770             delete sn_pendingAcks(i);
00771             if (i<sn_pendingAcks.Len()-1) i++;
00772         }

Here is the caller graph for this function:

void nWaitForAck::Resend (  )  [static]

Definition at line 774 of file nNetwork.cpp.

00776                         {
00777     static tReproducibleRandomizer randomizer;
00778 
00779     for(int i=sn_pendingAcks.Len()-1;i>=0;i--){
00780         nWaitForAck* pendingAck = sn_pendingAcks(i);
00781 
00782         nConnectionInfo & connection = sn_Connections[pendingAck->receiver];
00783 
00784         // don't resend if you can't.
00785         if ( !connection.bandwidthControl_.CanSend() )
00786             continue;
00787 
00788         REAL packetLoss = connection.PacketLoss();
00789         REAL timeout = pendingAck->timeout;
00790 
00791         // should we resend the packet? Certainly it if it is overdue
00792         bool resend = (pendingAck->timeSendAgain + timeout * .1 <=netTime);
00793 
00794         // or if there is already a message waiting...
00795         if ( !resend && connection.sendBuffer_.Len() > 0 )
00796         {
00797             // and we are on time
00798             if ( pendingAck->timeSendAgain <= netTime )
00799                 resend = true;
00800             // or the packet loss is so high that it is advisable to resend every message
00801             // multiple times if bandwidth is available ( we aim for 99% reliability )
00802             else if ( pendingAck->timeouts < 3 && pow( packetLoss, pendingAck->timeouts + 1 ) > .01 &&
00803                       connection.bandwidthControl_.Control( nBandwidthControl::Usage_Planning ) >100 )
00804                 resend = true;
00805 
00806             /* + sn_GetTimeout( pendingAck->receiver ) *
00807                                 ( 3.0 / ( pendingAck->timeouts + 1 ) )
00808                                 ( packetLoss * ( randomizer.Get() + .5 ) ) )
00809             */
00810         }
00811 
00812         if ( resend ){
00813             //con << net_ticks-sn_pendingAcks[i]->ticks_first_sent << '\n';
00814 
00815             // update timeout counters
00816             ::timeouts[pendingAck->receiver]++;
00817             pendingAck->timeouts++;
00818 
00819             if(netTime - pendingAck->timeFirstSent  >  killTimeout &&
00820                     ::timeouts[pendingAck->receiver] > 20){
00821                 // total timeout. Kill connection.
00822                 if (pendingAck->receiver<=MAXCLIENTS){
00823                     tOutput o;
00824                     o.SetTemplateParameter(1, pendingAck->receiver);
00825                     o << "$network_error_timeout";
00826                     con << o;
00827                     sn_DisconnectUser(pendingAck->receiver, "$network_kill_timeout" );
00828 
00829                     sn_Error = nTIMEOUT;
00830 
00831                     if (i>=sn_pendingAcks.Len())
00832                         i=sn_pendingAcks.Len()-1;
00833                 }
00834                 else // it is just in the login slot. Ignore it.
00835                     delete pendingAck;
00836             }
00837             else{
00838 #ifdef DEBUG
00839                 //if (pendingAck->message == sn_WatchMessage)
00840                 //st_Breakpoint();
00841 #endif
00842 
00843                 if (connection.socket){
00844                     //    if(sn_Connections[].rateControlPlanned[pendingAck->receiver]>-1000)
00845                     {
00846                         REAL timeoutFactor = .9 + .1 * pendingAck->timeouts + randomizer.Get() * .1;
00847                         pendingAck->timeSendAgain=netTime+timeout * timeoutFactor;
00848                         pendingAck->timeLastSent=netTime;
00849 
00850                         if (send_again_warn){
00851                             con << "sending packet again: " ;
00852                             deb_net=true;
00853                         }
00854                         connection.ReliableMessageSent();
00855                         pendingAck->message->SendImmediately
00856                         (pendingAck->receiver,false);
00857                         deb_net=false;
00858                     }
00859                 }
00860                 else
00861                     delete pendingAck;
00862             }
00863         }


Member Data Documentation

int nWaitForAck::id [protected]

Definition at line 620 of file nNetwork.h.

int nWaitForAck::receiver [protected]

Definition at line 622 of file nNetwork.h.

Referenced by nWaitForAck().

REAL nWaitForAck::timeout [protected]

Definition at line 623 of file nNetwork.h.

Referenced by nWaitForAck().

nTimeRolling nWaitForAck::timeSendAgain [protected]

Definition at line 624 of file nNetwork.h.

Referenced by nWaitForAck().

nTimeRolling nWaitForAck::timeFirstSent [protected]

Definition at line 625 of file nNetwork.h.

Referenced by nWaitForAck().

nTimeRolling nWaitForAck::timeLastSent [protected]

Definition at line 626 of file nNetwork.h.

Referenced by nWaitForAck().

int nWaitForAck::timeouts [protected]

Definition at line 627 of file nNetwork.h.


The documentation for this class was generated from the following files:
Generated on Sat Mar 15 23:51:03 2008 for Armagetron Advanced by  doxygen 1.5.4