refactor timer

This commit is contained in:
ridethepig 2023-02-17 05:17:06 +00:00
parent 1764b933de
commit ea7b9605a4
2 changed files with 38 additions and 34 deletions

View File

@ -20,9 +20,8 @@ using namespace std;
TCPSender::TCPSender(const size_t capacity, const uint16_t retx_timeout, const std::optional<WrappingInt32> fixed_isn) 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()()})) : _isn(fixed_isn.value_or(WrappingInt32{random_device()()}))
, _initial_retransmission_timeout{retx_timeout} , _initial_retransmission_timeout{retx_timeout}
, _stream(capacity) { , _stream(capacity)
_timer.reinit(_initial_retransmission_timeout); , _timer(retx_timeout) {}
}
uint64_t TCPSender::bytes_in_flight() const { return _next_seqno - _unack_seqno; } 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(); _next_seqno += seg.length_in_sequence_space();
hdr.syn = false; hdr.syn = false;
hdr.seqno = next_seqno(); hdr.seqno = next_seqno();
_timer.start();
if (sendptr >= data.size()) if (sendptr >= data.size())
break; break;
payload = data.substr(sendptr, TCPConfig::MAX_PAYLOAD_SIZE); payload = data.substr(sendptr, TCPConfig::MAX_PAYLOAD_SIZE);
@ -65,8 +65,8 @@ void TCPSender::fill_window() {
_segments_out.push(seg); _segments_out.push(seg);
_outstandings.push(seg); _outstandings.push(seg);
_next_seqno += seg.length_in_sequence_space(); _next_seqno += seg.length_in_sequence_space();
_timer.start();
} }
_timer.start();
} }
//! \param ackno The remote receiver's ackno (acknowledgment number) //! \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()) { if (abs_ackno >= _unack_seqno + _outstandings.front().length_in_sequence_space()) {
_unack_seqno += _outstandings.front().length_in_sequence_space(); _unack_seqno += _outstandings.front().length_in_sequence_space();
_outstandings.pop(); _outstandings.pop();
_timer.reinit(_initial_retransmission_timeout); _timer.reset_init(_initial_retransmission_timeout);
} else { } else {
break; 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 //! \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) { void TCPSender::tick(const size_t ms_since_last_tick) {
if (!_timer.started()) if (!_timer.is_started())
return; return;
_timer.count_down(ms_since_last_tick); _timer.tick(ms_since_last_tick);
if (!_timer.expired()) if (!_timer.is_expired())
return; return;
_segments_out.push(_outstandings.front()); _segments_out.push(_outstandings.front());
if (_window_size > 0) if (_window_size > 0)
_timer.consec_retrans(); _timer.retransmit();
_timer.reset(); _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() { void TCPSender::send_empty_segment() {
TCPHeader hdr; TCPHeader hdr;

View File

@ -14,36 +14,39 @@
//! God knows what this class does //! God knows what this class does
class TCPTimer { class TCPTimer {
private: private:
size_t RTO{0}; size_t RTO;
size_t rt_count{0}; size_t _cr_count{0};
size_t ti_count{0}; size_t _ti_count;
bool timer_on{false}; bool _is_started{false};
public: public:
TCPTimer() = default; TCPTimer(uint32_t initial_retransmission_timeout)
void reinit(uint32_t initial_RTO) { : RTO(initial_retransmission_timeout), _ti_count(initial_retransmission_timeout) {}
RTO = initial_RTO; void reset_init(uint32_t initial_retransmission_timeout) {
ti_count = RTO; RTO = initial_retransmission_timeout;
rt_count = 0; _ti_count = RTO;
timer_on = false; _cr_count = 0;
_is_started = false;
} }
void reset() { ti_count = RTO; } void reset() {
size_t cur_RTO() const { return RTO; } _ti_count = RTO;
void start() { timer_on = true; } _is_started = false;
bool started() const { return timer_on; } }
void stop() { timer_on = false; } void start() { _is_started = true; }
bool expired() const { return ti_count == 0; } void stop() { _is_started = false; }
void count_down(size_t milli_sec) { void tick(size_t milli_sec) {
if (ti_count >= milli_sec) if (_ti_count >= milli_sec)
ti_count -= milli_sec; _ti_count -= milli_sec;
else else
ti_count = 0; _ti_count = 0;
} }
void consec_retrans() { void retransmit() {
rt_count++; _cr_count++;
RTO <<= 1; 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. //! \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 //! current window size, default (and at least) should be 1 byte according to the handout
uint16_t _window_size{1}; uint16_t _window_size{1};
std::queue<TCPSegment> _outstandings{}; std::queue<TCPSegment> _outstandings{};
TCPTimer _timer{}; TCPTimer _timer;
public: public:
//! Initialize a TCPSender //! Initialize a TCPSender