Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
quic: use TimerWrap for idle and retransmit timers
Signed-off-by: James M Snell <jasnell@gmail.com>
  • Loading branch information
jasnell committed Jul 5, 2020
commit f7ad0bfff8a18c3e76db9bd3340fad8d827b47c8
9 changes: 3 additions & 6 deletions src/quic/node_quic_session-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -375,8 +375,7 @@ QuicCID QuicSession::dcid() const {
// timer to actually monitor. Here we take the calculated timeout
// and extend out the libuv timer.
void QuicSession::UpdateRetransmitTimer(uint64_t timeout) {
DCHECK_NOT_NULL(retransmit_);
retransmit_->Update(timeout);
retransmit_.Update(timeout, timeout);
}

void QuicSession::CheckAllocatedSize(size_t previous_size) const {
Expand Down Expand Up @@ -512,13 +511,11 @@ void QuicSession::set_remote_transport_params() {
}

void QuicSession::StopIdleTimer() {
CHECK_NOT_NULL(idle_);
idle_->Stop();
idle_.Stop();
}

void QuicSession::StopRetransmitTimer() {
CHECK_NOT_NULL(retransmit_);
retransmit_->Stop();
retransmit_.Stop();
}

// Called by the OnVersionNegotiation callback when a version
Expand Down
7 changes: 3 additions & 4 deletions src/quic/node_quic_session.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1431,8 +1431,8 @@ QuicSession::QuicSession(
socket_(socket),
alpn_(alpn),
hostname_(hostname),
idle_(new Timer(socket->env(), [this]() { OnIdleTimeout(); })),
retransmit_(new Timer(socket->env(), [this]() { MaybeTimeout(); })),
idle_(socket->env(), [this](void* data) { OnIdleTimeout(); }),
retransmit_(socket->env(), [this](void* data) { MaybeTimeout(); }),
dcid_(dcid),
state_(env()->isolate()),
quic_state_(socket->quic_state()) {
Expand Down Expand Up @@ -2461,14 +2461,13 @@ void QuicSession::UpdateConnectionID(
// will be silently closed. It is important to update this as activity
// occurs to keep the idle timer from firing.
void QuicSession::UpdateIdleTimer() {
CHECK_NOT_NULL(idle_);
uint64_t now = uv_hrtime();
uint64_t expiry = ngtcp2_conn_get_idle_expiry(connection());
// nano to millis
uint64_t timeout = expiry > now ? (expiry - now) / 1000000ULL : 1;
if (timeout == 0) timeout = 1;
Debug(this, "Updating idle timeout to %" PRIu64, timeout);
idle_->Update(timeout);
idle_.Update(timeout, timeout);
}


Expand Down
5 changes: 3 additions & 2 deletions src/quic/node_quic_session.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "node_quic_util.h"
#include "node_sockaddr.h"
#include "stream_base.h"
#include "timer_wrap.h"
#include "v8.h"
#include "uv.h"

Expand Down Expand Up @@ -1471,8 +1472,8 @@ class QuicSession : public AsyncWrap,
QuicSessionListener* listener_ = nullptr;
JSQuicSessionListener default_listener_;

TimerPointer idle_;
TimerPointer retransmit_;
TimerWrapHandle idle_;
TimerWrapHandle retransmit_;

QuicCID scid_;
QuicCID dcid_;
Expand Down
43 changes: 0 additions & 43 deletions src/quic/node_quic_util-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,49 +73,6 @@ size_t GetMaxPktLen(const SocketAddress& addr) {
NGTCP2_MAX_PKTLEN_IPV4;
}

Timer::Timer(Environment* env, std::function<void()> fn)
: env_(env),
fn_(fn) {
uv_timer_init(env_->event_loop(), &timer_);
timer_.data = this;
}

void Timer::Stop() {
if (stopped_)
return;
stopped_ = true;

if (timer_.data == this) {
uv_timer_stop(&timer_);
timer_.data = nullptr;
}
}

// If the timer is not currently active, interval must be either 0 or greater.
// If the timer is already active, interval is ignored.
void Timer::Update(uint64_t interval) {
if (stopped_)
return;
uv_timer_start(&timer_, OnTimeout, interval, interval);
uv_unref(reinterpret_cast<uv_handle_t*>(&timer_));
}

void Timer::Free(Timer* timer) {
timer->env_->CloseHandle(
reinterpret_cast<uv_handle_t*>(&timer->timer_),
[&](uv_handle_t* timer) {
Timer* t = ContainerOf(
&Timer::timer_,
reinterpret_cast<uv_timer_t*>(timer));
delete t;
});
}

void Timer::OnTimeout(uv_timer_t* timer) {
Timer* t = ContainerOf(&Timer::timer_, timer);
t->fn_();
}

QuicError::QuicError(
int32_t family_,
uint64_t code_) :
Expand Down
32 changes: 0 additions & 32 deletions src/quic/node_quic_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,38 +338,6 @@ class QuicCID : public MemoryRetainer {
const ngtcp2_cid* ptr_;
};

// Simple timer wrapper that is used to implement the internals
// for idle and retransmission timeouts. Call Update to start or
// reset the timer; Stop to halt the timer.
class Timer final : public MemoryRetainer {
public:
inline explicit Timer(Environment* env, std::function<void()> fn);

// Stops the timer with the side effect of the timer no longer being usable.
// It will be cleaned up and the Timer object will be destroyed.
inline void Stop();

// If the timer is not currently active, interval must be either 0 or greater.
// If the timer is already active, interval is ignored.
inline void Update(uint64_t interval);

static inline void Free(Timer* timer);

SET_NO_MEMORY_INFO()
SET_MEMORY_INFO_NAME(Timer)
SET_SELF_SIZE(Timer)

private:
static inline void OnTimeout(uv_timer_t* timer);

bool stopped_ = false;
Environment* env_;
std::function<void()> fn_;
uv_timer_t timer_;
};

using TimerPointer = DeleteFnPtr<Timer, Timer::Free>;

// A Stateless Reset Token is a mechanism by which a QUIC
// endpoint can discreetly signal to a peer that it has
// lost all state associated with a connection. This
Expand Down