blob: f875ab607e9819c7d340557ebfb64a7d1ecd9c88 [file] [log] [blame]
mikescarlett6459f842016-03-04 09:55:02 -08001/*
2 * Copyright 2016 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "webrtc/p2p/quic/quictransportchannel.h"
12
13#include <utility>
14
15#include "net/quic/crypto/proof_source.h"
16#include "net/quic/crypto/proof_verifier.h"
17#include "net/quic/crypto/quic_crypto_client_config.h"
18#include "net/quic/crypto/quic_crypto_server_config.h"
19#include "net/quic/quic_connection.h"
20#include "net/quic/quic_crypto_client_stream.h"
21#include "net/quic/quic_crypto_server_stream.h"
mikescarlettf5377682016-03-29 12:14:55 -070022#include "net/quic/quic_packet_writer.h"
mikescarlett6459f842016-03-04 09:55:02 -080023#include "net/quic/quic_protocol.h"
mikescarlett6459f842016-03-04 09:55:02 -080024#include "webrtc/p2p/base/common.h"
Edward Lemurc20978e2017-07-06 19:44:34 +020025#include "webrtc/rtc_base/checks.h"
26#include "webrtc/rtc_base/helpers.h"
27#include "webrtc/rtc_base/logging.h"
28#include "webrtc/rtc_base/socket.h"
29#include "webrtc/rtc_base/thread.h"
mikescarlett6459f842016-03-04 09:55:02 -080030
31namespace {
32
33// QUIC public header constants for net::QuicConnection. These are arbitrary
34// given that |channel_| only receives packets specific to this channel,
35// in which case we already know the QUIC packets have the correct destination.
36const net::QuicConnectionId kConnectionId = 0;
mikescarlettf5377682016-03-29 12:14:55 -070037const net::IPAddress kConnectionIpAddress(0, 0, 0, 0);
mikescarlett6459f842016-03-04 09:55:02 -080038const net::IPEndPoint kConnectionIpEndpoint(kConnectionIpAddress, 0);
39
40// Arbitrary server port number for net::QuicCryptoClientConfig.
41const int kQuicServerPort = 0;
42
43// QUIC connection timeout. This is large so that |channel_| can
44// be responsible for connection timeout.
45const int kIdleConnectionStateLifetime = 1000; // seconds
46
47// Length of HKDF input keying material, equal to its number of bytes.
48// https://tools.ietf.org/html/rfc5869#section-2.2.
49// TODO(mikescarlett): Verify that input keying material length is correct.
50const size_t kInputKeyingMaterialLength = 32;
51
52// We don't pull the RTP constants from rtputils.h, to avoid a layer violation.
53const size_t kMinRtpPacketLen = 12;
54
55bool IsRtpPacket(const char* data, size_t len) {
56 const uint8_t* u = reinterpret_cast<const uint8_t*>(data);
57 return (len >= kMinRtpPacketLen && (u[0] & 0xC0) == 0x80);
58}
59
60// Function for detecting QUIC packets based off
61// https://tools.ietf.org/html/draft-tsvwg-quic-protocol-02#section-6.
62const size_t kMinQuicPacketLen = 2;
63
64bool IsQuicPacket(const char* data, size_t len) {
65 const uint8_t* u = reinterpret_cast<const uint8_t*>(data);
66 return (len >= kMinQuicPacketLen && (u[0] & 0x80) == 0);
67}
68
69// Used by QuicCryptoServerConfig to provide dummy proof credentials.
70// TODO(mikescarlett): Remove when secure P2P QUIC handshake is possible.
71class DummyProofSource : public net::ProofSource {
72 public:
73 DummyProofSource() {}
74 ~DummyProofSource() override {}
75
76 // ProofSource override.
mikescarlettf5377682016-03-29 12:14:55 -070077 bool GetProof(const net::IPAddress& server_ip,
mikescarlett6459f842016-03-04 09:55:02 -080078 const std::string& hostname,
79 const std::string& server_config,
mikescarlettf5377682016-03-29 12:14:55 -070080 net::QuicVersion quic_version,
81 base::StringPiece chlo_hash,
mikescarlett6459f842016-03-04 09:55:02 -080082 bool ecdsa_ok,
mikescarlettf5377682016-03-29 12:14:55 -070083 scoped_refptr<net::ProofSource::Chain>* out_chain,
mikescarlett6459f842016-03-04 09:55:02 -080084 std::string* out_signature,
85 std::string* out_leaf_cert_sct) override {
mikescarlettf5377682016-03-29 12:14:55 -070086 LOG(LS_INFO) << "GetProof() providing dummy credentials for insecure QUIC";
87 std::vector<std::string> certs;
88 certs.push_back("Dummy cert");
89 *out_chain = new ProofSource::Chain(certs);
90 *out_signature = "Dummy signature";
91 *out_leaf_cert_sct = "Dummy timestamp";
mikescarlett6459f842016-03-04 09:55:02 -080092 return true;
93 }
94};
95
96// Used by QuicCryptoClientConfig to ignore the peer's credentials
97// and establish an insecure QUIC connection.
98// TODO(mikescarlett): Remove when secure P2P QUIC handshake is possible.
99class InsecureProofVerifier : public net::ProofVerifier {
100 public:
101 InsecureProofVerifier() {}
102 ~InsecureProofVerifier() override {}
103
104 // ProofVerifier override.
105 net::QuicAsyncStatus VerifyProof(
106 const std::string& hostname,
mikescarlett8d37d292016-04-29 15:35:00 -0700107 const uint16_t port,
mikescarlett6459f842016-03-04 09:55:02 -0800108 const std::string& server_config,
mikescarlett8d37d292016-04-29 15:35:00 -0700109 net::QuicVersion quic_version,
110 base::StringPiece chlo_hash,
mikescarlett6459f842016-03-04 09:55:02 -0800111 const std::vector<std::string>& certs,
112 const std::string& cert_sct,
113 const std::string& signature,
mikescarlett8d37d292016-04-29 15:35:00 -0700114 const net::ProofVerifyContext* context,
mikescarlett6459f842016-03-04 09:55:02 -0800115 std::string* error_details,
kwiberg3ec46792016-04-27 07:22:53 -0700116 std::unique_ptr<net::ProofVerifyDetails>* verify_details,
mikescarlett6459f842016-03-04 09:55:02 -0800117 net::ProofVerifierCallback* callback) override {
mikescarlettf5377682016-03-29 12:14:55 -0700118 LOG(LS_INFO) << "VerifyProof() ignoring credentials and returning success";
mikescarlett6459f842016-03-04 09:55:02 -0800119 return net::QUIC_SUCCESS;
120 }
121};
122
123} // namespace
124
125namespace cricket {
126
127QuicTransportChannel::QuicTransportChannel(TransportChannelImpl* channel)
128 : TransportChannelImpl(channel->transport_name(), channel->component()),
johan27c3d5b2016-10-17 00:54:57 -0700129 network_thread_(rtc::Thread::Current()),
mikescarlett6459f842016-03-04 09:55:02 -0800130 channel_(channel),
johan27c3d5b2016-10-17 00:54:57 -0700131 helper_(network_thread_) {
mikescarlett6459f842016-03-04 09:55:02 -0800132 channel_->SignalWritableState.connect(this,
133 &QuicTransportChannel::OnWritableState);
134 channel_->SignalReadPacket.connect(this, &QuicTransportChannel::OnReadPacket);
135 channel_->SignalSentPacket.connect(this, &QuicTransportChannel::OnSentPacket);
136 channel_->SignalReadyToSend.connect(this,
137 &QuicTransportChannel::OnReadyToSend);
138 channel_->SignalGatheringState.connect(
139 this, &QuicTransportChannel::OnGatheringState);
140 channel_->SignalCandidateGathered.connect(
141 this, &QuicTransportChannel::OnCandidateGathered);
142 channel_->SignalRoleConflict.connect(this,
143 &QuicTransportChannel::OnRoleConflict);
144 channel_->SignalRouteChange.connect(this,
145 &QuicTransportChannel::OnRouteChange);
Honghai Zhangcc411c02016-03-29 17:27:21 -0700146 channel_->SignalSelectedCandidatePairChanged.connect(
147 this, &QuicTransportChannel::OnSelectedCandidatePairChanged);
Honghai Zhang1590c392016-05-24 13:15:02 -0700148 channel_->SignalStateChanged.connect(
149 this, &QuicTransportChannel::OnChannelStateChanged);
mikescarlett6459f842016-03-04 09:55:02 -0800150 channel_->SignalReceivingState.connect(
151 this, &QuicTransportChannel::OnReceivingState);
152
153 // Set the QUIC connection timeout.
154 config_.SetIdleConnectionStateLifetime(
155 net::QuicTime::Delta::FromSeconds(kIdleConnectionStateLifetime),
156 net::QuicTime::Delta::FromSeconds(kIdleConnectionStateLifetime));
157 // Set the bytes reserved for the QUIC connection ID to zero.
158 config_.SetBytesForConnectionIdToSend(0);
159}
160
161QuicTransportChannel::~QuicTransportChannel() {}
162
163bool QuicTransportChannel::SetLocalCertificate(
164 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
165 if (!certificate) {
mikescarlettf5377682016-03-29 12:14:55 -0700166 LOG_J(LS_ERROR, this)
167 << "No local certificate was supplied. Not doing QUIC.";
mikescarlett6459f842016-03-04 09:55:02 -0800168 return false;
169 }
170 if (!local_certificate_) {
171 local_certificate_ = certificate;
172 return true;
173 }
174 if (certificate == local_certificate_) {
175 // This may happen during renegotiation.
mikescarlettf5377682016-03-29 12:14:55 -0700176 LOG_J(LS_INFO, this) << "Ignoring identical certificate";
mikescarlett6459f842016-03-04 09:55:02 -0800177 return true;
178 }
mikescarlettf5377682016-03-29 12:14:55 -0700179 LOG_J(LS_ERROR, this)
180 << "Local certificate of the QUIC connection already set. "
181 "Can't change the local certificate once it's active.";
mikescarlett6459f842016-03-04 09:55:02 -0800182 return false;
183}
184
185rtc::scoped_refptr<rtc::RTCCertificate>
186QuicTransportChannel::GetLocalCertificate() const {
187 return local_certificate_;
188}
189
190bool QuicTransportChannel::SetSslRole(rtc::SSLRole role) {
191 if (ssl_role_ && *ssl_role_ == role) {
mikescarlettf5377682016-03-29 12:14:55 -0700192 LOG_J(LS_WARNING, this) << "Ignoring SSL Role identical to current role.";
mikescarlett6459f842016-03-04 09:55:02 -0800193 return true;
194 }
195 if (quic_state_ != QUIC_TRANSPORT_CONNECTED) {
196 ssl_role_ = rtc::Optional<rtc::SSLRole>(role);
197 return true;
198 }
mikescarlettf5377682016-03-29 12:14:55 -0700199 LOG_J(LS_ERROR, this)
mikescarlett6459f842016-03-04 09:55:02 -0800200 << "SSL Role can't be reversed after the session is setup.";
201 return false;
202}
203
204bool QuicTransportChannel::GetSslRole(rtc::SSLRole* role) const {
205 if (!ssl_role_) {
206 return false;
207 }
208 *role = *ssl_role_;
209 return true;
210}
211
212bool QuicTransportChannel::SetRemoteFingerprint(const std::string& digest_alg,
213 const uint8_t* digest,
214 size_t digest_len) {
215 if (digest_alg.empty()) {
216 RTC_DCHECK(!digest_len);
mikescarlettf5377682016-03-29 12:14:55 -0700217 LOG_J(LS_ERROR, this) << "Remote peer doesn't support digest algorithm.";
mikescarlett6459f842016-03-04 09:55:02 -0800218 return false;
219 }
220 std::string remote_fingerprint_value(reinterpret_cast<const char*>(digest),
221 digest_len);
222 // Once we have the local certificate, the same remote fingerprint can be set
223 // multiple times. This may happen during renegotiation.
224 if (remote_fingerprint_ &&
225 remote_fingerprint_->value == remote_fingerprint_value &&
226 remote_fingerprint_->algorithm == digest_alg) {
mikescarlettf5377682016-03-29 12:14:55 -0700227 LOG_J(LS_INFO, this)
228 << "Ignoring identical remote fingerprint and algorithm";
mikescarlett6459f842016-03-04 09:55:02 -0800229 return true;
230 }
231 remote_fingerprint_ = rtc::Optional<RemoteFingerprint>(RemoteFingerprint());
232 remote_fingerprint_->value = remote_fingerprint_value;
233 remote_fingerprint_->algorithm = digest_alg;
234 return true;
235}
236
237bool QuicTransportChannel::ExportKeyingMaterial(const std::string& label,
238 const uint8_t* context,
239 size_t context_len,
240 bool use_context,
241 uint8_t* result,
242 size_t result_len) {
243 std::string quic_context(reinterpret_cast<const char*>(context), context_len);
244 std::string quic_result;
245 if (!quic_->ExportKeyingMaterial(label, quic_context, result_len,
246 &quic_result)) {
247 return false;
248 }
249 quic_result.copy(reinterpret_cast<char*>(result), result_len);
250 return true;
251}
252
253bool QuicTransportChannel::GetSrtpCryptoSuite(int* cipher) {
254 *cipher = rtc::SRTP_AES128_CM_SHA1_80;
255 return true;
256}
257
258// Called from upper layers to send a media packet.
259int QuicTransportChannel::SendPacket(const char* data,
260 size_t size,
261 const rtc::PacketOptions& options,
262 int flags) {
263 if ((flags & PF_SRTP_BYPASS) && IsRtpPacket(data, size)) {
264 return channel_->SendPacket(data, size, options);
265 }
mikescarlettf5377682016-03-29 12:14:55 -0700266 LOG(LS_ERROR) << "Failed to send an invalid SRTP bypass packet using QUIC.";
mikescarlett6459f842016-03-04 09:55:02 -0800267 return -1;
268}
269
270// The state transition logic here is as follows:
271// - Before the QUIC handshake is complete, the QUIC channel is unwritable.
272// - When |channel_| goes writable we start the QUIC handshake.
273// - Once the QUIC handshake completes, the state is that of the
274// |channel_| again.
275void QuicTransportChannel::OnWritableState(TransportChannel* channel) {
nisseede5da42017-01-12 05:15:36 -0800276 RTC_DCHECK(rtc::Thread::Current() == network_thread_);
277 RTC_DCHECK(channel == channel_.get());
mikescarlettf5377682016-03-29 12:14:55 -0700278 LOG_J(LS_VERBOSE, this)
mikescarlett6459f842016-03-04 09:55:02 -0800279 << "QuicTransportChannel: channel writable state changed to "
280 << channel_->writable();
281 switch (quic_state_) {
282 case QUIC_TRANSPORT_NEW:
283 // Start the QUIC handshake when |channel_| is writable.
284 // This will fail if the SSL role or remote fingerprint are not set.
285 // Otherwise failure could result from network or QUIC errors.
286 MaybeStartQuic();
287 break;
288 case QUIC_TRANSPORT_CONNECTED:
289 // Note: SignalWritableState fired by set_writable.
290 set_writable(channel_->writable());
291 if (HasDataToWrite()) {
292 OnCanWrite();
293 }
294 break;
295 case QUIC_TRANSPORT_CONNECTING:
296 // This channel is not writable until the QUIC handshake finishes. It
297 // might have been write blocked.
298 if (HasDataToWrite()) {
299 OnCanWrite();
300 }
301 break;
302 case QUIC_TRANSPORT_CLOSED:
303 // TODO(mikescarlett): Allow the QUIC connection to be reset if it drops
304 // due to a non-failure.
305 break;
306 }
307}
308
309void QuicTransportChannel::OnReceivingState(TransportChannel* channel) {
nisseede5da42017-01-12 05:15:36 -0800310 RTC_DCHECK(rtc::Thread::Current() == network_thread_);
311 RTC_DCHECK(channel == channel_.get());
mikescarlettf5377682016-03-29 12:14:55 -0700312 LOG_J(LS_VERBOSE, this)
mikescarlett6459f842016-03-04 09:55:02 -0800313 << "QuicTransportChannel: channel receiving state changed to "
314 << channel_->receiving();
315 if (quic_state_ == QUIC_TRANSPORT_CONNECTED) {
316 // Note: SignalReceivingState fired by set_receiving.
317 set_receiving(channel_->receiving());
318 }
319}
320
321void QuicTransportChannel::OnReadPacket(TransportChannel* channel,
322 const char* data,
323 size_t size,
324 const rtc::PacketTime& packet_time,
325 int flags) {
nisseede5da42017-01-12 05:15:36 -0800326 RTC_DCHECK(rtc::Thread::Current() == network_thread_);
327 RTC_DCHECK(channel == channel_.get());
328 RTC_DCHECK(flags == 0);
mikescarlett6459f842016-03-04 09:55:02 -0800329
330 switch (quic_state_) {
331 case QUIC_TRANSPORT_NEW:
332 // This would occur if other peer is ready to start QUIC but this peer
333 // hasn't started QUIC.
mikescarlettf5377682016-03-29 12:14:55 -0700334 LOG_J(LS_INFO, this) << "Dropping packet received before QUIC started.";
mikescarlett6459f842016-03-04 09:55:02 -0800335 break;
336 case QUIC_TRANSPORT_CONNECTING:
337 case QUIC_TRANSPORT_CONNECTED:
338 // We should only get QUIC or SRTP packets; STUN's already been demuxed.
339 // Is this potentially a QUIC packet?
340 if (IsQuicPacket(data, size)) {
341 if (!HandleQuicPacket(data, size)) {
mikescarlettf5377682016-03-29 12:14:55 -0700342 LOG_J(LS_ERROR, this) << "Failed to handle QUIC packet.";
mikescarlett6459f842016-03-04 09:55:02 -0800343 return;
344 }
345 } else {
346 // If this is an RTP packet, signal upwards as a bypass packet.
347 if (!IsRtpPacket(data, size)) {
mikescarlettf5377682016-03-29 12:14:55 -0700348 LOG_J(LS_ERROR, this)
349 << "Received unexpected non-QUIC, non-RTP packet.";
mikescarlett6459f842016-03-04 09:55:02 -0800350 return;
351 }
352 SignalReadPacket(this, data, size, packet_time, PF_SRTP_BYPASS);
353 }
354 break;
355 case QUIC_TRANSPORT_CLOSED:
356 // This shouldn't be happening. Drop the packet.
357 break;
358 }
359}
360
361void QuicTransportChannel::OnSentPacket(TransportChannel* channel,
362 const rtc::SentPacket& sent_packet) {
nisseede5da42017-01-12 05:15:36 -0800363 RTC_DCHECK(rtc::Thread::Current() == network_thread_);
mikescarlett6459f842016-03-04 09:55:02 -0800364 SignalSentPacket(this, sent_packet);
365}
366
367void QuicTransportChannel::OnReadyToSend(TransportChannel* channel) {
368 if (writable()) {
369 SignalReadyToSend(this);
370 }
371}
372
373void QuicTransportChannel::OnGatheringState(TransportChannelImpl* channel) {
nisseede5da42017-01-12 05:15:36 -0800374 RTC_DCHECK(channel == channel_.get());
mikescarlett6459f842016-03-04 09:55:02 -0800375 SignalGatheringState(this);
376}
377
378void QuicTransportChannel::OnCandidateGathered(TransportChannelImpl* channel,
379 const Candidate& c) {
nisseede5da42017-01-12 05:15:36 -0800380 RTC_DCHECK(channel == channel_.get());
mikescarlett6459f842016-03-04 09:55:02 -0800381 SignalCandidateGathered(this, c);
382}
383
384void QuicTransportChannel::OnRoleConflict(TransportChannelImpl* channel) {
nisseede5da42017-01-12 05:15:36 -0800385 RTC_DCHECK(channel == channel_.get());
mikescarlett6459f842016-03-04 09:55:02 -0800386 SignalRoleConflict(this);
387}
388
389void QuicTransportChannel::OnRouteChange(TransportChannel* channel,
390 const Candidate& candidate) {
nisseede5da42017-01-12 05:15:36 -0800391 RTC_DCHECK(channel == channel_.get());
mikescarlett6459f842016-03-04 09:55:02 -0800392 SignalRouteChange(this, candidate);
393}
394
Honghai Zhangcc411c02016-03-29 17:27:21 -0700395void QuicTransportChannel::OnSelectedCandidatePairChanged(
396 TransportChannel* channel,
Honghai Zhang52dce732016-03-31 12:37:31 -0700397 CandidatePairInterface* selected_candidate_pair,
zhihuangf2c2f8f2016-07-13 14:13:49 -0700398 int last_sent_packet_id,
399 bool ready_to_send) {
nisseede5da42017-01-12 05:15:36 -0800400 RTC_DCHECK(channel == channel_.get());
Honghai Zhang52dce732016-03-31 12:37:31 -0700401 SignalSelectedCandidatePairChanged(this, selected_candidate_pair,
Taylor Brandstetter6bb1ef22016-06-27 18:09:03 -0700402 last_sent_packet_id, ready_to_send);
Honghai Zhangcc411c02016-03-29 17:27:21 -0700403}
404
Honghai Zhang1590c392016-05-24 13:15:02 -0700405void QuicTransportChannel::OnChannelStateChanged(
406 TransportChannelImpl* channel) {
nisseede5da42017-01-12 05:15:36 -0800407 RTC_DCHECK(channel == channel_.get());
Honghai Zhang1590c392016-05-24 13:15:02 -0700408 SignalStateChanged(this);
mikescarlett6459f842016-03-04 09:55:02 -0800409}
410
411bool QuicTransportChannel::MaybeStartQuic() {
412 if (!channel_->writable()) {
mikescarlettf5377682016-03-29 12:14:55 -0700413 LOG_J(LS_ERROR, this) << "Couldn't start QUIC handshake.";
mikescarlett6459f842016-03-04 09:55:02 -0800414 return false;
415 }
416 if (!CreateQuicSession() || !StartQuicHandshake()) {
mikescarlettf5377682016-03-29 12:14:55 -0700417 LOG_J(LS_WARNING, this)
418 << "Underlying channel is writable but cannot start "
419 "the QUIC handshake.";
mikescarlett6459f842016-03-04 09:55:02 -0800420 return false;
421 }
422 // Verify connection is not closed due to QUIC bug or network failure.
423 // A closed connection should not happen since |channel_| is writable.
424 if (!quic_->connection()->connected()) {
mikescarlettf5377682016-03-29 12:14:55 -0700425 LOG_J(LS_ERROR, this)
426 << "QUIC connection should not be closed if underlying "
427 "channel is writable.";
mikescarlett6459f842016-03-04 09:55:02 -0800428 return false;
429 }
430 // Indicate that |quic_| is ready to receive QUIC packets.
431 set_quic_state(QUIC_TRANSPORT_CONNECTING);
432 return true;
433}
434
435bool QuicTransportChannel::CreateQuicSession() {
436 if (!ssl_role_ || !remote_fingerprint_) {
437 return false;
438 }
439 net::Perspective perspective = (*ssl_role_ == rtc::SSL_CLIENT)
440 ? net::Perspective::IS_CLIENT
441 : net::Perspective::IS_SERVER;
442 bool owns_writer = false;
kwiberg3ec46792016-04-27 07:22:53 -0700443 std::unique_ptr<net::QuicConnection> connection(new net::QuicConnection(
mikescarlett6459f842016-03-04 09:55:02 -0800444 kConnectionId, kConnectionIpEndpoint, &helper_, this, owns_writer,
445 perspective, net::QuicSupportedVersions()));
446 quic_.reset(new QuicSession(std::move(connection), config_));
447 quic_->SignalHandshakeComplete.connect(
448 this, &QuicTransportChannel::OnHandshakeComplete);
449 quic_->SignalConnectionClosed.connect(
450 this, &QuicTransportChannel::OnConnectionClosed);
mikescarlett18b67a52016-04-11 16:56:23 -0700451 quic_->SignalIncomingStream.connect(this,
452 &QuicTransportChannel::OnIncomingStream);
mikescarlett6459f842016-03-04 09:55:02 -0800453 return true;
454}
455
456bool QuicTransportChannel::StartQuicHandshake() {
457 if (*ssl_role_ == rtc::SSL_CLIENT) {
458 // Unique identifier for remote peer.
459 net::QuicServerId server_id(remote_fingerprint_->value, kQuicServerPort);
460 // Perform authentication of remote peer; owned by QuicCryptoClientConfig.
461 // TODO(mikescarlett): Actually verify proof.
462 net::ProofVerifier* proof_verifier = new InsecureProofVerifier();
463 quic_crypto_client_config_.reset(
464 new net::QuicCryptoClientConfig(proof_verifier));
465 net::QuicCryptoClientStream* crypto_stream =
466 new net::QuicCryptoClientStream(server_id, quic_.get(),
467 new net::ProofVerifyContext(),
468 quic_crypto_client_config_.get(), this);
469 quic_->StartClientHandshake(crypto_stream);
mikescarlettf5377682016-03-29 12:14:55 -0700470 LOG_J(LS_INFO, this) << "QuicTransportChannel: Started client handshake.";
mikescarlett6459f842016-03-04 09:55:02 -0800471 } else {
472 RTC_DCHECK_EQ(*ssl_role_, rtc::SSL_SERVER);
473 // Provide credentials to remote peer; owned by QuicCryptoServerConfig.
474 // TODO(mikescarlett): Actually provide credentials.
475 net::ProofSource* proof_source = new DummyProofSource();
476 // Input keying material to HKDF, per http://tools.ietf.org/html/rfc5869.
477 // This is pseudorandom so that HKDF-Extract outputs a pseudorandom key,
478 // since QuicCryptoServerConfig does not use a salt value.
479 std::string source_address_token_secret;
480 if (!rtc::CreateRandomString(kInputKeyingMaterialLength,
481 &source_address_token_secret)) {
mikescarlettf5377682016-03-29 12:14:55 -0700482 LOG_J(LS_ERROR, this)
483 << "Error generating input keying material for HKDF.";
mikescarlett6459f842016-03-04 09:55:02 -0800484 return false;
485 }
486 quic_crypto_server_config_.reset(new net::QuicCryptoServerConfig(
487 source_address_token_secret, helper_.GetRandomGenerator(),
488 proof_source));
489 // Provide server with serialized config string to prove ownership.
490 net::QuicCryptoServerConfig::ConfigOptions options;
491 quic_crypto_server_config_->AddDefaultConfig(helper_.GetRandomGenerator(),
492 helper_.GetClock(), options);
mikescarlett8d37d292016-04-29 15:35:00 -0700493 quic_compressed_certs_cache_.reset(new net::QuicCompressedCertsCache(
494 net::QuicCompressedCertsCache::kQuicCompressedCertsCacheSize));
495 // TODO(mikescarlett): Add support for stateless rejects.
496 bool use_stateless_rejects_if_peer_supported = false;
mikescarlett6459f842016-03-04 09:55:02 -0800497 net::QuicCryptoServerStream* crypto_stream =
498 new net::QuicCryptoServerStream(quic_crypto_server_config_.get(),
mikescarlett8d37d292016-04-29 15:35:00 -0700499 quic_compressed_certs_cache_.get(),
500 use_stateless_rejects_if_peer_supported,
mikescarlett6459f842016-03-04 09:55:02 -0800501 quic_.get());
502 quic_->StartServerHandshake(crypto_stream);
mikescarlettf5377682016-03-29 12:14:55 -0700503 LOG_J(LS_INFO, this) << "QuicTransportChannel: Started server handshake.";
mikescarlett6459f842016-03-04 09:55:02 -0800504 }
505 return true;
506}
507
508bool QuicTransportChannel::HandleQuicPacket(const char* data, size_t size) {
nisseede5da42017-01-12 05:15:36 -0800509 RTC_DCHECK(rtc::Thread::Current() == network_thread_);
mikescarlett6459f842016-03-04 09:55:02 -0800510 return quic_->OnReadPacket(data, size);
511}
512
513net::WriteResult QuicTransportChannel::WritePacket(
514 const char* buffer,
515 size_t buf_len,
mikescarlettf5377682016-03-29 12:14:55 -0700516 const net::IPAddress& self_address,
517 const net::IPEndPoint& peer_address,
518 net::PerPacketOptions* options) {
mikescarlett6459f842016-03-04 09:55:02 -0800519 // QUIC should never call this if IsWriteBlocked, but just in case...
520 if (IsWriteBlocked()) {
521 return net::WriteResult(net::WRITE_STATUS_BLOCKED, EWOULDBLOCK);
522 }
523 // TODO(mikescarlett): Figure out how to tell QUIC "I dropped your packet, but
524 // don't block" without the QUIC connection tearing itself down.
525 int sent = channel_->SendPacket(buffer, buf_len, rtc::PacketOptions());
526 int bytes_written = sent > 0 ? sent : 0;
527 return net::WriteResult(net::WRITE_STATUS_OK, bytes_written);
528}
529
530// TODO(mikescarlett): Implement check for whether |channel_| is currently
531// write blocked so that |quic_| does not try to write packet. This is
532// necessary because |channel_| can be writable yet write blocked and
533// channel_->GetError() is not flushed when there is no error.
534bool QuicTransportChannel::IsWriteBlocked() const {
535 return !channel_->writable();
536}
537
538void QuicTransportChannel::OnHandshakeComplete() {
539 set_quic_state(QUIC_TRANSPORT_CONNECTED);
540 set_writable(true);
541 // OnReceivingState might have been called before the QUIC channel was
542 // connected, in which case the QUIC channel is now receiving.
543 if (channel_->receiving()) {
544 set_receiving(true);
545 }
546}
547
548void QuicTransportChannel::OnConnectionClosed(net::QuicErrorCode error,
549 bool from_peer) {
mikescarlettf5377682016-03-29 12:14:55 -0700550 LOG_J(LS_INFO, this) << "Connection closed by "
551 << (from_peer ? "other" : "this") << " peer "
552 << "with QUIC error " << error;
mikescarlett6459f842016-03-04 09:55:02 -0800553 // TODO(mikescarlett): Allow the QUIC session to be reset when the connection
554 // does not close due to failure.
555 set_quic_state(QUIC_TRANSPORT_CLOSED);
556 set_writable(false);
mikescarlett18b67a52016-04-11 16:56:23 -0700557 SignalClosed();
mikescarlett6459f842016-03-04 09:55:02 -0800558}
559
560void QuicTransportChannel::OnProofValid(
561 const net::QuicCryptoClientConfig::CachedState& cached) {
mikescarlettf5377682016-03-29 12:14:55 -0700562 LOG_J(LS_INFO, this) << "Cached proof marked valid";
mikescarlett6459f842016-03-04 09:55:02 -0800563}
564
565void QuicTransportChannel::OnProofVerifyDetailsAvailable(
566 const net::ProofVerifyDetails& verify_details) {
mikescarlettf5377682016-03-29 12:14:55 -0700567 LOG_J(LS_INFO, this) << "Proof verify details available from"
568 << " QuicCryptoClientStream";
mikescarlett6459f842016-03-04 09:55:02 -0800569}
570
571bool QuicTransportChannel::HasDataToWrite() const {
572 return quic_ && quic_->HasDataToWrite();
573}
574
575void QuicTransportChannel::OnCanWrite() {
576 RTC_DCHECK(quic_ != nullptr);
577 quic_->connection()->OnCanWrite();
578}
579
580void QuicTransportChannel::set_quic_state(QuicTransportState state) {
mikescarlettf5377682016-03-29 12:14:55 -0700581 LOG_J(LS_VERBOSE, this) << "set_quic_state from:" << quic_state_ << " to "
582 << state;
mikescarlett6459f842016-03-04 09:55:02 -0800583 quic_state_ = state;
584}
585
mikescarlett18b67a52016-04-11 16:56:23 -0700586ReliableQuicStream* QuicTransportChannel::CreateQuicStream() {
587 if (quic_) {
mikescarlett70035ca2016-04-29 18:14:37 -0700588 net::SpdyPriority priority = 0; // Priority of the QUIC stream
mikescarlett18b67a52016-04-11 16:56:23 -0700589 return quic_->CreateOutgoingDynamicStream(priority);
590 }
591 return nullptr;
592}
593
594void QuicTransportChannel::OnIncomingStream(ReliableQuicStream* stream) {
595 SignalIncomingStream(stream);
596}
597
mikescarlett6459f842016-03-04 09:55:02 -0800598} // namespace cricket