OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/spdy/spdy_proxy_client_socket.h" | 5 #include "net/spdy/spdy_proxy_client_socket.h" |
6 | 6 |
7 #include <algorithm> // min | 7 #include <algorithm> // min |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
(...skipping 15 matching lines...) Expand all Loading... |
26 const std::string& user_agent, | 26 const std::string& user_agent, |
27 const HostPortPair& endpoint, | 27 const HostPortPair& endpoint, |
28 const GURL& url, | 28 const GURL& url, |
29 const HostPortPair& proxy_server, | 29 const HostPortPair& proxy_server, |
30 HttpAuthCache* auth_cache, | 30 HttpAuthCache* auth_cache, |
31 HttpAuthHandlerFactory* auth_handler_factory) | 31 HttpAuthHandlerFactory* auth_handler_factory) |
32 : ALLOW_THIS_IN_INITIALIZER_LIST( | 32 : ALLOW_THIS_IN_INITIALIZER_LIST( |
33 io_callback_(this, &SpdyProxyClientSocket::OnIOComplete)), | 33 io_callback_(this, &SpdyProxyClientSocket::OnIOComplete)), |
34 next_state_(STATE_DISCONNECTED), | 34 next_state_(STATE_DISCONNECTED), |
35 spdy_stream_(spdy_stream), | 35 spdy_stream_(spdy_stream), |
36 old_read_callback_(NULL), | |
37 write_callback_(NULL), | |
38 endpoint_(endpoint), | 36 endpoint_(endpoint), |
39 auth_( | 37 auth_( |
40 new HttpAuthController(HttpAuth::AUTH_PROXY, | 38 new HttpAuthController(HttpAuth::AUTH_PROXY, |
41 GURL("https://" + proxy_server.ToString()), | 39 GURL("https://" + proxy_server.ToString()), |
42 auth_cache, | 40 auth_cache, |
43 auth_handler_factory)), | 41 auth_handler_factory)), |
44 user_buffer_(NULL), | 42 user_buffer_(NULL), |
45 write_buffer_len_(0), | 43 write_buffer_len_(0), |
46 write_bytes_outstanding_(0), | 44 write_bytes_outstanding_(0), |
47 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), | 45 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
84 // Sends a SYN_STREAM frame to the proxy with a CONNECT request | 82 // Sends a SYN_STREAM frame to the proxy with a CONNECT request |
85 // for the specified endpoint. Waits for the server to send back | 83 // for the specified endpoint. Waits for the server to send back |
86 // a SYN_REPLY frame. OK will be returned if the status is 200. | 84 // a SYN_REPLY frame. OK will be returned if the status is 200. |
87 // ERR_TUNNEL_CONNECTION_FAILED will be returned for any other status. | 85 // ERR_TUNNEL_CONNECTION_FAILED will be returned for any other status. |
88 // In any of these cases, Read() may be called to retrieve the HTTP | 86 // In any of these cases, Read() may be called to retrieve the HTTP |
89 // response body. Any other return values should be considered fatal. | 87 // response body. Any other return values should be considered fatal. |
90 // TODO(rch): handle 407 proxy auth requested correctly, perhaps | 88 // TODO(rch): handle 407 proxy auth requested correctly, perhaps |
91 // by creating a new stream for the subsequent request. | 89 // by creating a new stream for the subsequent request. |
92 // TODO(rch): create a more appropriate error code to disambiguate | 90 // TODO(rch): create a more appropriate error code to disambiguate |
93 // the HTTPS Proxy tunnel failure from an HTTP Proxy tunnel failure. | 91 // the HTTPS Proxy tunnel failure from an HTTP Proxy tunnel failure. |
94 int SpdyProxyClientSocket::Connect(OldCompletionCallback* callback) { | 92 int SpdyProxyClientSocket::Connect(const CompletionCallback& callback) { |
95 DCHECK(!old_read_callback_ && read_callback_.is_null()); | 93 DCHECK(read_callback_.is_null()); |
96 if (next_state_ == STATE_OPEN) | 94 if (next_state_ == STATE_OPEN) |
97 return OK; | 95 return OK; |
98 | 96 |
99 DCHECK_EQ(STATE_DISCONNECTED, next_state_); | |
100 next_state_ = STATE_GENERATE_AUTH_TOKEN; | |
101 | |
102 int rv = DoLoop(OK); | |
103 if (rv == ERR_IO_PENDING) | |
104 old_read_callback_ = callback; | |
105 return rv; | |
106 } | |
107 int SpdyProxyClientSocket::Connect(const CompletionCallback& callback) { | |
108 DCHECK(!old_read_callback_ && read_callback_.is_null()); | |
109 if (next_state_ == STATE_OPEN) | |
110 return OK; | |
111 | |
112 DCHECK_EQ(STATE_DISCONNECTED, next_state_); | 97 DCHECK_EQ(STATE_DISCONNECTED, next_state_); |
113 next_state_ = STATE_GENERATE_AUTH_TOKEN; | 98 next_state_ = STATE_GENERATE_AUTH_TOKEN; |
114 | 99 |
115 int rv = DoLoop(OK); | 100 int rv = DoLoop(OK); |
116 if (rv == ERR_IO_PENDING) | 101 if (rv == ERR_IO_PENDING) |
117 read_callback_ = callback; | 102 read_callback_ = callback; |
118 return rv; | 103 return rv; |
119 } | 104 } |
120 | 105 |
121 void SpdyProxyClientSocket::Disconnect() { | 106 void SpdyProxyClientSocket::Disconnect() { |
122 read_buffer_.clear(); | 107 read_buffer_.clear(); |
123 user_buffer_ = NULL; | 108 user_buffer_ = NULL; |
124 old_read_callback_ = NULL; | |
125 read_callback_.Reset(); | 109 read_callback_.Reset(); |
126 | 110 |
127 write_buffer_len_ = 0; | 111 write_buffer_len_ = 0; |
128 write_bytes_outstanding_ = 0; | 112 write_bytes_outstanding_ = 0; |
129 write_callback_ = NULL; | 113 write_callback_.Reset(); |
130 | 114 |
131 next_state_ = STATE_DISCONNECTED; | 115 next_state_ = STATE_DISCONNECTED; |
132 | 116 |
133 if (spdy_stream_) | 117 if (spdy_stream_) |
134 // This will cause OnClose to be invoked, which takes care of | 118 // This will cause OnClose to be invoked, which takes care of |
135 // cleaning up all the internal state. | 119 // cleaning up all the internal state. |
136 spdy_stream_->Cancel(); | 120 spdy_stream_->Cancel(); |
137 } | 121 } |
138 | 122 |
139 bool SpdyProxyClientSocket::IsConnected() const { | 123 bool SpdyProxyClientSocket::IsConnected() const { |
(...skipping 26 matching lines...) Expand all Loading... |
166 | 150 |
167 int64 SpdyProxyClientSocket::NumBytesRead() const { | 151 int64 SpdyProxyClientSocket::NumBytesRead() const { |
168 return -1; | 152 return -1; |
169 } | 153 } |
170 | 154 |
171 base::TimeDelta SpdyProxyClientSocket::GetConnectTimeMicros() const { | 155 base::TimeDelta SpdyProxyClientSocket::GetConnectTimeMicros() const { |
172 return base::TimeDelta::FromMicroseconds(-1); | 156 return base::TimeDelta::FromMicroseconds(-1); |
173 } | 157 } |
174 | 158 |
175 int SpdyProxyClientSocket::Read(IOBuffer* buf, int buf_len, | 159 int SpdyProxyClientSocket::Read(IOBuffer* buf, int buf_len, |
176 OldCompletionCallback* callback) { | 160 const CompletionCallback& callback) { |
177 DCHECK(!old_read_callback_ && read_callback_.is_null()); | 161 DCHECK(read_callback_.is_null()); |
178 DCHECK(!user_buffer_); | 162 DCHECK(!user_buffer_); |
179 | 163 |
180 if (next_state_ == STATE_DISCONNECTED) | 164 if (next_state_ == STATE_DISCONNECTED) |
181 return ERR_SOCKET_NOT_CONNECTED; | |
182 | |
183 if (next_state_ == STATE_CLOSED && read_buffer_.empty()) { | |
184 return 0; | |
185 } | |
186 | |
187 DCHECK(next_state_ == STATE_OPEN || next_state_ == STATE_CLOSED); | |
188 DCHECK(buf); | |
189 user_buffer_ = new DrainableIOBuffer(buf, buf_len); | |
190 int result = PopulateUserReadBuffer(); | |
191 if (result == 0) { | |
192 DCHECK(callback); | |
193 old_read_callback_ = callback; | |
194 return ERR_IO_PENDING; | |
195 } | |
196 user_buffer_ = NULL; | |
197 return result; | |
198 } | |
199 int SpdyProxyClientSocket::Read(IOBuffer* buf, int buf_len, | |
200 const CompletionCallback& callback) { | |
201 DCHECK(!old_read_callback_ && read_callback_.is_null()); | |
202 DCHECK(!user_buffer_); | |
203 | |
204 if (next_state_ == STATE_DISCONNECTED) | |
205 return ERR_SOCKET_NOT_CONNECTED; | 165 return ERR_SOCKET_NOT_CONNECTED; |
206 | 166 |
207 if (next_state_ == STATE_CLOSED && read_buffer_.empty()) { | 167 if (next_state_ == STATE_CLOSED && read_buffer_.empty()) { |
208 return 0; | 168 return 0; |
209 } | 169 } |
210 | 170 |
211 DCHECK(next_state_ == STATE_OPEN || next_state_ == STATE_CLOSED); | 171 DCHECK(next_state_ == STATE_OPEN || next_state_ == STATE_CLOSED); |
212 DCHECK(buf); | 172 DCHECK(buf); |
213 user_buffer_ = new DrainableIOBuffer(buf, buf_len); | 173 user_buffer_ = new DrainableIOBuffer(buf, buf_len); |
214 int result = PopulateUserReadBuffer(); | 174 int result = PopulateUserReadBuffer(); |
(...skipping 21 matching lines...) Expand all Loading... |
236 read_buffer_.pop_front(); | 196 read_buffer_.pop_front(); |
237 } else { | 197 } else { |
238 data->DidConsume(bytes_to_copy); | 198 data->DidConsume(bytes_to_copy); |
239 } | 199 } |
240 } | 200 } |
241 | 201 |
242 return user_buffer_->BytesConsumed(); | 202 return user_buffer_->BytesConsumed(); |
243 } | 203 } |
244 | 204 |
245 int SpdyProxyClientSocket::Write(IOBuffer* buf, int buf_len, | 205 int SpdyProxyClientSocket::Write(IOBuffer* buf, int buf_len, |
246 OldCompletionCallback* callback) { | 206 const CompletionCallback& callback) { |
247 DCHECK(!write_callback_); | 207 DCHECK(write_callback_.is_null()); |
248 if (next_state_ != STATE_OPEN) | 208 if (next_state_ != STATE_OPEN) |
249 return ERR_SOCKET_NOT_CONNECTED; | 209 return ERR_SOCKET_NOT_CONNECTED; |
250 | 210 |
251 DCHECK(spdy_stream_); | 211 DCHECK(spdy_stream_); |
252 write_bytes_outstanding_= buf_len; | 212 write_bytes_outstanding_= buf_len; |
253 if (buf_len <= kMaxSpdyFrameChunkSize) { | 213 if (buf_len <= kMaxSpdyFrameChunkSize) { |
254 int rv = spdy_stream_->WriteStreamData(buf, buf_len, spdy::DATA_FLAG_NONE); | 214 int rv = spdy_stream_->WriteStreamData(buf, buf_len, spdy::DATA_FLAG_NONE); |
255 if (rv == ERR_IO_PENDING) { | 215 if (rv == ERR_IO_PENDING) { |
256 write_callback_ = callback; | 216 write_callback_ = callback; |
257 write_buffer_len_ = buf_len; | 217 write_buffer_len_ = buf_len; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 int SpdyProxyClientSocket::GetLocalAddress(IPEndPoint* address) const { | 262 int SpdyProxyClientSocket::GetLocalAddress(IPEndPoint* address) const { |
303 if (!IsConnected()) | 263 if (!IsConnected()) |
304 return ERR_SOCKET_NOT_CONNECTED; | 264 return ERR_SOCKET_NOT_CONNECTED; |
305 return spdy_stream_->GetLocalAddress(address); | 265 return spdy_stream_->GetLocalAddress(address); |
306 } | 266 } |
307 | 267 |
308 void SpdyProxyClientSocket::OnIOComplete(int result) { | 268 void SpdyProxyClientSocket::OnIOComplete(int result) { |
309 DCHECK_NE(STATE_DISCONNECTED, next_state_); | 269 DCHECK_NE(STATE_DISCONNECTED, next_state_); |
310 int rv = DoLoop(result); | 270 int rv = DoLoop(result); |
311 if (rv != ERR_IO_PENDING) { | 271 if (rv != ERR_IO_PENDING) { |
312 if (old_read_callback_) { | 272 CompletionCallback c = read_callback_; |
313 OldCompletionCallback* c = old_read_callback_; | 273 read_callback_.Reset(); |
314 old_read_callback_ = NULL; | 274 c.Run(rv); |
315 c->Run(rv); | |
316 } else { | |
317 CompletionCallback c = read_callback_; | |
318 read_callback_.Reset(); | |
319 c.Run(rv); | |
320 } | |
321 } | 275 } |
322 } | 276 } |
323 | 277 |
324 int SpdyProxyClientSocket::DoLoop(int last_io_result) { | 278 int SpdyProxyClientSocket::DoLoop(int last_io_result) { |
325 DCHECK_NE(next_state_, STATE_DISCONNECTED); | 279 DCHECK_NE(next_state_, STATE_DISCONNECTED); |
326 int rv = last_io_result; | 280 int rv = last_io_result; |
327 do { | 281 do { |
328 State state = next_state_; | 282 State state = next_state_; |
329 next_state_ = STATE_DISCONNECTED; | 283 next_state_ = STATE_DISCONNECTED; |
330 switch (state) { | 284 switch (state) { |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
509 // Called when data is received. | 463 // Called when data is received. |
510 void SpdyProxyClientSocket::OnDataReceived(const char* data, int length) { | 464 void SpdyProxyClientSocket::OnDataReceived(const char* data, int length) { |
511 if (length > 0) { | 465 if (length > 0) { |
512 // Save the received data. | 466 // Save the received data. |
513 scoped_refptr<IOBuffer> io_buffer(new IOBuffer(length)); | 467 scoped_refptr<IOBuffer> io_buffer(new IOBuffer(length)); |
514 memcpy(io_buffer->data(), data, length); | 468 memcpy(io_buffer->data(), data, length); |
515 read_buffer_.push_back( | 469 read_buffer_.push_back( |
516 make_scoped_refptr(new DrainableIOBuffer(io_buffer, length))); | 470 make_scoped_refptr(new DrainableIOBuffer(io_buffer, length))); |
517 } | 471 } |
518 | 472 |
519 if (old_read_callback_) { | 473 if (!read_callback_.is_null()) { |
520 int rv = PopulateUserReadBuffer(); | |
521 OldCompletionCallback* c = old_read_callback_; | |
522 old_read_callback_ = NULL; | |
523 user_buffer_ = NULL; | |
524 c->Run(rv); | |
525 } else if (!read_callback_.is_null()) { | |
526 int rv = PopulateUserReadBuffer(); | 474 int rv = PopulateUserReadBuffer(); |
527 CompletionCallback c = read_callback_; | 475 CompletionCallback c = read_callback_; |
528 read_callback_.Reset(); | 476 read_callback_.Reset(); |
529 user_buffer_ = NULL; | 477 user_buffer_ = NULL; |
530 c.Run(rv); | 478 c.Run(rv); |
531 } | 479 } |
532 } | 480 } |
533 | 481 |
534 void SpdyProxyClientSocket::OnDataSent(int length) { | 482 void SpdyProxyClientSocket::OnDataSent(int length) { |
535 DCHECK(write_callback_); | 483 DCHECK(!write_callback_.is_null()); |
536 | 484 |
537 write_bytes_outstanding_ -= length; | 485 write_bytes_outstanding_ -= length; |
538 | 486 |
539 DCHECK_GE(write_bytes_outstanding_, 0); | 487 DCHECK_GE(write_bytes_outstanding_, 0); |
540 | 488 |
541 if (write_bytes_outstanding_ == 0) { | 489 if (write_bytes_outstanding_ == 0) { |
542 int rv = write_buffer_len_; | 490 int rv = write_buffer_len_; |
543 write_buffer_len_ = 0; | 491 write_buffer_len_ = 0; |
544 write_bytes_outstanding_ = 0; | 492 write_bytes_outstanding_ = 0; |
545 OldCompletionCallback* c = write_callback_; | 493 CompletionCallback c = write_callback_; |
546 write_callback_ = NULL; | 494 write_callback_.Reset(); |
547 c->Run(rv); | 495 c.Run(rv); |
548 } | 496 } |
549 } | 497 } |
550 | 498 |
551 void SpdyProxyClientSocket::OnClose(int status) { | 499 void SpdyProxyClientSocket::OnClose(int status) { |
552 DCHECK(spdy_stream_); | 500 DCHECK(spdy_stream_); |
553 was_ever_used_ = spdy_stream_->WasEverUsed(); | 501 was_ever_used_ = spdy_stream_->WasEverUsed(); |
554 spdy_stream_ = NULL; | 502 spdy_stream_ = NULL; |
555 | 503 |
556 bool connecting = next_state_ != STATE_DISCONNECTED && | 504 bool connecting = next_state_ != STATE_DISCONNECTED && |
557 next_state_ < STATE_OPEN; | 505 next_state_ < STATE_OPEN; |
558 if (next_state_ == STATE_OPEN) | 506 if (next_state_ == STATE_OPEN) |
559 next_state_ = STATE_CLOSED; | 507 next_state_ = STATE_CLOSED; |
560 else | 508 else |
561 next_state_ = STATE_DISCONNECTED; | 509 next_state_ = STATE_DISCONNECTED; |
562 | 510 |
563 base::WeakPtr<SpdyProxyClientSocket> weak_ptr = weak_factory_.GetWeakPtr(); | 511 base::WeakPtr<SpdyProxyClientSocket> weak_ptr = weak_factory_.GetWeakPtr(); |
564 OldCompletionCallback* write_callback = write_callback_; | 512 CompletionCallback write_callback = write_callback_; |
565 write_callback_ = NULL; | 513 write_callback_.Reset(); |
566 write_buffer_len_ = 0; | 514 write_buffer_len_ = 0; |
567 write_bytes_outstanding_ = 0; | 515 write_bytes_outstanding_ = 0; |
568 | 516 |
569 // If we're in the middle of connecting, we need to make sure | 517 // If we're in the middle of connecting, we need to make sure |
570 // we invoke the connect callback. | 518 // we invoke the connect callback. |
571 if (connecting) { | 519 if (connecting) { |
572 DCHECK(old_read_callback_ || !read_callback_.is_null()); | 520 DCHECK(!read_callback_.is_null()); |
573 if (old_read_callback_) { | 521 CompletionCallback read_callback = read_callback_; |
574 OldCompletionCallback* read_callback = old_read_callback_; | 522 read_callback_.Reset(); |
575 old_read_callback_ = NULL; | 523 read_callback.Run(status); |
576 read_callback->Run(status); | 524 } else if (!read_callback_.is_null()) { |
577 } else { | |
578 CompletionCallback read_callback = read_callback_; | |
579 read_callback_.Reset(); | |
580 read_callback.Run(status); | |
581 } | |
582 } else if (old_read_callback_ || !read_callback_.is_null()) { | |
583 // If we have a read_callback_, the we need to make sure we call it back. | 525 // If we have a read_callback_, the we need to make sure we call it back. |
584 OnDataReceived(NULL, 0); | 526 OnDataReceived(NULL, 0); |
585 } | 527 } |
586 // This may have been deleted by read_callback_, so check first. | 528 // This may have been deleted by read_callback_, so check first. |
587 if (weak_ptr && write_callback) | 529 if (weak_ptr && !write_callback.is_null()) |
588 write_callback->Run(ERR_CONNECTION_CLOSED); | 530 write_callback.Run(ERR_CONNECTION_CLOSED); |
589 } | 531 } |
590 | 532 |
591 void SpdyProxyClientSocket::set_chunk_callback(ChunkCallback* /*callback*/) { | 533 void SpdyProxyClientSocket::set_chunk_callback(ChunkCallback* /*callback*/) { |
592 } | 534 } |
593 | 535 |
594 } // namespace net | 536 } // namespace net |
OLD | NEW |