blob: 000d10a842c6c8e78853153088b42d76bc239f4e [file] [log] [blame]
[email protected]e92fa7e12012-02-16 23:31:221// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]fe2f62a2010-10-01 03:34:072// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Bence Béky94658bf2018-05-11 19:22:585#include "net/spdy/spdy_proxy_client_socket.h"
[email protected]fe2f62a2010-10-01 03:34:076
7#include <algorithm> // min
dchengc7eeda422015-12-26 03:56:488#include <utility>
[email protected]fe2f62a2010-10-01 03:34:079
[email protected]49639fa2011-12-20 23:22:4110#include "base/bind.h"
11#include "base/bind_helpers.h"
[email protected]aa19cfc2013-05-23 16:41:3812#include "base/callback_helpers.h"
skyostil4891b25b2015-06-11 11:43:4513#include "base/location.h"
[email protected]fe2f62a2010-10-01 03:34:0714#include "base/logging.h"
skyostil4891b25b2015-06-11 11:43:4515#include "base/single_thread_task_runner.h"
[email protected]fc9be5802013-06-11 10:56:5116#include "base/strings/string_util.h"
gabf767595f2016-05-11 18:50:3517#include "base/threading/thread_task_runner_handle.h"
[email protected]f6c63db52013-02-02 00:35:2218#include "base/values.h"
[email protected]fe2f62a2010-10-01 03:34:0719#include "net/base/auth.h"
20#include "net/base/io_buffer.h"
[email protected]fe3b7dc2012-02-03 19:52:0921#include "net/http/http_auth_cache.h"
22#include "net/http/http_auth_handler_factory.h"
rchc5c07de2015-04-08 07:28:1823#include "net/http/http_request_info.h"
[email protected]b104b502010-10-18 20:21:3124#include "net/http/http_response_headers.h"
mikecirone8b85c432016-09-08 19:11:0025#include "net/log/net_log_event_type.h"
26#include "net/log/net_log_source_type.h"
Bence Béky94658bf2018-05-11 19:22:5827#include "net/spdy/spdy_http_utils.h"
[email protected]a2b2cfc2017-12-06 09:06:0828#include "net/traffic_annotation/network_traffic_annotation.h"
[email protected]f89276a72013-07-12 06:41:5429#include "url/gurl.h"
[email protected]fe2f62a2010-10-01 03:34:0730
31namespace net {
32
33SpdyProxyClientSocket::SpdyProxyClientSocket(
[email protected]d26ff352013-05-13 08:48:2834 const base::WeakPtr<SpdyStream>& spdy_stream,
Bence Béky4e83f492018-05-13 23:14:2535 const std::string& user_agent,
[email protected]fe2f62a2010-10-01 03:34:0736 const HostPortPair& endpoint,
tfarina42834112016-09-22 13:38:2037 const NetLogWithSource& source_net_log,
mmenke2a1781d2015-10-07 19:25:3338 HttpAuthController* auth_controller)
[email protected]49639fa2011-12-20 23:22:4139 : next_state_(STATE_DISCONNECTED),
[email protected]fe2f62a2010-10-01 03:34:0740 spdy_stream_(spdy_stream),
[email protected]fe2f62a2010-10-01 03:34:0741 endpoint_(endpoint),
mmenke2a1781d2015-10-07 19:25:3342 auth_(auth_controller),
rchecd3c552015-04-07 20:53:5443 user_agent_(user_agent),
[email protected]ca690b02013-04-17 10:38:4344 user_buffer_len_(0),
[email protected]fe2f62a2010-10-01 03:34:0745 write_buffer_len_(0),
[email protected]57d2dfa2013-06-24 06:04:1246 was_ever_used_(false),
tfarina42834112016-09-22 13:38:2047 net_log_(NetLogWithSource::Make(spdy_stream->net_log().net_log(),
48 NetLogSourceType::PROXY_CLIENT_SOCKET)),
bnc3d95ca92017-03-29 13:20:3449 source_dependency_(source_net_log.source()),
[email protected]0a428c22014-06-14 02:26:3750 weak_factory_(this),
51 write_callback_weak_factory_(this) {
[email protected]fe2f62a2010-10-01 03:34:0752 request_.method = "CONNECT";
rchecd3c552015-04-07 20:53:5453 request_.url = GURL("https://" + endpoint.ToString());
mikecirone8b85c432016-09-08 19:11:0054 net_log_.BeginEvent(NetLogEventType::SOCKET_ALIVE,
[email protected]f6c63db52013-02-02 00:35:2255 source_net_log.source().ToEventParametersCallback());
56 net_log_.AddEvent(
mikecirone8b85c432016-09-08 19:11:0057 NetLogEventType::HTTP2_PROXY_CLIENT_SESSION,
[email protected]f6c63db52013-02-02 00:35:2258 spdy_stream->net_log().source().ToEventParametersCallback());
59
[email protected]fe2f62a2010-10-01 03:34:0760 spdy_stream_->SetDelegate(this);
61 was_ever_used_ = spdy_stream_->WasEverUsed();
62}
63
64SpdyProxyClientSocket::~SpdyProxyClientSocket() {
65 Disconnect();
mikecirone8b85c432016-09-08 19:11:0066 net_log_.EndEvent(NetLogEventType::SOCKET_ALIVE);
[email protected]fe2f62a2010-10-01 03:34:0767}
68
[email protected]be1a48b2011-01-20 00:12:1369const HttpResponseInfo* SpdyProxyClientSocket::GetConnectResponseInfo() const {
[email protected]90499482013-06-01 00:39:5070 return response_.headers.get() ? &response_ : NULL;
[email protected]be1a48b2011-01-20 00:12:1371}
72
[email protected]c0fe941d2012-02-25 00:15:3273const scoped_refptr<HttpAuthController>&
74SpdyProxyClientSocket::GetAuthController() const {
75 return auth_;
76}
77
Bence Béky99832232018-02-11 04:21:0078int SpdyProxyClientSocket::RestartWithAuth(CompletionOnceCallback callback) {
[email protected]c0fe941d2012-02-25 00:15:3279 // A SPDY Stream can only handle a single request, so the underlying
80 // stream may not be reused and a new SpdyProxyClientSocket must be
81 // created (possibly on top of the same SPDY Session).
82 next_state_ = STATE_DISCONNECTED;
Matt Menkeae2cbb82019-02-21 20:20:1383 return ERR_UNABLE_TO_REUSE_CONNECTION_FOR_PROXY_AUTH;
[email protected]c0fe941d2012-02-25 00:15:3284}
85
86bool SpdyProxyClientSocket::IsUsingSpdy() const {
87 return true;
88}
89
bnc6227b26e2016-08-12 02:00:4390NextProto SpdyProxyClientSocket::GetProxyNegotiatedProtocol() const {
bnc4cb660c2016-08-11 19:43:1291 return spdy_stream_->GetNegotiatedProtocol();
[email protected]c0fe941d2012-02-25 00:15:3292}
93
Lily Chenf11e1292018-11-29 16:42:0994void SpdyProxyClientSocket::SetStreamPriority(RequestPriority priority) {
95 spdy_stream_->SetPriority(priority);
96}
97
bnc42331402016-07-25 13:36:1598// Sends a HEADERS frame to the proxy with a CONNECT request
[email protected]fe2f62a2010-10-01 03:34:0799// for the specified endpoint. Waits for the server to send back
bnc42331402016-07-25 13:36:15100// a HEADERS frame. OK will be returned if the status is 200.
[email protected]fe2f62a2010-10-01 03:34:07101// ERR_TUNNEL_CONNECTION_FAILED will be returned for any other status.
102// In any of these cases, Read() may be called to retrieve the HTTP
103// response body. Any other return values should be considered fatal.
[email protected]fe3b7dc2012-02-03 19:52:09104// TODO(rch): handle 407 proxy auth requested correctly, perhaps
105// by creating a new stream for the subsequent request.
[email protected]fe2f62a2010-10-01 03:34:07106// TODO(rch): create a more appropriate error code to disambiguate
107// the HTTPS Proxy tunnel failure from an HTTP Proxy tunnel failure.
Brad Lassey3a814172018-04-26 03:30:21108int SpdyProxyClientSocket::Connect(CompletionOnceCallback callback) {
[email protected]83039bb2011-12-09 18:43:55109 DCHECK(read_callback_.is_null());
[email protected]d9da5fe2010-10-13 22:37:16110 if (next_state_ == STATE_OPEN)
[email protected]fe2f62a2010-10-01 03:34:07111 return OK;
112
[email protected]d9da5fe2010-10-13 22:37:16113 DCHECK_EQ(STATE_DISCONNECTED, next_state_);
[email protected]fe2f62a2010-10-01 03:34:07114 next_state_ = STATE_GENERATE_AUTH_TOKEN;
115
116 int rv = DoLoop(OK);
117 if (rv == ERR_IO_PENDING)
Bence Békya25e3f72018-02-13 21:13:39118 read_callback_ = std::move(callback);
[email protected]fe2f62a2010-10-01 03:34:07119 return rv;
120}
121
122void SpdyProxyClientSocket::Disconnect() {
[email protected]ca690b02013-04-17 10:38:43123 read_buffer_queue_.Clear();
[email protected]d9da5fe2010-10-13 22:37:16124 user_buffer_ = NULL;
[email protected]ca690b02013-04-17 10:38:43125 user_buffer_len_ = 0;
[email protected]dbf036f2011-12-06 23:33:24126 read_callback_.Reset();
[email protected]d9da5fe2010-10-13 22:37:16127
128 write_buffer_len_ = 0;
[email protected]83039bb2011-12-09 18:43:55129 write_callback_.Reset();
[email protected]0a428c22014-06-14 02:26:37130 write_callback_weak_factory_.InvalidateWeakPtrs();
[email protected]d9da5fe2010-10-13 22:37:16131
132 next_state_ = STATE_DISCONNECTED;
133
[email protected]11fbca0b2013-06-02 23:37:21134 if (spdy_stream_.get()) {
[email protected]fe2f62a2010-10-01 03:34:07135 // This will cause OnClose to be invoked, which takes care of
136 // cleaning up all the internal state.
Bence Béky6b9c1352018-05-10 11:51:25137 spdy_stream_->Cancel(ERR_ABORTED);
[email protected]11fbca0b2013-06-02 23:37:21138 DCHECK(!spdy_stream_.get());
[email protected]f6a78292013-03-09 14:36:34139 }
[email protected]fe2f62a2010-10-01 03:34:07140}
141
142bool SpdyProxyClientSocket::IsConnected() const {
[email protected]194c7a92011-12-03 04:54:18143 return next_state_ == STATE_OPEN;
[email protected]fe2f62a2010-10-01 03:34:07144}
145
146bool SpdyProxyClientSocket::IsConnectedAndIdle() const {
[email protected]ca690b02013-04-17 10:38:43147 return IsConnected() && read_buffer_queue_.IsEmpty() &&
[email protected]5ff0ed32014-02-12 17:48:51148 spdy_stream_->IsOpen();
[email protected]fe2f62a2010-10-01 03:34:07149}
150
tfarina42834112016-09-22 13:38:20151const NetLogWithSource& SpdyProxyClientSocket::NetLog() const {
[email protected]e4be2dd2010-12-14 00:44:39152 return net_log_;
153}
154
[email protected]fe2f62a2010-10-01 03:34:07155bool SpdyProxyClientSocket::WasEverUsed() const {
[email protected]11fbca0b2013-06-02 23:37:21156 return was_ever_used_ || (spdy_stream_.get() && spdy_stream_->WasEverUsed());
[email protected]fe2f62a2010-10-01 03:34:07157}
158
tfarina2846404c2016-12-25 14:31:37159bool SpdyProxyClientSocket::WasAlpnNegotiated() const {
[email protected]2d88e7d2012-07-19 17:55:17160 return false;
161}
162
[email protected]33661e482012-04-03 16:16:26163NextProto SpdyProxyClientSocket::GetNegotiatedProtocol() const {
164 return kProtoUnknown;
165}
166
[email protected]2d88e7d2012-07-19 17:55:17167bool SpdyProxyClientSocket::GetSSLInfo(SSLInfo* ssl_info) {
bnc4cb660c2016-08-11 19:43:12168 return spdy_stream_->GetSSLInfo(ssl_info);
[email protected]2d88e7d2012-07-19 17:55:17169}
170
ttuttle23fdb7b2015-05-15 01:28:03171void SpdyProxyClientSocket::GetConnectionAttempts(
172 ConnectionAttempts* out) const {
173 out->clear();
174}
175
tbansalf82cc8e2015-10-14 20:05:49176int64_t SpdyProxyClientSocket::GetTotalReceivedBytes() const {
177 NOTIMPLEMENTED();
178 return 0;
179}
180
Paul Jensen0f49dec2017-12-12 23:39:58181void SpdyProxyClientSocket::ApplySocketTag(const SocketTag& tag) {
182 // Underlying SpdySession can be tagged, but |spdy_stream_| cannot.
183 CHECK(false);
184}
185
Bence Békya25e3f72018-02-13 21:13:39186int SpdyProxyClientSocket::Read(IOBuffer* buf,
187 int buf_len,
Brad Lassey3a814172018-04-26 03:30:21188 CompletionOnceCallback callback) {
Helen Lid7141882018-08-22 21:41:17189 int rv = ReadIfReady(buf, buf_len, std::move(callback));
190 if (rv == ERR_IO_PENDING) {
191 user_buffer_ = buf;
192 user_buffer_len_ = static_cast<size_t>(buf_len);
193 }
194 return rv;
195}
196
197int SpdyProxyClientSocket::ReadIfReady(IOBuffer* buf,
198 int buf_len,
199 CompletionOnceCallback callback) {
200 DCHECK(!read_callback_);
201 DCHECK(!user_buffer_);
[email protected]3f55aa12011-12-07 02:03:33202
203 if (next_state_ == STATE_DISCONNECTED)
204 return ERR_SOCKET_NOT_CONNECTED;
205
[email protected]ca690b02013-04-17 10:38:43206 if (next_state_ == STATE_CLOSED && read_buffer_queue_.IsEmpty()) {
[email protected]3f55aa12011-12-07 02:03:33207 return 0;
208 }
209
210 DCHECK(next_state_ == STATE_OPEN || next_state_ == STATE_CLOSED);
211 DCHECK(buf);
[email protected]ca690b02013-04-17 10:38:43212 size_t result = PopulateUserReadBuffer(buf->data(), buf_len);
[email protected]3f55aa12011-12-07 02:03:33213 if (result == 0) {
Brad Lassey3a814172018-04-26 03:30:21214 read_callback_ = std::move(callback);
[email protected]3f55aa12011-12-07 02:03:33215 return ERR_IO_PENDING;
216 }
[email protected]3f55aa12011-12-07 02:03:33217 return result;
218}
[email protected]fe2f62a2010-10-01 03:34:07219
Helen Lid7141882018-08-22 21:41:17220int SpdyProxyClientSocket::CancelReadIfReady() {
221 // Only a pending ReadIfReady() can be canceled.
222 DCHECK(!user_buffer_) << "Pending Read() cannot be canceled";
223 read_callback_.Reset();
224 return OK;
225}
226
[email protected]ca690b02013-04-17 10:38:43227size_t SpdyProxyClientSocket::PopulateUserReadBuffer(char* data, size_t len) {
[email protected]09a8d9172013-04-17 19:23:49228 return read_buffer_queue_.Dequeue(data, len);
[email protected]fe2f62a2010-10-01 03:34:07229}
230
[email protected]a2b2cfc2017-12-06 09:06:08231int SpdyProxyClientSocket::Write(
232 IOBuffer* buf,
233 int buf_len,
Brad Lassey3a814172018-04-26 03:30:21234 CompletionOnceCallback callback,
[email protected]a2b2cfc2017-12-06 09:06:08235 const NetworkTrafficAnnotationTag& traffic_annotation) {
[email protected]83039bb2011-12-09 18:43:55236 DCHECK(write_callback_.is_null());
[email protected]194c7a92011-12-03 04:54:18237 if (next_state_ != STATE_OPEN)
[email protected]d9da5fe2010-10-13 22:37:16238 return ERR_SOCKET_NOT_CONNECTED;
239
[email protected]11fbca0b2013-06-02 23:37:21240 DCHECK(spdy_stream_.get());
[email protected]edbfa8c2013-05-29 00:22:33241 spdy_stream_->SendData(buf, buf_len, MORE_DATA_TO_SEND);
mikecirone8b85c432016-09-08 19:11:00242 net_log_.AddByteTransferEvent(NetLogEventType::SOCKET_BYTES_SENT, buf_len,
243 buf->data());
Brad Lassey3a814172018-04-26 03:30:21244 write_callback_ = std::move(callback);
[email protected]aa19cfc2013-05-23 16:41:38245 write_buffer_len_ = buf_len;
246 return ERR_IO_PENDING;
[email protected]fe2f62a2010-10-01 03:34:07247}
248
Avi Drissman13fc8932015-12-20 04:40:46249int SpdyProxyClientSocket::SetReceiveBufferSize(int32_t size) {
[email protected]3268023f2011-05-05 00:08:10250 // Since this StreamSocket sits on top of a shared SpdySession, it
[email protected]28b96d1c2014-04-09 12:21:15251 // is not safe for callers to change this underlying socket.
252 return ERR_NOT_IMPLEMENTED;
[email protected]fe2f62a2010-10-01 03:34:07253}
254
Avi Drissman13fc8932015-12-20 04:40:46255int SpdyProxyClientSocket::SetSendBufferSize(int32_t size) {
[email protected]3268023f2011-05-05 00:08:10256 // Since this StreamSocket sits on top of a shared SpdySession, it
[email protected]28b96d1c2014-04-09 12:21:15257 // is not safe for callers to change this underlying socket.
258 return ERR_NOT_IMPLEMENTED;
[email protected]fe2f62a2010-10-01 03:34:07259}
260
[email protected]a3528692012-06-08 00:11:42261int SpdyProxyClientSocket::GetPeerAddress(IPEndPoint* address) const {
[email protected]fe2f62a2010-10-01 03:34:07262 if (!IsConnected())
[email protected]88e03fa2010-10-05 03:09:04263 return ERR_SOCKET_NOT_CONNECTED;
[email protected]fe2f62a2010-10-01 03:34:07264 return spdy_stream_->GetPeerAddress(address);
265}
266
[email protected]e7f74da2011-04-19 23:49:35267int SpdyProxyClientSocket::GetLocalAddress(IPEndPoint* address) const {
268 if (!IsConnected())
269 return ERR_SOCKET_NOT_CONNECTED;
270 return spdy_stream_->GetLocalAddress(address);
271}
272
Bence Békya25e3f72018-02-13 21:13:39273void SpdyProxyClientSocket::RunCallback(CompletionOnceCallback callback,
[email protected]0a428c22014-06-14 02:26:37274 int result) const {
Bence Békya25e3f72018-02-13 21:13:39275 std::move(callback).Run(result);
[email protected]0a428c22014-06-14 02:26:37276}
277
[email protected]fe2f62a2010-10-01 03:34:07278void SpdyProxyClientSocket::OnIOComplete(int result) {
[email protected]d9da5fe2010-10-13 22:37:16279 DCHECK_NE(STATE_DISCONNECTED, next_state_);
[email protected]fe2f62a2010-10-01 03:34:07280 int rv = DoLoop(result);
281 if (rv != ERR_IO_PENDING) {
Brad Lassey3a814172018-04-26 03:30:21282 std::move(read_callback_).Run(rv);
[email protected]fe2f62a2010-10-01 03:34:07283 }
284}
285
286int SpdyProxyClientSocket::DoLoop(int last_io_result) {
[email protected]d9da5fe2010-10-13 22:37:16287 DCHECK_NE(next_state_, STATE_DISCONNECTED);
[email protected]fe2f62a2010-10-01 03:34:07288 int rv = last_io_result;
289 do {
290 State state = next_state_;
[email protected]d9da5fe2010-10-13 22:37:16291 next_state_ = STATE_DISCONNECTED;
[email protected]fe2f62a2010-10-01 03:34:07292 switch (state) {
293 case STATE_GENERATE_AUTH_TOKEN:
294 DCHECK_EQ(OK, rv);
295 rv = DoGenerateAuthToken();
296 break;
297 case STATE_GENERATE_AUTH_TOKEN_COMPLETE:
298 rv = DoGenerateAuthTokenComplete(rv);
299 break;
300 case STATE_SEND_REQUEST:
301 DCHECK_EQ(OK, rv);
mikecirone8b85c432016-09-08 19:11:00302 net_log_.BeginEvent(
303 NetLogEventType::HTTP_TRANSACTION_TUNNEL_SEND_REQUEST);
[email protected]fe2f62a2010-10-01 03:34:07304 rv = DoSendRequest();
305 break;
306 case STATE_SEND_REQUEST_COMPLETE:
[email protected]d7fd1782011-02-08 19:16:43307 net_log_.EndEventWithNetErrorCode(
mikecirone8b85c432016-09-08 19:11:00308 NetLogEventType::HTTP_TRANSACTION_TUNNEL_SEND_REQUEST, rv);
[email protected]fe2f62a2010-10-01 03:34:07309 rv = DoSendRequestComplete(rv);
[email protected]f6c63db52013-02-02 00:35:22310 if (rv >= 0 || rv == ERR_IO_PENDING) {
311 // Emit extra event so can use the same events as
312 // HttpProxyClientSocket.
313 net_log_.BeginEvent(
mikecirone8b85c432016-09-08 19:11:00314 NetLogEventType::HTTP_TRANSACTION_TUNNEL_READ_HEADERS);
[email protected]f6c63db52013-02-02 00:35:22315 }
[email protected]fe2f62a2010-10-01 03:34:07316 break;
317 case STATE_READ_REPLY_COMPLETE:
318 rv = DoReadReplyComplete(rv);
[email protected]d7fd1782011-02-08 19:16:43319 net_log_.EndEventWithNetErrorCode(
mikecirone8b85c432016-09-08 19:11:00320 NetLogEventType::HTTP_TRANSACTION_TUNNEL_READ_HEADERS, rv);
[email protected]fe2f62a2010-10-01 03:34:07321 break;
322 default:
323 NOTREACHED() << "bad state";
324 rv = ERR_UNEXPECTED;
325 break;
326 }
[email protected]d9da5fe2010-10-13 22:37:16327 } while (rv != ERR_IO_PENDING && next_state_ != STATE_DISCONNECTED &&
328 next_state_ != STATE_OPEN);
[email protected]fe2f62a2010-10-01 03:34:07329 return rv;
330}
331
332int SpdyProxyClientSocket::DoGenerateAuthToken() {
333 next_state_ = STATE_GENERATE_AUTH_TOKEN_COMPLETE;
[email protected]49639fa2011-12-20 23:22:41334 return auth_->MaybeGenerateAuthToken(
335 &request_,
[email protected]f6a78292013-03-09 14:36:34336 base::Bind(&SpdyProxyClientSocket::OnIOComplete,
337 weak_factory_.GetWeakPtr()),
[email protected]49639fa2011-12-20 23:22:41338 net_log_);
[email protected]fe2f62a2010-10-01 03:34:07339}
340
341int SpdyProxyClientSocket::DoGenerateAuthTokenComplete(int result) {
342 DCHECK_NE(ERR_IO_PENDING, result);
343 if (result == OK)
344 next_state_ = STATE_SEND_REQUEST;
345 return result;
346}
347
348int SpdyProxyClientSocket::DoSendRequest() {
349 next_state_ = STATE_SEND_REQUEST_COMPLETE;
350
351 // Add Proxy-Authentication header if necessary.
352 HttpRequestHeaders authorization_headers;
353 if (auth_->HaveAuth()) {
354 auth_->AddAuthorizationHeader(&authorization_headers);
355 }
356
Bence Béky4e83f492018-05-13 23:14:25357 std::string request_line;
rchecd3c552015-04-07 20:53:54358 BuildTunnelRequest(endpoint_, authorization_headers, user_agent_,
359 &request_line, &request_.extra_headers);
[email protected]3abacd62012-06-10 20:20:32360
361 net_log_.AddEvent(
mikecirone8b85c432016-09-08 19:11:00362 NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]3abacd62012-06-10 20:20:32363 base::Bind(&HttpRequestHeaders::NetLogCallback,
rchecd3c552015-04-07 20:53:54364 base::Unretained(&request_.extra_headers), &request_line));
[email protected]fe2f62a2010-10-01 03:34:07365
Ryan Hamilton0239aac2018-05-19 00:03:13366 spdy::SpdyHeaderBlock headers;
Bence Béky1af94d6f2018-02-08 00:40:14367 CreateSpdyHeadersFromHttpRequest(request_, request_.extra_headers, &headers);
[email protected]fe2f62a2010-10-01 03:34:07368
dchengc7eeda422015-12-26 03:56:48369 return spdy_stream_->SendRequestHeaders(std::move(headers),
370 MORE_DATA_TO_SEND);
[email protected]fe2f62a2010-10-01 03:34:07371}
372
373int SpdyProxyClientSocket::DoSendRequestComplete(int result) {
374 if (result < 0)
375 return result;
376
bnc42331402016-07-25 13:36:15377 // Wait for HEADERS frame from the server
[email protected]fe2f62a2010-10-01 03:34:07378 next_state_ = STATE_READ_REPLY_COMPLETE;
379 return ERR_IO_PENDING;
380}
381
382int SpdyProxyClientSocket::DoReadReplyComplete(int result) {
383 // We enter this method directly from DoSendRequestComplete, since
bnc42331402016-07-25 13:36:15384 // we are notified by a callback when the HEADERS frame arrives.
[email protected]fe2f62a2010-10-01 03:34:07385
386 if (result < 0)
387 return result;
388
[email protected]fe2f62a2010-10-01 03:34:07389 // Require the "HTTP/1.x" status line for SSL CONNECT.
bncbe0f6af2015-10-15 17:49:56390 if (response_.headers->GetHttpVersion() < HttpVersion(1, 0))
[email protected]fe2f62a2010-10-01 03:34:07391 return ERR_TUNNEL_CONNECTION_FAILED;
392
[email protected]3abacd62012-06-10 20:20:32393 net_log_.AddEvent(
mikecirone8b85c432016-09-08 19:11:00394 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
[email protected]3abacd62012-06-10 20:20:32395 base::Bind(&HttpResponseHeaders::NetLogCallback, response_.headers));
[email protected]fe2f62a2010-10-01 03:34:07396
[email protected]4eddbc732012-08-09 05:40:17397 switch (response_.headers->response_code()) {
398 case 200: // OK
399 next_state_ = STATE_OPEN;
400 return OK;
401
402 case 302: // Found / Moved Temporarily
403 // Try to return a sanitized response so we can follow auth redirects.
404 // If we can't, fail the tunnel connection.
Matt Menkeabd9da82018-05-10 19:02:58405 if (!SanitizeProxyRedirect(&response_))
[email protected]4eddbc732012-08-09 05:40:17406 return ERR_TUNNEL_CONNECTION_FAILED;
[email protected]4eddbc732012-08-09 05:40:17407
Ryan Hamilton0239aac2018-05-19 00:03:13408 // Note that this triggers a spdy::ERROR_CODE_CANCEL.
ttuttle7933c112015-01-06 00:55:24409 spdy_stream_->DetachDelegate();
410 next_state_ = STATE_DISCONNECTED;
Eric Roman74103c72019-02-21 00:23:12411 return ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT;
ttuttle7933c112015-01-06 00:55:24412
[email protected]4eddbc732012-08-09 05:40:17413 case 407: // Proxy Authentication Required
414 next_state_ = STATE_OPEN;
Matt Menkeabd9da82018-05-10 19:02:58415 if (!SanitizeProxyAuth(&response_))
ttuttle7933c112015-01-06 00:55:24416 return ERR_TUNNEL_CONNECTION_FAILED;
[email protected]90499482013-06-01 00:39:50417 return HandleProxyAuthChallenge(auth_.get(), &response_, net_log_);
[email protected]4eddbc732012-08-09 05:40:17418
419 default:
420 // Ignore response to avoid letting the proxy impersonate the target
421 // server. (See http://crbug.com/137891.)
[email protected]4eddbc732012-08-09 05:40:17422 return ERR_TUNNEL_CONNECTION_FAILED;
[email protected]511f6f52010-12-17 03:58:29423 }
[email protected]fe2f62a2010-10-01 03:34:07424}
425
426// SpdyStream::Delegate methods:
427// Called when SYN frame has been sent.
428// Returns true if no more data to be sent after SYN frame.
bnc4c214312016-11-28 16:49:15429void SpdyProxyClientSocket::OnHeadersSent() {
[email protected]fe2f62a2010-10-01 03:34:07430 DCHECK_EQ(next_state_, STATE_SEND_REQUEST_COMPLETE);
431
[email protected]d46715c2013-04-15 00:21:42432 OnIOComplete(OK);
[email protected]fe2f62a2010-10-01 03:34:07433}
434
bnc4c214312016-11-28 16:49:15435void SpdyProxyClientSocket::OnHeadersReceived(
Ryan Hamilton0239aac2018-05-19 00:03:13436 const spdy::SpdyHeaderBlock& response_headers,
437 const spdy::SpdyHeaderBlock* pushed_request_headers) {
[email protected]d08358502010-12-03 22:04:03438 // If we've already received the reply, existing headers are too late.
439 // TODO(mbelshe): figure out a way to make HEADERS frames useful after the
440 // initial response.
441 if (next_state_ != STATE_READ_REPLY_COMPLETE)
bnc4c214312016-11-28 16:49:15442 return;
[email protected]fe2f62a2010-10-01 03:34:07443
[email protected]d08358502010-12-03 22:04:03444 // Save the response
bnc4c214312016-11-28 16:49:15445 const bool headers_valid =
446 SpdyHeadersToHttpResponse(response_headers, &response_);
447 DCHECK(headers_valid);
[email protected]fe2f62a2010-10-01 03:34:07448
[email protected]6d116e1a2013-06-24 07:42:15449 OnIOComplete(OK);
[email protected]fe2f62a2010-10-01 03:34:07450}
451
[email protected]ca690b02013-04-17 10:38:43452// Called when data is received or on EOF (if |buffer| is NULL).
danakjaee3e1ec2016-04-16 00:23:18453void SpdyProxyClientSocket::OnDataReceived(std::unique_ptr<SpdyBuffer> buffer) {
[email protected]ca690b02013-04-17 10:38:43454 if (buffer) {
mikecirone8b85c432016-09-08 19:11:00455 net_log_.AddByteTransferEvent(NetLogEventType::SOCKET_BYTES_RECEIVED,
[email protected]ca690b02013-04-17 10:38:43456 buffer->GetRemainingSize(),
457 buffer->GetRemainingData());
dchengc7eeda422015-12-26 03:56:48458 read_buffer_queue_.Enqueue(std::move(buffer));
[email protected]ca690b02013-04-17 10:38:43459 } else {
mikecirone8b85c432016-09-08 19:11:00460 net_log_.AddByteTransferEvent(NetLogEventType::SOCKET_BYTES_RECEIVED, 0,
461 NULL);
[email protected]fe2f62a2010-10-01 03:34:07462 }
463
Helen Lid7141882018-08-22 21:41:17464 if (read_callback_) {
465 if (user_buffer_) {
466 int rv = PopulateUserReadBuffer(user_buffer_->data(), user_buffer_len_);
467 user_buffer_ = nullptr;
468 user_buffer_len_ = 0;
469 std::move(read_callback_).Run(rv);
470 } else {
471 // If ReadIfReady() is used instead of Read(), tell the caller that data
472 // is available for reading.
473 std::move(read_callback_).Run(OK);
474 }
[email protected]fe2f62a2010-10-01 03:34:07475 }
476}
477
[email protected]aa19cfc2013-05-23 16:41:38478void SpdyProxyClientSocket::OnDataSent() {
[email protected]83039bb2011-12-09 18:43:55479 DCHECK(!write_callback_.is_null());
[email protected]fe2f62a2010-10-01 03:34:07480
[email protected]aa19cfc2013-05-23 16:41:38481 int rv = write_buffer_len_;
482 write_buffer_len_ = 0;
[email protected]89d4d792014-04-06 16:27:15483
484 // Proxy write callbacks result in deep callback chains. Post to allow the
485 // stream's write callback chain to unwind (see crbug.com/355511).
skyostil4891b25b2015-06-11 11:43:45486 base::ThreadTaskRunnerHandle::Get()->PostTask(
Bence Békya25e3f72018-02-13 21:13:39487 FROM_HERE, base::BindOnce(&SpdyProxyClientSocket::RunCallback,
488 write_callback_weak_factory_.GetWeakPtr(),
Brad Lassey3a814172018-04-26 03:30:21489 std::move(write_callback_), rv));
[email protected]fe2f62a2010-10-01 03:34:07490}
491
Ryan Hamilton0239aac2018-05-19 00:03:13492void SpdyProxyClientSocket::OnTrailers(const spdy::SpdyHeaderBlock& trailers) {
xunjieli294da722015-08-11 19:15:02493 // |spdy_stream_| is of type SPDY_BIDIRECTIONAL_STREAM, so trailers are
494 // combined with response headers and this method will not be calld.
495 NOTREACHED();
496}
497
[email protected]fe2f62a2010-10-01 03:34:07498void SpdyProxyClientSocket::OnClose(int status) {
[email protected]fe2f62a2010-10-01 03:34:07499 was_ever_used_ = spdy_stream_->WasEverUsed();
[email protected]d26ff352013-05-13 08:48:28500 spdy_stream_.reset();
[email protected]d9da5fe2010-10-13 22:37:16501
502 bool connecting = next_state_ != STATE_DISCONNECTED &&
503 next_state_ < STATE_OPEN;
504 if (next_state_ == STATE_OPEN)
505 next_state_ = STATE_CLOSED;
506 else
507 next_state_ = STATE_DISCONNECTED;
508
[email protected]6af4e412011-11-29 23:39:18509 base::WeakPtr<SpdyProxyClientSocket> weak_ptr = weak_factory_.GetWeakPtr();
Bence Békya25e3f72018-02-13 21:13:39510 CompletionOnceCallback write_callback = std::move(write_callback_);
[email protected]d9da5fe2010-10-13 22:37:16511 write_buffer_len_ = 0;
[email protected]d9da5fe2010-10-13 22:37:16512
513 // If we're in the middle of connecting, we need to make sure
514 // we invoke the connect callback.
515 if (connecting) {
[email protected]83039bb2011-12-09 18:43:55516 DCHECK(!read_callback_.is_null());
Brad Lassey3a814172018-04-26 03:30:21517 std::move(read_callback_).Run(status);
[email protected]83039bb2011-12-09 18:43:55518 } else if (!read_callback_.is_null()) {
[email protected]6af4e412011-11-29 23:39:18519 // If we have a read_callback_, the we need to make sure we call it back.
danakjaee3e1ec2016-04-16 00:23:18520 OnDataReceived(std::unique_ptr<SpdyBuffer>());
[email protected]d9da5fe2010-10-13 22:37:16521 }
[email protected]6af4e412011-11-29 23:39:18522 // This may have been deleted by read_callback_, so check first.
[email protected]11fbca0b2013-06-02 23:37:21523 if (weak_ptr.get() && !write_callback.is_null())
Bence Békya25e3f72018-02-13 21:13:39524 std::move(write_callback).Run(ERR_CONNECTION_CLOSED);
[email protected]fe2f62a2010-10-01 03:34:07525}
526
bnc3d95ca92017-03-29 13:20:34527NetLogSource SpdyProxyClientSocket::source_dependency() const {
528 return source_dependency_;
529}
530
[email protected]fe2f62a2010-10-01 03:34:07531} // namespace net