Allow TransportController to create a QuicTransportChannel
A QuicTransport is implemented that subclasses Transport and takes ownership of the QuicTransportChannel/P2PTransportChannel. Split from CL https://codereview.webrtc.org/1844803002/. BUG= Review-Url: https://codereview.webrtc.org/1856943002 Cr-Commit-Position: refs/heads/master@{#12575}
This commit is contained in:
parent
9bc517f123
commit
e7748674ee
@ -85,7 +85,7 @@ std::string SSLFingerprint::GetRfc4572Fingerprint() const {
|
||||
return fingerprint;
|
||||
}
|
||||
|
||||
std::string SSLFingerprint::ToString() {
|
||||
std::string SSLFingerprint::ToString() const {
|
||||
std::string fp_str = algorithm;
|
||||
fp_str.append(" ");
|
||||
fp_str.append(GetRfc4572Fingerprint());
|
||||
|
||||
@ -41,7 +41,7 @@ struct SSLFingerprint {
|
||||
|
||||
std::string GetRfc4572Fingerprint() const;
|
||||
|
||||
std::string ToString();
|
||||
std::string ToString() const;
|
||||
|
||||
std::string algorithm;
|
||||
rtc::CopyOnWriteBuffer digest;
|
||||
|
||||
@ -66,27 +66,11 @@ class DtlsTransport : public Base {
|
||||
rtc::SSLFingerprint* local_fp =
|
||||
Base::local_description()->identity_fingerprint.get();
|
||||
|
||||
if (local_fp) {
|
||||
// Sanity check local fingerprint.
|
||||
if (certificate_) {
|
||||
std::unique_ptr<rtc::SSLFingerprint> local_fp_tmp(
|
||||
rtc::SSLFingerprint::Create(local_fp->algorithm,
|
||||
certificate_->identity()));
|
||||
ASSERT(local_fp_tmp.get() != NULL);
|
||||
if (!(*local_fp_tmp == *local_fp)) {
|
||||
std::ostringstream desc;
|
||||
desc << "Local fingerprint does not match identity. Expected: ";
|
||||
desc << local_fp_tmp->ToString();
|
||||
desc << " Got: " << local_fp->ToString();
|
||||
return BadTransportDescription(desc.str(), error_desc);
|
||||
}
|
||||
} else {
|
||||
return BadTransportDescription(
|
||||
"Local fingerprint provided but no identity available.",
|
||||
error_desc);
|
||||
}
|
||||
} else {
|
||||
if (!local_fp) {
|
||||
certificate_ = nullptr;
|
||||
} else if (!Base::VerifyCertificateFingerprint(certificate_.get(), local_fp,
|
||||
error_desc)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!channel->SetLocalCertificate(certificate_)) {
|
||||
@ -105,96 +89,23 @@ class DtlsTransport : public Base {
|
||||
"transport descriptions are negotiated";
|
||||
return BadTransportDescription(msg, error_desc);
|
||||
}
|
||||
|
||||
rtc::SSLFingerprint* local_fp =
|
||||
Base::local_description()->identity_fingerprint.get();
|
||||
rtc::SSLFingerprint* remote_fp =
|
||||
Base::remote_description()->identity_fingerprint.get();
|
||||
|
||||
if (remote_fp && local_fp) {
|
||||
remote_fingerprint_.reset(new rtc::SSLFingerprint(*remote_fp));
|
||||
|
||||
// From RFC 4145, section-4.1, The following are the values that the
|
||||
// 'setup' attribute can take in an offer/answer exchange:
|
||||
// Offer Answer
|
||||
// ________________
|
||||
// active passive / holdconn
|
||||
// passive active / holdconn
|
||||
// actpass active / passive / holdconn
|
||||
// holdconn holdconn
|
||||
//
|
||||
// Set the role that is most conformant with RFC 5763, Section 5, bullet 1
|
||||
// The endpoint MUST use the setup attribute defined in [RFC4145].
|
||||
// The endpoint that is the offerer MUST use the setup attribute
|
||||
// value of setup:actpass and be prepared to receive a client_hello
|
||||
// before it receives the answer. The answerer MUST use either a
|
||||
// setup attribute value of setup:active or setup:passive. Note that
|
||||
// if the answerer uses setup:passive, then the DTLS handshake will
|
||||
// not begin until the answerer is received, which adds additional
|
||||
// latency. setup:active allows the answer and the DTLS handshake to
|
||||
// occur in parallel. Thus, setup:active is RECOMMENDED. Whichever
|
||||
// party is active MUST initiate a DTLS handshake by sending a
|
||||
// ClientHello over each flow (host/port quartet).
|
||||
// IOW - actpass and passive modes should be treated as server and
|
||||
// active as client.
|
||||
ConnectionRole local_connection_role =
|
||||
Base::local_description()->connection_role;
|
||||
ConnectionRole remote_connection_role =
|
||||
Base::remote_description()->connection_role;
|
||||
|
||||
bool is_remote_server = false;
|
||||
if (local_role == CA_OFFER) {
|
||||
if (local_connection_role != CONNECTIONROLE_ACTPASS) {
|
||||
return BadTransportDescription(
|
||||
"Offerer must use actpass value for setup attribute.",
|
||||
error_desc);
|
||||
}
|
||||
|
||||
if (remote_connection_role == CONNECTIONROLE_ACTIVE ||
|
||||
remote_connection_role == CONNECTIONROLE_PASSIVE ||
|
||||
remote_connection_role == CONNECTIONROLE_NONE) {
|
||||
is_remote_server = (remote_connection_role == CONNECTIONROLE_PASSIVE);
|
||||
} else {
|
||||
const std::string msg =
|
||||
"Answerer must use either active or passive value "
|
||||
"for setup attribute.";
|
||||
return BadTransportDescription(msg, error_desc);
|
||||
}
|
||||
// If remote is NONE or ACTIVE it will act as client.
|
||||
} else {
|
||||
if (remote_connection_role != CONNECTIONROLE_ACTPASS &&
|
||||
remote_connection_role != CONNECTIONROLE_NONE) {
|
||||
return BadTransportDescription(
|
||||
"Offerer must use actpass value for setup attribute.",
|
||||
error_desc);
|
||||
}
|
||||
|
||||
if (local_connection_role == CONNECTIONROLE_ACTIVE ||
|
||||
local_connection_role == CONNECTIONROLE_PASSIVE) {
|
||||
is_remote_server = (local_connection_role == CONNECTIONROLE_ACTIVE);
|
||||
} else {
|
||||
const std::string msg =
|
||||
"Answerer must use either active or passive value "
|
||||
"for setup attribute.";
|
||||
return BadTransportDescription(msg, error_desc);
|
||||
}
|
||||
|
||||
// If local is passive, local will act as server.
|
||||
if (!Base::NegotiateRole(local_role, &secure_role_, error_desc)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
secure_role_ = is_remote_server ? rtc::SSL_CLIENT :
|
||||
rtc::SSL_SERVER;
|
||||
|
||||
} else if (local_fp && (local_role == CA_ANSWER)) {
|
||||
return BadTransportDescription(
|
||||
"Local fingerprint supplied when caller didn't offer DTLS.",
|
||||
error_desc);
|
||||
} else {
|
||||
// We are not doing DTLS
|
||||
remote_fingerprint_.reset(new rtc::SSLFingerprint(
|
||||
"", NULL, 0));
|
||||
remote_fingerprint_.reset(new rtc::SSLFingerprint("", nullptr, 0));
|
||||
}
|
||||
|
||||
// Now run the negotiation for the base class.
|
||||
return Base::NegotiateTransportDescription(local_role, error_desc);
|
||||
}
|
||||
|
||||
@ -406,6 +406,8 @@ class FakeTransport : public Transport {
|
||||
|
||||
using Transport::local_description;
|
||||
using Transport::remote_description;
|
||||
using Transport::VerifyCertificateFingerprint;
|
||||
using Transport::NegotiateRole;
|
||||
|
||||
protected:
|
||||
TransportChannelImpl* CreateTransportChannel(int component) override {
|
||||
|
||||
@ -401,4 +401,107 @@ bool Transport::NegotiateTransportDescription(ContentAction local_role,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Transport::VerifyCertificateFingerprint(
|
||||
const rtc::RTCCertificate* certificate,
|
||||
const rtc::SSLFingerprint* fingerprint,
|
||||
std::string* error_desc) const {
|
||||
if (!fingerprint) {
|
||||
return BadTransportDescription("No fingerprint.", error_desc);
|
||||
}
|
||||
if (!certificate) {
|
||||
return BadTransportDescription(
|
||||
"Fingerprint provided but no identity available.", error_desc);
|
||||
}
|
||||
rtc::scoped_ptr<rtc::SSLFingerprint> fp_tmp(rtc::SSLFingerprint::Create(
|
||||
fingerprint->algorithm, certificate->identity()));
|
||||
ASSERT(fp_tmp.get() != NULL);
|
||||
if (*fp_tmp == *fingerprint) {
|
||||
return true;
|
||||
}
|
||||
std::ostringstream desc;
|
||||
desc << "Local fingerprint does not match identity. Expected: ";
|
||||
desc << fp_tmp->ToString();
|
||||
desc << " Got: " << fingerprint->ToString();
|
||||
return BadTransportDescription(desc.str(), error_desc);
|
||||
}
|
||||
|
||||
bool Transport::NegotiateRole(ContentAction local_role,
|
||||
rtc::SSLRole* ssl_role,
|
||||
std::string* error_desc) const {
|
||||
RTC_DCHECK(ssl_role);
|
||||
if (!local_description() || !remote_description()) {
|
||||
const std::string msg =
|
||||
"Local and Remote description must be set before "
|
||||
"transport descriptions are negotiated";
|
||||
return BadTransportDescription(msg, error_desc);
|
||||
}
|
||||
|
||||
// From RFC 4145, section-4.1, The following are the values that the
|
||||
// 'setup' attribute can take in an offer/answer exchange:
|
||||
// Offer Answer
|
||||
// ________________
|
||||
// active passive / holdconn
|
||||
// passive active / holdconn
|
||||
// actpass active / passive / holdconn
|
||||
// holdconn holdconn
|
||||
//
|
||||
// Set the role that is most conformant with RFC 5763, Section 5, bullet 1
|
||||
// The endpoint MUST use the setup attribute defined in [RFC4145].
|
||||
// The endpoint that is the offerer MUST use the setup attribute
|
||||
// value of setup:actpass and be prepared to receive a client_hello
|
||||
// before it receives the answer. The answerer MUST use either a
|
||||
// setup attribute value of setup:active or setup:passive. Note that
|
||||
// if the answerer uses setup:passive, then the DTLS handshake will
|
||||
// not begin until the answerer is received, which adds additional
|
||||
// latency. setup:active allows the answer and the DTLS handshake to
|
||||
// occur in parallel. Thus, setup:active is RECOMMENDED. Whichever
|
||||
// party is active MUST initiate a DTLS handshake by sending a
|
||||
// ClientHello over each flow (host/port quartet).
|
||||
// IOW - actpass and passive modes should be treated as server and
|
||||
// active as client.
|
||||
ConnectionRole local_connection_role = local_description()->connection_role;
|
||||
ConnectionRole remote_connection_role = remote_description()->connection_role;
|
||||
|
||||
bool is_remote_server = false;
|
||||
if (local_role == CA_OFFER) {
|
||||
if (local_connection_role != CONNECTIONROLE_ACTPASS) {
|
||||
return BadTransportDescription(
|
||||
"Offerer must use actpass value for setup attribute.", error_desc);
|
||||
}
|
||||
|
||||
if (remote_connection_role == CONNECTIONROLE_ACTIVE ||
|
||||
remote_connection_role == CONNECTIONROLE_PASSIVE ||
|
||||
remote_connection_role == CONNECTIONROLE_NONE) {
|
||||
is_remote_server = (remote_connection_role == CONNECTIONROLE_PASSIVE);
|
||||
} else {
|
||||
const std::string msg =
|
||||
"Answerer must use either active or passive value "
|
||||
"for setup attribute.";
|
||||
return BadTransportDescription(msg, error_desc);
|
||||
}
|
||||
// If remote is NONE or ACTIVE it will act as client.
|
||||
} else {
|
||||
if (remote_connection_role != CONNECTIONROLE_ACTPASS &&
|
||||
remote_connection_role != CONNECTIONROLE_NONE) {
|
||||
return BadTransportDescription(
|
||||
"Offerer must use actpass value for setup attribute.", error_desc);
|
||||
}
|
||||
|
||||
if (local_connection_role == CONNECTIONROLE_ACTIVE ||
|
||||
local_connection_role == CONNECTIONROLE_PASSIVE) {
|
||||
is_remote_server = (local_connection_role == CONNECTIONROLE_ACTIVE);
|
||||
} else {
|
||||
const std::string msg =
|
||||
"Answerer must use either active or passive value "
|
||||
"for setup attribute.";
|
||||
return BadTransportDescription(msg, error_desc);
|
||||
}
|
||||
|
||||
// If local is passive, local will act as server.
|
||||
}
|
||||
|
||||
*ssl_role = is_remote_server ? rtc::SSL_CLIENT : rtc::SSL_SERVER;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace cricket
|
||||
|
||||
@ -315,6 +315,20 @@ class Transport : public sigslot::has_slots<> {
|
||||
TransportChannelImpl* channel,
|
||||
std::string* error_desc);
|
||||
|
||||
// Returns false if the certificate's identity does not match the fingerprint,
|
||||
// or either is NULL.
|
||||
virtual bool VerifyCertificateFingerprint(
|
||||
const rtc::RTCCertificate* certificate,
|
||||
const rtc::SSLFingerprint* fingerprint,
|
||||
std::string* error_desc) const;
|
||||
|
||||
// Negotiates the SSL role based off the offer and answer as specified by
|
||||
// RFC 4145, section-4.1. Returns false if the SSL role cannot be determined
|
||||
// from the local description and remote description.
|
||||
virtual bool NegotiateRole(ContentAction local_role,
|
||||
rtc::SSLRole* ssl_role,
|
||||
std::string* error_desc) const;
|
||||
|
||||
private:
|
||||
// If a candidate is not acceptable, returns false and sets error.
|
||||
// Call this before calling OnRemoteCandidates.
|
||||
|
||||
@ -235,3 +235,180 @@ TEST_F(TransportTest, TestGetStats) {
|
||||
EXPECT_EQ(1, stats.channel_stats[0].component);
|
||||
}
|
||||
|
||||
// Tests that VerifyCertificateFingerprint only returns true when the
|
||||
// certificate matches the fingerprint.
|
||||
TEST_F(TransportTest, TestVerifyCertificateFingerprint) {
|
||||
std::string error_desc;
|
||||
EXPECT_FALSE(
|
||||
transport_->VerifyCertificateFingerprint(nullptr, nullptr, &error_desc));
|
||||
rtc::KeyType key_types[] = {rtc::KT_RSA, rtc::KT_ECDSA};
|
||||
|
||||
for (auto& key_type : key_types) {
|
||||
rtc::scoped_refptr<rtc::RTCCertificate> certificate =
|
||||
rtc::RTCCertificate::Create(rtc::scoped_ptr<rtc::SSLIdentity>(
|
||||
rtc::SSLIdentity::Generate("testing", key_type)));
|
||||
ASSERT_NE(nullptr, certificate);
|
||||
|
||||
std::string digest_algorithm;
|
||||
ASSERT_TRUE(certificate->ssl_certificate().GetSignatureDigestAlgorithm(
|
||||
&digest_algorithm));
|
||||
ASSERT_FALSE(digest_algorithm.empty());
|
||||
rtc::scoped_ptr<rtc::SSLFingerprint> good_fingerprint(
|
||||
rtc::SSLFingerprint::Create(digest_algorithm, certificate->identity()));
|
||||
ASSERT_NE(nullptr, good_fingerprint);
|
||||
|
||||
EXPECT_TRUE(transport_->VerifyCertificateFingerprint(
|
||||
certificate.get(), good_fingerprint.get(), &error_desc));
|
||||
EXPECT_FALSE(transport_->VerifyCertificateFingerprint(
|
||||
certificate.get(), nullptr, &error_desc));
|
||||
EXPECT_FALSE(transport_->VerifyCertificateFingerprint(
|
||||
nullptr, good_fingerprint.get(), &error_desc));
|
||||
|
||||
rtc::SSLFingerprint bad_fingerprint = *good_fingerprint;
|
||||
bad_fingerprint.digest.AppendData("0", 1);
|
||||
EXPECT_FALSE(transport_->VerifyCertificateFingerprint(
|
||||
certificate.get(), &bad_fingerprint, &error_desc));
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that NegotiateRole sets the SSL role correctly.
|
||||
TEST_F(TransportTest, TestNegotiateRole) {
|
||||
TransportDescription local_desc(kIceUfrag1, kIcePwd1);
|
||||
TransportDescription remote_desc(kIceUfrag2, kIcePwd2);
|
||||
|
||||
struct NegotiateRoleParams {
|
||||
cricket::ConnectionRole local_role;
|
||||
cricket::ConnectionRole remote_role;
|
||||
cricket::ContentAction local_action;
|
||||
cricket::ContentAction remote_action;
|
||||
};
|
||||
|
||||
rtc::SSLRole ssl_role;
|
||||
std::string error_desc;
|
||||
|
||||
// Parameters which set the SSL role to SSL_CLIENT.
|
||||
NegotiateRoleParams valid_client_params[] = {
|
||||
{cricket::CONNECTIONROLE_ACTIVE, cricket::CONNECTIONROLE_ACTPASS,
|
||||
cricket::CA_ANSWER, cricket::CA_OFFER},
|
||||
{cricket::CONNECTIONROLE_ACTIVE, cricket::CONNECTIONROLE_ACTPASS,
|
||||
cricket::CA_PRANSWER, cricket::CA_OFFER},
|
||||
{cricket::CONNECTIONROLE_ACTPASS, cricket::CONNECTIONROLE_PASSIVE,
|
||||
cricket::CA_OFFER, cricket::CA_ANSWER},
|
||||
{cricket::CONNECTIONROLE_ACTPASS, cricket::CONNECTIONROLE_PASSIVE,
|
||||
cricket::CA_OFFER, cricket::CA_PRANSWER}};
|
||||
|
||||
for (auto& param : valid_client_params) {
|
||||
local_desc.connection_role = param.local_role;
|
||||
remote_desc.connection_role = param.remote_role;
|
||||
|
||||
ASSERT_TRUE(transport_->SetRemoteTransportDescription(
|
||||
remote_desc, param.remote_action, nullptr));
|
||||
ASSERT_TRUE(transport_->SetLocalTransportDescription(
|
||||
local_desc, param.local_action, nullptr));
|
||||
EXPECT_TRUE(
|
||||
transport_->NegotiateRole(param.local_action, &ssl_role, &error_desc));
|
||||
EXPECT_EQ(rtc::SSL_CLIENT, ssl_role);
|
||||
}
|
||||
|
||||
// Parameters which set the SSL role to SSL_SERVER.
|
||||
NegotiateRoleParams valid_server_params[] = {
|
||||
{cricket::CONNECTIONROLE_PASSIVE, cricket::CONNECTIONROLE_ACTPASS,
|
||||
cricket::CA_ANSWER, cricket::CA_OFFER},
|
||||
{cricket::CONNECTIONROLE_PASSIVE, cricket::CONNECTIONROLE_ACTPASS,
|
||||
cricket::CA_PRANSWER, cricket::CA_OFFER},
|
||||
{cricket::CONNECTIONROLE_ACTPASS, cricket::CONNECTIONROLE_ACTIVE,
|
||||
cricket::CA_OFFER, cricket::CA_ANSWER},
|
||||
{cricket::CONNECTIONROLE_ACTPASS, cricket::CONNECTIONROLE_ACTIVE,
|
||||
cricket::CA_OFFER, cricket::CA_PRANSWER}};
|
||||
|
||||
for (auto& param : valid_server_params) {
|
||||
local_desc.connection_role = param.local_role;
|
||||
remote_desc.connection_role = param.remote_role;
|
||||
|
||||
ASSERT_TRUE(transport_->SetRemoteTransportDescription(
|
||||
remote_desc, param.remote_action, nullptr));
|
||||
ASSERT_TRUE(transport_->SetLocalTransportDescription(
|
||||
local_desc, param.local_action, nullptr));
|
||||
EXPECT_TRUE(
|
||||
transport_->NegotiateRole(param.local_action, &ssl_role, &error_desc));
|
||||
EXPECT_EQ(rtc::SSL_SERVER, ssl_role);
|
||||
}
|
||||
|
||||
// Invalid parameters due to both peers having a duplicate role.
|
||||
NegotiateRoleParams duplicate_params[] = {
|
||||
{cricket::CONNECTIONROLE_ACTIVE, cricket::CONNECTIONROLE_ACTIVE,
|
||||
cricket::CA_ANSWER, cricket::CA_OFFER},
|
||||
{cricket::CONNECTIONROLE_ACTPASS, cricket::CONNECTIONROLE_ACTPASS,
|
||||
cricket::CA_ANSWER, cricket::CA_OFFER},
|
||||
{cricket::CONNECTIONROLE_PASSIVE, cricket::CONNECTIONROLE_PASSIVE,
|
||||
cricket::CA_ANSWER, cricket::CA_OFFER},
|
||||
{cricket::CONNECTIONROLE_ACTIVE, cricket::CONNECTIONROLE_ACTIVE,
|
||||
cricket::CA_PRANSWER, cricket::CA_OFFER},
|
||||
{cricket::CONNECTIONROLE_ACTPASS, cricket::CONNECTIONROLE_ACTPASS,
|
||||
cricket::CA_PRANSWER, cricket::CA_OFFER},
|
||||
{cricket::CONNECTIONROLE_PASSIVE, cricket::CONNECTIONROLE_PASSIVE,
|
||||
cricket::CA_PRANSWER, cricket::CA_OFFER},
|
||||
{cricket::CONNECTIONROLE_ACTIVE, cricket::CONNECTIONROLE_ACTIVE,
|
||||
cricket::CA_OFFER, cricket::CA_ANSWER},
|
||||
{cricket::CONNECTIONROLE_ACTPASS, cricket::CONNECTIONROLE_ACTPASS,
|
||||
cricket::CA_OFFER, cricket::CA_ANSWER},
|
||||
{cricket::CONNECTIONROLE_PASSIVE, cricket::CONNECTIONROLE_PASSIVE,
|
||||
cricket::CA_OFFER, cricket::CA_ANSWER},
|
||||
{cricket::CONNECTIONROLE_ACTIVE, cricket::CONNECTIONROLE_ACTIVE,
|
||||
cricket::CA_OFFER, cricket::CA_PRANSWER},
|
||||
{cricket::CONNECTIONROLE_ACTPASS, cricket::CONNECTIONROLE_ACTPASS,
|
||||
cricket::CA_OFFER, cricket::CA_PRANSWER},
|
||||
{cricket::CONNECTIONROLE_PASSIVE, cricket::CONNECTIONROLE_PASSIVE,
|
||||
cricket::CA_OFFER, cricket::CA_PRANSWER}};
|
||||
|
||||
for (auto& param : duplicate_params) {
|
||||
local_desc.connection_role = param.local_role;
|
||||
remote_desc.connection_role = param.remote_role;
|
||||
|
||||
ASSERT_TRUE(transport_->SetRemoteTransportDescription(
|
||||
remote_desc, param.remote_action, nullptr));
|
||||
ASSERT_TRUE(transport_->SetLocalTransportDescription(
|
||||
local_desc, param.local_action, nullptr));
|
||||
EXPECT_FALSE(
|
||||
transport_->NegotiateRole(param.local_action, &ssl_role, &error_desc));
|
||||
}
|
||||
|
||||
// Invalid parameters due to the offerer not using ACTPASS.
|
||||
NegotiateRoleParams offerer_without_actpass_params[] = {
|
||||
{cricket::CONNECTIONROLE_ACTIVE, cricket::CONNECTIONROLE_PASSIVE,
|
||||
cricket::CA_ANSWER, cricket::CA_OFFER},
|
||||
{cricket::CONNECTIONROLE_PASSIVE, cricket::CONNECTIONROLE_ACTIVE,
|
||||
cricket::CA_ANSWER, cricket::CA_OFFER},
|
||||
{cricket::CONNECTIONROLE_ACTPASS, cricket::CONNECTIONROLE_PASSIVE,
|
||||
cricket::CA_ANSWER, cricket::CA_OFFER},
|
||||
{cricket::CONNECTIONROLE_ACTIVE, cricket::CONNECTIONROLE_PASSIVE,
|
||||
cricket::CA_PRANSWER, cricket::CA_OFFER},
|
||||
{cricket::CONNECTIONROLE_PASSIVE, cricket::CONNECTIONROLE_ACTIVE,
|
||||
cricket::CA_PRANSWER, cricket::CA_OFFER},
|
||||
{cricket::CONNECTIONROLE_ACTPASS, cricket::CONNECTIONROLE_PASSIVE,
|
||||
cricket::CA_PRANSWER, cricket::CA_OFFER},
|
||||
{cricket::CONNECTIONROLE_ACTIVE, cricket::CONNECTIONROLE_PASSIVE,
|
||||
cricket::CA_OFFER, cricket::CA_ANSWER},
|
||||
{cricket::CONNECTIONROLE_PASSIVE, cricket::CONNECTIONROLE_ACTIVE,
|
||||
cricket::CA_OFFER, cricket::CA_ANSWER},
|
||||
{cricket::CONNECTIONROLE_PASSIVE, cricket::CONNECTIONROLE_ACTPASS,
|
||||
cricket::CA_OFFER, cricket::CA_ANSWER},
|
||||
{cricket::CONNECTIONROLE_ACTIVE, cricket::CONNECTIONROLE_PASSIVE,
|
||||
cricket::CA_OFFER, cricket::CA_PRANSWER},
|
||||
{cricket::CONNECTIONROLE_PASSIVE, cricket::CONNECTIONROLE_ACTIVE,
|
||||
cricket::CA_OFFER, cricket::CA_PRANSWER},
|
||||
{cricket::CONNECTIONROLE_PASSIVE, cricket::CONNECTIONROLE_ACTPASS,
|
||||
cricket::CA_OFFER, cricket::CA_PRANSWER}};
|
||||
|
||||
for (auto& param : offerer_without_actpass_params) {
|
||||
local_desc.connection_role = param.local_role;
|
||||
remote_desc.connection_role = param.remote_role;
|
||||
|
||||
ASSERT_TRUE(transport_->SetRemoteTransportDescription(
|
||||
remote_desc, param.remote_action, nullptr));
|
||||
ASSERT_TRUE(transport_->SetLocalTransportDescription(
|
||||
local_desc, param.local_action, nullptr));
|
||||
EXPECT_FALSE(
|
||||
transport_->NegotiateRole(param.local_action, &ssl_role, &error_desc));
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,6 +20,10 @@
|
||||
#include "webrtc/p2p/base/p2ptransport.h"
|
||||
#include "webrtc/p2p/base/port.h"
|
||||
|
||||
#ifdef HAVE_QUIC
|
||||
#include "webrtc/p2p/quic/quictransport.h"
|
||||
#endif // HAVE_QUIC
|
||||
|
||||
namespace cricket {
|
||||
|
||||
enum {
|
||||
@ -219,6 +223,11 @@ Transport* TransportController::CreateTransport_w(
|
||||
const std::string& transport_name) {
|
||||
RTC_DCHECK(worker_thread_->IsCurrent());
|
||||
|
||||
#ifdef HAVE_QUIC
|
||||
if (quic_) {
|
||||
return new QuicTransport(transport_name, port_allocator(), certificate_);
|
||||
}
|
||||
#endif // HAVE_QUIC
|
||||
Transport* transport = new DtlsTransport<P2PTransport>(
|
||||
transport_name, port_allocator(), certificate_);
|
||||
return transport;
|
||||
|
||||
@ -91,6 +91,9 @@ class TransportController : public sigslot::has_slots<>,
|
||||
virtual void DestroyTransportChannel_w(const std::string& transport_name,
|
||||
int component);
|
||||
|
||||
void use_quic() { quic_ = true; }
|
||||
bool quic() const { return quic_; }
|
||||
|
||||
// All of these signals are fired on the signalling thread.
|
||||
|
||||
// If any transport failed => failed,
|
||||
@ -222,6 +225,8 @@ class TransportController : public sigslot::has_slots<>,
|
||||
uint64_t ice_tiebreaker_ = rtc::CreateRandomId64();
|
||||
rtc::scoped_refptr<rtc::RTCCertificate> certificate_;
|
||||
rtc::AsyncInvoker invoker_;
|
||||
// True if QUIC is used instead of DTLS.
|
||||
bool quic_ = false;
|
||||
};
|
||||
|
||||
} // namespace cricket
|
||||
|
||||
@ -107,6 +107,8 @@
|
||||
'quic/quicconnectionhelper.h',
|
||||
'quic/quicsession.cc',
|
||||
'quic/quicsession.h',
|
||||
'quic/quictransport.cc',
|
||||
'quic/quictransport.h',
|
||||
'quic/quictransportchannel.cc',
|
||||
'quic/quictransportchannel.h',
|
||||
'quic/reliablequicstream.cc',
|
||||
@ -182,6 +184,7 @@
|
||||
'sources': [
|
||||
'quic/quicconnectionhelper_unittest.cc',
|
||||
'quic/quicsession_unittest.cc',
|
||||
'quic/quictransport_unittest.cc',
|
||||
'quic/quictransportchannel_unittest.cc',
|
||||
'quic/reliablequicstream_unittest.cc',
|
||||
],
|
||||
|
||||
114
webrtc/p2p/quic/quictransport.cc
Normal file
114
webrtc/p2p/quic/quictransport.cc
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright 2016 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/p2p/quic/quictransport.h"
|
||||
|
||||
#include "webrtc/p2p/base/p2ptransportchannel.h"
|
||||
|
||||
namespace cricket {
|
||||
|
||||
QuicTransport::QuicTransport(
|
||||
const std::string& name,
|
||||
PortAllocator* allocator,
|
||||
const rtc::scoped_refptr<rtc::RTCCertificate>& certificate)
|
||||
: Transport(name, allocator), local_certificate_(certificate) {}
|
||||
|
||||
QuicTransport::~QuicTransport() {
|
||||
DestroyAllChannels();
|
||||
}
|
||||
|
||||
void QuicTransport::SetLocalCertificate(
|
||||
const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
|
||||
local_certificate_ = certificate;
|
||||
}
|
||||
bool QuicTransport::GetLocalCertificate(
|
||||
rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
|
||||
if (!local_certificate_) {
|
||||
return false;
|
||||
}
|
||||
*certificate = local_certificate_;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QuicTransport::ApplyLocalTransportDescription(
|
||||
TransportChannelImpl* channel,
|
||||
std::string* error_desc) {
|
||||
rtc::SSLFingerprint* local_fp =
|
||||
local_description()->identity_fingerprint.get();
|
||||
if (!VerifyCertificateFingerprint(local_certificate_.get(), local_fp,
|
||||
error_desc)) {
|
||||
return false;
|
||||
}
|
||||
if (!channel->SetLocalCertificate(local_certificate_)) {
|
||||
return BadTransportDescription("Failed to set local identity.", error_desc);
|
||||
}
|
||||
return Transport::ApplyLocalTransportDescription(channel, error_desc);
|
||||
}
|
||||
|
||||
bool QuicTransport::NegotiateTransportDescription(ContentAction action,
|
||||
std::string* error_desc) {
|
||||
if (!local_description() || !remote_description()) {
|
||||
const std::string msg =
|
||||
"Local and Remote description must be set before "
|
||||
"transport descriptions are negotiated";
|
||||
return BadTransportDescription(msg, error_desc);
|
||||
}
|
||||
rtc::SSLFingerprint* local_fp =
|
||||
local_description()->identity_fingerprint.get();
|
||||
rtc::SSLFingerprint* remote_fp =
|
||||
remote_description()->identity_fingerprint.get();
|
||||
if (!local_fp || !remote_fp) {
|
||||
return BadTransportDescription("Fingerprints must be supplied for QUIC.",
|
||||
error_desc);
|
||||
}
|
||||
remote_fingerprint_.reset(new rtc::SSLFingerprint(*remote_fp));
|
||||
if (!NegotiateRole(action, &local_role_, error_desc)) {
|
||||
return false;
|
||||
}
|
||||
// Now run the negotiation for the Transport class.
|
||||
return Transport::NegotiateTransportDescription(action, error_desc);
|
||||
}
|
||||
|
||||
QuicTransportChannel* QuicTransport::CreateTransportChannel(int component) {
|
||||
P2PTransportChannel* ice_channel =
|
||||
new P2PTransportChannel(name(), component, port_allocator());
|
||||
return new QuicTransportChannel(ice_channel);
|
||||
}
|
||||
|
||||
void QuicTransport::DestroyTransportChannel(TransportChannelImpl* channel) {
|
||||
delete channel;
|
||||
}
|
||||
|
||||
bool QuicTransport::GetSslRole(rtc::SSLRole* ssl_role) const {
|
||||
ASSERT(ssl_role != NULL);
|
||||
*ssl_role = local_role_;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QuicTransport::ApplyNegotiatedTransportDescription(
|
||||
TransportChannelImpl* channel,
|
||||
std::string* error_desc) {
|
||||
// Set ssl role and remote fingerprint. These are required for QUIC setup.
|
||||
if (!channel->SetSslRole(local_role_)) {
|
||||
return BadTransportDescription("Failed to set ssl role for the channel.",
|
||||
error_desc);
|
||||
}
|
||||
// Apply remote fingerprint.
|
||||
if (!channel->SetRemoteFingerprint(
|
||||
remote_fingerprint_->algorithm,
|
||||
reinterpret_cast<const uint8_t*>(remote_fingerprint_->digest.data()),
|
||||
remote_fingerprint_->digest.size())) {
|
||||
return BadTransportDescription("Failed to apply remote fingerprint.",
|
||||
error_desc);
|
||||
}
|
||||
return Transport::ApplyNegotiatedTransportDescription(channel, error_desc);
|
||||
}
|
||||
|
||||
} // namespace cricket
|
||||
63
webrtc/p2p/quic/quictransport.h
Normal file
63
webrtc/p2p/quic/quictransport.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2016 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_P2P_QUIC_QUICTRANSPORT_H_
|
||||
#define WEBRTC_P2P_QUIC_QUICTRANSPORT_H_
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include "webrtc/p2p/base/transport.h"
|
||||
#include "webrtc/p2p/quic/quictransportchannel.h"
|
||||
|
||||
namespace cricket {
|
||||
|
||||
class P2PTransportChannel;
|
||||
class PortAllocator;
|
||||
|
||||
// TODO(mikescarlett): Refactor to avoid code duplication with DtlsTransport.
|
||||
class QuicTransport : public Transport {
|
||||
public:
|
||||
QuicTransport(const std::string& name,
|
||||
PortAllocator* allocator,
|
||||
const rtc::scoped_refptr<rtc::RTCCertificate>& certificate);
|
||||
|
||||
~QuicTransport() override;
|
||||
|
||||
// Transport overrides.
|
||||
void SetLocalCertificate(
|
||||
const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) override;
|
||||
bool GetLocalCertificate(
|
||||
rtc::scoped_refptr<rtc::RTCCertificate>* certificate) override;
|
||||
bool SetSslMaxProtocolVersion(rtc::SSLProtocolVersion version) override {
|
||||
return true; // Not needed by QUIC
|
||||
}
|
||||
bool GetSslRole(rtc::SSLRole* ssl_role) const override;
|
||||
|
||||
protected:
|
||||
// Transport overrides.
|
||||
QuicTransportChannel* CreateTransportChannel(int component) override;
|
||||
void DestroyTransportChannel(TransportChannelImpl* channel) override;
|
||||
bool ApplyLocalTransportDescription(TransportChannelImpl* channel,
|
||||
std::string* error_desc) override;
|
||||
bool NegotiateTransportDescription(ContentAction action,
|
||||
std::string* error_desc) override;
|
||||
bool ApplyNegotiatedTransportDescription(TransportChannelImpl* channel,
|
||||
std::string* error_desc) override;
|
||||
|
||||
private:
|
||||
rtc::scoped_refptr<rtc::RTCCertificate> local_certificate_;
|
||||
rtc::SSLRole local_role_ = rtc::SSL_CLIENT;
|
||||
rtc::scoped_ptr<rtc::SSLFingerprint> remote_fingerprint_;
|
||||
};
|
||||
|
||||
} // namespace cricket
|
||||
|
||||
#endif // WEBRTC_P2P_QUIC_QUICTRANSPORT_H_
|
||||
159
webrtc/p2p/quic/quictransport_unittest.cc
Normal file
159
webrtc/p2p/quic/quictransport_unittest.cc
Normal file
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright 2016 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/p2p/quic/quictransport.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/base/gunit.h"
|
||||
#include "webrtc/base/rtccertificate.h"
|
||||
#include "webrtc/base/sslidentity.h"
|
||||
|
||||
using cricket::TransportChannelImpl;
|
||||
using cricket::QuicTransport;
|
||||
using cricket::Transport;
|
||||
using cricket::TransportDescription;
|
||||
|
||||
static const char kIceUfrag1[] = "TESTICEUFRAG0001";
|
||||
static const char kIcePwd1[] = "TESTICEPWD00000000000001";
|
||||
|
||||
static const char kIceUfrag2[] = "TESTICEUFRAG0002";
|
||||
static const char kIcePwd2[] = "TESTICEPWD00000000000002";
|
||||
|
||||
static rtc::scoped_refptr<rtc::RTCCertificate> CreateCertificate(
|
||||
std::string name) {
|
||||
return rtc::RTCCertificate::Create(rtc::scoped_ptr<rtc::SSLIdentity>(
|
||||
rtc::SSLIdentity::Generate(name, rtc::KT_DEFAULT)));
|
||||
}
|
||||
|
||||
static rtc::scoped_ptr<rtc::SSLFingerprint> CreateFingerprint(
|
||||
rtc::RTCCertificate* cert) {
|
||||
std::string digest_algorithm;
|
||||
cert->ssl_certificate().GetSignatureDigestAlgorithm(&digest_algorithm);
|
||||
return rtc::scoped_ptr<rtc::SSLFingerprint>(
|
||||
rtc::SSLFingerprint::Create(digest_algorithm, cert->identity()));
|
||||
}
|
||||
|
||||
class QuicTransportTest : public testing::Test {
|
||||
public:
|
||||
QuicTransportTest() : transport_("testing", nullptr, nullptr) {}
|
||||
|
||||
void SetTransportDescription(cricket::ConnectionRole local_role,
|
||||
cricket::ConnectionRole remote_role,
|
||||
cricket::ContentAction local_action,
|
||||
cricket::ContentAction remote_action,
|
||||
rtc::SSLRole expected_ssl_role) {
|
||||
TransportChannelImpl* channel = transport_.CreateChannel(1);
|
||||
ASSERT_NE(nullptr, channel);
|
||||
|
||||
rtc::scoped_refptr<rtc::RTCCertificate> local_certificate(
|
||||
CreateCertificate("local"));
|
||||
ASSERT_NE(nullptr, local_certificate);
|
||||
transport_.SetLocalCertificate(local_certificate);
|
||||
|
||||
rtc::scoped_ptr<rtc::SSLFingerprint> local_fingerprint =
|
||||
CreateFingerprint(local_certificate.get());
|
||||
ASSERT_NE(nullptr, local_fingerprint);
|
||||
TransportDescription local_desc(std::vector<std::string>(), kIceUfrag1,
|
||||
kIcePwd1, cricket::ICEMODE_FULL, local_role,
|
||||
local_fingerprint.get());
|
||||
ASSERT_TRUE(transport_.SetLocalTransportDescription(local_desc,
|
||||
local_action, nullptr));
|
||||
// The certificate is applied to QuicTransportChannel when the local
|
||||
// description is set.
|
||||
rtc::scoped_refptr<rtc::RTCCertificate> channel_local_certificate =
|
||||
channel->GetLocalCertificate();
|
||||
ASSERT_NE(nullptr, channel_local_certificate);
|
||||
EXPECT_EQ(local_certificate, channel_local_certificate);
|
||||
rtc::scoped_ptr<rtc::SSLFingerprint> remote_fingerprint =
|
||||
CreateFingerprint(CreateCertificate("remote").get());
|
||||
// NegotiateTransportDescription was not called yet. The SSL role should
|
||||
// not be set and neither should the remote fingerprint.
|
||||
rtc::scoped_ptr<rtc::SSLRole> role(new rtc::SSLRole());
|
||||
EXPECT_FALSE(channel->GetSslRole(role.get()));
|
||||
// Setting the remote description should set the SSL role.
|
||||
ASSERT_NE(nullptr, remote_fingerprint);
|
||||
TransportDescription remote_desc(std::vector<std::string>(), kIceUfrag2,
|
||||
kIcePwd2, cricket::ICEMODE_FULL,
|
||||
remote_role, remote_fingerprint.get());
|
||||
ASSERT_TRUE(transport_.SetRemoteTransportDescription(
|
||||
remote_desc, remote_action, nullptr));
|
||||
ASSERT_TRUE(channel->GetSslRole(role.get()));
|
||||
// SSL role should be client because the remote description is an ANSWER.
|
||||
EXPECT_EQ(expected_ssl_role, *role);
|
||||
}
|
||||
|
||||
protected:
|
||||
QuicTransport transport_;
|
||||
};
|
||||
|
||||
// Test setting the local certificate.
|
||||
TEST_F(QuicTransportTest, SetLocalCertificate) {
|
||||
rtc::scoped_refptr<rtc::RTCCertificate> local_certificate(
|
||||
CreateCertificate("local"));
|
||||
ASSERT_NE(nullptr, local_certificate);
|
||||
rtc::scoped_refptr<rtc::RTCCertificate> transport_local_certificate;
|
||||
EXPECT_FALSE(transport_.GetLocalCertificate(&transport_local_certificate));
|
||||
transport_.SetLocalCertificate(local_certificate);
|
||||
ASSERT_TRUE(transport_.GetLocalCertificate(&transport_local_certificate));
|
||||
ASSERT_NE(nullptr, transport_local_certificate);
|
||||
EXPECT_EQ(local_certificate, transport_local_certificate);
|
||||
}
|
||||
|
||||
// Test setting the ICE role.
|
||||
TEST_F(QuicTransportTest, SetIceRole) {
|
||||
TransportChannelImpl* channel1 = transport_.CreateChannel(1);
|
||||
ASSERT_NE(nullptr, channel1);
|
||||
transport_.SetIceRole(cricket::ICEROLE_CONTROLLING);
|
||||
EXPECT_EQ(cricket::ICEROLE_CONTROLLING, transport_.ice_role());
|
||||
TransportChannelImpl* channel2 = transport_.CreateChannel(2);
|
||||
ASSERT_NE(nullptr, channel2);
|
||||
EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel1->GetIceRole());
|
||||
EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel2->GetIceRole());
|
||||
}
|
||||
|
||||
// Test setting the ICE tie breaker.
|
||||
TEST_F(QuicTransportTest, SetIceTiebreaker) {
|
||||
transport_.SetIceTiebreaker(1u);
|
||||
EXPECT_EQ(1u, transport_.IceTiebreaker());
|
||||
}
|
||||
|
||||
// Test setting the local and remote descriptions for a SSL client.
|
||||
TEST_F(QuicTransportTest, SetLocalAndRemoteTransportDescriptionClient) {
|
||||
SetTransportDescription(cricket::CONNECTIONROLE_ACTPASS,
|
||||
cricket::CONNECTIONROLE_PASSIVE, cricket::CA_OFFER,
|
||||
cricket::CA_ANSWER, rtc::SSL_CLIENT);
|
||||
}
|
||||
|
||||
// Test setting the local and remote descriptions for a SSL server.
|
||||
TEST_F(QuicTransportTest, SetLocalAndRemoteTransportDescriptionServer) {
|
||||
SetTransportDescription(cricket::CONNECTIONROLE_ACTPASS,
|
||||
cricket::CONNECTIONROLE_ACTIVE, cricket::CA_OFFER,
|
||||
cricket::CA_ANSWER, rtc::SSL_SERVER);
|
||||
}
|
||||
|
||||
// Test creation and destruction of channels.
|
||||
TEST_F(QuicTransportTest, CreateAndDestroyChannels) {
|
||||
TransportChannelImpl* channel1 = transport_.CreateChannel(1);
|
||||
ASSERT_NE(nullptr, channel1);
|
||||
EXPECT_TRUE(transport_.HasChannel(1));
|
||||
EXPECT_EQ(channel1, transport_.GetChannel(1));
|
||||
TransportChannelImpl* channel2 = transport_.CreateChannel(2);
|
||||
ASSERT_NE(nullptr, channel2);
|
||||
EXPECT_TRUE(transport_.HasChannel(2));
|
||||
EXPECT_EQ(channel2, transport_.GetChannel(2));
|
||||
transport_.DestroyChannel(1);
|
||||
EXPECT_FALSE(transport_.HasChannel(1));
|
||||
EXPECT_EQ(nullptr, transport_.GetChannel(1));
|
||||
transport_.DestroyChannel(2);
|
||||
EXPECT_FALSE(transport_.HasChannel(2));
|
||||
EXPECT_EQ(nullptr, transport_.GetChannel(2));
|
||||
}
|
||||
@ -274,7 +274,7 @@ int QuicTransportChannel::SendPacket(const char* data,
|
||||
// |channel_| again.
|
||||
void QuicTransportChannel::OnWritableState(TransportChannel* channel) {
|
||||
ASSERT(rtc::Thread::Current() == worker_thread_);
|
||||
ASSERT(channel == channel_);
|
||||
ASSERT(channel == channel_.get());
|
||||
LOG_J(LS_VERBOSE, this)
|
||||
<< "QuicTransportChannel: channel writable state changed to "
|
||||
<< channel_->writable();
|
||||
@ -308,7 +308,7 @@ void QuicTransportChannel::OnWritableState(TransportChannel* channel) {
|
||||
|
||||
void QuicTransportChannel::OnReceivingState(TransportChannel* channel) {
|
||||
ASSERT(rtc::Thread::Current() == worker_thread_);
|
||||
ASSERT(channel == channel_);
|
||||
ASSERT(channel == channel_.get());
|
||||
LOG_J(LS_VERBOSE, this)
|
||||
<< "QuicTransportChannel: channel receiving state changed to "
|
||||
<< channel_->receiving();
|
||||
@ -324,7 +324,7 @@ void QuicTransportChannel::OnReadPacket(TransportChannel* channel,
|
||||
const rtc::PacketTime& packet_time,
|
||||
int flags) {
|
||||
ASSERT(rtc::Thread::Current() == worker_thread_);
|
||||
ASSERT(channel == channel_);
|
||||
ASSERT(channel == channel_.get());
|
||||
ASSERT(flags == 0);
|
||||
|
||||
switch (quic_state_) {
|
||||
@ -371,24 +371,24 @@ void QuicTransportChannel::OnReadyToSend(TransportChannel* channel) {
|
||||
}
|
||||
|
||||
void QuicTransportChannel::OnGatheringState(TransportChannelImpl* channel) {
|
||||
ASSERT(channel == channel_);
|
||||
ASSERT(channel == channel_.get());
|
||||
SignalGatheringState(this);
|
||||
}
|
||||
|
||||
void QuicTransportChannel::OnCandidateGathered(TransportChannelImpl* channel,
|
||||
const Candidate& c) {
|
||||
ASSERT(channel == channel_);
|
||||
ASSERT(channel == channel_.get());
|
||||
SignalCandidateGathered(this, c);
|
||||
}
|
||||
|
||||
void QuicTransportChannel::OnRoleConflict(TransportChannelImpl* channel) {
|
||||
ASSERT(channel == channel_);
|
||||
ASSERT(channel == channel_.get());
|
||||
SignalRoleConflict(this);
|
||||
}
|
||||
|
||||
void QuicTransportChannel::OnRouteChange(TransportChannel* channel,
|
||||
const Candidate& candidate) {
|
||||
ASSERT(channel == channel_);
|
||||
ASSERT(channel == channel_.get());
|
||||
SignalRouteChange(this, candidate);
|
||||
}
|
||||
|
||||
@ -396,13 +396,13 @@ void QuicTransportChannel::OnSelectedCandidatePairChanged(
|
||||
TransportChannel* channel,
|
||||
CandidatePairInterface* selected_candidate_pair,
|
||||
int last_sent_packet_id) {
|
||||
ASSERT(channel == channel_);
|
||||
ASSERT(channel == channel_.get());
|
||||
SignalSelectedCandidatePairChanged(this, selected_candidate_pair,
|
||||
last_sent_packet_id);
|
||||
}
|
||||
|
||||
void QuicTransportChannel::OnConnectionRemoved(TransportChannelImpl* channel) {
|
||||
ASSERT(channel == channel_);
|
||||
ASSERT(channel == channel_.get());
|
||||
SignalConnectionRemoved(this);
|
||||
}
|
||||
|
||||
|
||||
@ -273,7 +273,7 @@ class QuicTransportChannel : public TransportChannelImpl,
|
||||
rtc::Thread* worker_thread_;
|
||||
// Underlying channel which is responsible for connecting with the remote peer
|
||||
// and sending/receiving packets across the network.
|
||||
TransportChannelImpl* const channel_;
|
||||
std::unique_ptr<TransportChannelImpl> channel_;
|
||||
// Connectivity state of QuicTransportChannel.
|
||||
QuicTransportState quic_state_ = QUIC_TRANSPORT_NEW;
|
||||
// QUIC session which establishes the crypto handshake and converts data
|
||||
|
||||
@ -94,15 +94,15 @@ class QuicTestPeer : public sigslot::has_slots<> {
|
||||
explicit QuicTestPeer(const std::string& name)
|
||||
: name_(name),
|
||||
bytes_sent_(0),
|
||||
ice_channel_(name_, 0),
|
||||
quic_channel_(&ice_channel_),
|
||||
ice_channel_(new FailableTransportChannel(name_, 0)),
|
||||
quic_channel_(ice_channel_),
|
||||
incoming_stream_count_(0) {
|
||||
quic_channel_.SignalReadPacket.connect(
|
||||
this, &QuicTestPeer::OnTransportChannelReadPacket);
|
||||
quic_channel_.SignalIncomingStream.connect(this,
|
||||
&QuicTestPeer::OnIncomingStream);
|
||||
quic_channel_.SignalClosed.connect(this, &QuicTestPeer::OnClosed);
|
||||
ice_channel_.SetAsync(true);
|
||||
ice_channel_->SetAsync(true);
|
||||
rtc::scoped_refptr<rtc::RTCCertificate> local_cert =
|
||||
rtc::RTCCertificate::Create(std::unique_ptr<rtc::SSLIdentity>(
|
||||
rtc::SSLIdentity::Generate(name_, rtc::KT_DEFAULT)));
|
||||
@ -112,13 +112,13 @@ class QuicTestPeer : public sigslot::has_slots<> {
|
||||
|
||||
// Connects |ice_channel_| to that of the other peer.
|
||||
void Connect(QuicTestPeer* other_peer) {
|
||||
ice_channel_.Connect();
|
||||
other_peer->ice_channel_.Connect();
|
||||
ice_channel_.SetDestination(&other_peer->ice_channel_);
|
||||
ice_channel_->Connect();
|
||||
other_peer->ice_channel_->Connect();
|
||||
ice_channel_->SetDestination(other_peer->ice_channel_);
|
||||
}
|
||||
|
||||
// Disconnects |ice_channel_|.
|
||||
void Disconnect() { ice_channel_.SetDestination(nullptr); }
|
||||
void Disconnect() { ice_channel_->SetDestination(nullptr); }
|
||||
|
||||
// Generates ICE credentials and passes them to |quic_channel_|.
|
||||
void SetIceParameters(IceRole local_ice_role,
|
||||
@ -189,13 +189,13 @@ class QuicTestPeer : public sigslot::has_slots<> {
|
||||
|
||||
void ClearBytesReceived() { bytes_received_ = 0; }
|
||||
|
||||
void SetWriteError(int error) { ice_channel_.SetError(error); }
|
||||
void SetWriteError(int error) { ice_channel_->SetError(error); }
|
||||
|
||||
size_t bytes_received() const { return bytes_received_; }
|
||||
|
||||
size_t bytes_sent() const { return bytes_sent_; }
|
||||
|
||||
FailableTransportChannel* ice_channel() { return &ice_channel_; }
|
||||
FailableTransportChannel* ice_channel() { return ice_channel_; }
|
||||
|
||||
QuicTransportChannel* quic_channel() { return &quic_channel_; }
|
||||
|
||||
@ -230,7 +230,7 @@ class QuicTestPeer : public sigslot::has_slots<> {
|
||||
std::string name_; // Channel name.
|
||||
size_t bytes_sent_; // Bytes sent by QUIC channel.
|
||||
size_t bytes_received_; // Bytes received by QUIC channel.
|
||||
FailableTransportChannel ice_channel_; // Simulates an ICE channel.
|
||||
FailableTransportChannel* ice_channel_; // Simulates an ICE channel.
|
||||
QuicTransportChannel quic_channel_; // QUIC channel to test.
|
||||
std::unique_ptr<rtc::SSLFingerprint> local_fingerprint_;
|
||||
ReliableQuicStream* incoming_quic_stream_ = nullptr;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user