#include <nNetwork.h>
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 |
Definition at line 618 of file nNetwork.h.
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
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);
nWaitForAck::tCONTROLLED_PTR | ( | nMessage | ) | [protected] |
virtual void nWaitForAck::AckExtraAction | ( | ) | [inline, virtual] |
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 }
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 }
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 }
int nWaitForAck::id [protected] |
Definition at line 620 of file nNetwork.h.
int nWaitForAck::receiver [protected] |
REAL nWaitForAck::timeout [protected] |
nTimeRolling nWaitForAck::timeSendAgain [protected] |
nTimeRolling nWaitForAck::timeFirstSent [protected] |
nTimeRolling nWaitForAck::timeLastSent [protected] |
int nWaitForAck::timeouts [protected] |
Definition at line 627 of file nNetwork.h.