refactor timer
This commit is contained in:
parent
1764b933de
commit
ea7b9605a4
@ -20,9 +20,8 @@ using namespace std;
|
||||
TCPSender::TCPSender(const size_t capacity, const uint16_t retx_timeout, const std::optional<WrappingInt32> fixed_isn)
|
||||
: _isn(fixed_isn.value_or(WrappingInt32{random_device()()}))
|
||||
, _initial_retransmission_timeout{retx_timeout}
|
||||
, _stream(capacity) {
|
||||
_timer.reinit(_initial_retransmission_timeout);
|
||||
}
|
||||
, _stream(capacity)
|
||||
, _timer(retx_timeout) {}
|
||||
|
||||
uint64_t TCPSender::bytes_in_flight() const { return _next_seqno - _unack_seqno; }
|
||||
|
||||
@ -50,6 +49,7 @@ void TCPSender::fill_window() {
|
||||
_next_seqno += seg.length_in_sequence_space();
|
||||
hdr.syn = false;
|
||||
hdr.seqno = next_seqno();
|
||||
_timer.start();
|
||||
if (sendptr >= data.size())
|
||||
break;
|
||||
payload = data.substr(sendptr, TCPConfig::MAX_PAYLOAD_SIZE);
|
||||
@ -65,8 +65,8 @@ void TCPSender::fill_window() {
|
||||
_segments_out.push(seg);
|
||||
_outstandings.push(seg);
|
||||
_next_seqno += seg.length_in_sequence_space();
|
||||
}
|
||||
_timer.start();
|
||||
}
|
||||
}
|
||||
|
||||
//! \param ackno The remote receiver's ackno (acknowledgment number)
|
||||
@ -81,7 +81,7 @@ void TCPSender::ack_received(const WrappingInt32 ackno, const uint16_t window_si
|
||||
if (abs_ackno >= _unack_seqno + _outstandings.front().length_in_sequence_space()) {
|
||||
_unack_seqno += _outstandings.front().length_in_sequence_space();
|
||||
_outstandings.pop();
|
||||
_timer.reinit(_initial_retransmission_timeout);
|
||||
_timer.reset_init(_initial_retransmission_timeout);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
@ -95,18 +95,19 @@ void TCPSender::ack_received(const WrappingInt32 ackno, const uint16_t window_si
|
||||
|
||||
//! \param[in] ms_since_last_tick the number of milliseconds since the last call to this method
|
||||
void TCPSender::tick(const size_t ms_since_last_tick) {
|
||||
if (!_timer.started())
|
||||
if (!_timer.is_started())
|
||||
return;
|
||||
_timer.count_down(ms_since_last_tick);
|
||||
if (!_timer.expired())
|
||||
_timer.tick(ms_since_last_tick);
|
||||
if (!_timer.is_expired())
|
||||
return;
|
||||
_segments_out.push(_outstandings.front());
|
||||
if (_window_size > 0)
|
||||
_timer.consec_retrans();
|
||||
_timer.retransmit();
|
||||
_timer.reset();
|
||||
_timer.start();
|
||||
}
|
||||
|
||||
unsigned int TCPSender::consecutive_retransmissions() const { return _timer.consec_retrans_count(); }
|
||||
unsigned int TCPSender::consecutive_retransmissions() const { return _timer.consecutive_retransmissions(); }
|
||||
|
||||
void TCPSender::send_empty_segment() {
|
||||
TCPHeader hdr;
|
||||
|
||||
@ -14,36 +14,39 @@
|
||||
//! God knows what this class does
|
||||
class TCPTimer {
|
||||
private:
|
||||
size_t RTO{0};
|
||||
size_t rt_count{0};
|
||||
size_t ti_count{0};
|
||||
bool timer_on{false};
|
||||
size_t RTO;
|
||||
size_t _cr_count{0};
|
||||
size_t _ti_count;
|
||||
bool _is_started{false};
|
||||
|
||||
public:
|
||||
TCPTimer() = default;
|
||||
void reinit(uint32_t initial_RTO) {
|
||||
RTO = initial_RTO;
|
||||
ti_count = RTO;
|
||||
rt_count = 0;
|
||||
timer_on = false;
|
||||
TCPTimer(uint32_t initial_retransmission_timeout)
|
||||
: RTO(initial_retransmission_timeout), _ti_count(initial_retransmission_timeout) {}
|
||||
void reset_init(uint32_t initial_retransmission_timeout) {
|
||||
RTO = initial_retransmission_timeout;
|
||||
_ti_count = RTO;
|
||||
_cr_count = 0;
|
||||
_is_started = false;
|
||||
}
|
||||
void reset() { ti_count = RTO; }
|
||||
size_t cur_RTO() const { return RTO; }
|
||||
void start() { timer_on = true; }
|
||||
bool started() const { return timer_on; }
|
||||
void stop() { timer_on = false; }
|
||||
bool expired() const { return ti_count == 0; }
|
||||
void count_down(size_t milli_sec) {
|
||||
if (ti_count >= milli_sec)
|
||||
ti_count -= milli_sec;
|
||||
void reset() {
|
||||
_ti_count = RTO;
|
||||
_is_started = false;
|
||||
}
|
||||
void start() { _is_started = true; }
|
||||
void stop() { _is_started = false; }
|
||||
void tick(size_t milli_sec) {
|
||||
if (_ti_count >= milli_sec)
|
||||
_ti_count -= milli_sec;
|
||||
else
|
||||
ti_count = 0;
|
||||
_ti_count = 0;
|
||||
}
|
||||
void consec_retrans() {
|
||||
rt_count++;
|
||||
void retransmit() {
|
||||
_cr_count++;
|
||||
RTO <<= 1;
|
||||
}
|
||||
size_t consec_retrans_count() const { return rt_count; }
|
||||
bool is_started() const { return _is_started; }
|
||||
bool is_expired() const { return _ti_count == 0; }
|
||||
size_t consecutive_retransmissions() const { return _cr_count; }
|
||||
};
|
||||
|
||||
//! \brief The "sender" part of a TCP implementation.
|
||||
@ -73,7 +76,7 @@ class TCPSender {
|
||||
//! current window size, default (and at least) should be 1 byte according to the handout
|
||||
uint16_t _window_size{1};
|
||||
std::queue<TCPSegment> _outstandings{};
|
||||
TCPTimer _timer{};
|
||||
TCPTimer _timer;
|
||||
|
||||
public:
|
||||
//! Initialize a TCPSender
|
||||
|
||||
Loading…
Reference in New Issue
Block a user