Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / net / tools / quic / test_tools / quic_test_client.cc
blob3e77bb51d6dcea2ff79872cf89ebe926b9e8dfc6
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/tools/quic/test_tools/quic_test_client.h"
7 #include "base/time/time.h"
8 #include "net/base/completion_callback.h"
9 #include "net/base/net_errors.h"
10 #include "net/cert/cert_verify_result.h"
11 #include "net/cert/x509_certificate.h"
12 #include "net/quic/crypto/proof_verifier.h"
13 #include "net/quic/quic_server_id.h"
14 #include "net/quic/test_tools/quic_connection_peer.h"
15 #include "net/quic/test_tools/quic_session_peer.h"
16 #include "net/quic/test_tools/quic_test_utils.h"
17 #include "net/quic/test_tools/reliable_quic_stream_peer.h"
18 #include "net/tools/balsa/balsa_headers.h"
19 #include "net/tools/quic/quic_epoll_connection_helper.h"
20 #include "net/tools/quic/quic_packet_writer_wrapper.h"
21 #include "net/tools/quic/quic_spdy_client_stream.h"
22 #include "net/tools/quic/test_tools/http_message.h"
23 #include "net/tools/quic/test_tools/quic_client_peer.h"
24 #include "url/gurl.h"
26 using base::StringPiece;
27 using net::QuicServerId;
28 using net::test::QuicConnectionPeer;
29 using net::test::QuicSessionPeer;
30 using net::test::ReliableQuicStreamPeer;
31 using std::string;
32 using std::vector;
34 namespace net {
35 namespace tools {
36 namespace test {
37 namespace {
39 // RecordingProofVerifier accepts any certificate chain and records the common
40 // name of the leaf.
41 class RecordingProofVerifier : public ProofVerifier {
42 public:
43 // ProofVerifier interface.
44 virtual QuicAsyncStatus VerifyProof(
45 const string& hostname,
46 const string& server_config,
47 const vector<string>& certs,
48 const string& signature,
49 const ProofVerifyContext* context,
50 string* error_details,
51 scoped_ptr<ProofVerifyDetails>* details,
52 ProofVerifierCallback* callback) OVERRIDE {
53 common_name_.clear();
54 if (certs.empty()) {
55 return QUIC_FAILURE;
58 // Convert certs to X509Certificate.
59 vector<StringPiece> cert_pieces(certs.size());
60 for (unsigned i = 0; i < certs.size(); i++) {
61 cert_pieces[i] = StringPiece(certs[i]);
63 scoped_refptr<net::X509Certificate> cert =
64 net::X509Certificate::CreateFromDERCertChain(cert_pieces);
65 if (!cert.get()) {
66 return QUIC_FAILURE;
69 common_name_ = cert->subject().GetDisplayName();
70 return QUIC_SUCCESS;
73 const string& common_name() const { return common_name_; }
75 private:
76 string common_name_;
79 } // anonymous namespace
81 BalsaHeaders* MungeHeaders(const BalsaHeaders* const_headers,
82 bool secure) {
83 StringPiece uri = const_headers->request_uri();
84 if (uri.empty()) {
85 return NULL;
87 if (const_headers->request_method() == "CONNECT") {
88 return NULL;
90 BalsaHeaders* headers = new BalsaHeaders;
91 headers->CopyFrom(*const_headers);
92 if (!uri.starts_with("https://") &&
93 !uri.starts_with("http://")) {
94 // If we have a relative URL, set some defaults.
95 string full_uri = secure ? "https://www.google.com" :
96 "http://www.google.com";
97 full_uri.append(uri.as_string());
98 headers->SetRequestUri(full_uri);
100 return headers;
103 MockableQuicClient::MockableQuicClient(
104 IPEndPoint server_address,
105 const QuicServerId& server_id,
106 const QuicVersionVector& supported_versions,
107 EpollServer* epoll_server)
108 : QuicClient(server_address,
109 server_id,
110 supported_versions,
111 false,
112 epoll_server),
113 override_connection_id_(0),
114 test_writer_(NULL) {}
116 MockableQuicClient::MockableQuicClient(
117 IPEndPoint server_address,
118 const QuicServerId& server_id,
119 const QuicConfig& config,
120 const QuicVersionVector& supported_versions,
121 EpollServer* epoll_server)
122 : QuicClient(server_address,
123 server_id,
124 supported_versions,
125 false,
126 config,
127 epoll_server),
128 override_connection_id_(0),
129 test_writer_(NULL) {}
131 MockableQuicClient::~MockableQuicClient() {
132 if (connected()) {
133 Disconnect();
137 QuicPacketWriter* MockableQuicClient::CreateQuicPacketWriter() {
138 QuicPacketWriter* writer = QuicClient::CreateQuicPacketWriter();
139 if (!test_writer_) {
140 return writer;
142 test_writer_->set_writer(writer);
143 return test_writer_;
146 QuicConnectionId MockableQuicClient::GenerateConnectionId() {
147 return override_connection_id_ ? override_connection_id_
148 : QuicClient::GenerateConnectionId();
151 // Takes ownership of writer.
152 void MockableQuicClient::UseWriter(QuicPacketWriterWrapper* writer) {
153 CHECK(test_writer_ == NULL);
154 test_writer_ = writer;
157 void MockableQuicClient::UseConnectionId(QuicConnectionId connection_id) {
158 override_connection_id_ = connection_id;
161 QuicTestClient::QuicTestClient(IPEndPoint server_address,
162 const string& server_hostname,
163 const QuicVersionVector& supported_versions)
164 : client_(new MockableQuicClient(server_address,
165 QuicServerId(server_hostname,
166 server_address.port(),
167 false,
168 PRIVACY_MODE_DISABLED),
169 supported_versions,
170 &epoll_server_)) {
171 Initialize(true);
174 QuicTestClient::QuicTestClient(IPEndPoint server_address,
175 const string& server_hostname,
176 bool secure,
177 const QuicVersionVector& supported_versions)
178 : client_(new MockableQuicClient(server_address,
179 QuicServerId(server_hostname,
180 server_address.port(),
181 secure,
182 PRIVACY_MODE_DISABLED),
183 supported_versions,
184 &epoll_server_)) {
185 Initialize(secure);
188 QuicTestClient::QuicTestClient(
189 IPEndPoint server_address,
190 const string& server_hostname,
191 bool secure,
192 const QuicConfig& config,
193 const QuicVersionVector& supported_versions)
194 : client_(
195 new MockableQuicClient(server_address,
196 QuicServerId(server_hostname,
197 server_address.port(),
198 secure,
199 PRIVACY_MODE_DISABLED),
200 config,
201 supported_versions,
202 &epoll_server_)) {
203 Initialize(secure);
206 QuicTestClient::QuicTestClient() {
209 QuicTestClient::~QuicTestClient() {
210 if (stream_) {
211 stream_->set_visitor(NULL);
215 void QuicTestClient::Initialize(bool secure) {
216 priority_ = 3;
217 connect_attempted_ = false;
218 secure_ = secure;
219 auto_reconnect_ = false;
220 buffer_body_ = true;
221 fec_policy_ = FEC_PROTECT_OPTIONAL;
222 proof_verifier_ = NULL;
223 ClearPerRequestState();
224 ExpectCertificates(secure_);
227 void QuicTestClient::ExpectCertificates(bool on) {
228 if (on) {
229 proof_verifier_ = new RecordingProofVerifier;
230 client_->SetProofVerifier(proof_verifier_);
231 } else {
232 proof_verifier_ = NULL;
233 client_->SetProofVerifier(NULL);
237 void QuicTestClient::SetUserAgentID(const string& user_agent_id) {
238 client_->SetUserAgentID(user_agent_id);
241 ssize_t QuicTestClient::SendRequest(const string& uri) {
242 HTTPMessage message(HttpConstants::HTTP_1_1,
243 HttpConstants::GET,
244 uri);
245 return SendMessage(message);
248 ssize_t QuicTestClient::SendMessage(const HTTPMessage& message) {
249 stream_ = NULL; // Always force creation of a stream for SendMessage.
251 // If we're not connected, try to find an sni hostname.
252 if (!connected()) {
253 GURL url(message.headers()->request_uri().as_string());
254 if (!url.host().empty()) {
255 client_->set_server_id(
256 QuicServerId(url.host(),
257 url.EffectiveIntPort(),
258 url.SchemeIs("https"),
259 PRIVACY_MODE_DISABLED));
263 QuicSpdyClientStream* stream = GetOrCreateStream();
264 if (!stream) { return 0; }
266 scoped_ptr<BalsaHeaders> munged_headers(MungeHeaders(message.headers(),
267 secure_));
268 ssize_t ret = GetOrCreateStream()->SendRequest(
269 munged_headers.get() ? *munged_headers.get() : *message.headers(),
270 message.body(),
271 message.has_complete_message());
272 WaitForWriteToFlush();
273 return ret;
276 ssize_t QuicTestClient::SendData(string data, bool last_data) {
277 QuicSpdyClientStream* stream = GetOrCreateStream();
278 if (!stream) { return 0; }
279 GetOrCreateStream()->SendBody(data, last_data);
280 WaitForWriteToFlush();
281 return data.length();
284 bool QuicTestClient::response_complete() const {
285 return response_complete_;
288 int QuicTestClient::response_header_size() const {
289 return response_header_size_;
292 int64 QuicTestClient::response_body_size() const {
293 return response_body_size_;
296 bool QuicTestClient::buffer_body() const {
297 return buffer_body_;
300 void QuicTestClient::set_buffer_body(bool buffer_body) {
301 buffer_body_ = buffer_body;
304 bool QuicTestClient::ServerInLameDuckMode() const {
305 return false;
308 const string& QuicTestClient::response_body() {
309 return response_;
312 string QuicTestClient::SendCustomSynchronousRequest(
313 const HTTPMessage& message) {
314 SendMessage(message);
315 WaitForResponse();
316 return response_;
319 string QuicTestClient::SendSynchronousRequest(const string& uri) {
320 if (SendRequest(uri) == 0) {
321 DLOG(ERROR) << "Failed the request for uri:" << uri;
322 return "";
324 WaitForResponse();
325 return response_;
328 QuicSpdyClientStream* QuicTestClient::GetOrCreateStream() {
329 if (!connect_attempted_ || auto_reconnect_) {
330 if (!connected()) {
331 Connect();
333 if (!connected()) {
334 return NULL;
337 if (!stream_) {
338 stream_ = client_->CreateReliableClientStream();
339 if (stream_ == NULL) {
340 return NULL;
342 stream_->set_visitor(this);
343 reinterpret_cast<QuicSpdyClientStream*>(stream_)->set_priority(priority_);
344 // Set FEC policy on stream.
345 ReliableQuicStreamPeer::SetFecPolicy(stream_, fec_policy_);
348 return stream_;
351 QuicErrorCode QuicTestClient::connection_error() {
352 return client()->session()->error();
355 MockableQuicClient* QuicTestClient::client() { return client_.get(); }
357 const string& QuicTestClient::cert_common_name() const {
358 return reinterpret_cast<RecordingProofVerifier*>(proof_verifier_)
359 ->common_name();
362 QuicTagValueMap QuicTestClient::GetServerConfig() const {
363 QuicCryptoClientConfig* config =
364 QuicClientPeer::GetCryptoConfig(client_.get());
365 QuicCryptoClientConfig::CachedState* state =
366 config->LookupOrCreate(client_->server_id());
367 const CryptoHandshakeMessage* handshake_msg = state->GetServerConfig();
368 if (handshake_msg != NULL) {
369 return handshake_msg->tag_value_map();
370 } else {
371 return QuicTagValueMap();
375 bool QuicTestClient::connected() const {
376 return client_->connected();
379 void QuicTestClient::Connect() {
380 DCHECK(!connected());
381 if (!connect_attempted_) {
382 client_->Initialize();
384 client_->Connect();
385 connect_attempted_ = true;
388 void QuicTestClient::ResetConnection() {
389 Disconnect();
390 Connect();
393 void QuicTestClient::Disconnect() {
394 client_->Disconnect();
395 connect_attempted_ = false;
398 IPEndPoint QuicTestClient::LocalSocketAddress() const {
399 return client_->client_address();
402 void QuicTestClient::ClearPerRequestState() {
403 stream_error_ = QUIC_STREAM_NO_ERROR;
404 stream_ = NULL;
405 response_ = "";
406 response_complete_ = false;
407 response_headers_complete_ = false;
408 headers_.Clear();
409 bytes_read_ = 0;
410 bytes_written_ = 0;
411 response_header_size_ = 0;
412 response_body_size_ = 0;
415 void QuicTestClient::WaitForResponseForMs(int timeout_ms) {
416 int64 timeout_us = timeout_ms * base::Time::kMicrosecondsPerMillisecond;
417 int64 old_timeout_us = epoll_server()->timeout_in_us();
418 if (timeout_us > 0) {
419 epoll_server()->set_timeout_in_us(timeout_us);
421 const QuicClock* clock =
422 QuicConnectionPeer::GetHelper(client()->session()->connection())->
423 GetClock();
424 QuicTime end_waiting_time = clock->Now().Add(
425 QuicTime::Delta::FromMicroseconds(timeout_us));
426 while (stream_ != NULL &&
427 !client_->session()->IsClosedStream(stream_->id()) &&
428 (timeout_us < 0 || clock->Now() < end_waiting_time)) {
429 client_->WaitForEvents();
431 if (timeout_us > 0) {
432 epoll_server()->set_timeout_in_us(old_timeout_us);
436 void QuicTestClient::WaitForInitialResponseForMs(int timeout_ms) {
437 int64 timeout_us = timeout_ms * base::Time::kMicrosecondsPerMillisecond;
438 int64 old_timeout_us = epoll_server()->timeout_in_us();
439 if (timeout_us > 0) {
440 epoll_server()->set_timeout_in_us(timeout_us);
442 const QuicClock* clock =
443 QuicConnectionPeer::GetHelper(client()->session()->connection())->
444 GetClock();
445 QuicTime end_waiting_time = clock->Now().Add(
446 QuicTime::Delta::FromMicroseconds(timeout_us));
447 while (stream_ != NULL &&
448 !client_->session()->IsClosedStream(stream_->id()) &&
449 stream_->stream_bytes_read() == 0 &&
450 (timeout_us < 0 || clock->Now() < end_waiting_time)) {
451 client_->WaitForEvents();
453 if (timeout_us > 0) {
454 epoll_server()->set_timeout_in_us(old_timeout_us);
458 ssize_t QuicTestClient::Send(const void *buffer, size_t size) {
459 return SendData(string(static_cast<const char*>(buffer), size), false);
462 bool QuicTestClient::response_headers_complete() const {
463 if (stream_ != NULL) {
464 return stream_->headers_decompressed();
465 } else {
466 return response_headers_complete_;
470 const BalsaHeaders* QuicTestClient::response_headers() const {
471 if (stream_ != NULL) {
472 return &stream_->headers();
473 } else {
474 return &headers_;
478 int64 QuicTestClient::response_size() const {
479 return bytes_read_;
482 size_t QuicTestClient::bytes_read() const {
483 return bytes_read_;
486 size_t QuicTestClient::bytes_written() const {
487 return bytes_written_;
490 void QuicTestClient::OnClose(QuicDataStream* stream) {
491 if (stream_ != stream) {
492 return;
494 if (buffer_body()) {
495 // TODO(fnk): The stream still buffers the whole thing. Fix that.
496 response_ = stream_->data();
498 response_complete_ = true;
499 response_headers_complete_ = stream_->headers_decompressed();
500 headers_.CopyFrom(stream_->headers());
501 stream_error_ = stream_->stream_error();
502 bytes_read_ = stream_->stream_bytes_read() + stream_->header_bytes_read();
503 bytes_written_ =
504 stream_->stream_bytes_written() + stream_->header_bytes_written();
505 response_header_size_ = headers_.GetSizeForWriteBuffer();
506 response_body_size_ = stream_->data().size();
507 stream_ = NULL;
510 void QuicTestClient::UseWriter(QuicPacketWriterWrapper* writer) {
511 client_->UseWriter(writer);
514 void QuicTestClient::UseConnectionId(QuicConnectionId connection_id) {
515 DCHECK(!connected());
516 client_->UseConnectionId(connection_id);
519 ssize_t QuicTestClient::SendAndWaitForResponse(const void *buffer,
520 size_t size) {
521 LOG(DFATAL) << "Not implemented";
522 return 0;
525 void QuicTestClient::Bind(IPEndPoint* local_address) {
526 DLOG(WARNING) << "Bind will be done during connect";
529 string QuicTestClient::SerializeMessage(const HTTPMessage& message) {
530 LOG(DFATAL) << "Not implemented";
531 return "";
534 IPAddressNumber QuicTestClient::bind_to_address() const {
535 return client_->bind_to_address();
538 void QuicTestClient::set_bind_to_address(IPAddressNumber address) {
539 client_->set_bind_to_address(address);
542 const IPEndPoint& QuicTestClient::address() const {
543 LOG(DFATAL) << "Not implemented";
544 return client_->server_address();
547 size_t QuicTestClient::requests_sent() const {
548 LOG(DFATAL) << "Not implemented";
549 return 0;
552 void QuicTestClient::WaitForWriteToFlush() {
553 while (connected() && client()->session()->HasDataToWrite()) {
554 client_->WaitForEvents();
558 void QuicTestClient::SetFecPolicy(FecPolicy fec_policy) {
559 fec_policy_ = fec_policy;
560 // Set policy for headers and crypto streams.
561 ReliableQuicStreamPeer::SetFecPolicy(
562 QuicSessionPeer::GetHeadersStream(client()->session()), fec_policy);
563 ReliableQuicStreamPeer::SetFecPolicy(client()->session()->GetCryptoStream(),
564 fec_policy);
567 } // namespace test
568 } // namespace tools
569 } // namespace net