1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
// Copyright (c) 2015 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/tools/quic/quic_client_base.h"
#include "net/quic/crypto/quic_random.h"
#include "net/quic/quic_server_id.h"
namespace net {
QuicClientBase::QuicClientBase(const QuicServerId& server_id,
const QuicVersionVector& supported_versions,
const QuicConfig& config,
QuicConnectionHelperInterface* helper,
ProofVerifier* proof_verifier)
: server_id_(server_id),
config_(config),
crypto_config_(proof_verifier),
helper_(helper),
supported_versions_(supported_versions),
initial_max_packet_length_(0),
num_stateless_rejects_received_(0),
num_sent_client_hellos_(0),
connection_error_(QUIC_NO_ERROR),
connected_or_attempting_connect_(false) {}
QuicClientBase::~QuicClientBase() {}
bool QuicClientBase::Initialize() {
num_sent_client_hellos_ = 0;
num_stateless_rejects_received_ = 0;
connection_error_ = QUIC_NO_ERROR;
connected_or_attempting_connect_ = false;
return true;
}
ProofVerifier* QuicClientBase::proof_verifier() const {
return crypto_config_.proof_verifier();
}
QuicClientSession* QuicClientBase::CreateQuicClientSession(
QuicConnection* connection) {
session_.reset(new QuicClientSession(config_, connection, server_id_,
&crypto_config_, &push_promise_index_));
if (initial_max_packet_length_ != 0) {
session()->connection()->SetMaxPacketLength(initial_max_packet_length_);
}
return session_.get();
}
bool QuicClientBase::EncryptionBeingEstablished() {
return !session_->IsEncryptionEstablished() &&
session_->connection()->connected();
}
QuicSpdyClientStream* QuicClientBase::CreateReliableClientStream() {
if (!connected()) {
return nullptr;
}
return session_->CreateOutgoingDynamicStream(kDefaultPriority);
}
void QuicClientBase::WaitForStreamToClose(QuicStreamId id) {
DCHECK(connected());
while (connected() && !session_->IsClosedStream(id)) {
WaitForEvents();
}
}
void QuicClientBase::WaitForCryptoHandshakeConfirmed() {
DCHECK(connected());
while (connected() && !session_->IsCryptoHandshakeConfirmed()) {
WaitForEvents();
}
}
bool QuicClientBase::connected() const {
return session_.get() && session_->connection() &&
session_->connection()->connected();
}
bool QuicClientBase::goaway_received() const {
return session_ != nullptr && session_->goaway_received();
}
int QuicClientBase::GetNumSentClientHellos() {
// If we are not actively attempting to connect, the session object
// corresponds to the previous connection and should not be used.
const int current_session_hellos = !connected_or_attempting_connect_
? 0
: session_->GetNumSentClientHellos();
return num_sent_client_hellos_ + current_session_hellos;
}
void QuicClientBase::UpdateStats() {
num_sent_client_hellos_ += session()->GetNumSentClientHellos();
if (session()->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT) {
++num_stateless_rejects_received_;
}
}
QuicErrorCode QuicClientBase::connection_error() const {
// Return the high-level error if there was one. Otherwise, return the
// connection error from the last session.
if (connection_error_ != QUIC_NO_ERROR) {
return connection_error_;
}
if (session_.get() == nullptr) {
return QUIC_NO_ERROR;
}
return session_->error();
}
QuicConnectionId QuicClientBase::GetNextConnectionId() {
QuicConnectionId server_designated_id = GetNextServerDesignatedConnectionId();
return server_designated_id ? server_designated_id
: GenerateNewConnectionId();
}
QuicConnectionId QuicClientBase::GetNextServerDesignatedConnectionId() {
QuicCryptoClientConfig::CachedState* cached =
crypto_config_.LookupOrCreate(server_id_);
// If the cached state indicates that we should use a server-designated
// connection ID, then return that connection ID.
CHECK(cached != nullptr) << "QuicClientCryptoConfig::LookupOrCreate returned "
<< "unexpected nullptr.";
return cached->has_server_designated_connection_id()
? cached->GetNextServerDesignatedConnectionId()
: 0;
}
QuicConnectionId QuicClientBase::GenerateNewConnectionId() {
return QuicRandom::GetInstance()->RandUint64();
}
} // namespace net
|