Commit 1377ae3e authored by Victor Vasiliev's avatar Victor Vasiliev Committed by Commit Bot

Synchronize QuaRTC code up to the Wed Jul 25 20:25:29 EDT 2018

This reverts commit 8cc4e50c and relands
812abd15 with iOS tests disabled.

R=rch@chromium.org

Change-Id: I56fb4be93602fcaa9deccdf9a1837ebcd787af11
Reviewed-on: https://chromium-review.googlesource.com/1154361Reviewed-by: default avatarZhongyi Shi <zhongyi@chromium.org>
Commit-Queue: Victor Vasiliev <vasilvv@chromium.org>
Cr-Commit-Position: refs/heads/master@{#579229}
parent 6d3e637f
...@@ -1561,20 +1561,14 @@ component("net") { ...@@ -1561,20 +1561,14 @@ component("net") {
"third_party/quic/platform/impl/quic_url_impl.h", "third_party/quic/platform/impl/quic_url_impl.h",
"third_party/quic/platform/impl/quic_url_utils_impl.cc", "third_party/quic/platform/impl/quic_url_utils_impl.cc",
"third_party/quic/platform/impl/quic_url_utils_impl.h", "third_party/quic/platform/impl/quic_url_utils_impl.h",
"third_party/quic/quartc/quartc_clock_interface.h",
"third_party/quic/quartc/quartc_factory.cc", "third_party/quic/quartc/quartc_factory.cc",
"third_party/quic/quartc/quartc_factory.h", "third_party/quic/quartc/quartc_factory.h",
"third_party/quic/quartc/quartc_factory_interface.cc",
"third_party/quic/quartc/quartc_factory_interface.h",
"third_party/quic/quartc/quartc_packet_writer.cc", "third_party/quic/quartc/quartc_packet_writer.cc",
"third_party/quic/quartc/quartc_packet_writer.h", "third_party/quic/quartc/quartc_packet_writer.h",
"third_party/quic/quartc/quartc_session.cc", "third_party/quic/quartc/quartc_session.cc",
"third_party/quic/quartc/quartc_session.h", "third_party/quic/quartc/quartc_session.h",
"third_party/quic/quartc/quartc_session_interface.h",
"third_party/quic/quartc/quartc_stream.cc", "third_party/quic/quartc/quartc_stream.cc",
"third_party/quic/quartc/quartc_stream.h", "third_party/quic/quartc/quartc_stream.h",
"third_party/quic/quartc/quartc_stream_interface.h",
"third_party/quic/quartc/quartc_task_runner_interface.h",
"third_party/spdy/core/fuzzing/hpack_fuzz_util.cc", "third_party/spdy/core/fuzzing/hpack_fuzz_util.cc",
"third_party/spdy/core/fuzzing/hpack_fuzz_util.h", "third_party/spdy/core/fuzzing/hpack_fuzz_util.h",
"third_party/spdy/core/hpack/hpack_constants.cc", "third_party/spdy/core/hpack/hpack_constants.cc",
......
// Copyright (c) 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_THIRD_PARTY_QUIC_QUARTC_QUARTC_CLOCK_INTERFACE_H_
#define NET_THIRD_PARTY_QUIC_QUARTC_QUARTC_CLOCK_INTERFACE_H_
#include <stdint.h>
namespace quic {
// Implemented by the Quartc API user to provide a timebase.
class QuartcClockInterface {
public:
virtual ~QuartcClockInterface() {}
virtual int64_t NowMicroseconds() = 0;
};
} // namespace quic
#endif // NET_THIRD_PARTY_QUIC_QUARTC_QUARTC_CLOCK_INTERFACE_H_
...@@ -11,106 +11,17 @@ ...@@ -11,106 +11,17 @@
namespace quic { namespace quic {
namespace {
// Implements the QuicAlarm with QuartcTaskRunnerInterface for the Quartc
// users other than Chromium. For example, WebRTC will create QuartcAlarm with
// a QuartcTaskRunner implemented by WebRTC.
class QuartcAlarm : public QuicAlarm, public QuartcTaskRunnerInterface::Task {
public:
QuartcAlarm(const QuicClock* clock,
QuartcTaskRunnerInterface* task_runner,
QuicArenaScopedPtr<QuicAlarm::Delegate> delegate)
: QuicAlarm(std::move(delegate)),
clock_(clock),
task_runner_(task_runner) {}
~QuartcAlarm() override {
// Cancel the scheduled task before getting deleted.
CancelImpl();
}
// QuicAlarm overrides.
void SetImpl() override {
DCHECK(deadline().IsInitialized());
// Cancel it if already set.
CancelImpl();
int64_t delay_ms = (deadline() - (clock_->Now())).ToMilliseconds();
if (delay_ms < 0) {
delay_ms = 0;
}
DCHECK(task_runner_);
DCHECK(!scheduled_task_);
scheduled_task_ = task_runner_->Schedule(this, delay_ms);
}
void CancelImpl() override {
if (scheduled_task_) {
scheduled_task_->Cancel();
scheduled_task_.reset();
}
}
// QuartcTaskRunner::Task overrides.
void Run() override {
// The alarm may have been cancelled.
if (!deadline().IsInitialized()) {
return;
}
// The alarm may have been re-set to a later time.
if (clock_->Now() < deadline()) {
SetImpl();
return;
}
Fire();
}
private:
// Not owned by QuartcAlarm. Owned by the QuartcFactory.
const QuicClock* clock_;
// Not owned by QuartcAlarm. Owned by the QuartcFactory.
QuartcTaskRunnerInterface* task_runner_;
// Owned by QuartcAlarm.
std::unique_ptr<QuartcTaskRunnerInterface::ScheduledTask> scheduled_task_;
};
// Adapts QuartcClockInterface (provided by the user) to QuicClock
// (expected by QUIC).
class QuartcClock : public QuicClock {
public:
explicit QuartcClock(QuartcClockInterface* clock) : clock_(clock) {}
QuicTime ApproximateNow() const override { return Now(); }
QuicTime Now() const override {
return QuicTime::Zero() +
QuicTime::Delta::FromMicroseconds(clock_->NowMicroseconds());
}
QuicWallTime WallNow() const override {
return QuicWallTime::FromUNIXMicroseconds(clock_->NowMicroseconds());
}
private:
QuartcClockInterface* clock_;
};
} // namespace
QuartcFactory::QuartcFactory(const QuartcFactoryConfig& factory_config) QuartcFactory::QuartcFactory(const QuartcFactoryConfig& factory_config)
: task_runner_(factory_config.task_runner), : alarm_factory_(factory_config.alarm_factory),
clock_(new QuartcClock(factory_config.clock)) {} clock_(factory_config.clock) {}
QuartcFactory::~QuartcFactory() {} QuartcFactory::~QuartcFactory() {}
std::unique_ptr<QuartcSessionInterface> QuartcFactory::CreateQuartcSession( std::unique_ptr<QuartcSession> QuartcFactory::CreateQuartcSession(
const QuartcSessionConfig& quartc_session_config) { const QuartcSessionConfig& quartc_session_config) {
DCHECK(quartc_session_config.packet_transport); DCHECK(quartc_session_config.packet_transport);
Perspective perspective = quartc_session_config.is_server Perspective perspective = quartc_session_config.perspective;
? Perspective::IS_SERVER
: Perspective::IS_CLIENT;
// QuartcSession will eventually own both |writer| and |quic_connection|. // QuartcSession will eventually own both |writer| and |quic_connection|.
auto writer = auto writer =
...@@ -135,53 +46,50 @@ std::unique_ptr<QuartcSessionInterface> QuartcFactory::CreateQuartcSession( ...@@ -135,53 +46,50 @@ std::unique_ptr<QuartcSessionInterface> QuartcFactory::CreateQuartcSession(
// Enable time-based loss detection. // Enable time-based loss detection.
copt.push_back(kTIME); copt.push_back(kTIME);
if (quartc_session_config.congestion_control == copt.push_back(kTBBR);
QuartcCongestionControl::kBBR) {
copt.push_back(kTBBR); // Note: These settings have no effect for Exoblaze builds since
// SetQuicReloadableFlag() gets stubbed out.
// Note: These settings have no effect for Exoblaze builds since SetQuicReloadableFlag(quic_bbr_less_probe_rtt, true);
// SetQuicReloadableFlag() gets stubbed out. SetQuicReloadableFlag(quic_unified_iw_options, true);
SetQuicReloadableFlag(quic_bbr_less_probe_rtt, true); for (const auto option : quartc_session_config.bbr_options) {
SetQuicReloadableFlag(quic_unified_iw_options, true); switch (option) {
for (const auto option : quartc_session_config.bbr_options) { case (QuartcBbrOptions::kSlowerStartup):
switch (option) { copt.push_back(kBBRS);
case (QuartcBbrOptions::kSlowerStartup): break;
copt.push_back(kBBRS); case (QuartcBbrOptions::kFullyDrainQueue):
break; copt.push_back(kBBR3);
case (QuartcBbrOptions::kFullyDrainQueue): break;
copt.push_back(kBBR3); case (QuartcBbrOptions::kReduceProbeRtt):
break; copt.push_back(kBBR6);
case (QuartcBbrOptions::kReduceProbeRtt): break;
copt.push_back(kBBR6); case (QuartcBbrOptions::kSkipProbeRtt):
break; copt.push_back(kBBR7);
case (QuartcBbrOptions::kSkipProbeRtt): break;
copt.push_back(kBBR7); case (QuartcBbrOptions::kSkipProbeRttAggressively):
break; copt.push_back(kBBR8);
case (QuartcBbrOptions::kSkipProbeRttAggressively): break;
copt.push_back(kBBR8); case (QuartcBbrOptions::kFillUpLinkDuringProbing):
break; quic_connection->set_fill_up_link_during_probing(true);
case (QuartcBbrOptions::kFillUpLinkDuringProbing): break;
quic_connection->set_fill_up_link_during_probing(true); case (QuartcBbrOptions::kInitialWindow3):
break; copt.push_back(kIW03);
case (QuartcBbrOptions::kInitialWindow3): break;
copt.push_back(kIW03); case (QuartcBbrOptions::kInitialWindow10):
break; copt.push_back(kIW10);
case (QuartcBbrOptions::kInitialWindow10): break;
copt.push_back(kIW10); case (QuartcBbrOptions::kInitialWindow20):
break; copt.push_back(kIW20);
case (QuartcBbrOptions::kInitialWindow20): break;
copt.push_back(kIW20); case (QuartcBbrOptions::kInitialWindow50):
break; copt.push_back(kIW50);
case (QuartcBbrOptions::kInitialWindow50): break;
copt.push_back(kIW50); case (QuartcBbrOptions::kStartup1RTT):
break; copt.push_back(k1RTT);
case (QuartcBbrOptions::kStartup1RTT): break;
copt.push_back(k1RTT); case (QuartcBbrOptions::kStartup2RTT):
break; copt.push_back(k2RTT);
case (QuartcBbrOptions::kStartup2RTT): break;
copt.push_back(k2RTT);
break;
}
} }
} }
QuicConfig quic_config; QuicConfig quic_config;
...@@ -202,15 +110,15 @@ std::unique_ptr<QuartcSessionInterface> QuartcFactory::CreateQuartcSession( ...@@ -202,15 +110,15 @@ std::unique_ptr<QuartcSessionInterface> QuartcFactory::CreateQuartcSession(
kStreamReceiveWindowLimit); kStreamReceiveWindowLimit);
quic_config.SetConnectionOptionsToSend(copt); quic_config.SetConnectionOptionsToSend(copt);
quic_config.SetClientConnectionOptions(copt); quic_config.SetClientConnectionOptions(copt);
if (quartc_session_config.max_time_before_crypto_handshake_secs > 0) { if (quartc_session_config.max_time_before_crypto_handshake >
QuicTime::Delta::Zero()) {
quic_config.set_max_time_before_crypto_handshake( quic_config.set_max_time_before_crypto_handshake(
QuicTime::Delta::FromSeconds( quartc_session_config.max_time_before_crypto_handshake);
quartc_session_config.max_time_before_crypto_handshake_secs));
} }
if (quartc_session_config.max_idle_time_before_crypto_handshake_secs > 0) { if (quartc_session_config.max_idle_time_before_crypto_handshake >
QuicTime::Delta::Zero()) {
quic_config.set_max_idle_time_before_crypto_handshake( quic_config.set_max_idle_time_before_crypto_handshake(
QuicTime::Delta::FromSeconds( quartc_session_config.max_idle_time_before_crypto_handshake);
quartc_session_config.max_idle_time_before_crypto_handshake_secs));
} }
if (quartc_session_config.idle_network_timeout > QuicTime::Delta::Zero()) { if (quartc_session_config.idle_network_timeout > QuicTime::Delta::Zero()) {
quic_config.SetIdleNetworkTimeout( quic_config.SetIdleNetworkTimeout(
...@@ -224,7 +132,7 @@ std::unique_ptr<QuartcSessionInterface> QuartcFactory::CreateQuartcSession( ...@@ -224,7 +132,7 @@ std::unique_ptr<QuartcSessionInterface> QuartcFactory::CreateQuartcSession(
return QuicMakeUnique<QuartcSession>( return QuicMakeUnique<QuartcSession>(
std::move(quic_connection), quic_config, std::move(quic_connection), quic_config,
quartc_session_config.unique_remote_server_id, perspective, quartc_session_config.unique_remote_server_id, perspective,
this /*QuicConnectionHelperInterface*/, clock_.get(), std::move(writer)); this /*QuicConnectionHelperInterface*/, clock_, std::move(writer));
} }
std::unique_ptr<QuicConnection> QuartcFactory::CreateQuicConnection( std::unique_ptr<QuicConnection> QuartcFactory::CreateQuicConnection(
...@@ -236,28 +144,12 @@ std::unique_ptr<QuicConnection> QuartcFactory::CreateQuicConnection( ...@@ -236,28 +144,12 @@ std::unique_ptr<QuicConnection> QuartcFactory::CreateQuicConnection(
QuicSocketAddress dummy_address(QuicIpAddress::Any4(), 0 /*Port*/); QuicSocketAddress dummy_address(QuicIpAddress::Any4(), 0 /*Port*/);
return QuicMakeUnique<QuicConnection>( return QuicMakeUnique<QuicConnection>(
dummy_id, dummy_address, this, /*QuicConnectionHelperInterface*/ dummy_id, dummy_address, this, /*QuicConnectionHelperInterface*/
this /*QuicAlarmFactory*/, packet_writer, /*owns_writer=*/false, alarm_factory_ /*QuicAlarmFactory*/, packet_writer, /*owns_writer=*/false,
perspective, CurrentSupportedVersions()); perspective, CurrentSupportedVersions());
} }
QuicAlarm* QuartcFactory::CreateAlarm(QuicAlarm::Delegate* delegate) {
return new QuartcAlarm(GetClock(), task_runner_,
QuicArenaScopedPtr<QuicAlarm::Delegate>(delegate));
}
QuicArenaScopedPtr<QuicAlarm> QuartcFactory::CreateAlarm(
QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,
QuicConnectionArena* arena) {
if (arena != nullptr) {
return arena->New<QuartcAlarm>(GetClock(), task_runner_,
std::move(delegate));
}
return QuicArenaScopedPtr<QuicAlarm>(
new QuartcAlarm(GetClock(), task_runner_, std::move(delegate)));
}
const QuicClock* QuartcFactory::GetClock() const { const QuicClock* QuartcFactory::GetClock() const {
return clock_.get(); return clock_;
} }
QuicRandom* QuartcFactory::GetRandomGenerator() { QuicRandom* QuartcFactory::GetRandomGenerator() {
...@@ -268,10 +160,9 @@ QuicBufferAllocator* QuartcFactory::GetStreamSendBufferAllocator() { ...@@ -268,10 +160,9 @@ QuicBufferAllocator* QuartcFactory::GetStreamSendBufferAllocator() {
return &buffer_allocator_; return &buffer_allocator_;
} }
std::unique_ptr<QuartcFactoryInterface> CreateQuartcFactory( std::unique_ptr<QuartcFactory> CreateQuartcFactory(
const QuartcFactoryConfig& factory_config) { const QuartcFactoryConfig& factory_config) {
return std::unique_ptr<QuartcFactoryInterface>( return std::unique_ptr<QuartcFactory>(new QuartcFactory(factory_config));
new QuartcFactory(factory_config));
} }
} // namespace quic } // namespace quic
...@@ -8,34 +8,83 @@ ...@@ -8,34 +8,83 @@
#include "net/third_party/quic/core/quic_alarm_factory.h" #include "net/third_party/quic/core/quic_alarm_factory.h"
#include "net/third_party/quic/core/quic_connection.h" #include "net/third_party/quic/core/quic_connection.h"
#include "net/third_party/quic/core/quic_simple_buffer_allocator.h" #include "net/third_party/quic/core/quic_simple_buffer_allocator.h"
#include "net/third_party/quic/platform/api/quic_export.h"
#include "net/third_party/quic/quartc/quartc_factory_interface.h"
#include "net/third_party/quic/quartc/quartc_packet_writer.h" #include "net/third_party/quic/quartc/quartc_packet_writer.h"
#include "net/third_party/quic/quartc/quartc_task_runner_interface.h" #include "net/third_party/quic/quartc/quartc_session.h"
namespace quic { namespace quic {
// Implements the QuartcFactoryInterface to create the instances of // Options that control the BBR algorithm.
// QuartcSessionInterface. Implements the QuicAlarmFactory to create alarms enum class QuartcBbrOptions {
// using the QuartcTaskRunner. Implements the QuicConnectionHelperInterface used kSlowerStartup, // Once a loss is encountered in STARTUP,
// by the QuicConnections. Only one QuartcFactory is expected to be created. // switches startup to a 1.5x pacing gain.
class QUIC_EXPORT_PRIVATE QuartcFactory : public QuartcFactoryInterface, kFullyDrainQueue, // Fully drains the queue once per cycle.
public QuicAlarmFactory, kReduceProbeRtt, // Probe RTT reduces CWND to 0.75 * BDP instead of 4
public QuicConnectionHelperInterface { // packets.
kSkipProbeRtt, // Skip Probe RTT and extend the existing min_rtt if a
// recent min_rtt is within 12.5% of the current min_rtt.
kSkipProbeRttAggressively, // Skip ProbeRTT and extend the existing min_rtt
// as long as you've been app limited at least
// once.
kFillUpLinkDuringProbing, // Sends probing retransmissions whenever we
// become application limited.
kInitialWindow3, // Use a 3-packet initial congestion window.
kInitialWindow10, // Use a 10-packet initial congestion window.
kInitialWindow20, // Use a 20-packet initial congestion window.
kInitialWindow50, // Use a 50-packet initial congestion window.
kStartup1RTT, // Stay in STARTUP for 1 RTT.
kStartup2RTT, // Stay in STARTUP for 2 RTTs.
};
// The configuration for creating a QuartcFactory.
struct QuartcFactoryConfig {
// Factory for |QuicAlarm|s. Implemented by the Quartc user with different
// mechanisms. For example in WebRTC, it is implemented with rtc::Thread.
// Owned by the user, and needs to stay alive for as long as the QuartcFactory
// exists.
QuicAlarmFactory* alarm_factory = nullptr;
// The clock used by |QuicAlarm|s. Implemented by the Quartc user. Owned by
// the user, and needs to stay alive for as long as the QuartcFactory exists.
QuicClock* clock = nullptr;
};
struct QuartcSessionConfig {
// When using Quartc, there are two endpoints. The QuartcSession on one
// endpoint must act as a server and the one on the other side must act as a
// client.
Perspective perspective = Perspective::IS_CLIENT;
// This is only needed when is_server = false. It must be unique
// for each endpoint the local endpoint may communicate with. For example,
// a WebRTC client could use the remote endpoint's crypto fingerprint
QuicString unique_remote_server_id;
// The way the QuicConnection will send and receive packets, like a virtual
// UDP socket. For WebRTC, this will typically be an IceTransport.
QuartcPacketTransport* packet_transport = nullptr;
// The maximum size of the packet can be written with the packet writer.
// 1200 bytes by default.
QuicPacketLength max_packet_size = 1200;
// Options to control the BBR algorithm. In case the congestion control is
// set to anything but BBR, these options are ignored.
std::vector<QuartcBbrOptions> bbr_options;
// Timeouts for the crypto handshake. Set them to higher values to
// prevent closing the session before it started on a slow network.
// Zero entries are ignored and QUIC defaults are used in that case.
QuicTime::Delta max_idle_time_before_crypto_handshake =
QuicTime::Delta::Zero();
QuicTime::Delta max_time_before_crypto_handshake = QuicTime::Delta::Zero();
QuicTime::Delta idle_network_timeout = QuicTime::Delta::Zero();
};
// Factory that creates instances of QuartcSession. Implements the
// QuicConnectionHelperInterface used by the QuicConnections. Only one
// QuartcFactory is expected to be created.
class QUIC_EXPORT_PRIVATE QuartcFactory : public QuicConnectionHelperInterface {
public: public:
explicit QuartcFactory(const QuartcFactoryConfig& factory_config); explicit QuartcFactory(const QuartcFactoryConfig& factory_config);
~QuartcFactory() override; ~QuartcFactory() override;
// QuartcFactoryInterface overrides. // Creates a new QuartcSession using the given configuration.
std::unique_ptr<QuartcSessionInterface> CreateQuartcSession( std::unique_ptr<QuartcSession> CreateQuartcSession(
const QuartcSessionConfig& quartc_session_config) override; const QuartcSessionConfig& quartc_session_config);
// QuicAlarmFactory overrides.
QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) override;
QuicArenaScopedPtr<QuicAlarm> CreateAlarm(
QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,
QuicConnectionArena* arena) override;
// QuicConnectionHelperInterface overrides. // QuicConnectionHelperInterface overrides.
const QuicClock* GetClock() const override; const QuicClock* GetClock() const override;
...@@ -49,15 +98,19 @@ class QUIC_EXPORT_PRIVATE QuartcFactory : public QuartcFactoryInterface, ...@@ -49,15 +98,19 @@ class QUIC_EXPORT_PRIVATE QuartcFactory : public QuartcFactoryInterface,
Perspective perspective, Perspective perspective,
QuartcPacketWriter* packet_writer); QuartcPacketWriter* packet_writer);
// Used to implement QuicAlarmFactory.. // Used to implement QuicAlarmFactory. Owned by the user and must outlive
QuartcTaskRunnerInterface* task_runner_; // QuartcFactory.
// Used to implement the QuicConnectionHelperInterface. QuicAlarmFactory* alarm_factory_;
// The QuicClock wrapper held in this variable is owned by QuartcFactory, // Used to implement the QuicConnectionHelperInterface. Owned by the user and
// but the QuartcClockInterface inside of it belongs to the user! // must outlive QuartcFactory.
std::unique_ptr<QuicClock> clock_; QuicClock* clock_;
SimpleBufferAllocator buffer_allocator_; SimpleBufferAllocator buffer_allocator_;
}; };
// Creates a new instance of QuartcFactory.
std::unique_ptr<QuartcFactory> CreateQuartcFactory(
const QuartcFactoryConfig& factory_config);
} // namespace quic } // namespace quic
#endif // NET_THIRD_PARTY_QUIC_QUARTC_QUARTC_FACTORY_H_ #endif // NET_THIRD_PARTY_QUIC_QUARTC_QUARTC_FACTORY_H_
// Copyright (c) 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/third_party/quic/quartc/quartc_factory_interface.h"
namespace quic {
QuartcFactoryInterface::QuartcSessionConfig::QuartcSessionConfig() = default;
QuartcFactoryInterface::QuartcSessionConfig::~QuartcSessionConfig() = default;
} // namespace quic
// Copyright (c) 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_THIRD_PARTY_QUIC_QUARTC_QUARTC_FACTORY_INTERFACE_H_
#define NET_THIRD_PARTY_QUIC_QUARTC_QUARTC_FACTORY_INTERFACE_H_
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include "net/third_party/quic/platform/api/quic_export.h"
#include "net/third_party/quic/quartc/quartc_clock_interface.h"
#include "net/third_party/quic/quartc/quartc_session_interface.h"
#include "net/third_party/quic/quartc/quartc_task_runner_interface.h"
namespace quic {
// Algorithm to use for congestion control.
enum class QuartcCongestionControl {
kDefault, // Use an arbitrary algorithm chosen by QUIC.
kBBR, // Use BBR.
};
// Options that control the BBR algorithm.
enum class QuartcBbrOptions {
kSlowerStartup, // Once a loss is encountered in STARTUP,
// switches startup to a 1.5x pacing gain.
kFullyDrainQueue, // Fully drains the queue once per cycle.
kReduceProbeRtt, // Probe RTT reduces CWND to 0.75 * BDP instead of 4
// packets.
kSkipProbeRtt, // Skip Probe RTT and extend the existing min_rtt if a
// recent min_rtt is within 12.5% of the current min_rtt.
kSkipProbeRttAggressively, // Skip ProbeRTT and extend the existing min_rtt
// as long as you've been app limited at least
// once.
kFillUpLinkDuringProbing, // Sends probing retransmissions whenever we
// become application limited.
kInitialWindow3, // Use a 3-packet initial congestion window.
kInitialWindow10, // Use a 10-packet initial congestion window.
kInitialWindow20, // Use a 20-packet initial congestion window.
kInitialWindow50, // Use a 50-packet initial congestion window.
kStartup1RTT, // Stay in STARTUP for 1 RTT.
kStartup2RTT, // Stay in STARTUP for 2 RTTs.
};
// Used to create instances for Quartc objects such as QuartcSession.
class QUIC_EXPORT_PRIVATE QuartcFactoryInterface {
public:
virtual ~QuartcFactoryInterface() {}
struct QuartcSessionConfig {
QuartcSessionConfig();
~QuartcSessionConfig();
// When using Quartc, there are two endpoints. The QuartcSession on one
// endpoint must act as a server and the one on the other side must act as a
// client.
bool is_server = false;
// This is only needed when is_server = false. It must be unique
// for each endpoint the local endpoint may communicate with. For example,
// a WebRTC client could use the remote endpoint's crypto fingerprint
std::string unique_remote_server_id;
// The way the QuicConnection will send and receive packets, like a virtual
// UDP socket. For WebRTC, this will typically be an IceTransport.
QuartcPacketTransport* packet_transport = nullptr;
// The maximum size of the packet can be written with the packet writer.
// 1200 bytes by default.
uint64_t max_packet_size = 1200;
// Algorithm to use for congestion control. By default, uses an arbitrary
// congestion control algorithm chosen by QUIC.
QuartcCongestionControl congestion_control =
QuartcCongestionControl::kDefault;
// Options to control the BBR algorithm. In case the congestion control is
// set to anything but BBR, these options are ignored.
std::vector<QuartcBbrOptions> bbr_options;
// Timeouts for the crypto handshake. Set them to higher values to
// prevent closing the session before it started on a slow network.
// Zero entries are ignored and QUIC defaults are used in that case.
uint32_t max_idle_time_before_crypto_handshake_secs = 0;
uint32_t max_time_before_crypto_handshake_secs = 0;
QuicTime::Delta idle_network_timeout = QuicTime::Delta::Zero();
};
virtual std::unique_ptr<QuartcSessionInterface> CreateQuartcSession(
const QuartcSessionConfig& quartc_config) = 0;
};
// The configuration for creating a QuartcFactory.
struct QuartcFactoryConfig {
// The task runner used by the QuartcAlarm. Implemented by the Quartc user
// with different mechanism. For example in WebRTC, it is implemented with
// rtc::Thread. Owned by the user, and needs to stay alive for as long
// as the QuartcFactory exists.
QuartcTaskRunnerInterface* task_runner = nullptr;
// The clock used by QuartcAlarms. Implemented by the Quartc user. Owned by
// the user, and needs to stay alive for as long as the QuartcFactory exists.
QuartcClockInterface* clock = nullptr;
};
// Creates a new instance of QuartcFactoryInterface.
std::unique_ptr<QuartcFactoryInterface> CreateQuartcFactory(
const QuartcFactoryConfig& factory_config);
} // namespace quic
#endif // NET_THIRD_PARTY_QUIC_QUARTC_QUARTC_FACTORY_INTERFACE_H_
...@@ -5,12 +5,31 @@ ...@@ -5,12 +5,31 @@
#ifndef NET_THIRD_PARTY_QUIC_QUARTC_QUARTC_PACKET_WRITER_H_ #ifndef NET_THIRD_PARTY_QUIC_QUARTC_QUARTC_PACKET_WRITER_H_
#define NET_THIRD_PARTY_QUIC_QUARTC_QUARTC_PACKET_WRITER_H_ #define NET_THIRD_PARTY_QUIC_QUARTC_QUARTC_PACKET_WRITER_H_
#include "net/third_party/quic/core/quic_connection.h"
#include "net/third_party/quic/core/quic_packet_writer.h" #include "net/third_party/quic/core/quic_packet_writer.h"
#include "net/third_party/quic/core/quic_types.h"
#include "net/third_party/quic/platform/api/quic_export.h" #include "net/third_party/quic/platform/api/quic_export.h"
#include "net/third_party/quic/quartc/quartc_session_interface.h"
namespace quic { namespace quic {
// Send and receive packets, like a virtual UDP socket. For example, this
// could be implemented by WebRTC's IceTransport.
class QUIC_EXPORT_PRIVATE QuartcPacketTransport {
public:
// Additional metadata provided for each packet written.
struct PacketInfo {
QuicPacketNumber packet_number;
};
virtual ~QuartcPacketTransport() {}
// Called by the QuartcPacketWriter when writing packets to the network.
// Return the number of written bytes. Return 0 if the write is blocked.
virtual int Write(const char* buffer,
size_t buf_len,
const PacketInfo& info) = 0;
};
// Implements a QuicPacketWriter using a QuartcPacketTransport, which allows a // Implements a QuicPacketWriter using a QuartcPacketTransport, which allows a
// QuicConnection to use (for example), a WebRTC IceTransport. // QuicConnection to use (for example), a WebRTC IceTransport.
class QUIC_EXPORT_PRIVATE QuartcPacketWriter : public QuicPacketWriter { class QUIC_EXPORT_PRIVATE QuartcPacketWriter : public QuicPacketWriter {
...@@ -20,7 +39,7 @@ class QUIC_EXPORT_PRIVATE QuartcPacketWriter : public QuicPacketWriter { ...@@ -20,7 +39,7 @@ class QUIC_EXPORT_PRIVATE QuartcPacketWriter : public QuicPacketWriter {
~QuartcPacketWriter() override {} ~QuartcPacketWriter() override {}
// The QuicConnection calls WritePacket and the QuicPacketWriter writes them // The QuicConnection calls WritePacket and the QuicPacketWriter writes them
// to the QuartcSessionInterface::PacketTransport. // to the QuartcSession::PacketTransport.
WriteResult WritePacket(const char* buffer, WriteResult WritePacket(const char* buffer,
size_t buf_len, size_t buf_len,
const QuicIpAddress& self_address, const QuicIpAddress& self_address,
......
...@@ -8,8 +8,6 @@ ...@@ -8,8 +8,6 @@
#include "net/third_party/quic/core/tls_server_handshaker.h" #include "net/third_party/quic/core/tls_server_handshaker.h"
#include "net/third_party/quic/platform/api/quic_ptr_util.h" #include "net/third_party/quic/platform/api/quic_ptr_util.h"
using std::string;
namespace quic { namespace quic {
namespace { namespace {
...@@ -31,14 +29,14 @@ class DummyProofSource : public ProofSource { ...@@ -31,14 +29,14 @@ class DummyProofSource : public ProofSource {
// ProofSource override. // ProofSource override.
void GetProof(const QuicSocketAddress& server_addr, void GetProof(const QuicSocketAddress& server_addr,
const string& hostname, const QuicString& hostname,
const string& server_config, const QuicString& server_config,
QuicTransportVersion transport_version, QuicTransportVersion transport_version,
QuicStringPiece chlo_hash, QuicStringPiece chlo_hash,
std::unique_ptr<Callback> callback) override { std::unique_ptr<Callback> callback) override {
QuicReferenceCountedPointer<ProofSource::Chain> chain; QuicReferenceCountedPointer<ProofSource::Chain> chain;
QuicCryptoProof proof; QuicCryptoProof proof;
std::vector<string> certs; std::vector<QuicString> certs;
certs.push_back("Dummy cert"); certs.push_back("Dummy cert");
chain = new ProofSource::Chain(certs); chain = new ProofSource::Chain(certs);
proof.signature = "Dummy signature"; proof.signature = "Dummy signature";
...@@ -48,13 +46,13 @@ class DummyProofSource : public ProofSource { ...@@ -48,13 +46,13 @@ class DummyProofSource : public ProofSource {
QuicReferenceCountedPointer<Chain> GetCertChain( QuicReferenceCountedPointer<Chain> GetCertChain(
const QuicSocketAddress& server_address, const QuicSocketAddress& server_address,
const string& hostname) override { const QuicString& hostname) override {
return QuicReferenceCountedPointer<Chain>(); return QuicReferenceCountedPointer<Chain>();
} }
void ComputeTlsSignature( void ComputeTlsSignature(
const QuicSocketAddress& server_address, const QuicSocketAddress& server_address,
const string& hostname, const QuicString& hostname,
uint16_t signature_algorithm, uint16_t signature_algorithm,
QuicStringPiece in, QuicStringPiece in,
std::unique_ptr<SignatureCallback> callback) override { std::unique_ptr<SignatureCallback> callback) override {
...@@ -72,26 +70,26 @@ class InsecureProofVerifier : public ProofVerifier { ...@@ -72,26 +70,26 @@ class InsecureProofVerifier : public ProofVerifier {
// ProofVerifier override. // ProofVerifier override.
QuicAsyncStatus VerifyProof( QuicAsyncStatus VerifyProof(
const string& hostname, const QuicString& hostname,
const uint16_t port, const uint16_t port,
const string& server_config, const QuicString& server_config,
QuicTransportVersion transport_version, QuicTransportVersion transport_version,
QuicStringPiece chlo_hash, QuicStringPiece chlo_hash,
const std::vector<string>& certs, const std::vector<QuicString>& certs,
const string& cert_sct, const QuicString& cert_sct,
const string& signature, const QuicString& signature,
const ProofVerifyContext* context, const ProofVerifyContext* context,
string* error_details, QuicString* error_details,
std::unique_ptr<ProofVerifyDetails>* verify_details, std::unique_ptr<ProofVerifyDetails>* verify_details,
std::unique_ptr<ProofVerifierCallback> callback) override { std::unique_ptr<ProofVerifierCallback> callback) override {
return QUIC_SUCCESS; return QUIC_SUCCESS;
} }
QuicAsyncStatus VerifyCertChain( QuicAsyncStatus VerifyCertChain(
const string& hostname, const QuicString& hostname,
const std::vector<string>& certs, const std::vector<QuicString>& certs,
const ProofVerifyContext* context, const ProofVerifyContext* context,
string* error_details, QuicString* error_details,
std::unique_ptr<ProofVerifyDetails>* details, std::unique_ptr<ProofVerifyDetails>* details,
std::unique_ptr<ProofVerifierCallback> callback) override { std::unique_ptr<ProofVerifierCallback> callback) override {
return QUIC_SUCCESS; return QUIC_SUCCESS;
...@@ -114,65 +112,13 @@ bool QuartcCryptoServerStreamHelper::CanAcceptClientHello( ...@@ -114,65 +112,13 @@ bool QuartcCryptoServerStreamHelper::CanAcceptClientHello(
const QuicSocketAddress& client_address, const QuicSocketAddress& client_address,
const QuicSocketAddress& peer_address, const QuicSocketAddress& peer_address,
const QuicSocketAddress& self_address, const QuicSocketAddress& self_address,
string* error_details) const { QuicString* error_details) const {
return true; return true;
} }
QuartcSessionVisitorAdapter::~QuartcSessionVisitorAdapter() {}
QuartcSessionVisitorAdapter::QuartcSessionVisitorAdapter() {}
void QuartcSessionVisitorAdapter::OnPacketSent(
const SerializedPacket& serialized_packet,
QuicPacketNumber original_packet_number,
TransmissionType transmission_type,
QuicTime sent_time) {
for (QuartcSessionVisitor* visitor : visitors_) {
visitor->OnPacketSent(serialized_packet, original_packet_number,
transmission_type, sent_time);
}
}
void QuartcSessionVisitorAdapter::OnIncomingAck(
const QuicAckFrame& ack_frame,
QuicTime ack_receive_time,
QuicPacketNumber largest_observed,
bool rtt_updated,
QuicPacketNumber least_unacked_sent_packet) {
for (QuartcSessionVisitor* visitor : visitors_) {
visitor->OnIncomingAck(ack_frame, ack_receive_time, largest_observed,
rtt_updated, least_unacked_sent_packet);
}
}
void QuartcSessionVisitorAdapter::OnPacketLoss(
QuicPacketNumber lost_packet_number,
TransmissionType transmission_type,
QuicTime detection_time) {
for (QuartcSessionVisitor* visitor : visitors_) {
visitor->OnPacketLoss(lost_packet_number, transmission_type,
detection_time);
}
}
void QuartcSessionVisitorAdapter::OnWindowUpdateFrame(
const QuicWindowUpdateFrame& frame,
const QuicTime& receive_time) {
for (QuartcSessionVisitor* visitor : visitors_) {
visitor->OnWindowUpdateFrame(frame, receive_time);
}
}
void QuartcSessionVisitorAdapter::OnSuccessfulVersionNegotiation(
const ParsedQuicVersion& version) {
for (QuartcSessionVisitor* visitor : visitors_) {
visitor->OnSuccessfulVersionNegotiation(version);
}
}
QuartcSession::QuartcSession(std::unique_ptr<QuicConnection> connection, QuartcSession::QuartcSession(std::unique_ptr<QuicConnection> connection,
const QuicConfig& config, const QuicConfig& config,
const string& unique_remote_server_id, const QuicString& unique_remote_server_id,
Perspective perspective, Perspective perspective,
QuicConnectionHelperInterface* helper, QuicConnectionHelperInterface* helper,
QuicClock* clock, QuicClock* clock,
...@@ -200,7 +146,7 @@ QuartcSession::QuartcSession(std::unique_ptr<QuicConnection> connection, ...@@ -200,7 +146,7 @@ QuartcSession::QuartcSession(std::unique_ptr<QuicConnection> connection,
helper_->GetRandomGenerator()->RandBytes(source_address_token_secret, helper_->GetRandomGenerator()->RandBytes(source_address_token_secret,
kInputKeyingMaterialLength); kInputKeyingMaterialLength);
quic_crypto_server_config_ = QuicMakeUnique<QuicCryptoServerConfig>( quic_crypto_server_config_ = QuicMakeUnique<QuicCryptoServerConfig>(
string(source_address_token_secret, kInputKeyingMaterialLength), QuicString(source_address_token_secret, kInputKeyingMaterialLength),
helper_->GetRandomGenerator(), std::move(proof_source), helper_->GetRandomGenerator(), std::move(proof_source),
TlsServerHandshaker::CreateSslCtx()); TlsServerHandshaker::CreateSslCtx());
// Provide server with serialized config string to prove ownership. // Provide server with serialized config string to prove ownership.
...@@ -241,15 +187,6 @@ void QuartcSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) { ...@@ -241,15 +187,6 @@ void QuartcSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
} }
} }
void QuartcSession::CloseStream(QuicStreamId stream_id) {
if (IsClosedStream(stream_id)) {
// When CloseStream has been called recursively (via
// QuicStream::OnClose), the stream is already closed so return.
return;
}
QuicSession::CloseStream(stream_id);
}
void QuartcSession::CancelStream(QuicStreamId stream_id) { void QuartcSession::CancelStream(QuicStreamId stream_id) {
ResetStream(stream_id, QuicRstStreamErrorCode::QUIC_STREAM_CANCELLED); ResetStream(stream_id, QuicRstStreamErrorCode::QUIC_STREAM_CANCELLED);
} }
...@@ -265,21 +202,12 @@ void QuartcSession::ResetStream(QuicStreamId stream_id, ...@@ -265,21 +202,12 @@ void QuartcSession::ResetStream(QuicStreamId stream_id,
} }
} }
bool QuartcSession::IsOpenStream(QuicStreamId stream_id) {
return QuicSession::IsOpenStream(stream_id);
}
QuicConnectionStats QuartcSession::GetStats() {
return connection_->GetStats();
}
void QuartcSession::OnConnectionClosed(QuicErrorCode error, void QuartcSession::OnConnectionClosed(QuicErrorCode error,
const string& error_details, const QuicString& error_details,
ConnectionCloseSource source) { ConnectionCloseSource source) {
QuicSession::OnConnectionClosed(error, error_details, source); QuicSession::OnConnectionClosed(error, error_details, source);
DCHECK(session_delegate_); DCHECK(session_delegate_);
session_delegate_->OnConnectionClosed( session_delegate_->OnConnectionClosed(error, error_details, source);
error, source == ConnectionCloseSource::FROM_PEER);
} }
void QuartcSession::SetPreSharedKey(QuicStringPiece key) { void QuartcSession::SetPreSharedKey(QuicStringPiece key) {
...@@ -313,35 +241,13 @@ void QuartcSession::StartCryptoHandshake() { ...@@ -313,35 +241,13 @@ void QuartcSession::StartCryptoHandshake() {
} }
} }
bool QuartcSession::ExportKeyingMaterial(const string& label, void QuartcSession::CloseConnection(const QuicString& details) {
const uint8_t* context,
size_t context_len,
bool used_context,
uint8_t* result,
size_t result_len) {
string quic_context(reinterpret_cast<const char*>(context), context_len);
string quic_result;
bool success = crypto_stream_->ExportKeyingMaterial(label, quic_context,
result_len, &quic_result);
quic_result.copy(reinterpret_cast<char*>(result), result_len);
DCHECK(quic_result.length() == result_len);
return success;
}
void QuartcSession::CloseConnection(const string& details) {
connection_->CloseConnection( connection_->CloseConnection(
QuicErrorCode::QUIC_CONNECTION_CANCELLED, details, QuicErrorCode::QUIC_CONNECTION_CANCELLED, details,
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET_WITH_NO_ACK); ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET_WITH_NO_ACK);
} }
QuartcStreamInterface* QuartcSession::CreateOutgoingStream( void QuartcSession::SetDelegate(Delegate* session_delegate) {
const OutgoingStreamParameters& param) {
// The |param| is for forward-compatibility. Not used for now.
return CreateOutgoingDynamicStream();
}
void QuartcSession::SetDelegate(
QuartcSessionInterface::Delegate* session_delegate) {
if (session_delegate_) { if (session_delegate_) {
LOG(WARNING) << "The delegate for the session has already been set."; LOG(WARNING) << "The delegate for the session has already been set.";
} }
...@@ -349,25 +255,6 @@ void QuartcSession::SetDelegate( ...@@ -349,25 +255,6 @@ void QuartcSession::SetDelegate(
DCHECK(session_delegate_); DCHECK(session_delegate_);
} }
void QuartcSession::AddSessionVisitor(QuartcSessionVisitor* visitor) {
// If there aren't any visitors yet, install the adapter as a connection debug
// visitor to delegate any future calls.
if (session_visitor_adapter_.visitors().empty()) {
connection_->set_debug_visitor(&session_visitor_adapter_);
}
session_visitor_adapter_.mutable_visitors().insert(visitor);
visitor->OnQuicConnection(connection_.get());
}
void QuartcSession::RemoveSessionVisitor(QuartcSessionVisitor* visitor) {
session_visitor_adapter_.mutable_visitors().erase(visitor);
// If the last visitor is removed, uninstall the connection debug visitor to
// avoid delegating debug calls unnecessarily.
if (session_visitor_adapter_.visitors().empty()) {
connection_->set_debug_visitor(nullptr);
}
}
void QuartcSession::OnTransportCanWrite() { void QuartcSession::OnTransportCanWrite() {
connection()->writer()->SetWritable(); connection()->writer()->SetWritable();
if (HasDataToWrite()) { if (HasDataToWrite()) {
...@@ -376,29 +263,12 @@ void QuartcSession::OnTransportCanWrite() { ...@@ -376,29 +263,12 @@ void QuartcSession::OnTransportCanWrite() {
} }
bool QuartcSession::OnTransportReceived(const char* data, size_t data_len) { bool QuartcSession::OnTransportReceived(const char* data, size_t data_len) {
// If the session is currently bundling packets, it must stop and flush writes
// before processing incoming data. QUIC expects pending packets to be
// written before receiving data, because received data may change the
// contents of ACK frames in pending packets.
FlushWrites();
QuicReceivedPacket packet(data, data_len, clock_->Now()); QuicReceivedPacket packet(data, data_len, clock_->Now());
ProcessUdpPacket(connection()->self_address(), connection()->peer_address(), ProcessUdpPacket(connection()->self_address(), connection()->peer_address(),
packet); packet);
return true; return true;
} }
void QuartcSession::BundleWrites() {
if (!packet_flusher_) {
packet_flusher_ = QuicMakeUnique<QuicConnection::ScopedPacketFlusher>(
connection_.get(), QuicConnection::SEND_ACK_IF_QUEUED);
}
}
void QuartcSession::FlushWrites() {
packet_flusher_ = nullptr;
}
void QuartcSession::OnProofValid( void QuartcSession::OnProofValid(
const QuicCryptoClientConfig::CachedState& cached) { const QuicCryptoClientConfig::CachedState& cached) {
// TODO(zhihuang): Handle the proof verification. // TODO(zhihuang): Handle the proof verification.
...@@ -409,16 +279,6 @@ void QuartcSession::OnProofVerifyDetailsAvailable( ...@@ -409,16 +279,6 @@ void QuartcSession::OnProofVerifyDetailsAvailable(
// TODO(zhihuang): Handle the proof verification. // TODO(zhihuang): Handle the proof verification.
} }
void QuartcSession::SetClientCryptoConfig(
QuicCryptoClientConfig* client_config) {
quic_crypto_client_config_.reset(client_config);
}
void QuartcSession::SetServerCryptoConfig(
QuicCryptoServerConfig* server_config) {
quic_crypto_server_config_.reset(server_config);
}
QuicStream* QuartcSession::CreateIncomingDynamicStream(QuicStreamId id) { QuicStream* QuartcSession::CreateIncomingDynamicStream(QuicStreamId id) {
return ActivateDataStream(CreateDataStream(id, QuicStream::kDefaultPriority)); return ActivateDataStream(CreateDataStream(id, QuicStream::kDefaultPriority));
} }
......
...@@ -11,9 +11,7 @@ ...@@ -11,9 +11,7 @@
#include "net/third_party/quic/core/quic_error_codes.h" #include "net/third_party/quic/core/quic_error_codes.h"
#include "net/third_party/quic/core/quic_session.h" #include "net/third_party/quic/core/quic_session.h"
#include "net/third_party/quic/platform/api/quic_export.h" #include "net/third_party/quic/platform/api/quic_export.h"
#include "net/third_party/quic/quartc/quartc_clock_interface.h"
#include "net/third_party/quic/quartc/quartc_packet_writer.h" #include "net/third_party/quic/quartc/quartc_packet_writer.h"
#include "net/third_party/quic/quartc/quartc_session_interface.h"
#include "net/third_party/quic/quartc/quartc_stream.h" #include "net/third_party/quic/quartc/quartc_stream.h"
namespace quic { namespace quic {
...@@ -28,58 +26,23 @@ class QuartcCryptoServerStreamHelper : public QuicCryptoServerStream::Helper { ...@@ -28,58 +26,23 @@ class QuartcCryptoServerStreamHelper : public QuicCryptoServerStream::Helper {
const QuicSocketAddress& client_address, const QuicSocketAddress& client_address,
const QuicSocketAddress& peer_address, const QuicSocketAddress& peer_address,
const QuicSocketAddress& self_address, const QuicSocketAddress& self_address,
std::string* error_details) const override; QuicString* error_details) const override;
};
// Adapts |QuartcSessionVisitor|s to the |QuicConnectionDebugVisitor| interface.
// Keeps a set of |QuartcSessionVisitor|s and forwards QUIC debug callbacks to
// each visitor in the set.
class QuartcSessionVisitorAdapter : public QuicConnectionDebugVisitor {
public:
QuartcSessionVisitorAdapter();
~QuartcSessionVisitorAdapter() override;
void OnPacketSent(const SerializedPacket& serialized_packet,
QuicPacketNumber original_packet_number,
TransmissionType transmission_type,
QuicTime sent_time) override;
void OnIncomingAck(const QuicAckFrame& ack_frame,
QuicTime ack_receive_time,
QuicPacketNumber largest_observed,
bool rtt_updated,
QuicPacketNumber least_unacked_sent_packet) override;
void OnPacketLoss(QuicPacketNumber lost_packet_number,
TransmissionType transmission_type,
QuicTime detection_time) override;
void OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame,
const QuicTime& receive_time) override;
void OnSuccessfulVersionNegotiation(
const ParsedQuicVersion& version) override;
const std::set<QuartcSessionVisitor*>& visitors() const { return visitors_; }
std::set<QuartcSessionVisitor*>& mutable_visitors() { return visitors_; }
// Disallow copy and assign.
QuartcSessionVisitorAdapter(const QuartcSessionVisitorAdapter&) = delete;
QuartcSessionVisitorAdapter operator=(const QuartcSessionVisitorAdapter&) =
delete;
private:
std::set<QuartcSessionVisitor*> visitors_;
}; };
// QuartcSession owns and manages a QUIC connection.
class QUIC_EXPORT_PRIVATE QuartcSession class QUIC_EXPORT_PRIVATE QuartcSession
: public QuicSession, : public QuicSession,
public QuartcSessionInterface,
public QuicCryptoClientStream::ProofHandler { public QuicCryptoClientStream::ProofHandler {
public: public:
QuartcSession(std::unique_ptr<QuicConnection> connection, QuartcSession(std::unique_ptr<QuicConnection> connection,
const QuicConfig& config, const QuicConfig& config,
const std::string& unique_remote_server_id, const QuicString& unique_remote_server_id,
Perspective perspective, Perspective perspective,
QuicConnectionHelperInterface* helper, QuicConnectionHelperInterface* helper,
QuicClock* clock, QuicClock* clock,
std::unique_ptr<QuartcPacketWriter> packet_writer); std::unique_ptr<QuartcPacketWriter> packet_writer);
QuartcSession(const QuartcSession&) = delete;
QuartcSession& operator=(const QuartcSession&) = delete;
~QuartcSession() override; ~QuartcSession() override;
// QuicSession overrides. // QuicSession overrides.
...@@ -91,48 +54,67 @@ class QUIC_EXPORT_PRIVATE QuartcSession ...@@ -91,48 +54,67 @@ class QUIC_EXPORT_PRIVATE QuartcSession
void OnCryptoHandshakeEvent(CryptoHandshakeEvent event) override; void OnCryptoHandshakeEvent(CryptoHandshakeEvent event) override;
void CloseStream(QuicStreamId stream_id) override;
// QuicConnectionVisitorInterface overrides. // QuicConnectionVisitorInterface overrides.
void OnConnectionClosed(QuicErrorCode error, void OnConnectionClosed(QuicErrorCode error,
const std::string& error_details, const QuicString& error_details,
ConnectionCloseSource source) override; ConnectionCloseSource source) override;
// QuartcSessionInterface overrides // QuartcSession methods.
void SetPreSharedKey(QuicStringPiece key) override;
void StartCryptoHandshake() override; // Sets a pre-shared key for use during the crypto handshake. Must be set
// before StartCryptoHandshake() is called.
void SetPreSharedKey(QuicStringPiece key);
bool ExportKeyingMaterial(const std::string& label, void StartCryptoHandshake();
const uint8_t* context,
size_t context_len,
bool used_context,
uint8_t* result,
size_t result_len) override;
void CloseConnection(const std::string& details) override; // Closes the connection with the given human-readable error details.
// The connection closes with the QUIC_CONNECTION_CANCELLED error code to
// indicate the application closed it.
//
// Informs the peer that the connection has been closed. This prevents the
// peer from waiting until the connection times out.
//
// Cleans up the underlying QuicConnection's state. Closing the connection
// makes it safe to delete the QuartcSession.
void CloseConnection(const QuicString& details);
QuartcStreamInterface* CreateOutgoingStream( // If the given stream is still open, sends a reset frame to cancel it.
const OutgoingStreamParameters& param) override; // Note: This method cancels a stream by QuicStreamId rather than by pointer
// (or by a method on QuartcStream) because QuartcSession (and not
// the caller) owns the streams. Streams may finish and be deleted before the
// caller tries to cancel them, rendering the caller's pointers invalid.
void CancelStream(QuicStreamId stream_id);
void CancelStream(QuicStreamId stream_id) override; // Callbacks called by the QuartcSession to notify the user of the
// QuartcSession of certain events.
class Delegate {
public:
virtual ~Delegate() {}
bool IsOpenStream(QuicStreamId stream_id) override; // Called when the crypto handshake is complete.
virtual void OnCryptoHandshakeComplete() = 0;
QuicConnectionStats GetStats() override; // Called when a new stream is received from the remote endpoint.
virtual void OnIncomingStream(QuartcStream* stream) = 0;
void SetDelegate(QuartcSessionInterface::Delegate* session_delegate) override; // Called when the connection is closed. This means all of the streams will
// be closed and no new streams can be created.
virtual void OnConnectionClosed(QuicErrorCode error_code,
const QuicString& error_details,
ConnectionCloseSource source) = 0;
void AddSessionVisitor(QuartcSessionVisitor* visitor) override; // TODO(zhihuang): Add proof verification.
void RemoveSessionVisitor(QuartcSessionVisitor* visitor) override; };
void OnTransportCanWrite() override; // The |delegate| is not owned by QuartcSession.
void SetDelegate(Delegate* session_delegate);
// Decrypts an incoming QUIC packet to a data stream. // Called when CanWrite() changes from false to true.
bool OnTransportReceived(const char* data, size_t data_len) override; void OnTransportCanWrite();
void BundleWrites() override; // Called when a packet has been received and should be handled by the
void FlushWrites() override; // QuicConnection.
bool OnTransportReceived(const char* data, size_t data_len);
// ProofHandler overrides. // ProofHandler overrides.
void OnProofValid(const QuicCryptoClientConfig::CachedState& cached) override; void OnProofValid(const QuicCryptoClientConfig::CachedState& cached) override;
...@@ -143,12 +125,6 @@ class QUIC_EXPORT_PRIVATE QuartcSession ...@@ -143,12 +125,6 @@ class QUIC_EXPORT_PRIVATE QuartcSession
void OnProofVerifyDetailsAvailable( void OnProofVerifyDetailsAvailable(
const ProofVerifyDetails& verify_details) override; const ProofVerifyDetails& verify_details) override;
// Override the default crypto configuration.
// The session will take the ownership of the configurations.
void SetClientCryptoConfig(QuicCryptoClientConfig* client_config);
void SetServerCryptoConfig(QuicCryptoServerConfig* server_config);
protected: protected:
// QuicSession override. // QuicSession override.
QuicStream* CreateIncomingDynamicStream(QuicStreamId id) override; QuicStream* CreateIncomingDynamicStream(QuicStreamId id) override;
...@@ -164,7 +140,7 @@ class QUIC_EXPORT_PRIVATE QuartcSession ...@@ -164,7 +140,7 @@ class QUIC_EXPORT_PRIVATE QuartcSession
private: private:
// For crypto handshake. // For crypto handshake.
std::unique_ptr<QuicCryptoStream> crypto_stream_; std::unique_ptr<QuicCryptoStream> crypto_stream_;
const std::string unique_remote_server_id_; const QuicString unique_remote_server_id_;
Perspective perspective_; Perspective perspective_;
// Packet writer used by |connection_|. // Packet writer used by |connection_|.
...@@ -179,7 +155,7 @@ class QUIC_EXPORT_PRIVATE QuartcSession ...@@ -179,7 +155,7 @@ class QUIC_EXPORT_PRIVATE QuartcSession
// For recording packet receipt time // For recording packet receipt time
QuicClock* clock_; QuicClock* clock_;
// Not owned by QuartcSession. // Not owned by QuartcSession.
QuartcSessionInterface::Delegate* session_delegate_ = nullptr; Delegate* session_delegate_ = nullptr;
// Used by QUIC crypto server stream to track most recently compressed certs. // Used by QUIC crypto server stream to track most recently compressed certs.
std::unique_ptr<QuicCompressedCertsCache> quic_compressed_certs_cache_; std::unique_ptr<QuicCompressedCertsCache> quic_compressed_certs_cache_;
// This helper is needed when create QuicCryptoServerStream. // This helper is needed when create QuicCryptoServerStream.
...@@ -188,14 +164,6 @@ class QUIC_EXPORT_PRIVATE QuartcSession ...@@ -188,14 +164,6 @@ class QUIC_EXPORT_PRIVATE QuartcSession
std::unique_ptr<QuicCryptoClientConfig> quic_crypto_client_config_; std::unique_ptr<QuicCryptoClientConfig> quic_crypto_client_config_;
// Config for QUIC crypto server stream, used by the server. // Config for QUIC crypto server stream, used by the server.
std::unique_ptr<QuicCryptoServerConfig> quic_crypto_server_config_; std::unique_ptr<QuicCryptoServerConfig> quic_crypto_server_config_;
// Holds pointers to QuartcSessionVisitors and adapts them to the
// QuicConnectionDebugVisitor interface.
QuartcSessionVisitorAdapter session_visitor_adapter_;
std::unique_ptr<QuicConnection::ScopedPacketFlusher> packet_flusher_;
DISALLOW_COPY_AND_ASSIGN(QuartcSession);
}; };
} // namespace quic } // namespace quic
......
// Copyright (c) 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_THIRD_PARTY_QUIC_QUARTC_QUARTC_SESSION_INTERFACE_H_
#define NET_THIRD_PARTY_QUIC_QUARTC_QUARTC_SESSION_INTERFACE_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include "net/third_party/quic/core/quic_bandwidth.h"
#include "net/third_party/quic/core/quic_error_codes.h"
#include "net/third_party/quic/core/quic_time.h"
#include "net/third_party/quic/core/quic_types.h"
#include "net/third_party/quic/platform/api/quic_export.h"
#include "net/third_party/quic/quartc/quartc_session_visitor_interface.h"
#include "net/third_party/quic/quartc/quartc_stream_interface.h"
namespace quic {
// Send and receive packets, like a virtual UDP socket. For example, this
// could be implemented by WebRTC's IceTransport.
class QUIC_EXPORT_PRIVATE QuartcPacketTransport {
public:
// Additional metadata provided for each packet written.
struct PacketInfo {
QuicPacketNumber packet_number;
};
virtual ~QuartcPacketTransport() {}
// Called by the QuartcPacketWriter when writing packets to the network.
// Return the number of written bytes. Return 0 if the write is blocked.
virtual int Write(const char* buffer,
size_t buf_len,
const PacketInfo& info) = 0;
};
// Given a PacketTransport, provides a way to send and receive separate streams
// of reliable, in-order, encrypted data. For example, this can build on top of
// a WebRTC IceTransport for sending and receiving data over QUIC.
class QUIC_EXPORT_PRIVATE QuartcSessionInterface {
public:
virtual ~QuartcSessionInterface() {}
// Sets a pre-shared key for use during the crypto handshake. Must be set
// before StartCryptoHandshake() is called.
virtual void SetPreSharedKey(QuicStringPiece key) = 0;
virtual void StartCryptoHandshake() = 0;
// Only needed when using SRTP with QuicTransport
// Key Exporter interface from RFC 5705
// Arguments are:
// label -- the exporter label.
// part of the RFC defining each exporter usage (IN)
// context/context_len -- a context to bind to for this connection;
// optional, can be NULL, 0 (IN)
// use_context -- whether to use the context value
// (needed to distinguish no context from
// zero-length ones).
// result -- where to put the computed value
// result_len -- the length of the computed value
virtual bool ExportKeyingMaterial(const std::string& label,
const uint8_t* context,
size_t context_len,
bool used_context,
uint8_t* result,
size_t result_len) = 0;
// Closes the connection with the given human-readable error details.
// The connection closes with the QUIC_CONNECTION_CANCELLED error code to
// indicate the application closed it.
//
// Informs the peer that the connection has been closed. This prevents the
// peer from waiting until the connection times out.
//
// Cleans up the underlying QuicConnection's state. Closing the connection
// makes it safe to delete the QuartcSession.
virtual void CloseConnection(const std::string& error_details) = 0;
// For forward-compatibility. More parameters could be added through the
// struct without changing the API.
struct OutgoingStreamParameters {};
virtual QuartcStreamInterface* CreateOutgoingStream(
const OutgoingStreamParameters& params) = 0;
// If the given stream is still open, sends a reset frame to cancel it.
// Note: This method cancels a stream by QuicStreamId rather than by pointer
// (or by a method on QuartcStreamInterface) because QuartcSession (and not
// the caller) owns the streams. Streams may finish and be deleted before the
// caller tries to cancel them, rendering the caller's pointers invalid.
virtual void CancelStream(QuicStreamId stream_id) = 0;
// This method verifies if a stream is still open and stream pointer can be
// used. When true is returned, the interface pointer is good for making a
// call immediately on the same thread, but may be rendered invalid by ANY
// other QUIC activity.
virtual bool IsOpenStream(QuicStreamId stream_id) = 0;
// Gets stats associated with the current QUIC connection.
virtual QuicConnectionStats GetStats() = 0;
// Called when CanWrite() changes from false to true.
virtual void OnTransportCanWrite() = 0;
// Called when a packet has been received and should be handled by the
// QuicConnection.
virtual bool OnTransportReceived(const char* data, size_t data_len) = 0;
// Bundles subsequent writes on a best-effort basis.
// Data is sent whenever enough data is accumulated to fill a packet.
// The session stops bundling writes and sends data immediately as soon as
// FlushWrites() is called or a packet is received.
virtual void BundleWrites() = 0;
// Stop bundling writes and flush any pending writes immediately.
virtual void FlushWrites() = 0;
// Callbacks called by the QuartcSession to notify the user of the
// QuartcSession of certain events.
class Delegate {
public:
virtual ~Delegate() {}
// Called when the crypto handshake is complete.
virtual void OnCryptoHandshakeComplete() = 0;
// Called when a new stream is received from the remote endpoint.
virtual void OnIncomingStream(QuartcStreamInterface* stream) = 0;
// Called when the connection is closed. This means all of the streams will
// be closed and no new streams can be created.
// TODO(zhihuang): Create mapping from integer error code to WebRTC error
// code.
virtual void OnConnectionClosed(int error_code, bool from_remote) = 0;
// TODO(zhihuang): Add proof verification.
};
// The |delegate| is not owned by QuartcSession.
virtual void SetDelegate(Delegate* delegate) = 0;
// Add or remove session visitors. Session visitors observe internals of the
// Quartc/QUIC session for the purpose of gathering metrics or debug
// information.
virtual void AddSessionVisitor(QuartcSessionVisitor* visitor) = 0;
virtual void RemoveSessionVisitor(QuartcSessionVisitor* visitor) = 0;
};
} // namespace quic
#endif // NET_THIRD_PARTY_QUIC_QUARTC_QUARTC_SESSION_INTERFACE_H_
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "net/third_party/quic/quartc/quartc_session.h" #include "net/third_party/quic/quartc/quartc_session.h"
#include "build/build_config.h"
#include "net/third_party/quic/core/crypto/crypto_server_config_protobuf.h" #include "net/third_party/quic/core/crypto/crypto_server_config_protobuf.h"
#include "net/third_party/quic/core/quic_simple_buffer_allocator.h" #include "net/third_party/quic/core/quic_simple_buffer_allocator.h"
#include "net/third_party/quic/core/quic_types.h" #include "net/third_party/quic/core/quic_types.h"
...@@ -13,229 +14,100 @@ ...@@ -13,229 +14,100 @@
#include "net/third_party/quic/platform/api/quic_test.h" #include "net/third_party/quic/platform/api/quic_test.h"
#include "net/third_party/quic/platform/api/quic_test_mem_slice_vector.h" #include "net/third_party/quic/platform/api/quic_test_mem_slice_vector.h"
#include "net/third_party/quic/quartc/quartc_factory.h" #include "net/third_party/quic/quartc/quartc_factory.h"
#include "net/third_party/quic/quartc/quartc_factory_interface.h"
#include "net/third_party/quic/quartc/quartc_packet_writer.h" #include "net/third_party/quic/quartc/quartc_packet_writer.h"
#include "net/third_party/quic/quartc/quartc_stream_interface.h"
#include "net/third_party/quic/test_tools/mock_clock.h" #include "net/third_party/quic/test_tools/mock_clock.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
using std::string; // Tests flaky on iOS.
// TODO(vasilvv): figure out what's wrong and re-enable if possible.
#if !defined(OS_IOS)
namespace quic { namespace quic {
namespace { namespace {
static const char kExporterLabel[] = "label";
static const uint8_t kExporterContext[] = "context";
static const size_t kExporterContextLen = sizeof(kExporterContext);
static const size_t kOutputKeyLength = 20;
static QuartcStreamInterface::WriteParameters kDefaultWriteParam;
static QuartcSessionInterface::OutgoingStreamParameters kDefaultStreamParam;
static QuicByteCount kDefaultMaxPacketSize = 1200; static QuicByteCount kDefaultMaxPacketSize = 1200;
// Single-threaded scheduled task runner based on a MockClock. // Single-threaded alarm implementation based on a MockClock.
// //
// Simulates asynchronous execution on a single thread by holding scheduled // Simulates asynchronous execution on a single thread by holding alarms
// tasks until Run() is called. Performs no synchronization, assumes that // until Run() is called. Performs no synchronization, assumes that
// Schedule() and Run() are called on the same thread. // CreateAlarm(), Set(), Cancel(), and Run() are called on the same thread.
class FakeTaskRunner : public QuartcTaskRunnerInterface { class FakeAlarmFactory : public QuicAlarmFactory {
public: public:
explicit FakeTaskRunner(MockClock* clock) class FakeAlarm : public QuicAlarm {
: tasks_([this](const TaskType& l, const TaskType& r) {
// Items at a later time should run after items at an earlier time.
// Priority queue comparisons should return true if l appears after r.
return l->time() > r->time();
}),
clock_(clock) {}
~FakeTaskRunner() override {}
// Runs all tasks scheduled in the next total_ms milliseconds. Advances the
// clock by total_ms. Runs tasks in time order. Executes tasks scheduled at
// the same in an arbitrary order.
void Run(uint32_t total_ms) {
for (uint32_t i = 0; i < total_ms; ++i) {
while (!tasks_.empty() && tasks_.top()->time() <= clock_->Now()) {
tasks_.top()->Run();
tasks_.pop();
}
clock_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
}
}
private:
class InnerTask {
public: public:
InnerTask(std::function<void()> task, QuicTime time) FakeAlarm(QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,
: task_(std::move(task)), time_(time) {} FakeAlarmFactory* parent)
: QuicAlarm(std::move(delegate)), parent_(parent) {}
void Cancel() { cancelled_ = true; }
void Run() {
if (!cancelled_) {
task_();
}
}
QuicTime time() const { return time_; }
private: ~FakeAlarm() override { parent_->RemoveAlarm(this); }
bool cancelled_ = false;
std::function<void()> task_;
QuicTime time_;
};
public: void SetImpl() override { parent_->AddAlarm(this); }
// Hook for cancelling a scheduled task.
class ScheduledTask : public QuartcTaskRunnerInterface::ScheduledTask {
public:
explicit ScheduledTask(std::shared_ptr<InnerTask> inner)
: inner_(std::move(inner)) {}
// Cancel if the caller deletes the ScheduledTask. This behavior is void CancelImpl() override { parent_->RemoveAlarm(this); }
// consistent with the actual task runner Quartc uses.
~ScheduledTask() override { Cancel(); }
// ScheduledTask implementation. void Run() { Fire(); }
void Cancel() override { inner_->Cancel(); }
private: private:
std::shared_ptr<InnerTask> inner_; FakeAlarmFactory* parent_;
}; };
// See QuartcTaskRunnerInterface. explicit FakeAlarmFactory(MockClock* clock) : clock_(clock) {}
std::unique_ptr<QuartcTaskRunnerInterface::ScheduledTask> Schedule( FakeAlarmFactory(const FakeAlarmFactory&) = delete;
Task* task, FakeAlarmFactory& operator=(const FakeAlarmFactory&) = delete;
uint64_t delay_ms) override {
auto inner = std::shared_ptr<InnerTask>(new InnerTask(
[task] { task->Run(); },
clock_->Now() + QuicTime::Delta::FromMilliseconds(delay_ms)));
tasks_.push(inner);
return std::unique_ptr<QuartcTaskRunnerInterface::ScheduledTask>(
new ScheduledTask(inner));
}
// Schedules a function to run immediately. QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) override {
void Schedule(std::function<void()> task) { return new FakeAlarm(QuicArenaScopedPtr<QuicAlarm::Delegate>(delegate),
tasks_.push(std::shared_ptr<InnerTask>( this);
new InnerTask(std::move(task), clock_->Now())));
} }
private: QuicArenaScopedPtr<QuicAlarm> CreateAlarm(
// InnerTasks are shared by the queue and ScheduledTask (which hooks into it QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,
// to implement Cancel()). QuicConnectionArena* arena) override {
using TaskType = std::shared_ptr<InnerTask>; return arena->New<FakeAlarm>(std::move(delegate), this);
std::priority_queue<TaskType,
std::vector<TaskType>,
std::function<bool(const TaskType&, const TaskType&)>>
tasks_;
MockClock* clock_;
};
// QuartcClock that wraps a MockClock.
//
// This is silly because Quartc wraps it as a QuicClock, and MockClock is
// already a QuicClock. But we don't have much choice. We need to pass a
// QuartcClockInterface into the Quartc wrappers.
class MockQuartcClock : public QuartcClockInterface {
public:
explicit MockQuartcClock(MockClock* clock) : clock_(clock) {}
int64_t NowMicroseconds() override {
return clock_->WallNow().ToUNIXMicroseconds();
} }
private: // Runs all alarms scheduled in the next total_ms milliseconds. Advances the
MockClock* clock_; // clock by total_ms. Runs tasks in time order. Executes tasks scheduled at
}; // the same in an arbitrary order.
void Run(uint32_t total_ms) {
// Used by QuicCryptoServerConfig to provide server credentials, returning a for (uint32_t i = 0; i < total_ms; ++i) {
// canned response equal to |success|. while (!alarms_.empty() && alarms_.top()->deadline() <= clock_->Now()) {
class FakeProofSource : public ProofSource { alarms_.top()->Run();
public: alarms_.pop();
explicit FakeProofSource(bool success) : success_(success) {} }
clock_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
// ProofSource override.
void GetProof(const QuicSocketAddress& server_ip,
const string& hostname,
const string& server_config,
QuicTransportVersion transport_version,
QuicStringPiece chlo_hash,
std::unique_ptr<Callback> callback) override {
QuicReferenceCountedPointer<ProofSource::Chain> chain;
QuicCryptoProof proof;
if (success_) {
std::vector<string> certs;
certs.push_back("Required to establish handshake");
chain = new ProofSource::Chain(certs);
proof.signature = "Signature";
proof.leaf_cert_scts = "Time";
} }
callback->Run(success_, chain, proof, nullptr /* details */);
}
QuicReferenceCountedPointer<Chain> GetCertChain(
const QuicSocketAddress& server_address,
const string& hostname) override {
return QuicReferenceCountedPointer<Chain>();
}
void ComputeTlsSignature(
const QuicSocketAddress& server_address,
const string& hostname,
uint16_t signature_algorithm,
QuicStringPiece in,
std::unique_ptr<SignatureCallback> callback) override {
callback->Run(true, "Signature");
} }
private: private:
// Whether or not obtaining proof source succeeds. void RemoveAlarm(FakeAlarm* alarm) {
bool success_; std::vector<FakeAlarm*> leftovers;
}; while (!alarms_.empty()) {
FakeAlarm* top = alarms_.top();
// Used by QuicCryptoClientConfig to verify server credentials, returning a alarms_.pop();
// canned response of QUIC_SUCCESS if |success| is true. if (top == alarm) {
class FakeProofVerifier : public ProofVerifier { break;
public: }
explicit FakeProofVerifier(bool success) : success_(success) {} leftovers.push_back(top);
}
// ProofVerifier override for (FakeAlarm* leftover : leftovers) {
QuicAsyncStatus VerifyProof( alarms_.push(leftover);
const string& hostname, }
const uint16_t port,
const string& server_config,
QuicTransportVersion transport_version,
QuicStringPiece chlo_hash,
const std::vector<string>& certs,
const string& cert_sct,
const string& signature,
const ProofVerifyContext* context,
string* error_details,
std::unique_ptr<ProofVerifyDetails>* verify_details,
std::unique_ptr<ProofVerifierCallback> callback) override {
return success_ ? QUIC_SUCCESS : QUIC_FAILURE;
} }
QuicAsyncStatus VerifyCertChain( void AddAlarm(FakeAlarm* alarm) { alarms_.push(alarm); }
const string& hostname,
const std::vector<string>& certs,
const ProofVerifyContext* context,
string* error_details,
std::unique_ptr<ProofVerifyDetails>* details,
std::unique_ptr<ProofVerifierCallback> callback) override {
LOG(INFO) << "VerifyProof() ignoring credentials and returning success";
return success_ ? QUIC_SUCCESS : QUIC_FAILURE;
}
std::unique_ptr<ProofVerifyContext> CreateDefaultContext() override { MockClock* clock_;
return nullptr;
}
private: using AlarmCompare = std::function<bool(const FakeAlarm*, const FakeAlarm*)>;
// Whether or not proof verification succeeds. const AlarmCompare alarm_later_ = [](const FakeAlarm* l, const FakeAlarm* r) {
bool success_; // Sort alarms so that the earliest deadline appears first.
return l->deadline() > r->deadline();
};
std::priority_queue<FakeAlarm*, std::vector<FakeAlarm*>, AlarmCompare>
alarms_{alarm_later_};
}; };
// Used by the FakeTransportChannel. // Used by the FakeTransportChannel.
...@@ -244,15 +116,17 @@ class FakeTransportChannelObserver { ...@@ -244,15 +116,17 @@ class FakeTransportChannelObserver {
virtual ~FakeTransportChannelObserver() {} virtual ~FakeTransportChannelObserver() {}
// Called when the other peer is trying to send message. // Called when the other peer is trying to send message.
virtual void OnTransportChannelReadPacket(const string& data) = 0; virtual void OnTransportChannelReadPacket(const QuicString& data) = 0;
}; };
// Simulate the P2P communication transport. Used by the // Simulate the P2P communication transport. Used by the
// QuartcSessionInterface::Transport. // QuartcSession::Transport.
class FakeTransportChannel { class FakeTransportChannel : QuicAlarm::Delegate {
public: public:
explicit FakeTransportChannel(FakeTaskRunner* task_runner, MockClock* clock) explicit FakeTransportChannel(QuicAlarmFactory* alarm_factory,
: task_runner_(task_runner), clock_(clock) {} MockClock* clock)
: alarm_(alarm_factory->CreateAlarm(new AlarmDelegate(this))),
clock_(clock) {}
void SetDestination(FakeTransportChannel* dest) { void SetDestination(FakeTransportChannel* dest) {
if (!dest_) { if (!dest_) {
...@@ -268,21 +142,16 @@ class FakeTransportChannel { ...@@ -268,21 +142,16 @@ class FakeTransportChannel {
} }
// Advance the time 10us to ensure the RTT is never 0ms. // Advance the time 10us to ensure the RTT is never 0ms.
clock_->AdvanceTime(QuicTime::Delta::FromMicroseconds(10)); clock_->AdvanceTime(QuicTime::Delta::FromMicroseconds(10));
if (async_ && task_runner_) { if (async_) {
string packet(data, len); packet_queue_.emplace_back(data, len);
task_runner_->Schedule([this, packet] { send(packet); }); alarm_->Cancel();
alarm_->Set(clock_->Now());
} else { } else {
send(string(data, len)); Send(QuicString(data, len));
} }
return static_cast<int>(len); return static_cast<int>(len);
} }
void send(const string& data) {
DCHECK(dest_);
DCHECK(dest_->observer());
dest_->observer()->OnTransportChannelReadPacket(data);
}
FakeTransportChannelObserver* observer() { return observer_; } FakeTransportChannelObserver* observer() { return observer_; }
void SetObserver(FakeTransportChannelObserver* observer) { void SetObserver(FakeTransportChannelObserver* observer) {
...@@ -292,14 +161,43 @@ class FakeTransportChannel { ...@@ -292,14 +161,43 @@ class FakeTransportChannel {
void SetAsync(bool async) { async_ = async; } void SetAsync(bool async) { async_ = async; }
private: private:
class AlarmDelegate : public QuicAlarm::Delegate {
public:
explicit AlarmDelegate(FakeTransportChannel* channel) : channel_(channel) {}
void OnAlarm() override { channel_->OnAlarm(); }
private:
FakeTransportChannel* channel_;
};
void Send(const QuicString& data) {
DCHECK(dest_);
DCHECK(dest_->observer());
dest_->observer()->OnTransportChannelReadPacket(data);
}
void OnAlarm() override {
QUIC_LOG(WARNING) << "Sending packet: " << packet_queue_.front();
Send(packet_queue_.front());
packet_queue_.pop_front();
if (!packet_queue_.empty()) {
alarm_->Cancel();
alarm_->Set(clock_->Now());
}
}
// The writing destination of this channel. // The writing destination of this channel.
FakeTransportChannel* dest_ = nullptr; FakeTransportChannel* dest_ = nullptr;
// The observer of this channel. Called when the received the data. // The observer of this channel. Called when the received the data.
FakeTransportChannelObserver* observer_ = nullptr; FakeTransportChannelObserver* observer_ = nullptr;
// If async, will send packets by running asynchronous tasks. // If async, will send packets by running asynchronous tasks.
bool async_ = false; bool async_ = false;
// Used to send data asynchronously. // If async, packets are queued here to send.
FakeTaskRunner* task_runner_; QuicDeque<QuicString> packet_queue_;
// Alarm used to send data asynchronously.
QuicArenaScopedPtr<QuicAlarm> alarm_;
// The test clock. Used to ensure the RTT is not 0. // The test clock. Used to ensure the RTT is not 0.
MockClock* clock_; MockClock* clock_;
}; };
...@@ -331,51 +229,52 @@ class FakeTransport : public QuartcPacketTransport { ...@@ -331,51 +229,52 @@ class FakeTransport : public QuartcPacketTransport {
QuicPacketCount packets_to_lose_ = 0; QuicPacketCount packets_to_lose_ = 0;
}; };
class FakeQuartcSessionDelegate : public QuartcSessionInterface::Delegate { class FakeQuartcSessionDelegate : public QuartcSession::Delegate {
public: public:
explicit FakeQuartcSessionDelegate( explicit FakeQuartcSessionDelegate(QuartcStream::Delegate* stream_delegate)
QuartcStreamInterface::Delegate* stream_delegate)
: stream_delegate_(stream_delegate) {} : stream_delegate_(stream_delegate) {}
// Called when peers have established forward-secure encryption // Called when peers have established forward-secure encryption
void OnCryptoHandshakeComplete() override { void OnCryptoHandshakeComplete() override {
LOG(INFO) << "Crypto handshake complete!"; LOG(INFO) << "Crypto handshake complete!";
} }
// Called when connection closes locally, or remotely by peer. // Called when connection closes locally, or remotely by peer.
void OnConnectionClosed(int error_code, bool from_remote) override { void OnConnectionClosed(QuicErrorCode error_code,
const QuicString& error_details,
ConnectionCloseSource source) override {
connected_ = false; connected_ = false;
} }
// Called when an incoming QUIC stream is created. // Called when an incoming QUIC stream is created.
void OnIncomingStream(QuartcStreamInterface* quartc_stream) override { void OnIncomingStream(QuartcStream* quartc_stream) override {
last_incoming_stream_ = quartc_stream; last_incoming_stream_ = quartc_stream;
last_incoming_stream_->SetDelegate(stream_delegate_); last_incoming_stream_->SetDelegate(stream_delegate_);
} }
QuartcStreamInterface* incoming_stream() { return last_incoming_stream_; } QuartcStream* incoming_stream() { return last_incoming_stream_; }
bool connected() { return connected_; } bool connected() { return connected_; }
private: private:
QuartcStreamInterface* last_incoming_stream_; QuartcStream* last_incoming_stream_;
bool connected_ = true; bool connected_ = true;
QuartcStream::Delegate* stream_delegate_; QuartcStream::Delegate* stream_delegate_;
}; };
class FakeQuartcStreamDelegate : public QuartcStreamInterface::Delegate { class FakeQuartcStreamDelegate : public QuartcStream::Delegate {
public: public:
void OnReceived(QuartcStreamInterface* stream, void OnReceived(QuartcStream* stream,
const char* data, const char* data,
size_t size) override { size_t size) override {
received_data_[stream->stream_id()] += string(data, size); received_data_[stream->id()] += QuicString(data, size);
} }
void OnClose(QuartcStreamInterface* stream) override {} void OnClose(QuartcStream* stream) override {}
void OnBufferChanged(QuartcStreamInterface* stream) override {} void OnBufferChanged(QuartcStream* stream) override {}
std::map<QuicStreamId, string> data() { return received_data_; } std::map<QuicStreamId, QuicString> data() { return received_data_; }
private: private:
std::map<QuicStreamId, string> received_data_; std::map<QuicStreamId, QuicString> received_data_;
}; };
class QuartcSessionForTest : public QuartcSession, class QuartcSessionForTest : public QuartcSession,
...@@ -383,7 +282,7 @@ class QuartcSessionForTest : public QuartcSession, ...@@ -383,7 +282,7 @@ class QuartcSessionForTest : public QuartcSession,
public: public:
QuartcSessionForTest(std::unique_ptr<QuicConnection> connection, QuartcSessionForTest(std::unique_ptr<QuicConnection> connection,
const QuicConfig& config, const QuicConfig& config,
const string& remote_fingerprint_value, const QuicString& remote_fingerprint_value,
Perspective perspective, Perspective perspective,
QuicConnectionHelperInterface* helper, QuicConnectionHelperInterface* helper,
QuicClock* clock, QuicClock* clock,
...@@ -403,11 +302,11 @@ class QuartcSessionForTest : public QuartcSession, ...@@ -403,11 +302,11 @@ class QuartcSessionForTest : public QuartcSession,
} }
// QuartcPacketWriter override. // QuartcPacketWriter override.
void OnTransportChannelReadPacket(const string& data) override { void OnTransportChannelReadPacket(const QuicString& data) override {
OnTransportReceived(data.c_str(), data.length()); OnTransportReceived(data.c_str(), data.length());
} }
std::map<QuicStreamId, string> data() { return stream_delegate_->data(); } std::map<QuicStreamId, QuicString> data() { return stream_delegate_->data(); }
bool has_data() { return !data().empty(); } bool has_data() { return !data().empty(); }
...@@ -431,9 +330,9 @@ class QuartcSessionTest : public QuicTest, ...@@ -431,9 +330,9 @@ class QuartcSessionTest : public QuicTest,
// Quic crashes if packets are sent at time 0, and the clock defaults to 0. // Quic crashes if packets are sent at time 0, and the clock defaults to 0.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1000)); clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1000));
client_channel_ = client_channel_ =
QuicMakeUnique<FakeTransportChannel>(&task_runner_, &clock_); QuicMakeUnique<FakeTransportChannel>(&alarm_factory_, &clock_);
server_channel_ = server_channel_ =
QuicMakeUnique<FakeTransportChannel>(&task_runner_, &clock_); QuicMakeUnique<FakeTransportChannel>(&alarm_factory_, &clock_);
// Make the channel asynchronous so that two peer will not keep calling each // Make the channel asynchronous so that two peer will not keep calling each
// other when they exchange information. // other when they exchange information.
client_channel_->SetAsync(true); client_channel_->SetAsync(true);
...@@ -453,8 +352,7 @@ class QuartcSessionTest : public QuicTest, ...@@ -453,8 +352,7 @@ class QuartcSessionTest : public QuicTest,
// The parameters are used to control whether the handshake will success or // The parameters are used to control whether the handshake will success or
// not. // not.
void CreateClientAndServerSessions(bool client_handshake_success = true, void CreateClientAndServerSessions() {
bool server_handshake_success = true) {
Init(); Init();
client_peer_ = client_peer_ =
CreateSession(Perspective::IS_CLIENT, std::move(client_writer_)); CreateSession(Perspective::IS_CLIENT, std::move(client_writer_));
...@@ -463,26 +361,6 @@ class QuartcSessionTest : public QuicTest, ...@@ -463,26 +361,6 @@ class QuartcSessionTest : public QuicTest,
client_channel_->SetObserver(client_peer_.get()); client_channel_->SetObserver(client_peer_.get());
server_channel_->SetObserver(server_peer_.get()); server_channel_->SetObserver(server_peer_.get());
client_peer_->SetClientCryptoConfig(new QuicCryptoClientConfig(
std::unique_ptr<ProofVerifier>(
new FakeProofVerifier(client_handshake_success)),
TlsClientHandshaker::CreateSslCtx()));
QuicCryptoServerConfig* server_config = new QuicCryptoServerConfig(
"TESTING", QuicRandom::GetInstance(),
std::unique_ptr<FakeProofSource>(
new FakeProofSource(server_handshake_success)),
TlsServerHandshaker::CreateSslCtx());
// Provide server with serialized config string to prove ownership.
QuicCryptoServerConfig::ConfigOptions options;
std::unique_ptr<QuicServerConfigProtobuf> primary_config(
server_config->GenerateConfig(QuicRandom::GetInstance(), &clock_,
options));
std::unique_ptr<CryptoHandshakeMessage> message(
server_config->AddConfig(std::move(primary_config), clock_.WallNow()));
server_peer_->SetServerCryptoConfig(server_config);
} }
std::unique_ptr<QuartcSessionForTest> CreateSession( std::unique_ptr<QuartcSessionForTest> CreateSession(
...@@ -490,7 +368,7 @@ class QuartcSessionTest : public QuicTest, ...@@ -490,7 +368,7 @@ class QuartcSessionTest : public QuicTest,
std::unique_ptr<QuartcPacketWriter> writer) { std::unique_ptr<QuartcPacketWriter> writer) {
std::unique_ptr<QuicConnection> quic_connection = std::unique_ptr<QuicConnection> quic_connection =
CreateConnection(perspective, writer.get()); CreateConnection(perspective, writer.get());
string remote_fingerprint_value = "value"; QuicString remote_fingerprint_value = "value";
QuicConfig config; QuicConfig config;
return QuicMakeUnique<QuartcSessionForTest>( return QuicMakeUnique<QuartcSessionForTest>(
std::move(quic_connection), config, remote_fingerprint_value, std::move(quic_connection), config, remote_fingerprint_value,
...@@ -501,22 +379,14 @@ class QuartcSessionTest : public QuicTest, ...@@ -501,22 +379,14 @@ class QuartcSessionTest : public QuicTest,
QuartcPacketWriter* writer) { QuartcPacketWriter* writer) {
QuicIpAddress ip; QuicIpAddress ip;
ip.FromString("0.0.0.0"); ip.FromString("0.0.0.0");
if (!alarm_factory_) {
// QuartcFactory is only used as an alarm factory.
QuartcFactoryConfig config;
config.clock = &quartc_clock_;
config.task_runner = &task_runner_;
alarm_factory_ = QuicMakeUnique<QuartcFactory>(config);
}
return QuicMakeUnique<QuicConnection>( return QuicMakeUnique<QuicConnection>(
0, QuicSocketAddress(ip, 0), this /*QuicConnectionHelperInterface*/, 0, QuicSocketAddress(ip, 0), this /*QuicConnectionHelperInterface*/,
alarm_factory_.get(), writer, /*owns_writer=*/false, perspective, &alarm_factory_, writer, /*owns_writer=*/false, perspective,
CurrentSupportedVersions()); CurrentSupportedVersions());
} }
// Runs all tasks scheduled in the next 200 ms. // Runs all tasks scheduled in the next 200 ms.
void RunTasks() { task_runner_.Run(200); } void RunTasks() { alarm_factory_.Run(200); }
void StartHandshake() { void StartHandshake() {
server_peer_->StartCryptoHandshake(); server_peer_->StartCryptoHandshake();
...@@ -532,23 +402,9 @@ class QuartcSessionTest : public QuicTest, ...@@ -532,23 +402,9 @@ class QuartcSessionTest : public QuicTest,
ASSERT_TRUE(server_peer_->IsEncryptionEstablished()); ASSERT_TRUE(server_peer_->IsEncryptionEstablished());
ASSERT_TRUE(client_peer_->IsEncryptionEstablished()); ASSERT_TRUE(client_peer_->IsEncryptionEstablished());
uint8_t server_key[kOutputKeyLength];
uint8_t client_key[kOutputKeyLength];
bool use_context = true;
bool server_success = server_peer_->ExportKeyingMaterial(
kExporterLabel, kExporterContext, kExporterContextLen, use_context,
server_key, kOutputKeyLength);
ASSERT_TRUE(server_success);
bool client_success = client_peer_->ExportKeyingMaterial(
kExporterLabel, kExporterContext, kExporterContextLen, use_context,
client_key, kOutputKeyLength);
ASSERT_TRUE(client_success);
EXPECT_EQ(0, memcmp(server_key, client_key, sizeof(server_key)));
// Now we can establish encrypted outgoing stream. // Now we can establish encrypted outgoing stream.
QuartcStreamInterface* outgoing_stream = QuartcStream* outgoing_stream = server_peer_->CreateOutgoingDynamicStream();
server_peer_->CreateOutgoingStream(kDefaultStreamParam); QuicStreamId stream_id = outgoing_stream->id();
QuicStreamId stream_id = outgoing_stream->stream_id();
ASSERT_NE(nullptr, outgoing_stream); ASSERT_NE(nullptr, outgoing_stream);
EXPECT_TRUE(server_peer_->HasOpenDynamicStreams()); EXPECT_TRUE(server_peer_->HasOpenDynamicStreams());
...@@ -558,16 +414,16 @@ class QuartcSessionTest : public QuicTest, ...@@ -558,16 +414,16 @@ class QuartcSessionTest : public QuicTest,
char kTestMessage[] = "Hello"; char kTestMessage[] = "Hello";
test::QuicTestMemSliceVector data( test::QuicTestMemSliceVector data(
{std::make_pair(kTestMessage, strlen(kTestMessage))}); {std::make_pair(kTestMessage, strlen(kTestMessage))});
outgoing_stream->Write(data.span(), kDefaultWriteParam); outgoing_stream->WriteMemSlices(data.span(), /*fin=*/false);
RunTasks(); RunTasks();
// Wait for peer 2 to receive messages. // Wait for peer 2 to receive messages.
ASSERT_TRUE(client_peer_->has_data()); ASSERT_TRUE(client_peer_->has_data());
QuartcStreamInterface* incoming = QuartcStream* incoming =
client_peer_->session_delegate()->incoming_stream(); client_peer_->session_delegate()->incoming_stream();
ASSERT_TRUE(incoming); ASSERT_TRUE(incoming);
EXPECT_EQ(incoming->stream_id(), stream_id); EXPECT_EQ(incoming->id(), stream_id);
EXPECT_TRUE(client_peer_->HasOpenDynamicStreams()); EXPECT_TRUE(client_peer_->HasOpenDynamicStreams());
EXPECT_EQ(client_peer_->data()[stream_id], kTestMessage); EXPECT_EQ(client_peer_->data()[stream_id], kTestMessage);
...@@ -575,7 +431,7 @@ class QuartcSessionTest : public QuicTest, ...@@ -575,7 +431,7 @@ class QuartcSessionTest : public QuicTest,
char kTestResponse[] = "Response"; char kTestResponse[] = "Response";
test::QuicTestMemSliceVector response( test::QuicTestMemSliceVector response(
{std::make_pair(kTestResponse, strlen(kTestResponse))}); {std::make_pair(kTestResponse, strlen(kTestResponse))});
incoming->Write(response.span(), kDefaultWriteParam); incoming->WriteMemSlices(response.span(), /*fin=*/false);
RunTasks(); RunTasks();
// Wait for peer 1 to receive messages. // Wait for peer 1 to receive messages.
ASSERT_TRUE(server_peer_->has_data()); ASSERT_TRUE(server_peer_->has_data());
...@@ -606,10 +462,9 @@ class QuartcSessionTest : public QuicTest, ...@@ -606,10 +462,9 @@ class QuartcSessionTest : public QuicTest,
} }
protected: protected:
std::unique_ptr<QuicAlarmFactory> alarm_factory_;
SimpleBufferAllocator buffer_allocator_;
MockClock clock_; MockClock clock_;
MockQuartcClock quartc_clock_{&clock_}; FakeAlarmFactory alarm_factory_{&clock_};
SimpleBufferAllocator buffer_allocator_;
std::unique_ptr<FakeTransportChannel> client_channel_; std::unique_ptr<FakeTransportChannel> client_channel_;
std::unique_ptr<FakeTransportChannel> server_channel_; std::unique_ptr<FakeTransportChannel> server_channel_;
...@@ -619,8 +474,6 @@ class QuartcSessionTest : public QuicTest, ...@@ -619,8 +474,6 @@ class QuartcSessionTest : public QuicTest,
std::unique_ptr<QuartcPacketWriter> server_writer_; std::unique_ptr<QuartcPacketWriter> server_writer_;
std::unique_ptr<QuartcSessionForTest> client_peer_; std::unique_ptr<QuartcSessionForTest> client_peer_;
std::unique_ptr<QuartcSessionForTest> server_peer_; std::unique_ptr<QuartcSessionForTest> server_peer_;
FakeTaskRunner task_runner_{&clock_};
}; };
TEST_F(QuartcSessionTest, StreamConnection) { TEST_F(QuartcSessionTest, StreamConnection) {
...@@ -629,42 +482,19 @@ TEST_F(QuartcSessionTest, StreamConnection) { ...@@ -629,42 +482,19 @@ TEST_F(QuartcSessionTest, StreamConnection) {
TestStreamConnection(); TestStreamConnection();
} }
TEST_F(QuartcSessionTest, ClientRejection) { TEST_F(QuartcSessionTest, PreSharedKeyHandshake) {
CreateClientAndServerSessions(false /*client_handshake_success*/, CreateClientAndServerSessions();
true /*server_handshake_success*/); client_peer_->SetPreSharedKey("foo");
StartHandshake(); server_peer_->SetPreSharedKey("foo");
TestDisconnectAfterFailedHandshake();
}
TEST_F(QuartcSessionTest, ServerRejection) {
CreateClientAndServerSessions(true /*client_handshake_success*/,
false /*server_handshake_success*/);
StartHandshake(); StartHandshake();
TestDisconnectAfterFailedHandshake(); TestStreamConnection();
} }
// Test that data streams are not created before handshake. // Test that data streams are not created before handshake.
TEST_F(QuartcSessionTest, CannotCreateDataStreamBeforeHandshake) { TEST_F(QuartcSessionTest, CannotCreateDataStreamBeforeHandshake) {
CreateClientAndServerSessions(); CreateClientAndServerSessions();
EXPECT_EQ(nullptr, server_peer_->CreateOutgoingStream(kDefaultStreamParam)); EXPECT_EQ(nullptr, server_peer_->CreateOutgoingDynamicStream());
EXPECT_EQ(nullptr, client_peer_->CreateOutgoingStream(kDefaultStreamParam)); EXPECT_EQ(nullptr, client_peer_->CreateOutgoingDynamicStream());
}
TEST_F(QuartcSessionTest, CloseQuartcStream) {
CreateClientAndServerSessions();
StartHandshake();
ASSERT_TRUE(client_peer_->IsCryptoHandshakeConfirmed());
ASSERT_TRUE(server_peer_->IsCryptoHandshakeConfirmed());
QuartcStreamInterface* stream =
client_peer_->CreateOutgoingStream(kDefaultStreamParam);
ASSERT_NE(nullptr, stream);
uint32_t id = stream->stream_id();
EXPECT_FALSE(client_peer_->IsClosedStream(id));
stream->SetDelegate(client_peer_->stream_delegate());
stream->Close();
RunTasks();
EXPECT_TRUE(client_peer_->IsClosedStream(id));
} }
TEST_F(QuartcSessionTest, CancelQuartcStream) { TEST_F(QuartcSessionTest, CancelQuartcStream) {
...@@ -673,11 +503,10 @@ TEST_F(QuartcSessionTest, CancelQuartcStream) { ...@@ -673,11 +503,10 @@ TEST_F(QuartcSessionTest, CancelQuartcStream) {
ASSERT_TRUE(client_peer_->IsCryptoHandshakeConfirmed()); ASSERT_TRUE(client_peer_->IsCryptoHandshakeConfirmed());
ASSERT_TRUE(server_peer_->IsCryptoHandshakeConfirmed()); ASSERT_TRUE(server_peer_->IsCryptoHandshakeConfirmed());
QuartcStreamInterface* stream = QuartcStream* stream = client_peer_->CreateOutgoingDynamicStream();
client_peer_->CreateOutgoingStream(kDefaultStreamParam);
ASSERT_NE(nullptr, stream); ASSERT_NE(nullptr, stream);
uint32_t id = stream->stream_id(); uint32_t id = stream->id();
EXPECT_FALSE(client_peer_->IsClosedStream(id)); EXPECT_FALSE(client_peer_->IsClosedStream(id));
stream->SetDelegate(client_peer_->stream_delegate()); stream->SetDelegate(client_peer_->stream_delegate());
client_peer_->CancelStream(id); client_peer_->CancelStream(id);
...@@ -686,103 +515,19 @@ TEST_F(QuartcSessionTest, CancelQuartcStream) { ...@@ -686,103 +515,19 @@ TEST_F(QuartcSessionTest, CancelQuartcStream) {
EXPECT_TRUE(client_peer_->IsClosedStream(id)); EXPECT_TRUE(client_peer_->IsClosedStream(id));
} }
TEST_F(QuartcSessionTest, BundleWrites) {
CreateClientAndServerSessions();
StartHandshake();
ASSERT_TRUE(client_peer_->IsCryptoHandshakeConfirmed());
ASSERT_TRUE(server_peer_->IsCryptoHandshakeConfirmed());
client_peer_->BundleWrites();
QuartcStreamInterface* first =
client_peer_->CreateOutgoingStream(kDefaultStreamParam);
QuicStreamId first_id = first->stream_id();
first->SetDelegate(client_peer_->stream_delegate());
char kFirstMessage[] = "Hello";
test::QuicTestMemSliceVector first_data(
{std::make_pair(kFirstMessage, strlen(kFirstMessage))});
first->Write(first_data.span(), kDefaultWriteParam);
RunTasks();
// Server should not receive any data until the client flushes writes.
EXPECT_FALSE(server_peer_->has_data());
QuartcStreamInterface* second =
client_peer_->CreateOutgoingStream(kDefaultStreamParam);
QuicStreamId second_id = second->stream_id();
second->SetDelegate(client_peer_->stream_delegate());
char kSecondMessage[] = "World";
test::QuicTestMemSliceVector second_data(
{std::make_pair(kSecondMessage, strlen(kSecondMessage))});
second->Write(second_data.span(), kDefaultWriteParam);
RunTasks();
EXPECT_FALSE(server_peer_->has_data());
client_peer_->FlushWrites();
RunTasks();
ASSERT_TRUE(server_peer_->has_data());
EXPECT_EQ(server_peer_->data()[first_id], kFirstMessage);
EXPECT_EQ(server_peer_->data()[second_id], kSecondMessage);
}
TEST_F(QuartcSessionTest, StopBundlingOnIncomingData) {
CreateClientAndServerSessions();
StartHandshake();
ASSERT_TRUE(client_peer_->IsCryptoHandshakeConfirmed());
ASSERT_TRUE(server_peer_->IsCryptoHandshakeConfirmed());
client_peer_->BundleWrites();
QuartcStreamInterface* first =
client_peer_->CreateOutgoingStream(kDefaultStreamParam);
QuicStreamId first_id = first->stream_id();
first->SetDelegate(client_peer_->stream_delegate());
char kFirstMessage[] = "Hello";
test::QuicTestMemSliceVector first_data(
{std::make_pair(kFirstMessage, strlen(kFirstMessage))});
first->Write(first_data.span(), kDefaultWriteParam);
RunTasks();
// Server should not receive any data until the client flushes writes.
EXPECT_FALSE(server_peer_->has_data());
QuartcStreamInterface* second =
server_peer_->CreateOutgoingStream(kDefaultStreamParam);
QuicStreamId second_id = second->stream_id();
second->SetDelegate(server_peer_->stream_delegate());
char kSecondMessage[] = "World";
test::QuicTestMemSliceVector second_data(
{std::make_pair(kSecondMessage, strlen(kSecondMessage))});
second->Write(second_data.span(), kDefaultWriteParam);
RunTasks();
ASSERT_TRUE(client_peer_->has_data());
EXPECT_EQ(client_peer_->data()[second_id], kSecondMessage);
// Server should receive data as well, since the client stops bundling to
// process incoming packets.
ASSERT_TRUE(server_peer_->has_data());
EXPECT_EQ(server_peer_->data()[first_id], kFirstMessage);
}
TEST_F(QuartcSessionTest, WriterGivesPacketNumberToTransport) { TEST_F(QuartcSessionTest, WriterGivesPacketNumberToTransport) {
CreateClientAndServerSessions(); CreateClientAndServerSessions();
StartHandshake(); StartHandshake();
ASSERT_TRUE(client_peer_->IsCryptoHandshakeConfirmed()); ASSERT_TRUE(client_peer_->IsCryptoHandshakeConfirmed());
ASSERT_TRUE(server_peer_->IsCryptoHandshakeConfirmed()); ASSERT_TRUE(server_peer_->IsCryptoHandshakeConfirmed());
QuartcStreamInterface* stream = QuartcStream* stream = client_peer_->CreateOutgoingDynamicStream();
client_peer_->CreateOutgoingStream(kDefaultStreamParam);
stream->SetDelegate(client_peer_->stream_delegate()); stream->SetDelegate(client_peer_->stream_delegate());
char kClientMessage[] = "Hello"; char kClientMessage[] = "Hello";
test::QuicTestMemSliceVector stream_data( test::QuicTestMemSliceVector stream_data(
{std::make_pair(kClientMessage, strlen(kClientMessage))}); {std::make_pair(kClientMessage, strlen(kClientMessage))});
stream->Write(stream_data.span(), kDefaultWriteParam); stream->WriteMemSlices(stream_data.span(), /*fin=*/false);
RunTasks(); RunTasks();
// The transport should see the latest packet number sent by QUIC. // The transport should see the latest packet number sent by QUIC.
...@@ -791,33 +536,6 @@ TEST_F(QuartcSessionTest, WriterGivesPacketNumberToTransport) { ...@@ -791,33 +536,6 @@ TEST_F(QuartcSessionTest, WriterGivesPacketNumberToTransport) {
client_peer_->connection()->sent_packet_manager().GetLargestSentPacket()); client_peer_->connection()->sent_packet_manager().GetLargestSentPacket());
} }
TEST_F(QuartcSessionTest, GetStats) {
CreateClientAndServerSessions();
StartHandshake();
ASSERT_TRUE(client_peer_->IsCryptoHandshakeConfirmed());
ASSERT_TRUE(server_peer_->IsCryptoHandshakeConfirmed());
QuicConnectionStats stats = server_peer_->GetStats();
EXPECT_GT(stats.estimated_bandwidth, QuicBandwidth::Zero());
EXPECT_GT(stats.srtt_us, 0);
EXPECT_GT(stats.packets_sent, 0u);
EXPECT_EQ(stats.packets_lost, 0u);
}
TEST_F(QuartcSessionTest, DISABLED_PacketLossStats) {
CreateClientAndServerSessions();
StartHandshake();
ASSERT_TRUE(client_peer_->IsCryptoHandshakeConfirmed());
ASSERT_TRUE(server_peer_->IsCryptoHandshakeConfirmed());
// Packet loss doesn't count until the handshake is done.
server_transport_->set_packets_to_lose(1);
TestStreamConnection();
QuicConnectionStats stats = server_peer_->GetStats();
EXPECT_EQ(stats.packets_lost, 1u);
}
TEST_F(QuartcSessionTest, CloseConnection) { TEST_F(QuartcSessionTest, CloseConnection) {
CreateClientAndServerSessions(); CreateClientAndServerSessions();
StartHandshake(); StartHandshake();
...@@ -833,3 +551,4 @@ TEST_F(QuartcSessionTest, CloseConnection) { ...@@ -833,3 +551,4 @@ TEST_F(QuartcSessionTest, CloseConnection) {
} // namespace } // namespace
} // namespace quic } // namespace quic
#endif // !defined(OS_IOS)
// Copyright (c) 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_THIRD_PARTY_QUIC_QUARTC_QUARTC_SESSION_VISITOR_INTERFACE_H_
#define NET_THIRD_PARTY_QUIC_QUARTC_QUARTC_SESSION_VISITOR_INTERFACE_H_
#include "net/third_party/quic/core/quic_connection.h"
#include "net/third_party/quic/platform/api/quic_export.h"
namespace quic {
// QuartcSessionVisitor observes internals of a Quartc/QUIC session for the
// purpose of gathering metrics or debug information.
class QUIC_EXPORT_PRIVATE QuartcSessionVisitor {
public:
virtual ~QuartcSessionVisitor() {}
// Informs this visitor of a |QuicConnection| for the session.
// Called once when the visitor is attached to a QuartcSession, or when a new
// |QuicConnection| starts.
virtual void OnQuicConnection(QuicConnection* connection) {}
// Called when a packet has been sent.
virtual void OnPacketSent(const SerializedPacket& serialized_packet,
QuicPacketNumber original_packet_number,
TransmissionType transmission_type,
QuicTime sent_time) {}
// Called when an ack is received.
virtual void OnIncomingAck(const QuicAckFrame& ack_frame,
QuicTime ack_receive_time,
QuicPacketNumber largest_observed,
bool rtt_updated,
QuicPacketNumber least_unacked_sent_packet) {}
// Called when a packet is lost.
virtual void OnPacketLoss(QuicPacketNumber lost_packet_number,
TransmissionType transmission_type,
QuicTime detection_time) {}
// Called when a WindowUpdateFrame is received.
virtual void OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame,
const QuicTime& receive_time) {}
// Called when version negotiation succeeds.
virtual void OnSuccessfulVersionNegotiation(
const ParsedQuicVersion& version) {}
};
} // namespace quic
#endif // NET_THIRD_PARTY_QUIC_QUARTC_QUARTC_SESSION_VISITOR_INTERFACE_H_
...@@ -50,39 +50,11 @@ void QuartcStream::OnDataBuffered( ...@@ -50,39 +50,11 @@ void QuartcStream::OnDataBuffered(
delegate_->OnBufferChanged(this); delegate_->OnBufferChanged(this);
} }
uint32_t QuartcStream::stream_id() {
return id();
}
uint64_t QuartcStream::bytes_buffered() {
return BufferedDataBytes();
}
bool QuartcStream::fin_sent() {
return QuicStream::fin_sent();
}
int QuartcStream::stream_error() {
return QuicStream::stream_error();
}
void QuartcStream::Write(QuicMemSliceSpan data, const WriteParameters& param) {
WriteMemSlices(data, param.fin);
}
void QuartcStream::FinishWriting() { void QuartcStream::FinishWriting() {
WriteOrBufferData(QuicStringPiece(nullptr, 0), true, nullptr); WriteOrBufferData(QuicStringPiece(nullptr, 0), true, nullptr);
} }
void QuartcStream::FinishReading() { void QuartcStream::SetDelegate(Delegate* delegate) {
QuicStream::StopReading();
}
void QuartcStream::Close() {
QuicStream::session()->CloseStream(id());
}
void QuartcStream::SetDelegate(QuartcStreamInterface::Delegate* delegate) {
if (delegate_) { if (delegate_) {
LOG(WARNING) << "The delegate for Stream " << id() LOG(WARNING) << "The delegate for Stream " << id()
<< " has already been set."; << " has already been set.";
......
...@@ -8,13 +8,15 @@ ...@@ -8,13 +8,15 @@
#include "net/third_party/quic/core/quic_session.h" #include "net/third_party/quic/core/quic_session.h"
#include "net/third_party/quic/core/quic_stream.h" #include "net/third_party/quic/core/quic_stream.h"
#include "net/third_party/quic/platform/api/quic_export.h" #include "net/third_party/quic/platform/api/quic_export.h"
#include "net/third_party/quic/quartc/quartc_stream_interface.h" #include "net/third_party/quic/platform/api/quic_mem_slice_span.h"
namespace quic { namespace quic {
// Implements a QuartcStreamInterface using a QuicStream. // Sends and receives data with a particular QUIC stream ID, reliably and
class QUIC_EXPORT_PRIVATE QuartcStream : public QuicStream, // in-order. To send/receive data out of order, use separate streams. To
public QuartcStreamInterface { // send/receive unreliably, close a stream after reliability is no longer
// needed.
class QUIC_EXPORT_PRIVATE QuartcStream : public QuicStream {
public: public:
QuartcStream(QuicStreamId id, QuicSession* session); QuartcStream(QuicStreamId id, QuicSession* session);
...@@ -33,27 +35,43 @@ class QUIC_EXPORT_PRIVATE QuartcStream : public QuicStream, ...@@ -33,27 +35,43 @@ class QUIC_EXPORT_PRIVATE QuartcStream : public QuicStream,
const QuicReferenceCountedPointer<QuicAckListenerInterface>& ack_listener) const QuicReferenceCountedPointer<QuicAckListenerInterface>& ack_listener)
override; override;
// QuartcStreamInterface overrides. // QuartcStream interface methods.
uint32_t stream_id() override;
// Marks this stream as finished writing. Asynchronously sends a FIN and
uint64_t bytes_buffered() override; // closes the write-side. It is not necessary to call FinishWriting() if the
// last call to Write() sends a FIN.
bool fin_sent() override; void FinishWriting();
int stream_error() override; // Implemented by the user of the QuartcStream to receive incoming
// data and be notified of state changes.
void Write(QuicMemSliceSpan data, const WriteParameters& param) override; class Delegate {
public:
void FinishWriting() override; virtual ~Delegate() {}
void FinishReading() override; // Called when the stream receives data. Called with |size| == 0 after all
// stream data has been delivered (once the stream receives a FIN bit).
void Close() override; // Note that the same packet may include both data and a FIN bit, causing
// this method to be called twice.
void SetDelegate(QuartcStreamInterface::Delegate* delegate) override; virtual void OnReceived(QuartcStream* stream,
const char* data,
size_t size) = 0;
// Called when the stream is closed, either locally or by the remote
// endpoint. Streams close when (a) fin bits are both sent and received,
// (b) Close() is called, or (c) the stream is reset.
// TODO(zhihuang) Creates a map from the integer error_code to WebRTC native
// error code.
virtual void OnClose(QuartcStream* stream) = 0;
// Called when the contents of the stream's buffer changes.
virtual void OnBufferChanged(QuartcStream* stream) = 0;
};
// The |delegate| is not owned by QuartcStream.
void SetDelegate(Delegate* delegate);
private: private:
QuartcStreamInterface::Delegate* delegate_ = nullptr; Delegate* delegate_ = nullptr;
}; };
} // namespace quic } // namespace quic
......
// Copyright (c) 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_THIRD_PARTY_QUIC_QUARTC_QUARTC_STREAM_INTERFACE_H_
#define NET_THIRD_PARTY_QUIC_QUARTC_QUARTC_STREAM_INTERFACE_H_
#include <stddef.h>
#include <stdint.h>
#include "net/third_party/quic/platform/api/quic_export.h"
#include "net/third_party/quic/platform/api/quic_mem_slice_span.h"
namespace quic {
// Sends and receives data with a particular QUIC stream ID, reliably and
// in-order. To send/receive data out of order, use separate streams. To
// send/receive unreliably, close a stream after reliability is no longer
// needed.
class QUIC_EXPORT_PRIVATE QuartcStreamInterface {
public:
virtual ~QuartcStreamInterface() {}
// The QUIC stream ID.
virtual uint32_t stream_id() = 0;
// The amount of data buffered on this stream.
virtual uint64_t bytes_buffered() = 0;
// Return true if the FIN has been sent. Used by the outgoing streams to
// determine if all the data has been sent
virtual bool fin_sent() = 0;
virtual int stream_error() = 0;
struct WriteParameters {
// |fin| is set to be true when there is no more data need to be send
// through a particular stream. The receiving side will used it to determine
// if the sender finish sending data.
bool fin = false;
};
// Sends data reliably and in-order. Returns the amount sent.
// Does not buffer data.
virtual void Write(QuicMemSliceSpan data, const WriteParameters& param) = 0;
// Marks this stream as finished writing. Asynchronously sends a FIN and
// closes the write-side. The stream will no longer call OnCanWrite().
// It is not necessary to call FinishWriting() if the last call to Write()
// sends a FIN.
virtual void FinishWriting() = 0;
// Marks this stream as finished reading. Further incoming data is discarded.
// The stream will no longer call OnReceived().
// It is never necessary to call FinishReading(). The read-side closes when a
// FIN is received, regardless of whether FinishReading() has been called.
virtual void FinishReading() = 0;
// Once Close is called, no more data can be sent, all buffered data will be
// dropped and no data will be retransmitted.
virtual void Close() = 0;
// Implemented by the user of the QuartcStreamInterface to receive incoming
// data and be notified of state changes.
class Delegate {
public:
virtual ~Delegate() {}
// Called when the stream receives the data. Called with |size| == 0 after
// all stream data has been delivered.
virtual void OnReceived(QuartcStreamInterface* stream,
const char* data,
size_t size) = 0;
// Called when the stream is closed, either locally or by the remote
// endpoint. Streams close when (a) fin bits are both sent and received,
// (b) Close() is called, or (c) the stream is reset.
// TODO(zhihuang) Creates a map from the integer error_code to WebRTC native
// error code.
virtual void OnClose(QuartcStreamInterface* stream) = 0;
// Called when the contents of the stream's buffer changes.
virtual void OnBufferChanged(QuartcStreamInterface* stream) = 0;
};
// The |delegate| is not owned by QuartcStream.
virtual void SetDelegate(Delegate* delegate) = 0;
};
} // namespace quic
#endif // NET_THIRD_PARTY_QUIC_QUARTC_QUARTC_STREAM_INTERFACE_H_
...@@ -11,9 +11,9 @@ ...@@ -11,9 +11,9 @@
#include "net/third_party/quic/platform/api/quic_ptr_util.h" #include "net/third_party/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quic/platform/api/quic_test.h" #include "net/third_party/quic/platform/api/quic_test.h"
#include "net/third_party/quic/platform/api/quic_test_mem_slice_vector.h" #include "net/third_party/quic/platform/api/quic_test_mem_slice_vector.h"
#include "net/third_party/quic/quartc/quartc_clock_interface.h"
#include "net/third_party/quic/quartc/quartc_factory.h" #include "net/third_party/quic/quartc/quartc_factory.h"
#include "net/third_party/quic/test_tools/mock_clock.h" #include "net/third_party/quic/test_tools/mock_clock.h"
#include "net/third_party/quic/test_tools/quic_test_utils.h"
#include "net/third_party/spdy/core/spdy_protocol.h" #include "net/third_party/spdy/core/spdy_protocol.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -23,7 +23,6 @@ namespace quic { ...@@ -23,7 +23,6 @@ namespace quic {
namespace { namespace {
static const QuicStreamId kStreamId = 5; static const QuicStreamId kStreamId = 5;
static const QuartcStreamInterface::WriteParameters kDefaultParam;
// MockQuicSession that does not create streams and writes data from // MockQuicSession that does not create streams and writes data from
// QuicStream to a string. // QuicStream to a string.
...@@ -31,7 +30,7 @@ class MockQuicSession : public QuicSession { ...@@ -31,7 +30,7 @@ class MockQuicSession : public QuicSession {
public: public:
MockQuicSession(QuicConnection* connection, MockQuicSession(QuicConnection* connection,
const QuicConfig& config, const QuicConfig& config,
std::string* write_buffer) QuicString* write_buffer)
: QuicSession(connection, nullptr /*visitor*/, config), : QuicSession(connection, nullptr /*visitor*/, config),
write_buffer_(write_buffer) {} write_buffer_(write_buffer) {}
...@@ -92,7 +91,7 @@ class MockQuicSession : public QuicSession { ...@@ -92,7 +91,7 @@ class MockQuicSession : public QuicSession {
private: private:
// Stores written data from ReliableQuicStreamAdapter. // Stores written data from ReliableQuicStreamAdapter.
std::string* write_buffer_; QuicString* write_buffer_;
// Whether data is written to write_buffer_. // Whether data is written to write_buffer_.
bool writable_ = true; bool writable_ = true;
}; };
...@@ -132,23 +131,23 @@ class DummyPacketWriter : public QuicPacketWriter { ...@@ -132,23 +131,23 @@ class DummyPacketWriter : public QuicPacketWriter {
WriteResult Flush() override { return WriteResult(WRITE_STATUS_OK, 0); } WriteResult Flush() override { return WriteResult(WRITE_STATUS_OK, 0); }
}; };
class MockQuartcStreamDelegate : public QuartcStreamInterface::Delegate { class MockQuartcStreamDelegate : public QuartcStream::Delegate {
public: public:
MockQuartcStreamDelegate(int id, std::string* read_buffer) MockQuartcStreamDelegate(int id, QuicString* read_buffer)
: id_(id), read_buffer_(read_buffer) {} : id_(id), read_buffer_(read_buffer) {}
void OnBufferChanged(QuartcStreamInterface* stream) override { void OnBufferChanged(QuartcStream* stream) override {
last_bytes_buffered_ = stream->bytes_buffered(); last_bytes_buffered_ = stream->BufferedDataBytes();
} }
void OnReceived(QuartcStreamInterface* stream, void OnReceived(QuartcStream* stream,
const char* data, const char* data,
size_t size) override { size_t size) override {
EXPECT_EQ(id_, stream->stream_id()); EXPECT_EQ(id_, stream->id());
read_buffer_->append(data, size); read_buffer_->append(data, size);
} }
void OnClose(QuartcStreamInterface* stream) override { closed_ = true; } void OnClose(QuartcStream* stream) override { closed_ = true; }
bool closed() { return closed_; } bool closed() { return closed_; }
...@@ -157,7 +156,7 @@ class MockQuartcStreamDelegate : public QuartcStreamInterface::Delegate { ...@@ -157,7 +156,7 @@ class MockQuartcStreamDelegate : public QuartcStreamInterface::Delegate {
protected: protected:
uint32_t id_; uint32_t id_;
// Data read by the QuicStream. // Data read by the QuicStream.
std::string* read_buffer_; QuicString* read_buffer_;
// Whether the QuicStream is closed. // Whether the QuicStream is closed.
bool closed_ = false; bool closed_ = false;
...@@ -174,9 +173,7 @@ class QuartcStreamTest : public QuicTest, public QuicConnectionHelperInterface { ...@@ -174,9 +173,7 @@ class QuartcStreamTest : public QuicTest, public QuicConnectionHelperInterface {
ip.FromString("0.0.0.0"); ip.FromString("0.0.0.0");
bool owns_writer = true; bool owns_writer = true;
// We only use QuartcFactory for its role as an alarm factory. alarm_factory_ = QuicMakeUnique<test::MockAlarmFactory>();
QuartcFactoryConfig config;
alarm_factory_ = QuicMakeUnique<QuartcFactory>(config);
connection_ = QuicMakeUnique<QuicConnection>( connection_ = QuicMakeUnique<QuicConnection>(
0, QuicSocketAddress(ip, 0), this /*QuicConnectionHelperInterface*/, 0, QuicSocketAddress(ip, 0), this /*QuicConnectionHelperInterface*/,
...@@ -210,9 +207,9 @@ class QuartcStreamTest : public QuicTest, public QuicConnectionHelperInterface { ...@@ -210,9 +207,9 @@ class QuartcStreamTest : public QuicTest, public QuicConnectionHelperInterface {
std::unique_ptr<MockQuartcStreamDelegate> mock_stream_delegate_; std::unique_ptr<MockQuartcStreamDelegate> mock_stream_delegate_;
std::unique_ptr<MockQuicSession> session_; std::unique_ptr<MockQuicSession> session_;
// Data written by the ReliableQuicStreamAdapterTest. // Data written by the ReliableQuicStreamAdapterTest.
std::string write_buffer_; QuicString write_buffer_;
// Data read by the ReliableQuicStreamAdapterTest. // Data read by the ReliableQuicStreamAdapterTest.
std::string read_buffer_; QuicString read_buffer_;
std::unique_ptr<QuicAlarmFactory> alarm_factory_; std::unique_ptr<QuicAlarmFactory> alarm_factory_;
std::unique_ptr<QuicConnection> connection_; std::unique_ptr<QuicConnection> connection_;
// Used to implement the QuicConnectionHelperInterface. // Used to implement the QuicConnectionHelperInterface.
...@@ -225,7 +222,7 @@ TEST_F(QuartcStreamTest, WriteDataWhole) { ...@@ -225,7 +222,7 @@ TEST_F(QuartcStreamTest, WriteDataWhole) {
CreateReliableQuicStream(); CreateReliableQuicStream();
char message[] = "Foo bar"; char message[] = "Foo bar";
test::QuicTestMemSliceVector data({std::make_pair(message, 7)}); test::QuicTestMemSliceVector data({std::make_pair(message, 7)});
stream_->Write(data.span(), kDefaultParam); stream_->WriteMemSlices(data.span(), /*fin=*/false);
EXPECT_EQ("Foo bar", write_buffer_); EXPECT_EQ("Foo bar", write_buffer_);
} }
...@@ -234,7 +231,7 @@ TEST_F(QuartcStreamTest, WriteDataPartial) { ...@@ -234,7 +231,7 @@ TEST_F(QuartcStreamTest, WriteDataPartial) {
CreateReliableQuicStream(); CreateReliableQuicStream();
char message[] = "Foo bar"; char message[] = "Foo bar";
test::QuicTestMemSliceVector data({std::make_pair(message, 5)}); test::QuicTestMemSliceVector data({std::make_pair(message, 5)});
stream_->Write(data.span(), kDefaultParam); stream_->WriteMemSlices(data.span(), /*fin=*/false);
EXPECT_EQ("Foo b", write_buffer_); EXPECT_EQ("Foo b", write_buffer_);
} }
...@@ -247,11 +244,11 @@ TEST_F(QuartcStreamTest, StreamBuffersData) { ...@@ -247,11 +244,11 @@ TEST_F(QuartcStreamTest, StreamBuffersData) {
// The stream is not yet writable, so data will be buffered. // The stream is not yet writable, so data will be buffered.
session_->set_writable(false); session_->set_writable(false);
stream_->Write(data.span(), kDefaultParam); stream_->WriteMemSlices(data.span(), /*fin=*/false);
// Check that data is buffered. // Check that data is buffered.
EXPECT_TRUE(stream_->HasBufferedData()); EXPECT_TRUE(stream_->HasBufferedData());
EXPECT_EQ(7u, stream_->bytes_buffered()); EXPECT_EQ(7u, stream_->BufferedDataBytes());
// Check that the stream told its delegate about the buffer change. // Check that the stream told its delegate about the buffer change.
EXPECT_EQ(7u, mock_stream_delegate_->last_bytes_buffered()); EXPECT_EQ(7u, mock_stream_delegate_->last_bytes_buffered());
...@@ -265,10 +262,10 @@ TEST_F(QuartcStreamTest, StreamBuffersData) { ...@@ -265,10 +262,10 @@ TEST_F(QuartcStreamTest, StreamBuffersData) {
test::QuicTestMemSliceVector data1({std::make_pair(message1, 5)}); test::QuicTestMemSliceVector data1({std::make_pair(message1, 5)});
// More writes go into the buffer. // More writes go into the buffer.
stream_->Write(data1.span(), kDefaultParam); stream_->WriteMemSlices(data1.span(), /*fin=*/false);
EXPECT_TRUE(stream_->HasBufferedData()); EXPECT_TRUE(stream_->HasBufferedData());
EXPECT_EQ(12u, stream_->bytes_buffered()); EXPECT_EQ(12u, stream_->BufferedDataBytes());
EXPECT_EQ(12u, mock_stream_delegate_->last_bytes_buffered()); EXPECT_EQ(12u, mock_stream_delegate_->last_bytes_buffered());
EXPECT_EQ(0ul, write_buffer_.size()); EXPECT_EQ(0ul, write_buffer_.size());
...@@ -277,7 +274,7 @@ TEST_F(QuartcStreamTest, StreamBuffersData) { ...@@ -277,7 +274,7 @@ TEST_F(QuartcStreamTest, StreamBuffersData) {
stream_->OnCanWrite(); stream_->OnCanWrite();
EXPECT_FALSE(stream_->HasBufferedData()); EXPECT_FALSE(stream_->HasBufferedData());
EXPECT_EQ(0u, stream_->bytes_buffered()); EXPECT_EQ(0u, stream_->BufferedDataBytes());
EXPECT_EQ(0u, mock_stream_delegate_->last_bytes_buffered()); EXPECT_EQ(0u, mock_stream_delegate_->last_bytes_buffered());
EXPECT_EQ("Foo barxyzzy", write_buffer_); EXPECT_EQ("Foo barxyzzy", write_buffer_);
} }
...@@ -317,10 +314,11 @@ TEST_F(QuartcStreamTest, ReadDataPartial) { ...@@ -317,10 +314,11 @@ TEST_F(QuartcStreamTest, ReadDataPartial) {
EXPECT_EQ("Hello", read_buffer_); EXPECT_EQ("Hello", read_buffer_);
} }
// Streams do not call OnReceived() after FinishReading(). // Streams do not call OnReceived() after StopReading().
TEST_F(QuartcStreamTest, FinishReading) { // Note: this is tested here because Quartc relies on this behavior.
TEST_F(QuartcStreamTest, StopReading) {
CreateReliableQuicStream(); CreateReliableQuicStream();
stream_->FinishReading(); stream_->StopReading();
QuicStreamFrame frame(kStreamId, false, 0, "Hello, World!"); QuicStreamFrame frame(kStreamId, false, 0, "Hello, World!");
stream_->OnStreamFrame(frame); stream_->OnStreamFrame(frame);
...@@ -348,10 +346,8 @@ TEST_F(QuartcStreamTest, CloseOnFins) { ...@@ -348,10 +346,8 @@ TEST_F(QuartcStreamTest, CloseOnFins) {
QuicStreamFrame frame(kStreamId, true, 0, 0); QuicStreamFrame frame(kStreamId, true, 0, 0);
stream_->OnStreamFrame(frame); stream_->OnStreamFrame(frame);
QuartcStreamInterface::WriteParameters param;
param.fin = true;
test::QuicTestMemSliceVector data({}); test::QuicTestMemSliceVector data({});
stream_->Write(data.span(), param); stream_->WriteMemSlices(data.span(), /*fin=*/true);
// Check that the OnClose() callback occurred. // Check that the OnClose() callback occurred.
EXPECT_TRUE(mock_stream_delegate_->closed()); EXPECT_TRUE(mock_stream_delegate_->closed());
......
// Copyright (c) 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_THIRD_PARTY_QUIC_QUARTC_QUARTC_TASK_RUNNER_INTERFACE_H_
#define NET_THIRD_PARTY_QUIC_QUARTC_QUARTC_TASK_RUNNER_INTERFACE_H_
#include <stdint.h>
#include <memory>
namespace quic {
// Used by platform specific QuicAlarms. For example, WebRTC will use it to set
// and cancel an alarm. When setting an alarm, the task runner will schedule a
// task on rtc::Thread. When canceling an alarm, the canceler for that task will
// be called.
class QuartcTaskRunnerInterface {
public:
virtual ~QuartcTaskRunnerInterface() {}
class Task {
public:
virtual ~Task() {}
// Called when it's time to start the task.
virtual void Run() = 0;
};
// A handler used to cancel a scheduled task. In some cases, a task cannot
// be directly canceled with its pointer. For example, in WebRTC, the task
// will be scheduled on rtc::Thread. When canceling a task, its pointer cannot
// locate the scheduled task in the thread message queue. So when scheduling a
// task, an additional handler (ScheduledTask) will be returned.
class ScheduledTask {
public:
virtual ~ScheduledTask() {}
// Cancels a scheduled task, meaning the task will not be run.
virtual void Cancel() = 0;
};
// Schedules a task, which will be run after the given delay. A ScheduledTask
// may be used to cancel the task.
virtual std::unique_ptr<ScheduledTask> Schedule(Task* task,
uint64_t delay_ms) = 0;
};
} // namespace quic
#endif // NET_THIRD_PARTY_QUIC_QUARTC_QUARTC_TASK_RUNNER_INTERFACE_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment