OLD | NEW |
| (Empty) |
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. | |
4 // | |
5 // TODO(ukai): code is similar with http_network_transaction.cc. We should | |
6 // think about ways to share code, if possible. | |
7 | |
8 #include "net/socket_stream/socket_stream.h" | |
9 | |
10 #include <set> | |
11 #include <string> | |
12 #include <vector> | |
13 | |
14 #include "base/bind.h" | |
15 #include "base/bind_helpers.h" | |
16 #include "base/compiler_specific.h" | |
17 #include "base/logging.h" | |
18 #include "base/message_loop/message_loop.h" | |
19 #include "base/strings/string_util.h" | |
20 #include "base/strings/stringprintf.h" | |
21 #include "base/strings/utf_string_conversions.h" | |
22 #include "net/base/auth.h" | |
23 #include "net/base/io_buffer.h" | |
24 #include "net/base/load_flags.h" | |
25 #include "net/base/net_errors.h" | |
26 #include "net/base/net_util.h" | |
27 #include "net/dns/host_resolver.h" | |
28 #include "net/http/http_auth_controller.h" | |
29 #include "net/http/http_network_session.h" | |
30 #include "net/http/http_request_headers.h" | |
31 #include "net/http/http_request_info.h" | |
32 #include "net/http/http_response_headers.h" | |
33 #include "net/http/http_stream_factory.h" | |
34 #include "net/http/http_transaction_factory.h" | |
35 #include "net/http/http_util.h" | |
36 #include "net/socket/client_socket_factory.h" | |
37 #include "net/socket/client_socket_handle.h" | |
38 #include "net/socket/socks5_client_socket.h" | |
39 #include "net/socket/socks_client_socket.h" | |
40 #include "net/socket/ssl_client_socket.h" | |
41 #include "net/socket/tcp_client_socket.h" | |
42 #include "net/socket_stream/socket_stream_metrics.h" | |
43 #include "net/ssl/ssl_cert_request_info.h" | |
44 #include "net/ssl/ssl_info.h" | |
45 #include "net/url_request/url_request.h" | |
46 #include "net/url_request/url_request_context.h" | |
47 | |
48 static const int kMaxPendingSendAllowed = 32768; // 32 kilobytes. | |
49 static const int kReadBufferSize = 4096; | |
50 | |
51 namespace net { | |
52 | |
53 int SocketStream::Delegate::OnStartOpenConnection( | |
54 SocketStream* socket, const CompletionCallback& callback) { | |
55 return OK; | |
56 } | |
57 | |
58 void SocketStream::Delegate::OnAuthRequired(SocketStream* socket, | |
59 AuthChallengeInfo* auth_info) { | |
60 // By default, no credential is available and close the connection. | |
61 socket->Close(); | |
62 } | |
63 | |
64 void SocketStream::Delegate::OnSSLCertificateError( | |
65 SocketStream* socket, | |
66 const SSLInfo& ssl_info, | |
67 bool fatal) { | |
68 socket->CancelWithSSLError(ssl_info); | |
69 } | |
70 | |
71 bool SocketStream::Delegate::CanGetCookies(SocketStream* socket, | |
72 const GURL& url) { | |
73 return true; | |
74 } | |
75 | |
76 bool SocketStream::Delegate::CanSetCookie(SocketStream* request, | |
77 const GURL& url, | |
78 const std::string& cookie_line, | |
79 CookieOptions* options) { | |
80 return true; | |
81 } | |
82 | |
83 SocketStream::ResponseHeaders::ResponseHeaders() : IOBuffer() {} | |
84 | |
85 void SocketStream::ResponseHeaders::Realloc(size_t new_size) { | |
86 headers_.reset(static_cast<char*>(realloc(headers_.release(), new_size))); | |
87 } | |
88 | |
89 SocketStream::ResponseHeaders::~ResponseHeaders() { data_ = NULL; } | |
90 | |
91 SocketStream::SocketStream(const GURL& url, Delegate* delegate, | |
92 URLRequestContext* context, | |
93 CookieStore* cookie_store) | |
94 : delegate_(delegate), | |
95 url_(url), | |
96 max_pending_send_allowed_(kMaxPendingSendAllowed), | |
97 context_(context), | |
98 next_state_(STATE_NONE), | |
99 factory_(ClientSocketFactory::GetDefaultFactory()), | |
100 proxy_mode_(kDirectConnection), | |
101 proxy_url_(url), | |
102 pac_request_(NULL), | |
103 connection_(new ClientSocketHandle), | |
104 privacy_mode_(PRIVACY_MODE_DISABLED), | |
105 // Unretained() is required; without it, Bind() creates a circular | |
106 // dependency and the SocketStream object will not be freed. | |
107 io_callback_(base::Bind(&SocketStream::OnIOCompleted, | |
108 base::Unretained(this))), | |
109 read_buf_(NULL), | |
110 current_write_buf_(NULL), | |
111 waiting_for_write_completion_(false), | |
112 closing_(false), | |
113 server_closed_(false), | |
114 metrics_(new SocketStreamMetrics(url)), | |
115 cookie_store_(cookie_store) { | |
116 DCHECK(base::MessageLoop::current()) | |
117 << "The current base::MessageLoop must exist"; | |
118 DCHECK(base::MessageLoopForIO::IsCurrent()) | |
119 << "The current base::MessageLoop must be TYPE_IO"; | |
120 DCHECK(delegate_); | |
121 | |
122 if (context_) { | |
123 if (!cookie_store_.get()) | |
124 cookie_store_ = context_->cookie_store(); | |
125 | |
126 net_log_ = BoundNetLog::Make( | |
127 context->net_log(), | |
128 NetLog::SOURCE_SOCKET_STREAM); | |
129 | |
130 net_log_.BeginEvent(NetLog::TYPE_REQUEST_ALIVE); | |
131 } | |
132 } | |
133 | |
134 SocketStream::UserData* SocketStream::GetUserData( | |
135 const void* key) const { | |
136 UserDataMap::const_iterator found = user_data_.find(key); | |
137 if (found != user_data_.end()) | |
138 return found->second.get(); | |
139 return NULL; | |
140 } | |
141 | |
142 void SocketStream::SetUserData(const void* key, UserData* data) { | |
143 user_data_[key] = linked_ptr<UserData>(data); | |
144 } | |
145 | |
146 bool SocketStream::is_secure() const { | |
147 return url_.SchemeIs("wss"); | |
148 } | |
149 | |
150 void SocketStream::DetachContext() { | |
151 if (!context_) | |
152 return; | |
153 | |
154 if (pac_request_) { | |
155 context_->proxy_service()->CancelPacRequest(pac_request_); | |
156 pac_request_ = NULL; | |
157 } | |
158 | |
159 net_log_.EndEvent(NetLog::TYPE_REQUEST_ALIVE); | |
160 net_log_ = BoundNetLog(); | |
161 | |
162 context_ = NULL; | |
163 cookie_store_ = NULL; | |
164 } | |
165 | |
166 void SocketStream::CheckPrivacyMode() { | |
167 if (context_ && context_->network_delegate()) { | |
168 bool enable = context_->network_delegate()->CanEnablePrivacyMode(url_, | |
169 url_); | |
170 privacy_mode_ = enable ? PRIVACY_MODE_ENABLED : PRIVACY_MODE_DISABLED; | |
171 // Disable Channel ID if privacy mode is enabled. | |
172 if (enable) | |
173 server_ssl_config_.channel_id_enabled = false; | |
174 } | |
175 } | |
176 | |
177 void SocketStream::Connect() { | |
178 DCHECK(base::MessageLoop::current()) | |
179 << "The current base::MessageLoop must exist"; | |
180 DCHECK(base::MessageLoopForIO::IsCurrent()) | |
181 << "The current base::MessageLoop must be TYPE_IO"; | |
182 if (context_) { | |
183 context_->ssl_config_service()->GetSSLConfig(&server_ssl_config_); | |
184 proxy_ssl_config_ = server_ssl_config_; | |
185 } | |
186 CheckPrivacyMode(); | |
187 | |
188 DCHECK_EQ(next_state_, STATE_NONE); | |
189 | |
190 AddRef(); // Released in Finish() | |
191 // Open a connection asynchronously, so that delegate won't be called | |
192 // back before returning Connect(). | |
193 next_state_ = STATE_BEFORE_CONNECT; | |
194 net_log_.BeginEvent( | |
195 NetLog::TYPE_SOCKET_STREAM_CONNECT, | |
196 NetLog::StringCallback("url", &url_.possibly_invalid_spec())); | |
197 base::MessageLoop::current()->PostTask( | |
198 FROM_HERE, base::Bind(&SocketStream::DoLoop, this, OK)); | |
199 } | |
200 | |
201 size_t SocketStream::GetTotalSizeOfPendingWriteBufs() const { | |
202 size_t total_size = 0; | |
203 for (PendingDataQueue::const_iterator iter = pending_write_bufs_.begin(); | |
204 iter != pending_write_bufs_.end(); | |
205 ++iter) | |
206 total_size += (*iter)->size(); | |
207 return total_size; | |
208 } | |
209 | |
210 bool SocketStream::SendData(const char* data, int len) { | |
211 DCHECK(base::MessageLoop::current()) | |
212 << "The current base::MessageLoop must exist"; | |
213 DCHECK(base::MessageLoopForIO::IsCurrent()) | |
214 << "The current base::MessageLoop must be TYPE_IO"; | |
215 DCHECK_GT(len, 0); | |
216 | |
217 if (!connection_->socket() || | |
218 !connection_->socket()->IsConnected() || next_state_ == STATE_NONE) { | |
219 return false; | |
220 } | |
221 | |
222 int total_buffered_bytes = len; | |
223 if (current_write_buf_.get()) { | |
224 // Since | |
225 // - the purpose of this check is to limit the amount of buffer used by | |
226 // this instance. | |
227 // - the DrainableIOBuffer doesn't release consumed memory. | |
228 // we need to use not BytesRemaining() but size() here. | |
229 total_buffered_bytes += current_write_buf_->size(); | |
230 } | |
231 total_buffered_bytes += GetTotalSizeOfPendingWriteBufs(); | |
232 if (total_buffered_bytes > max_pending_send_allowed_) | |
233 return false; | |
234 | |
235 // TODO(tyoshino): Split data into smaller chunks e.g. 8KiB to free consumed | |
236 // buffer progressively | |
237 pending_write_bufs_.push_back(make_scoped_refptr( | |
238 new IOBufferWithSize(len))); | |
239 memcpy(pending_write_bufs_.back()->data(), data, len); | |
240 | |
241 // If current_write_buf_ is not NULL, it means that a) there's ongoing write | |
242 // operation or b) the connection is being closed. If a), the buffer we just | |
243 // pushed will be automatically handled when the completion callback runs | |
244 // the loop, and therefore we don't need to enqueue DoLoop(). If b), it's ok | |
245 // to do nothing. If current_write_buf_ is NULL, to make sure DoLoop() is | |
246 // ran soon, enequeue it. | |
247 if (!current_write_buf_.get()) { | |
248 // Send pending data asynchronously, so that delegate won't be called | |
249 // back before returning from SendData(). | |
250 base::MessageLoop::current()->PostTask( | |
251 FROM_HERE, base::Bind(&SocketStream::DoLoop, this, OK)); | |
252 } | |
253 | |
254 return true; | |
255 } | |
256 | |
257 void SocketStream::Close() { | |
258 DCHECK(base::MessageLoop::current()) | |
259 << "The current base::MessageLoop must exist"; | |
260 DCHECK(base::MessageLoopForIO::IsCurrent()) | |
261 << "The current base::MessageLoop must be TYPE_IO"; | |
262 // If next_state_ is STATE_NONE, the socket was not opened, or already | |
263 // closed. So, return immediately. | |
264 // Otherwise, it might call Finish() more than once, so breaks balance | |
265 // of AddRef() and Release() in Connect() and Finish(), respectively. | |
266 if (next_state_ == STATE_NONE) | |
267 return; | |
268 base::MessageLoop::current()->PostTask( | |
269 FROM_HERE, base::Bind(&SocketStream::DoClose, this)); | |
270 } | |
271 | |
272 void SocketStream::RestartWithAuth(const AuthCredentials& credentials) { | |
273 DCHECK(base::MessageLoop::current()) | |
274 << "The current base::MessageLoop must exist"; | |
275 DCHECK(base::MessageLoopForIO::IsCurrent()) | |
276 << "The current base::MessageLoop must be TYPE_IO"; | |
277 DCHECK(proxy_auth_controller_.get()); | |
278 if (!connection_->socket()) { | |
279 DVLOG(1) << "Socket is closed before restarting with auth."; | |
280 return; | |
281 } | |
282 | |
283 proxy_auth_controller_->ResetAuth(credentials); | |
284 | |
285 base::MessageLoop::current()->PostTask( | |
286 FROM_HERE, base::Bind(&SocketStream::DoRestartWithAuth, this)); | |
287 } | |
288 | |
289 void SocketStream::DetachDelegate() { | |
290 if (!delegate_) | |
291 return; | |
292 delegate_ = NULL; | |
293 // Prevent the rest of the function from executing if we are being called from | |
294 // within Finish(). | |
295 if (next_state_ == STATE_NONE) | |
296 return; | |
297 net_log_.AddEvent(NetLog::TYPE_CANCELLED); | |
298 // We don't need to send pending data when client detach the delegate. | |
299 pending_write_bufs_.clear(); | |
300 Close(); | |
301 } | |
302 | |
303 const ProxyServer& SocketStream::proxy_server() const { | |
304 return proxy_info_.proxy_server(); | |
305 } | |
306 | |
307 void SocketStream::SetClientSocketFactory( | |
308 ClientSocketFactory* factory) { | |
309 DCHECK(factory); | |
310 factory_ = factory; | |
311 } | |
312 | |
313 void SocketStream::CancelWithError(int error) { | |
314 base::MessageLoop::current()->PostTask( | |
315 FROM_HERE, base::Bind(&SocketStream::DoLoop, this, error)); | |
316 } | |
317 | |
318 void SocketStream::CancelWithSSLError(const SSLInfo& ssl_info) { | |
319 CancelWithError(MapCertStatusToNetError(ssl_info.cert_status)); | |
320 } | |
321 | |
322 void SocketStream::ContinueDespiteError() { | |
323 base::MessageLoop::current()->PostTask( | |
324 FROM_HERE, base::Bind(&SocketStream::DoLoop, this, OK)); | |
325 } | |
326 | |
327 SocketStream::~SocketStream() { | |
328 DetachContext(); | |
329 DCHECK(!delegate_); | |
330 DCHECK(!pac_request_); | |
331 } | |
332 | |
333 SocketStream::RequestHeaders::~RequestHeaders() { data_ = NULL; } | |
334 | |
335 void SocketStream::set_addresses(const AddressList& addresses) { | |
336 addresses_ = addresses; | |
337 } | |
338 | |
339 void SocketStream::DoClose() { | |
340 closing_ = true; | |
341 // If next_state_ is: | |
342 // - STATE_TCP_CONNECT_COMPLETE, it's waiting other socket establishing | |
343 // connection. | |
344 // - STATE_AUTH_REQUIRED, it's waiting for restarting. | |
345 // - STATE_RESOLVE_PROTOCOL_COMPLETE, it's waiting for delegate_ to finish | |
346 // OnStartOpenConnection method call | |
347 // In these states, we'll close the SocketStream now. | |
348 if (next_state_ == STATE_TCP_CONNECT_COMPLETE || | |
349 next_state_ == STATE_AUTH_REQUIRED || | |
350 next_state_ == STATE_RESOLVE_PROTOCOL_COMPLETE) { | |
351 DoLoop(ERR_ABORTED); | |
352 return; | |
353 } | |
354 // If next_state_ is STATE_READ_WRITE, we'll run DoLoop and close | |
355 // the SocketStream. | |
356 // If it's writing now, we should defer the closing after the current | |
357 // writing is completed. | |
358 if (next_state_ == STATE_READ_WRITE && !current_write_buf_.get()) | |
359 DoLoop(ERR_ABORTED); | |
360 | |
361 // In other next_state_, we'll wait for callback of other APIs, such as | |
362 // ResolveProxy(). | |
363 } | |
364 | |
365 void SocketStream::Finish(int result) { | |
366 DCHECK(base::MessageLoop::current()) | |
367 << "The current base::MessageLoop must exist"; | |
368 DCHECK(base::MessageLoopForIO::IsCurrent()) | |
369 << "The current base::MessageLoop must be TYPE_IO"; | |
370 DCHECK_LE(result, OK); | |
371 if (result == OK) | |
372 result = ERR_CONNECTION_CLOSED; | |
373 DCHECK_EQ(next_state_, STATE_NONE); | |
374 DVLOG(1) << "Finish result=" << ErrorToString(result); | |
375 | |
376 metrics_->OnClose(); | |
377 | |
378 if (result != ERR_CONNECTION_CLOSED && delegate_) | |
379 delegate_->OnError(this, result); | |
380 if (result != ERR_PROTOCOL_SWITCHED && delegate_) | |
381 delegate_->OnClose(this); | |
382 delegate_ = NULL; | |
383 | |
384 Release(); | |
385 } | |
386 | |
387 int SocketStream::DidEstablishConnection() { | |
388 if (!connection_->socket() || !connection_->socket()->IsConnected()) { | |
389 next_state_ = STATE_CLOSE; | |
390 return ERR_CONNECTION_FAILED; | |
391 } | |
392 next_state_ = STATE_READ_WRITE; | |
393 metrics_->OnConnected(); | |
394 | |
395 net_log_.EndEvent(NetLog::TYPE_SOCKET_STREAM_CONNECT); | |
396 if (delegate_) | |
397 delegate_->OnConnected(this, max_pending_send_allowed_); | |
398 | |
399 return OK; | |
400 } | |
401 | |
402 int SocketStream::DidReceiveData(int result) { | |
403 DCHECK(read_buf_.get()); | |
404 DCHECK_GT(result, 0); | |
405 net_log_.AddEvent(NetLog::TYPE_SOCKET_STREAM_RECEIVED); | |
406 int len = result; | |
407 metrics_->OnRead(len); | |
408 if (delegate_) { | |
409 // Notify recevied data to delegate. | |
410 delegate_->OnReceivedData(this, read_buf_->data(), len); | |
411 } | |
412 read_buf_ = NULL; | |
413 return OK; | |
414 } | |
415 | |
416 void SocketStream::DidSendData(int result) { | |
417 DCHECK_GT(result, 0); | |
418 DCHECK(current_write_buf_.get()); | |
419 net_log_.AddEvent(NetLog::TYPE_SOCKET_STREAM_SENT); | |
420 | |
421 int bytes_sent = result; | |
422 | |
423 metrics_->OnWrite(bytes_sent); | |
424 | |
425 current_write_buf_->DidConsume(result); | |
426 | |
427 if (current_write_buf_->BytesRemaining()) | |
428 return; | |
429 | |
430 size_t bytes_freed = current_write_buf_->size(); | |
431 | |
432 current_write_buf_ = NULL; | |
433 | |
434 // We freed current_write_buf_ and this instance is now able to accept more | |
435 // data via SendData() (note that DidConsume() doesn't free consumed memory). | |
436 // We can tell that to delegate_ by calling OnSentData(). | |
437 if (delegate_) | |
438 delegate_->OnSentData(this, bytes_freed); | |
439 } | |
440 | |
441 void SocketStream::OnIOCompleted(int result) { | |
442 DoLoop(result); | |
443 } | |
444 | |
445 void SocketStream::OnReadCompleted(int result) { | |
446 if (result == 0) { | |
447 // 0 indicates end-of-file, so socket was closed. | |
448 // Don't close the socket if it's still writing. | |
449 server_closed_ = true; | |
450 } else if (result > 0 && read_buf_.get()) { | |
451 result = DidReceiveData(result); | |
452 } | |
453 DoLoop(result); | |
454 } | |
455 | |
456 void SocketStream::OnWriteCompleted(int result) { | |
457 waiting_for_write_completion_ = false; | |
458 if (result > 0) { | |
459 DidSendData(result); | |
460 result = OK; | |
461 } | |
462 DoLoop(result); | |
463 } | |
464 | |
465 void SocketStream::DoLoop(int result) { | |
466 if (next_state_ == STATE_NONE) | |
467 return; | |
468 | |
469 // If context was not set, close immediately. | |
470 if (!context_) | |
471 next_state_ = STATE_CLOSE; | |
472 | |
473 do { | |
474 State state = next_state_; | |
475 next_state_ = STATE_NONE; | |
476 switch (state) { | |
477 case STATE_BEFORE_CONNECT: | |
478 DCHECK_EQ(OK, result); | |
479 result = DoBeforeConnect(); | |
480 break; | |
481 case STATE_BEFORE_CONNECT_COMPLETE: | |
482 result = DoBeforeConnectComplete(result); | |
483 break; | |
484 case STATE_RESOLVE_PROXY: | |
485 DCHECK_EQ(OK, result); | |
486 result = DoResolveProxy(); | |
487 break; | |
488 case STATE_RESOLVE_PROXY_COMPLETE: | |
489 result = DoResolveProxyComplete(result); | |
490 break; | |
491 case STATE_RESOLVE_HOST: | |
492 DCHECK_EQ(OK, result); | |
493 result = DoResolveHost(); | |
494 break; | |
495 case STATE_RESOLVE_HOST_COMPLETE: | |
496 result = DoResolveHostComplete(result); | |
497 break; | |
498 case STATE_RESOLVE_PROTOCOL: | |
499 result = DoResolveProtocol(result); | |
500 break; | |
501 case STATE_RESOLVE_PROTOCOL_COMPLETE: | |
502 result = DoResolveProtocolComplete(result); | |
503 break; | |
504 case STATE_TCP_CONNECT: | |
505 result = DoTcpConnect(result); | |
506 break; | |
507 case STATE_TCP_CONNECT_COMPLETE: | |
508 result = DoTcpConnectComplete(result); | |
509 break; | |
510 case STATE_GENERATE_PROXY_AUTH_TOKEN: | |
511 result = DoGenerateProxyAuthToken(); | |
512 break; | |
513 case STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE: | |
514 result = DoGenerateProxyAuthTokenComplete(result); | |
515 break; | |
516 case STATE_WRITE_TUNNEL_HEADERS: | |
517 DCHECK_EQ(OK, result); | |
518 result = DoWriteTunnelHeaders(); | |
519 break; | |
520 case STATE_WRITE_TUNNEL_HEADERS_COMPLETE: | |
521 result = DoWriteTunnelHeadersComplete(result); | |
522 break; | |
523 case STATE_READ_TUNNEL_HEADERS: | |
524 DCHECK_EQ(OK, result); | |
525 result = DoReadTunnelHeaders(); | |
526 break; | |
527 case STATE_READ_TUNNEL_HEADERS_COMPLETE: | |
528 result = DoReadTunnelHeadersComplete(result); | |
529 break; | |
530 case STATE_SOCKS_CONNECT: | |
531 DCHECK_EQ(OK, result); | |
532 result = DoSOCKSConnect(); | |
533 break; | |
534 case STATE_SOCKS_CONNECT_COMPLETE: | |
535 result = DoSOCKSConnectComplete(result); | |
536 break; | |
537 case STATE_SECURE_PROXY_CONNECT: | |
538 DCHECK_EQ(OK, result); | |
539 result = DoSecureProxyConnect(); | |
540 break; | |
541 case STATE_SECURE_PROXY_CONNECT_COMPLETE: | |
542 result = DoSecureProxyConnectComplete(result); | |
543 break; | |
544 case STATE_SECURE_PROXY_HANDLE_CERT_ERROR: | |
545 result = DoSecureProxyHandleCertError(result); | |
546 break; | |
547 case STATE_SECURE_PROXY_HANDLE_CERT_ERROR_COMPLETE: | |
548 result = DoSecureProxyHandleCertErrorComplete(result); | |
549 break; | |
550 case STATE_SSL_CONNECT: | |
551 DCHECK_EQ(OK, result); | |
552 result = DoSSLConnect(); | |
553 break; | |
554 case STATE_SSL_CONNECT_COMPLETE: | |
555 result = DoSSLConnectComplete(result); | |
556 break; | |
557 case STATE_SSL_HANDLE_CERT_ERROR: | |
558 result = DoSSLHandleCertError(result); | |
559 break; | |
560 case STATE_SSL_HANDLE_CERT_ERROR_COMPLETE: | |
561 result = DoSSLHandleCertErrorComplete(result); | |
562 break; | |
563 case STATE_READ_WRITE: | |
564 result = DoReadWrite(result); | |
565 break; | |
566 case STATE_AUTH_REQUIRED: | |
567 // It might be called when DoClose is called while waiting in | |
568 // STATE_AUTH_REQUIRED. | |
569 Finish(result); | |
570 return; | |
571 case STATE_CLOSE: | |
572 DCHECK_LE(result, OK); | |
573 Finish(result); | |
574 return; | |
575 default: | |
576 NOTREACHED() << "bad state " << state; | |
577 Finish(result); | |
578 return; | |
579 } | |
580 if (state == STATE_RESOLVE_PROTOCOL && result == ERR_PROTOCOL_SWITCHED) | |
581 continue; | |
582 // If the connection is not established yet and had actual errors, | |
583 // record the error. In next iteration, it will close the connection. | |
584 if (state != STATE_READ_WRITE && result < ERR_IO_PENDING) { | |
585 net_log_.EndEventWithNetErrorCode( | |
586 NetLog::TYPE_SOCKET_STREAM_CONNECT, result); | |
587 } | |
588 } while (result != ERR_IO_PENDING); | |
589 } | |
590 | |
591 int SocketStream::DoBeforeConnect() { | |
592 next_state_ = STATE_BEFORE_CONNECT_COMPLETE; | |
593 if (!context_ || !context_->network_delegate()) | |
594 return OK; | |
595 | |
596 int result = context_->network_delegate()->NotifyBeforeSocketStreamConnect( | |
597 this, io_callback_); | |
598 if (result != OK && result != ERR_IO_PENDING) | |
599 next_state_ = STATE_CLOSE; | |
600 | |
601 return result; | |
602 } | |
603 | |
604 int SocketStream::DoBeforeConnectComplete(int result) { | |
605 DCHECK_NE(ERR_IO_PENDING, result); | |
606 | |
607 if (result == OK) | |
608 next_state_ = STATE_RESOLVE_PROXY; | |
609 else | |
610 next_state_ = STATE_CLOSE; | |
611 | |
612 return result; | |
613 } | |
614 | |
615 int SocketStream::DoResolveProxy() { | |
616 DCHECK(context_); | |
617 DCHECK(!pac_request_); | |
618 next_state_ = STATE_RESOLVE_PROXY_COMPLETE; | |
619 | |
620 if (!proxy_url_.is_valid()) { | |
621 next_state_ = STATE_CLOSE; | |
622 return ERR_INVALID_ARGUMENT; | |
623 } | |
624 | |
625 // TODO(toyoshim): Check server advertisement of SPDY through the HTTP | |
626 // Alternate-Protocol header, then switch to SPDY if SPDY is available. | |
627 // Usually we already have a session to the SPDY server because JavaScript | |
628 // running WebSocket itself would be served by SPDY. But, in some situation | |
629 // (E.g. Used by Chrome Extensions or used for cross origin connection), this | |
630 // connection might be the first one. At that time, we should check | |
631 // Alternate-Protocol header here for ws:// or TLS NPN extension for wss:// . | |
632 | |
633 return context_->proxy_service()->ResolveProxy( | |
634 proxy_url_, net::LOAD_NORMAL, &proxy_info_, io_callback_, &pac_request_, | |
635 NULL, net_log_); | |
636 } | |
637 | |
638 int SocketStream::DoResolveProxyComplete(int result) { | |
639 pac_request_ = NULL; | |
640 if (result != OK) { | |
641 DVLOG(1) << "Failed to resolve proxy: " << result; | |
642 if (delegate_) | |
643 delegate_->OnError(this, result); | |
644 proxy_info_.UseDirect(); | |
645 } | |
646 if (proxy_info_.is_direct()) { | |
647 // If proxy was not found for original URL (i.e. websocket URL), | |
648 // try again with https URL, like Safari implementation. | |
649 // Note that we don't want to use http proxy, because we'll use tunnel | |
650 // proxy using CONNECT method, which is used by https proxy. | |
651 if (!proxy_url_.SchemeIs("https")) { | |
652 const std::string scheme = "https"; | |
653 GURL::Replacements repl; | |
654 repl.SetSchemeStr(scheme); | |
655 proxy_url_ = url_.ReplaceComponents(repl); | |
656 DVLOG(1) << "Try https proxy: " << proxy_url_; | |
657 next_state_ = STATE_RESOLVE_PROXY; | |
658 return OK; | |
659 } | |
660 } | |
661 | |
662 if (proxy_info_.is_empty()) { | |
663 // No proxies/direct to choose from. This happens when we don't support any | |
664 // of the proxies in the returned list. | |
665 return ERR_NO_SUPPORTED_PROXIES; | |
666 } | |
667 | |
668 next_state_ = STATE_RESOLVE_HOST; | |
669 return OK; | |
670 } | |
671 | |
672 int SocketStream::DoResolveHost() { | |
673 next_state_ = STATE_RESOLVE_HOST_COMPLETE; | |
674 | |
675 DCHECK(!proxy_info_.is_empty()); | |
676 if (proxy_info_.is_direct()) | |
677 proxy_mode_ = kDirectConnection; | |
678 else if (proxy_info_.proxy_server().is_socks()) | |
679 proxy_mode_ = kSOCKSProxy; | |
680 else | |
681 proxy_mode_ = kTunnelProxy; | |
682 | |
683 // Determine the host and port to connect to. | |
684 HostPortPair host_port_pair; | |
685 if (proxy_mode_ != kDirectConnection) { | |
686 host_port_pair = proxy_info_.proxy_server().host_port_pair(); | |
687 } else { | |
688 host_port_pair = HostPortPair::FromURL(url_); | |
689 } | |
690 | |
691 HostResolver::RequestInfo resolve_info(host_port_pair); | |
692 | |
693 DCHECK(context_->host_resolver()); | |
694 resolver_.reset(new SingleRequestHostResolver(context_->host_resolver())); | |
695 return resolver_->Resolve(resolve_info, | |
696 DEFAULT_PRIORITY, | |
697 &addresses_, | |
698 base::Bind(&SocketStream::OnIOCompleted, this), | |
699 net_log_); | |
700 } | |
701 | |
702 int SocketStream::DoResolveHostComplete(int result) { | |
703 if (result == OK) | |
704 next_state_ = STATE_RESOLVE_PROTOCOL; | |
705 else | |
706 next_state_ = STATE_CLOSE; | |
707 // TODO(ukai): if error occured, reconsider proxy after error. | |
708 return result; | |
709 } | |
710 | |
711 int SocketStream::DoResolveProtocol(int result) { | |
712 DCHECK_EQ(OK, result); | |
713 | |
714 if (!delegate_) { | |
715 next_state_ = STATE_CLOSE; | |
716 return result; | |
717 } | |
718 | |
719 next_state_ = STATE_RESOLVE_PROTOCOL_COMPLETE; | |
720 result = delegate_->OnStartOpenConnection(this, io_callback_); | |
721 if (result == ERR_IO_PENDING) | |
722 metrics_->OnWaitConnection(); | |
723 else if (result != OK && result != ERR_PROTOCOL_SWITCHED) | |
724 next_state_ = STATE_CLOSE; | |
725 return result; | |
726 } | |
727 | |
728 int SocketStream::DoResolveProtocolComplete(int result) { | |
729 DCHECK_NE(ERR_IO_PENDING, result); | |
730 | |
731 if (result == ERR_PROTOCOL_SWITCHED) { | |
732 next_state_ = STATE_CLOSE; | |
733 metrics_->OnCountWireProtocolType( | |
734 SocketStreamMetrics::WIRE_PROTOCOL_SPDY); | |
735 } else if (result == OK) { | |
736 next_state_ = STATE_TCP_CONNECT; | |
737 metrics_->OnCountWireProtocolType( | |
738 SocketStreamMetrics::WIRE_PROTOCOL_WEBSOCKET); | |
739 } else { | |
740 next_state_ = STATE_CLOSE; | |
741 } | |
742 return result; | |
743 } | |
744 | |
745 int SocketStream::DoTcpConnect(int result) { | |
746 if (result != OK) { | |
747 next_state_ = STATE_CLOSE; | |
748 return result; | |
749 } | |
750 next_state_ = STATE_TCP_CONNECT_COMPLETE; | |
751 DCHECK(factory_); | |
752 connection_->SetSocket( | |
753 factory_->CreateTransportClientSocket(addresses_, | |
754 net_log_.net_log(), | |
755 net_log_.source())); | |
756 metrics_->OnStartConnection(); | |
757 return connection_->socket()->Connect(io_callback_); | |
758 } | |
759 | |
760 int SocketStream::DoTcpConnectComplete(int result) { | |
761 // TODO(ukai): if error occured, reconsider proxy after error. | |
762 if (result != OK) { | |
763 next_state_ = STATE_CLOSE; | |
764 return result; | |
765 } | |
766 | |
767 if (proxy_mode_ == kTunnelProxy) { | |
768 if (proxy_info_.is_https()) | |
769 next_state_ = STATE_SECURE_PROXY_CONNECT; | |
770 else | |
771 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN; | |
772 } else if (proxy_mode_ == kSOCKSProxy) { | |
773 next_state_ = STATE_SOCKS_CONNECT; | |
774 } else if (is_secure()) { | |
775 next_state_ = STATE_SSL_CONNECT; | |
776 } else { | |
777 result = DidEstablishConnection(); | |
778 } | |
779 return result; | |
780 } | |
781 | |
782 int SocketStream::DoGenerateProxyAuthToken() { | |
783 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE; | |
784 if (!proxy_auth_controller_.get()) { | |
785 DCHECK(context_); | |
786 DCHECK(context_->http_transaction_factory()); | |
787 DCHECK(context_->http_transaction_factory()->GetSession()); | |
788 HttpNetworkSession* session = | |
789 context_->http_transaction_factory()->GetSession(); | |
790 const char* scheme = proxy_info_.is_https() ? "https://" : "http://"; | |
791 GURL auth_url(scheme + | |
792 proxy_info_.proxy_server().host_port_pair().ToString()); | |
793 proxy_auth_controller_ = | |
794 new HttpAuthController(HttpAuth::AUTH_PROXY, | |
795 auth_url, | |
796 session->http_auth_cache(), | |
797 session->http_auth_handler_factory()); | |
798 } | |
799 HttpRequestInfo request_info; | |
800 request_info.url = url_; | |
801 request_info.method = "CONNECT"; | |
802 return proxy_auth_controller_->MaybeGenerateAuthToken( | |
803 &request_info, io_callback_, net_log_); | |
804 } | |
805 | |
806 int SocketStream::DoGenerateProxyAuthTokenComplete(int result) { | |
807 if (result != OK) { | |
808 next_state_ = STATE_CLOSE; | |
809 return result; | |
810 } | |
811 | |
812 next_state_ = STATE_WRITE_TUNNEL_HEADERS; | |
813 return result; | |
814 } | |
815 | |
816 int SocketStream::DoWriteTunnelHeaders() { | |
817 DCHECK_EQ(kTunnelProxy, proxy_mode_); | |
818 | |
819 next_state_ = STATE_WRITE_TUNNEL_HEADERS_COMPLETE; | |
820 | |
821 if (!tunnel_request_headers_.get()) { | |
822 metrics_->OnCountConnectionType(SocketStreamMetrics::TUNNEL_CONNECTION); | |
823 tunnel_request_headers_ = new RequestHeaders(); | |
824 tunnel_request_headers_bytes_sent_ = 0; | |
825 } | |
826 if (tunnel_request_headers_->headers_.empty()) { | |
827 HttpRequestHeaders request_headers; | |
828 request_headers.SetHeader("Host", GetHostAndOptionalPort(url_)); | |
829 request_headers.SetHeader("Proxy-Connection", "keep-alive"); | |
830 if (proxy_auth_controller_.get() && proxy_auth_controller_->HaveAuth()) | |
831 proxy_auth_controller_->AddAuthorizationHeader(&request_headers); | |
832 tunnel_request_headers_->headers_ = base::StringPrintf( | |
833 "CONNECT %s HTTP/1.1\r\n" | |
834 "%s", | |
835 GetHostAndPort(url_).c_str(), | |
836 request_headers.ToString().c_str()); | |
837 } | |
838 tunnel_request_headers_->SetDataOffset(tunnel_request_headers_bytes_sent_); | |
839 int buf_len = static_cast<int>(tunnel_request_headers_->headers_.size() - | |
840 tunnel_request_headers_bytes_sent_); | |
841 DCHECK_GT(buf_len, 0); | |
842 return connection_->socket()->Write( | |
843 tunnel_request_headers_.get(), buf_len, io_callback_); | |
844 } | |
845 | |
846 int SocketStream::DoWriteTunnelHeadersComplete(int result) { | |
847 DCHECK_EQ(kTunnelProxy, proxy_mode_); | |
848 | |
849 if (result < 0) { | |
850 next_state_ = STATE_CLOSE; | |
851 return result; | |
852 } | |
853 | |
854 tunnel_request_headers_bytes_sent_ += result; | |
855 if (tunnel_request_headers_bytes_sent_ < | |
856 tunnel_request_headers_->headers_.size()) { | |
857 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN; | |
858 } else { | |
859 // Handling a cert error or a client cert request requires reconnection. | |
860 // DoWriteTunnelHeaders() will be called again. | |
861 // Thus |tunnel_request_headers_bytes_sent_| should be reset to 0 for | |
862 // sending |tunnel_request_headers_| correctly. | |
863 tunnel_request_headers_bytes_sent_ = 0; | |
864 next_state_ = STATE_READ_TUNNEL_HEADERS; | |
865 } | |
866 return OK; | |
867 } | |
868 | |
869 int SocketStream::DoReadTunnelHeaders() { | |
870 DCHECK_EQ(kTunnelProxy, proxy_mode_); | |
871 | |
872 next_state_ = STATE_READ_TUNNEL_HEADERS_COMPLETE; | |
873 | |
874 if (!tunnel_response_headers_.get()) { | |
875 tunnel_response_headers_ = new ResponseHeaders(); | |
876 tunnel_response_headers_capacity_ = kMaxTunnelResponseHeadersSize; | |
877 tunnel_response_headers_->Realloc(tunnel_response_headers_capacity_); | |
878 tunnel_response_headers_len_ = 0; | |
879 } | |
880 | |
881 int buf_len = tunnel_response_headers_capacity_ - | |
882 tunnel_response_headers_len_; | |
883 tunnel_response_headers_->SetDataOffset(tunnel_response_headers_len_); | |
884 CHECK(tunnel_response_headers_->data()); | |
885 | |
886 return connection_->socket()->Read( | |
887 tunnel_response_headers_.get(), buf_len, io_callback_); | |
888 } | |
889 | |
890 int SocketStream::DoReadTunnelHeadersComplete(int result) { | |
891 DCHECK_EQ(kTunnelProxy, proxy_mode_); | |
892 | |
893 if (result < 0) { | |
894 next_state_ = STATE_CLOSE; | |
895 return result; | |
896 } | |
897 | |
898 if (result == 0) { | |
899 // 0 indicates end-of-file, so socket was closed. | |
900 next_state_ = STATE_CLOSE; | |
901 return ERR_CONNECTION_CLOSED; | |
902 } | |
903 | |
904 tunnel_response_headers_len_ += result; | |
905 DCHECK(tunnel_response_headers_len_ <= tunnel_response_headers_capacity_); | |
906 | |
907 int eoh = HttpUtil::LocateEndOfHeaders( | |
908 tunnel_response_headers_->headers(), tunnel_response_headers_len_, 0); | |
909 if (eoh == -1) { | |
910 if (tunnel_response_headers_len_ >= kMaxTunnelResponseHeadersSize) { | |
911 next_state_ = STATE_CLOSE; | |
912 return ERR_RESPONSE_HEADERS_TOO_BIG; | |
913 } | |
914 | |
915 next_state_ = STATE_READ_TUNNEL_HEADERS; | |
916 return OK; | |
917 } | |
918 // DidReadResponseHeaders | |
919 scoped_refptr<HttpResponseHeaders> headers; | |
920 headers = new HttpResponseHeaders( | |
921 HttpUtil::AssembleRawHeaders(tunnel_response_headers_->headers(), eoh)); | |
922 if (headers->GetParsedHttpVersion() < HttpVersion(1, 0)) { | |
923 // Require the "HTTP/1.x" status line. | |
924 next_state_ = STATE_CLOSE; | |
925 return ERR_TUNNEL_CONNECTION_FAILED; | |
926 } | |
927 switch (headers->response_code()) { | |
928 case 200: // OK | |
929 if (is_secure()) { | |
930 DCHECK_EQ(eoh, tunnel_response_headers_len_); | |
931 next_state_ = STATE_SSL_CONNECT; | |
932 } else { | |
933 result = DidEstablishConnection(); | |
934 if (result < 0) { | |
935 next_state_ = STATE_CLOSE; | |
936 return result; | |
937 } | |
938 if ((eoh < tunnel_response_headers_len_) && delegate_) | |
939 delegate_->OnReceivedData( | |
940 this, tunnel_response_headers_->headers() + eoh, | |
941 tunnel_response_headers_len_ - eoh); | |
942 } | |
943 return OK; | |
944 case 407: // Proxy Authentication Required. | |
945 if (proxy_mode_ != kTunnelProxy) | |
946 return ERR_UNEXPECTED_PROXY_AUTH; | |
947 | |
948 result = proxy_auth_controller_->HandleAuthChallenge( | |
949 headers, false, true, net_log_); | |
950 if (result != OK) | |
951 return result; | |
952 DCHECK(!proxy_info_.is_empty()); | |
953 next_state_ = STATE_AUTH_REQUIRED; | |
954 if (proxy_auth_controller_->HaveAuth()) { | |
955 base::MessageLoop::current()->PostTask( | |
956 FROM_HERE, base::Bind(&SocketStream::DoRestartWithAuth, this)); | |
957 return ERR_IO_PENDING; | |
958 } | |
959 if (delegate_) { | |
960 // Wait until RestartWithAuth or Close is called. | |
961 base::MessageLoop::current()->PostTask( | |
962 FROM_HERE, base::Bind(&SocketStream::DoAuthRequired, this)); | |
963 return ERR_IO_PENDING; | |
964 } | |
965 break; | |
966 default: | |
967 break; | |
968 } | |
969 next_state_ = STATE_CLOSE; | |
970 return ERR_TUNNEL_CONNECTION_FAILED; | |
971 } | |
972 | |
973 int SocketStream::DoSOCKSConnect() { | |
974 DCHECK_EQ(kSOCKSProxy, proxy_mode_); | |
975 | |
976 next_state_ = STATE_SOCKS_CONNECT_COMPLETE; | |
977 | |
978 HostResolver::RequestInfo req_info(HostPortPair::FromURL(url_)); | |
979 | |
980 DCHECK(!proxy_info_.is_empty()); | |
981 scoped_ptr<StreamSocket> s; | |
982 if (proxy_info_.proxy_server().scheme() == ProxyServer::SCHEME_SOCKS5) { | |
983 s.reset(new SOCKS5ClientSocket(connection_.Pass(), req_info)); | |
984 } else { | |
985 s.reset(new SOCKSClientSocket(connection_.Pass(), | |
986 req_info, | |
987 DEFAULT_PRIORITY, | |
988 context_->host_resolver())); | |
989 } | |
990 connection_.reset(new ClientSocketHandle); | |
991 connection_->SetSocket(s.Pass()); | |
992 metrics_->OnCountConnectionType(SocketStreamMetrics::SOCKS_CONNECTION); | |
993 return connection_->socket()->Connect(io_callback_); | |
994 } | |
995 | |
996 int SocketStream::DoSOCKSConnectComplete(int result) { | |
997 DCHECK_EQ(kSOCKSProxy, proxy_mode_); | |
998 | |
999 if (result == OK) { | |
1000 if (is_secure()) | |
1001 next_state_ = STATE_SSL_CONNECT; | |
1002 else | |
1003 result = DidEstablishConnection(); | |
1004 } else { | |
1005 next_state_ = STATE_CLOSE; | |
1006 } | |
1007 return result; | |
1008 } | |
1009 | |
1010 int SocketStream::DoSecureProxyConnect() { | |
1011 DCHECK(factory_); | |
1012 SSLClientSocketContext ssl_context; | |
1013 ssl_context.cert_verifier = context_->cert_verifier(); | |
1014 ssl_context.transport_security_state = context_->transport_security_state(); | |
1015 ssl_context.channel_id_service = context_->channel_id_service(); | |
1016 scoped_ptr<StreamSocket> socket(factory_->CreateSSLClientSocket( | |
1017 connection_.Pass(), | |
1018 proxy_info_.proxy_server().host_port_pair(), | |
1019 proxy_ssl_config_, | |
1020 ssl_context)); | |
1021 connection_.reset(new ClientSocketHandle); | |
1022 connection_->SetSocket(socket.Pass()); | |
1023 next_state_ = STATE_SECURE_PROXY_CONNECT_COMPLETE; | |
1024 metrics_->OnCountConnectionType(SocketStreamMetrics::SECURE_PROXY_CONNECTION); | |
1025 return connection_->socket()->Connect(io_callback_); | |
1026 } | |
1027 | |
1028 int SocketStream::DoSecureProxyConnectComplete(int result) { | |
1029 DCHECK_EQ(STATE_NONE, next_state_); | |
1030 // Reconnect with client authentication. | |
1031 if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) | |
1032 return HandleCertificateRequest(result, &proxy_ssl_config_); | |
1033 | |
1034 if (IsCertificateError(result)) | |
1035 next_state_ = STATE_SECURE_PROXY_HANDLE_CERT_ERROR; | |
1036 else if (result == OK) | |
1037 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN; | |
1038 else | |
1039 next_state_ = STATE_CLOSE; | |
1040 return result; | |
1041 } | |
1042 | |
1043 int SocketStream::DoSecureProxyHandleCertError(int result) { | |
1044 DCHECK_EQ(STATE_NONE, next_state_); | |
1045 DCHECK(IsCertificateError(result)); | |
1046 result = HandleCertificateError(result); | |
1047 if (result == ERR_IO_PENDING) | |
1048 next_state_ = STATE_SECURE_PROXY_HANDLE_CERT_ERROR_COMPLETE; | |
1049 else | |
1050 next_state_ = STATE_CLOSE; | |
1051 return result; | |
1052 } | |
1053 | |
1054 int SocketStream::DoSecureProxyHandleCertErrorComplete(int result) { | |
1055 DCHECK_EQ(STATE_NONE, next_state_); | |
1056 if (result == OK) { | |
1057 if (!connection_->socket()->IsConnectedAndIdle()) | |
1058 return AllowCertErrorForReconnection(&proxy_ssl_config_); | |
1059 next_state_ = STATE_GENERATE_PROXY_AUTH_TOKEN; | |
1060 } else { | |
1061 next_state_ = STATE_CLOSE; | |
1062 } | |
1063 return result; | |
1064 } | |
1065 | |
1066 int SocketStream::DoSSLConnect() { | |
1067 DCHECK(factory_); | |
1068 SSLClientSocketContext ssl_context; | |
1069 ssl_context.cert_verifier = context_->cert_verifier(); | |
1070 ssl_context.transport_security_state = context_->transport_security_state(); | |
1071 ssl_context.channel_id_service = context_->channel_id_service(); | |
1072 scoped_ptr<StreamSocket> socket( | |
1073 factory_->CreateSSLClientSocket(connection_.Pass(), | |
1074 HostPortPair::FromURL(url_), | |
1075 server_ssl_config_, | |
1076 ssl_context)); | |
1077 connection_.reset(new ClientSocketHandle); | |
1078 connection_->SetSocket(socket.Pass()); | |
1079 next_state_ = STATE_SSL_CONNECT_COMPLETE; | |
1080 metrics_->OnCountConnectionType(SocketStreamMetrics::SSL_CONNECTION); | |
1081 return connection_->socket()->Connect(io_callback_); | |
1082 } | |
1083 | |
1084 int SocketStream::DoSSLConnectComplete(int result) { | |
1085 DCHECK_EQ(STATE_NONE, next_state_); | |
1086 // Reconnect with client authentication. | |
1087 if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) | |
1088 return HandleCertificateRequest(result, &server_ssl_config_); | |
1089 | |
1090 if (IsCertificateError(result)) | |
1091 next_state_ = STATE_SSL_HANDLE_CERT_ERROR; | |
1092 else if (result == OK) | |
1093 result = DidEstablishConnection(); | |
1094 else | |
1095 next_state_ = STATE_CLOSE; | |
1096 return result; | |
1097 } | |
1098 | |
1099 int SocketStream::DoSSLHandleCertError(int result) { | |
1100 DCHECK_EQ(STATE_NONE, next_state_); | |
1101 DCHECK(IsCertificateError(result)); | |
1102 result = HandleCertificateError(result); | |
1103 if (result == OK || result == ERR_IO_PENDING) | |
1104 next_state_ = STATE_SSL_HANDLE_CERT_ERROR_COMPLETE; | |
1105 else | |
1106 next_state_ = STATE_CLOSE; | |
1107 return result; | |
1108 } | |
1109 | |
1110 int SocketStream::DoSSLHandleCertErrorComplete(int result) { | |
1111 DCHECK_EQ(STATE_NONE, next_state_); | |
1112 // TODO(toyoshim): Upgrade to SPDY through TLS NPN extension if possible. | |
1113 // If we use HTTPS and this is the first connection to the SPDY server, | |
1114 // we should take care of TLS NPN extension here. | |
1115 | |
1116 if (result == OK) { | |
1117 if (!connection_->socket()->IsConnectedAndIdle()) | |
1118 return AllowCertErrorForReconnection(&server_ssl_config_); | |
1119 result = DidEstablishConnection(); | |
1120 } else { | |
1121 next_state_ = STATE_CLOSE; | |
1122 } | |
1123 return result; | |
1124 } | |
1125 | |
1126 int SocketStream::DoReadWrite(int result) { | |
1127 if (result < OK) { | |
1128 next_state_ = STATE_CLOSE; | |
1129 return result; | |
1130 } | |
1131 if (!connection_->socket() || !connection_->socket()->IsConnected()) { | |
1132 next_state_ = STATE_CLOSE; | |
1133 return ERR_CONNECTION_CLOSED; | |
1134 } | |
1135 | |
1136 // If client has requested close(), and there's nothing to write, then | |
1137 // let's close the socket. | |
1138 // We don't care about receiving data after the socket is closed. | |
1139 if (closing_ && !current_write_buf_.get() && pending_write_bufs_.empty()) { | |
1140 connection_->socket()->Disconnect(); | |
1141 next_state_ = STATE_CLOSE; | |
1142 return OK; | |
1143 } | |
1144 | |
1145 next_state_ = STATE_READ_WRITE; | |
1146 | |
1147 // If server already closed the socket, we don't try to read. | |
1148 if (!server_closed_) { | |
1149 if (!read_buf_.get()) { | |
1150 // No read pending and server didn't close the socket. | |
1151 read_buf_ = new IOBuffer(kReadBufferSize); | |
1152 result = connection_->socket()->Read( | |
1153 read_buf_.get(), | |
1154 kReadBufferSize, | |
1155 base::Bind(&SocketStream::OnReadCompleted, base::Unretained(this))); | |
1156 if (result > 0) { | |
1157 return DidReceiveData(result); | |
1158 } else if (result == 0) { | |
1159 // 0 indicates end-of-file, so socket was closed. | |
1160 next_state_ = STATE_CLOSE; | |
1161 server_closed_ = true; | |
1162 return ERR_CONNECTION_CLOSED; | |
1163 } | |
1164 // If read is pending, try write as well. | |
1165 // Otherwise, return the result and do next loop (to close the | |
1166 // connection). | |
1167 if (result != ERR_IO_PENDING) { | |
1168 next_state_ = STATE_CLOSE; | |
1169 server_closed_ = true; | |
1170 return result; | |
1171 } | |
1172 } | |
1173 // Read is pending. | |
1174 DCHECK(read_buf_.get()); | |
1175 } | |
1176 | |
1177 if (waiting_for_write_completion_) | |
1178 return ERR_IO_PENDING; | |
1179 | |
1180 if (!current_write_buf_.get()) { | |
1181 if (pending_write_bufs_.empty()) { | |
1182 // Nothing buffered for send. | |
1183 return ERR_IO_PENDING; | |
1184 } | |
1185 | |
1186 current_write_buf_ = new DrainableIOBuffer( | |
1187 pending_write_bufs_.front().get(), pending_write_bufs_.front()->size()); | |
1188 pending_write_bufs_.pop_front(); | |
1189 } | |
1190 | |
1191 result = connection_->socket()->Write( | |
1192 current_write_buf_.get(), | |
1193 current_write_buf_->BytesRemaining(), | |
1194 base::Bind(&SocketStream::OnWriteCompleted, base::Unretained(this))); | |
1195 | |
1196 if (result == ERR_IO_PENDING) { | |
1197 waiting_for_write_completion_ = true; | |
1198 } else if (result < 0) { | |
1199 // Shortcut. Enter STATE_CLOSE now by changing next_state_ here than by | |
1200 // calling DoReadWrite() again with the error code. | |
1201 next_state_ = STATE_CLOSE; | |
1202 } else if (result > 0) { | |
1203 // Write is not pending. Return OK and do next loop. | |
1204 DidSendData(result); | |
1205 result = OK; | |
1206 } | |
1207 | |
1208 return result; | |
1209 } | |
1210 | |
1211 GURL SocketStream::ProxyAuthOrigin() const { | |
1212 DCHECK(!proxy_info_.is_empty()); | |
1213 return GURL("http://" + | |
1214 proxy_info_.proxy_server().host_port_pair().ToString()); | |
1215 } | |
1216 | |
1217 int SocketStream::HandleCertificateRequest(int result, SSLConfig* ssl_config) { | |
1218 if (ssl_config->send_client_cert) { | |
1219 // We already have performed SSL client authentication once and failed. | |
1220 return result; | |
1221 } | |
1222 | |
1223 DCHECK(connection_->socket()); | |
1224 scoped_refptr<SSLCertRequestInfo> cert_request_info = new SSLCertRequestInfo; | |
1225 SSLClientSocket* ssl_socket = | |
1226 static_cast<SSLClientSocket*>(connection_->socket()); | |
1227 ssl_socket->GetSSLCertRequestInfo(cert_request_info.get()); | |
1228 | |
1229 HttpTransactionFactory* factory = context_->http_transaction_factory(); | |
1230 if (!factory) | |
1231 return result; | |
1232 scoped_refptr<HttpNetworkSession> session = factory->GetSession(); | |
1233 if (!session.get()) | |
1234 return result; | |
1235 | |
1236 // If the user selected one of the certificates in client_certs or declined | |
1237 // to provide one for this server before, use the past decision | |
1238 // automatically. | |
1239 scoped_refptr<X509Certificate> client_cert; | |
1240 if (!session->ssl_client_auth_cache()->Lookup( | |
1241 cert_request_info->host_and_port, &client_cert)) { | |
1242 return result; | |
1243 } | |
1244 | |
1245 // Note: |client_cert| may be NULL, indicating that the caller | |
1246 // wishes to proceed anonymously (eg: continue the handshake | |
1247 // without sending a client cert) | |
1248 // | |
1249 // Check that the certificate selected is still a certificate the server | |
1250 // is likely to accept, based on the criteria supplied in the | |
1251 // CertificateRequest message. | |
1252 const std::vector<std::string>& cert_authorities = | |
1253 cert_request_info->cert_authorities; | |
1254 if (client_cert.get() && !cert_authorities.empty() && | |
1255 !client_cert->IsIssuedByEncoded(cert_authorities)) { | |
1256 return result; | |
1257 } | |
1258 | |
1259 ssl_config->send_client_cert = true; | |
1260 ssl_config->client_cert = client_cert; | |
1261 next_state_ = STATE_TCP_CONNECT; | |
1262 return OK; | |
1263 } | |
1264 | |
1265 int SocketStream::AllowCertErrorForReconnection(SSLConfig* ssl_config) { | |
1266 DCHECK(ssl_config); | |
1267 // The SSL handshake didn't finish, or the server closed the SSL connection. | |
1268 // So, we should restart establishing connection with the certificate in | |
1269 // allowed bad certificates in |ssl_config|. | |
1270 // See also net/http/http_network_transaction.cc HandleCertificateError() and | |
1271 // RestartIgnoringLastError(). | |
1272 SSLClientSocket* ssl_socket = | |
1273 static_cast<SSLClientSocket*>(connection_->socket()); | |
1274 SSLInfo ssl_info; | |
1275 ssl_socket->GetSSLInfo(&ssl_info); | |
1276 if (ssl_info.cert.get() == NULL || | |
1277 ssl_config->IsAllowedBadCert(ssl_info.cert.get(), NULL)) { | |
1278 // If we already have the certificate in the set of allowed bad | |
1279 // certificates, we did try it and failed again, so we should not | |
1280 // retry again: the connection should fail at last. | |
1281 next_state_ = STATE_CLOSE; | |
1282 return ERR_UNEXPECTED; | |
1283 } | |
1284 // Add the bad certificate to the set of allowed certificates in the | |
1285 // SSL config object. | |
1286 SSLConfig::CertAndStatus bad_cert; | |
1287 if (!X509Certificate::GetDEREncoded(ssl_info.cert->os_cert_handle(), | |
1288 &bad_cert.der_cert)) { | |
1289 next_state_ = STATE_CLOSE; | |
1290 return ERR_UNEXPECTED; | |
1291 } | |
1292 bad_cert.cert_status = ssl_info.cert_status; | |
1293 ssl_config->allowed_bad_certs.push_back(bad_cert); | |
1294 // Restart connection ignoring the bad certificate. | |
1295 connection_->socket()->Disconnect(); | |
1296 connection_->SetSocket(scoped_ptr<StreamSocket>()); | |
1297 next_state_ = STATE_TCP_CONNECT; | |
1298 return OK; | |
1299 } | |
1300 | |
1301 void SocketStream::DoAuthRequired() { | |
1302 if (delegate_ && proxy_auth_controller_.get()) | |
1303 delegate_->OnAuthRequired(this, proxy_auth_controller_->auth_info().get()); | |
1304 else | |
1305 DoLoop(ERR_UNEXPECTED); | |
1306 } | |
1307 | |
1308 void SocketStream::DoRestartWithAuth() { | |
1309 DCHECK_EQ(next_state_, STATE_AUTH_REQUIRED); | |
1310 tunnel_request_headers_ = NULL; | |
1311 tunnel_request_headers_bytes_sent_ = 0; | |
1312 tunnel_response_headers_ = NULL; | |
1313 tunnel_response_headers_capacity_ = 0; | |
1314 tunnel_response_headers_len_ = 0; | |
1315 | |
1316 next_state_ = STATE_TCP_CONNECT; | |
1317 DoLoop(OK); | |
1318 } | |
1319 | |
1320 int SocketStream::HandleCertificateError(int result) { | |
1321 DCHECK(IsCertificateError(result)); | |
1322 SSLClientSocket* ssl_socket = | |
1323 static_cast<SSLClientSocket*>(connection_->socket()); | |
1324 DCHECK(ssl_socket); | |
1325 | |
1326 if (!context_) | |
1327 return result; | |
1328 | |
1329 if (SSLClientSocket::IgnoreCertError(result, LOAD_IGNORE_ALL_CERT_ERRORS)) { | |
1330 const HttpNetworkSession::Params* session_params = | |
1331 context_->GetNetworkSessionParams(); | |
1332 if (session_params && session_params->ignore_certificate_errors) | |
1333 return OK; | |
1334 } | |
1335 | |
1336 if (!delegate_) | |
1337 return result; | |
1338 | |
1339 SSLInfo ssl_info; | |
1340 ssl_socket->GetSSLInfo(&ssl_info); | |
1341 | |
1342 TransportSecurityState* state = context_->transport_security_state(); | |
1343 const bool fatal = state && state->ShouldSSLErrorsBeFatal(url_.host()); | |
1344 | |
1345 delegate_->OnSSLCertificateError(this, ssl_info, fatal); | |
1346 return ERR_IO_PENDING; | |
1347 } | |
1348 | |
1349 CookieStore* SocketStream::cookie_store() const { | |
1350 return cookie_store_.get(); | |
1351 } | |
1352 | |
1353 } // namespace net | |
OLD | NEW |