We started redesigning GpuMemoryBuffer interface to handle multiple buffers [0].
[chromium-blink-merge.git] / net / tools / quic / quic_simple_client.cc
blob703f22fa17ad4b24ebb73b8e46d704b9e9ac0201
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/quic_simple_client.h"
7 #include "base/logging.h"
8 #include "base/run_loop.h"
9 #include "net/base/net_errors.h"
10 #include "net/http/http_request_info.h"
11 #include "net/http/http_response_info.h"
12 #include "net/quic/crypto/quic_random.h"
13 #include "net/quic/quic_connection.h"
14 #include "net/quic/quic_connection_helper.h"
15 #include "net/quic/quic_default_packet_writer.h"
16 #include "net/quic/quic_protocol.h"
17 #include "net/quic/quic_server_id.h"
18 #include "net/spdy/spdy_http_utils.h"
19 #include "net/udp/udp_client_socket.h"
21 using std::string;
22 using std::vector;
24 namespace net {
25 namespace tools {
27 QuicSimpleClient::QuicSimpleClient(IPEndPoint server_address,
28 const QuicServerId& server_id,
29 const QuicVersionVector& supported_versions)
30 : server_address_(server_address),
31 server_id_(server_id),
32 local_port_(0),
33 helper_(CreateQuicConnectionHelper()),
34 initialized_(false),
35 supported_versions_(supported_versions),
36 weak_factory_(this) {
39 QuicSimpleClient::QuicSimpleClient(IPEndPoint server_address,
40 const QuicServerId& server_id,
41 const QuicVersionVector& supported_versions,
42 const QuicConfig& config)
43 : server_address_(server_address),
44 server_id_(server_id),
45 config_(config),
46 local_port_(0),
47 helper_(CreateQuicConnectionHelper()),
48 initialized_(false),
49 supported_versions_(supported_versions),
50 weak_factory_(this) {
53 QuicSimpleClient::~QuicSimpleClient() {
54 if (connected()) {
55 session()->connection()->SendConnectionClosePacket(
56 QUIC_PEER_GOING_AWAY, "");
60 bool QuicSimpleClient::Initialize() {
61 DCHECK(!initialized_);
63 if (!CreateUDPSocket()) {
64 return false;
67 initialized_ = true;
68 return true;
71 QuicSimpleClient::DummyPacketWriterFactory::DummyPacketWriterFactory(
72 QuicPacketWriter* writer)
73 : writer_(writer) {}
75 QuicSimpleClient::DummyPacketWriterFactory::~DummyPacketWriterFactory() {}
77 QuicPacketWriter* QuicSimpleClient::DummyPacketWriterFactory::Create(
78 QuicConnection* /*connection*/) const {
79 return writer_;
82 bool QuicSimpleClient::CreateUDPSocket() {
83 scoped_ptr<UDPClientSocket> socket(
84 new UDPClientSocket(DatagramSocket::DEFAULT_BIND,
85 RandIntCallback(),
86 &net_log_,
87 NetLog::Source()));
89 int address_family = server_address_.GetSockAddrFamily();
90 if (bind_to_address_.size() != 0) {
91 client_address_ = IPEndPoint(bind_to_address_, local_port_);
92 } else if (address_family == AF_INET) {
93 IPAddressNumber any4;
94 CHECK(net::ParseIPLiteralToNumber("0.0.0.0", &any4));
95 client_address_ = IPEndPoint(any4, local_port_);
96 } else {
97 IPAddressNumber any6;
98 CHECK(net::ParseIPLiteralToNumber("::", &any6));
99 client_address_ = IPEndPoint(any6, local_port_);
102 int rc = socket->Connect(server_address_);
103 if (rc != OK) {
104 LOG(ERROR) << "Connect failed: " << ErrorToShortString(rc);
105 return false;
108 rc = socket->SetReceiveBufferSize(kDefaultSocketReceiveBuffer);
109 if (rc != OK) {
110 LOG(ERROR) << "SetReceiveBufferSize() failed: " << ErrorToShortString(rc);
111 return false;
114 rc = socket->SetSendBufferSize(kDefaultSocketReceiveBuffer);
115 if (rc != OK) {
116 LOG(ERROR) << "SetSendBufferSize() failed: " << ErrorToShortString(rc);
117 return false;
120 rc = socket->GetLocalAddress(&client_address_);
121 if (rc != OK) {
122 LOG(ERROR) << "GetLocalAddress failed: " << ErrorToShortString(rc);
123 return false;
126 socket_.swap(socket);
127 packet_reader_.reset(new QuicPacketReader(socket_.get(), this,
128 BoundNetLog()));
130 if (socket != nullptr) {
131 socket->Close();
134 return true;
137 bool QuicSimpleClient::Connect() {
138 StartConnect();
139 packet_reader_->StartReading();
140 while (EncryptionBeingEstablished()) {
141 WaitForEvents();
143 return session_->connection()->connected();
146 void QuicSimpleClient::StartConnect() {
147 DCHECK(initialized_);
148 DCHECK(!connected());
150 writer_.reset(CreateQuicPacketWriter());
151 connection_ = new QuicConnection(GenerateConnectionId(),
152 server_address_,
153 helper_.get(),
154 DummyPacketWriterFactory(writer_.get()),
155 /* owns_writer= */ false,
156 Perspective::IS_CLIENT,
157 server_id_.is_https(),
158 supported_versions_);
159 session_.reset(new QuicClientSession(config_, connection_));
160 session_->InitializeSession(server_id_, &crypto_config_);
161 session_->CryptoConnect();
164 bool QuicSimpleClient::EncryptionBeingEstablished() {
165 return !session_->IsEncryptionEstablished() &&
166 session_->connection()->connected();
169 void QuicSimpleClient::Disconnect() {
170 DCHECK(initialized_);
172 if (connected()) {
173 session()->connection()->SendConnectionClose(QUIC_PEER_GOING_AWAY);
176 writer_.reset();
177 packet_reader_.reset();
179 initialized_ = false;
182 void QuicSimpleClient::SendRequest(const HttpRequestInfo& headers,
183 base::StringPiece body,
184 bool fin) {
185 QuicSpdyClientStream* stream = CreateReliableClientStream();
186 if (stream == nullptr) {
187 LOG(DFATAL) << "stream creation failed!";
188 return;
190 SpdyHeaderBlock header_block;
191 CreateSpdyHeadersFromHttpRequest(headers, headers.extra_headers, SPDY3, true,
192 &header_block);
193 stream->SendRequest(header_block, body, fin);
194 stream->set_visitor(this);
197 void QuicSimpleClient::SendRequestAndWaitForResponse(
198 const HttpRequestInfo& request,
199 base::StringPiece body,
200 bool fin) {
201 SendRequest(request, body, fin);
202 while (WaitForEvents()) {}
205 void QuicSimpleClient::SendRequestsAndWaitForResponse(
206 const base::CommandLine::StringVector& url_list) {
207 for (size_t i = 0; i < url_list.size(); ++i) {
208 HttpRequestInfo request;
209 request.method = "GET";
210 request.url = GURL(url_list[i]);
211 SendRequest(request, "", true);
214 while (WaitForEvents()) {}
217 QuicSpdyClientStream* QuicSimpleClient::CreateReliableClientStream() {
218 if (!connected()) {
219 return nullptr;
222 return session_->CreateOutgoingDataStream();
225 void QuicSimpleClient::WaitForStreamToClose(QuicStreamId id) {
226 DCHECK(connected());
228 while (connected() && !session_->IsClosedStream(id)) {
229 WaitForEvents();
233 void QuicSimpleClient::WaitForCryptoHandshakeConfirmed() {
234 DCHECK(connected());
236 while (connected() && !session_->IsCryptoHandshakeConfirmed()) {
237 WaitForEvents();
241 bool QuicSimpleClient::WaitForEvents() {
242 DCHECK(connected());
244 base::RunLoop().RunUntilIdle();
245 return session_->num_active_requests() != 0;
248 void QuicSimpleClient::OnClose(QuicDataStream* stream) {
249 QuicSpdyClientStream* client_stream =
250 static_cast<QuicSpdyClientStream*>(stream);
251 HttpResponseInfo response;
252 SpdyHeadersToHttpResponse(client_stream->headers(), SPDY3, &response);
253 if (response_listener_.get() != nullptr) {
254 response_listener_->OnCompleteResponse(
255 stream->id(), *response.headers, client_stream->data());
258 // Store response headers and body.
259 if (store_response_) {
260 latest_response_code_ = client_stream->response_code();
261 response.headers->GetNormalizedHeaders(&latest_response_headers_);
262 latest_response_body_ = client_stream->data();
266 bool QuicSimpleClient::connected() const {
267 return session_.get() && session_->connection() &&
268 session_->connection()->connected();
271 bool QuicSimpleClient::goaway_received() const {
272 return session_ != nullptr && session_->goaway_received();
275 size_t QuicSimpleClient::latest_response_code() const {
276 LOG_IF(DFATAL, !store_response_) << "Response not stored!";
277 return latest_response_code_;
280 const string& QuicSimpleClient::latest_response_headers() const {
281 LOG_IF(DFATAL, !store_response_) << "Response not stored!";
282 return latest_response_headers_;
285 const string& QuicSimpleClient::latest_response_body() const {
286 LOG_IF(DFATAL, !store_response_) << "Response not stored!";
287 return latest_response_body_;
290 QuicConnectionId QuicSimpleClient::GenerateConnectionId() {
291 return helper_->GetRandomGenerator()->RandUint64();
294 QuicConnectionHelper* QuicSimpleClient::CreateQuicConnectionHelper() {
295 return new QuicConnectionHelper(
296 base::MessageLoop::current()->message_loop_proxy().get(),
297 &clock_,
298 QuicRandom::GetInstance());
301 QuicPacketWriter* QuicSimpleClient::CreateQuicPacketWriter() {
302 return new QuicDefaultPacketWriter(socket_.get());
305 void QuicSimpleClient::OnReadError(int result) {
306 LOG(ERROR) << "QuicSimpleClient read failed: " << ErrorToShortString(result);
307 Disconnect();
310 bool QuicSimpleClient::OnPacket(const QuicEncryptedPacket& packet,
311 IPEndPoint local_address,
312 IPEndPoint peer_address) {
313 session_->connection()->ProcessUdpPacket(local_address, peer_address, packet);
314 if (!session_->connection()->connected()) {
315 return false;
318 return true;
321 } // namespace tools
322 } // namespace net