Only update timestamp and targeting on higher sequence number

This commit is contained in:
Keith Winstein
2011-08-14 02:31:33 -04:00
parent ec4a75dcaf
commit ee7e9a1e2b
3 changed files with 42 additions and 34 deletions
+40 -33
View File
@@ -93,6 +93,7 @@ Connection::Connection() /* server */
direction( TO_CLIENT ), direction( TO_CLIENT ),
next_seq( 0 ), next_seq( 0 ),
saved_timestamp( -1 ), saved_timestamp( -1 ),
expected_receiver_seq( 0 ),
RTT_hit( false ), RTT_hit( false ),
SRTT( 1000 ), SRTT( 1000 ),
RTTVAR( 500 ) RTTVAR( 500 )
@@ -111,6 +112,7 @@ Connection::Connection( const char *key_str, const char *ip, int port ) /* clien
direction( TO_SERVER ), direction( TO_SERVER ),
next_seq( 0 ), next_seq( 0 ),
saved_timestamp( -1 ), saved_timestamp( -1 ),
expected_receiver_seq( 0 ),
RTT_hit( false ), RTT_hit( false ),
SRTT( 1000 ), SRTT( 1000 ),
RTTVAR( 500 ) RTTVAR( 500 )
@@ -213,46 +215,51 @@ string Connection::recv( void )
Packet p( string( buf, received_len ), &session ); Packet p( string( buf, received_len ), &session );
if ( p.timestamp != uint64_t(-1) ) { dos_assert( p.direction == (server ? TO_SERVER : TO_CLIENT) ); /* prevent malicious playback to sender */
saved_timestamp = p.timestamp;
}
if ( p.timestamp_reply != uint64_t(-1) ) { if ( p.seq >= expected_receiver_seq ) { /* don't use out-of-order packets for timestamp or targeting */
uint64_t now = timestamp(); expected_receiver_seq = p.seq + 1; /* this is security-sensitive because a replay attack could otherwise
assert( now >= p.timestamp_reply ); screw up the timestamp and targeting */
double R = now - p.timestamp_reply;
if ( R < 5000 ) { /* ignore large values, e.g. server was Ctrl-Zed */ if ( p.timestamp != uint64_t(-1) ) {
if ( !RTT_hit ) { /* first measurement */ saved_timestamp = p.timestamp;
SRTT = R; }
RTTVAR = R / 2;
RTT_hit = true;
} else {
const double alpha = 1.0 / 8.0;
const double beta = 1.0 / 4.0;
RTTVAR = (1 - beta) * RTTVAR + ( beta * fabs( SRTT - R ) ); if ( p.timestamp_reply != uint64_t(-1) ) {
SRTT = (1 - alpha) * SRTT + ( alpha * R ); uint64_t now = timestamp();
assert( now >= p.timestamp_reply );
double R = now - p.timestamp_reply;
if ( R < 5000 ) { /* ignore large values, e.g. server was Ctrl-Zed */
if ( !RTT_hit ) { /* first measurement */
SRTT = R;
RTTVAR = R / 2;
RTT_hit = true;
} else {
const double alpha = 1.0 / 8.0;
const double beta = 1.0 / 4.0;
RTTVAR = (1 - beta) * RTTVAR + ( beta * fabs( SRTT - R ) );
SRTT = (1 - alpha) * SRTT + ( alpha * R );
}
}
}
/* server auto-adjusts to client */
if ( server ) {
attached = true;
if ( (remote_addr.sin_addr.s_addr != packet_remote_addr.sin_addr.s_addr)
|| (remote_addr.sin_port != packet_remote_addr.sin_port) ) {
remote_addr = packet_remote_addr;
fprintf( stderr, "Server now attached to client at %s:%d\n",
inet_ntoa( remote_addr.sin_addr ),
ntohs( remote_addr.sin_port ) );
} }
} }
} }
dos_assert( p.direction == (server ? TO_SERVER : TO_CLIENT) ); /* prevent malicious playback to sender */ return p.payload; /* we do return out-of-order or duplicated packets to caller */
/* server auto-adjusts to client */
if ( server ) {
attached = true;
if ( (remote_addr.sin_addr.s_addr != packet_remote_addr.sin_addr.s_addr)
|| (remote_addr.sin_port != packet_remote_addr.sin_port) ) {
remote_addr = packet_remote_addr;
fprintf( stderr, "Server now attached to client at %s:%d\n",
inet_ntoa( remote_addr.sin_addr ),
ntohs( remote_addr.sin_port ) );
}
}
return p.payload;
} }
int Connection::port( void ) int Connection::port( void )
+1
View File
@@ -74,6 +74,7 @@ namespace Network {
Direction direction; Direction direction;
uint64_t next_seq; uint64_t next_seq;
uint64_t saved_timestamp; uint64_t saved_timestamp;
uint64_t expected_receiver_seq;
bool RTT_hit; bool RTT_hit;
double SRTT; double SRTT;
+1 -1
View File
@@ -196,7 +196,7 @@ void Transport<MyState, RemoteState>::recv( void )
if ( !found ) { if ( !found ) {
// fprintf( stderr, "Ignoring out-of-order packet. Reference state %d has been discarded or hasn't yet been received.\n", int(inst.old_num) ); // fprintf( stderr, "Ignoring out-of-order packet. Reference state %d has been discarded or hasn't yet been received.\n", int(inst.old_num) );
return; return; /* this is security-sensitive and part of how we enforce idempotency */
} }
/* apply diff to reference state */ /* apply diff to reference state */