Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

quiche:: Implement QuicAlarm interface #7094

Merged
merged 9 commits into from Jun 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
43 changes: 43 additions & 0 deletions bazel/external/quiche.BUILD
Expand Up @@ -362,6 +362,37 @@ envoy_cc_library(
],
)

envoy_cc_library(
name = "quic_core_arena_scoped_ptr_lib",
hdrs = ["quiche/quic/core/quic_arena_scoped_ptr.h"],
repository = "@envoy",
visibility = ["//visibility:public"],
deps = [":quic_platform_base"],
)

envoy_cc_library(
name = "quic_core_alarm_lib",
srcs = ["quiche/quic/core/quic_alarm.cc"],
hdrs = ["quiche/quic/core/quic_alarm.h"],
repository = "@envoy",
visibility = ["//visibility:public"],
deps = [
":quic_core_arena_scoped_ptr_lib",
":quic_core_time_lib",
],
)

envoy_cc_library(
name = "quic_core_alarm_factory_lib",
hdrs = ["quiche/quic/core/quic_alarm_factory.h"],
repository = "@envoy",
visibility = ["//visibility:public"],
deps = [
":quic_core_alarm_lib",
":quic_core_one_block_arena_lib",
],
)

envoy_cc_library(
name = "quic_core_buffer_allocator_lib",
srcs = [
Expand All @@ -387,6 +418,18 @@ envoy_cc_library(
deps = [":quic_platform_export"],
)

envoy_cc_library(
name = "quic_core_one_block_arena_lib",
srcs = ["quiche/quic/core/quic_one_block_arena.h"],
repository = "@envoy",
visibility = ["//visibility:public"],
deps = [
":quic_core_arena_scoped_ptr_lib",
":quic_core_types_lib",
":quic_platform_base",
],
)

envoy_cc_library(
name = "quic_core_time_lib",
srcs = ["quiche/quic/core/quic_time.cc"],
Expand Down
27 changes: 21 additions & 6 deletions source/extensions/quic_listeners/quiche/BUILD
Expand Up @@ -8,11 +8,26 @@ load(

envoy_package()

# Placeholder library to verify/illustrate depending on a QUICHE build target.
# TODO(mpwarres): remove once real build rules added here.
envoy_cc_library(
name = "dummy_lib",
srcs = ["dummy.cc"],
hdrs = ["dummy.h"],
external_deps = ["quiche_http2_platform"],
name = "envoy_quic_alarm_lib",
srcs = ["envoy_quic_alarm.cc"],
hdrs = ["envoy_quic_alarm.h"],
external_deps = ["quiche_quic_platform"],
deps = [
"//include/envoy/event:timer_interface",
"@com_googlesource_quiche//:quic_core_alarm_lib",
],
)

envoy_cc_library(
name = "envoy_quic_alarm_factory_lib",
srcs = ["envoy_quic_alarm_factory.cc"],
hdrs = ["envoy_quic_alarm_factory.h"],
external_deps = ["quiche_quic_platform"],
deps = [
":envoy_quic_alarm_lib",
"@com_googlesource_quiche//:quic_core_alarm_factory_lib",
"@com_googlesource_quiche//:quic_core_arena_scoped_ptr_lib",
"@com_googlesource_quiche//:quic_core_one_block_arena_lib",
],
)
35 changes: 35 additions & 0 deletions source/extensions/quic_listeners/quiche/envoy_quic_alarm.cc
@@ -0,0 +1,35 @@
#include "extensions/quic_listeners/quiche/envoy_quic_alarm.h"

namespace Envoy {
namespace Quic {

EnvoyQuicAlarm::EnvoyQuicAlarm(Event::Scheduler& scheduler, quic::QuicClock& clock,
quic::QuicArenaScopedPtr<quic::QuicAlarm::Delegate> delegate)
: QuicAlarm(std::move(delegate)), scheduler_(scheduler),
timer_(scheduler_.createTimer([this]() { Fire(); })), clock_(clock) {}

void EnvoyQuicAlarm::CancelImpl() { timer_->disableTimer(); }

void EnvoyQuicAlarm::SetImpl() {
// TODO(#7170) switch to use microseconds if it is supported.
timer_->enableTimer(std::chrono::milliseconds(getDurationBeforeDeadline().ToMilliseconds()));
}

void EnvoyQuicAlarm::UpdateImpl() {
// Since Timer::enableTimer() overrides its deadline from previous calls,
// there is no need to disable the timer before enabling it again.
SetImpl();
}

quic::QuicTime::Delta EnvoyQuicAlarm::getDurationBeforeDeadline() {
quic::QuicTime::Delta duration(quic::QuicTime::Delta::Zero());
quic::QuicTime now = clock_.ApproximateNow();
quic::QuicTime tmp = deadline();
if (tmp > now) {
duration = tmp - now;
}
return duration;
}

} // namespace Quic
} // namespace Envoy
39 changes: 39 additions & 0 deletions source/extensions/quic_listeners/quiche/envoy_quic_alarm.h
@@ -0,0 +1,39 @@
#pragma once

#include "envoy/event/timer.h"

#include "common/common/assert.h"

#include "quiche/quic/core/quic_alarm.h"
#include "quiche/quic/core/quic_time.h"
#include "quiche/quic/platform/api/quic_clock.h"

namespace Envoy {
namespace Quic {

// Implements QUIC interface
// https://quiche.googlesource.com/quiche/+/refs/heads/master/quic/core/quic_alarm.h This class
// wraps an Event::Timer object and provide interface for QUIC to interact with the timer.
class EnvoyQuicAlarm : public quic::QuicAlarm {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably worth some class comments here and in other classes. I can tell you are trying to mate two different time-systems and it may be worth a whiteboard discussion on the strategy.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added comment. The current plan is to use TimeSystem to implement QuicTime and Timer to implement QuicAlarm. These two are quite straight forward integration.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool. Consider using TimeSource rather than TimeSystem if possible. The only user of TimeSystem outside of tests currently is DIspatcher and we'd prefer to keep it that way if possible.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QuicClock has a ApproximateNow() which needs to interact with Dispatcher to get a timestamp in each event loop. This is not implemented yet, see TODO in EnvoyQuicClock.
TimeSystem has createScheduler() which allows us to plumb through to pass around that timestamp. So I use TimeSystem for QuicTime.

And EnvoyQuicClock will be instantiated with the TimeSystem in Dispatcher.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the semantics of ApproximateNow()? How would it interact with the dispatcher? Might be worth a quick write-up to explain your plans. Maybe discuss in the context of a github issue, and reference that issue here in a code comment?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

opened #7177. Since alarm is not directly related to QuicClock, I didn't reference the issue here. I think the original TODO in QuicClock is sufficient.

public:
EnvoyQuicAlarm(Event::Scheduler& scheduler, quic::QuicClock& clock,
quic::QuicArenaScopedPtr<quic::QuicAlarm::Delegate> delegate);

~EnvoyQuicAlarm() override { ASSERT(!IsSet()); };

// quic::QuicAlarm
void CancelImpl() override;
void SetImpl() override;
// Overridden to avoid cancel before set.
void UpdateImpl() override;

private:
quic::QuicTime::Delta getDurationBeforeDeadline();

Event::Scheduler& scheduler_;
Event::TimerPtr timer_;
quic::QuicClock& clock_;
};

} // namespace Quic
} // namespace Envoy
@@ -0,0 +1,22 @@
#include "extensions/quic_listeners/quiche/envoy_quic_alarm_factory.h"

namespace Envoy {
namespace Quic {

quic::QuicAlarm* EnvoyQuicAlarmFactory::CreateAlarm(quic::QuicAlarm::Delegate* delegate) {
return new EnvoyQuicAlarm(scheduler_, clock_,
quic::QuicArenaScopedPtr<quic::QuicAlarm::Delegate>(delegate));
}

quic::QuicArenaScopedPtr<quic::QuicAlarm>
EnvoyQuicAlarmFactory::CreateAlarm(quic::QuicArenaScopedPtr<quic::QuicAlarm::Delegate> delegate,
quic::QuicConnectionArena* arena) {
if (arena != nullptr) {
return arena->New<EnvoyQuicAlarm>(scheduler_, clock_, std::move(delegate));
}
return quic::QuicArenaScopedPtr<quic::QuicAlarm>(
new EnvoyQuicAlarm(scheduler_, clock_, std::move(delegate)));
}

} // namespace Quic
} // namespace Envoy
39 changes: 39 additions & 0 deletions source/extensions/quic_listeners/quiche/envoy_quic_alarm_factory.h
@@ -0,0 +1,39 @@
#pragma once

#include "common/common/non_copyable.h"

#include "extensions/quic_listeners/quiche/envoy_quic_alarm.h"

#pragma GCC diagnostic push

// QUICHE allows unused parameters.
#pragma GCC diagnostic ignored "-Wunused-parameter"
#include "quiche/quic/core/quic_alarm_factory.h"
#include "quiche/quic/core/quic_arena_scoped_ptr.h"
#include "quiche/quic/core/quic_one_block_arena.h"

#pragma GCC diagnostic pop

namespace Envoy {
namespace Quic {

class EnvoyQuicAlarmFactory : public quic::QuicAlarmFactory, NonCopyable {
public:
EnvoyQuicAlarmFactory(Event::Scheduler& scheduler, quic::QuicClock& clock)
: scheduler_(scheduler), clock_(clock) {}

~EnvoyQuicAlarmFactory() override {}

// QuicAlarmFactory
quic::QuicAlarm* CreateAlarm(quic::QuicAlarm::Delegate* delegate) override;
quic::QuicArenaScopedPtr<quic::QuicAlarm>
CreateAlarm(quic::QuicArenaScopedPtr<quic::QuicAlarm::Delegate> delegate,
quic::QuicConnectionArena* arena) override;

private:
Event::Scheduler& scheduler_;
quic::QuicClock& clock_;
};

} // namespace Quic
} // namespace Envoy
12 changes: 7 additions & 5 deletions test/extensions/quic_listeners/quiche/BUILD
Expand Up @@ -13,11 +13,13 @@ load(
envoy_package()

envoy_cc_test(
name = "dummy_test",
srcs = ["dummy_test.cc"],
external_deps = ["quiche_http2_platform"],
name = "envoy_quic_alarm_test",
srcs = ["envoy_quic_alarm_test.cc"],
external_deps = ["quiche_quic_platform"],
deps = [
"//source/extensions/quic_listeners/quiche:dummy_lib",
"//test/test_common:utility_lib",
"//source/extensions/quic_listeners/quiche:envoy_quic_alarm_factory_lib",
"//source/extensions/quic_listeners/quiche:envoy_quic_alarm_lib",
"//source/extensions/quic_listeners/quiche/platform:envoy_quic_clock_lib",
"//test/test_common:simulated_time_system_lib",
],
)