| 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 |