Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2009 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 <string> | |
| 11 | |
| 12 #include "base/compiler_specific.h" | |
| 13 #include "base/logging.h" | |
| 14 #include "base/message_loop.h" | |
| 15 #include "base/string_util.h" | |
| 16 #include "net/base/host_resolver.h" | |
| 17 #include "net/base/io_buffer.h" | |
| 18 #include "net/base/net_errors.h" | |
| 19 #include "net/base/net_util.h" | |
| 20 #include "net/http/http_response_headers.h" | |
| 21 #include "net/http/http_util.h" | |
| 22 #include "net/socket/client_socket_factory.h" | |
| 23 #include "net/socket/ssl_client_socket.h" | |
| 24 #include "net/socket/socks5_client_socket.h" | |
| 25 #include "net/socket/socks_client_socket.h" | |
| 26 #include "net/socket/tcp_client_socket.h" | |
| 27 #include "net/url_request/url_request.h" | |
| 28 | |
| 29 static const int kMaxPendingSendAllowed = 32768; // 32 kilobytes. | |
| 30 static const int kReadBufferSize = 4096; | |
| 31 | |
| 32 namespace net { | |
| 33 | |
| 34 void SocketStream::ResponseHeaders::Realloc(size_t new_size) { | |
| 35 headers_.reset(static_cast<char*>(realloc(headers_.release(), new_size))); | |
| 36 } | |
| 37 | |
| 38 SocketStream::SocketStream(const GURL& url, Delegate* delegate) | |
| 39 : url_(url), | |
| 40 delegate_(delegate), | |
| 41 max_pending_send_allowed_(kMaxPendingSendAllowed), | |
| 42 next_state_(STATE_NONE), | |
| 43 host_resolver_(CreateSystemHostResolver()), | |
|
eroman
2009/11/09 22:22:11
The HostResolver should be passed in as a dependen
eroman
2009/11/09 22:26:28
Also the HostResolver created in the chrome code i
| |
| 44 factory_(ClientSocketFactory::GetDefaultFactory()), | |
| 45 proxy_mode_(kDirectConnection), | |
| 46 pac_request_(NULL), | |
| 47 ALLOW_THIS_IN_INITIALIZER_LIST( | |
| 48 io_callback_(this, &SocketStream::OnIOCompleted)), | |
| 49 ALLOW_THIS_IN_INITIALIZER_LIST( | |
| 50 read_callback_(this, &SocketStream::OnReadCompleted)), | |
| 51 ALLOW_THIS_IN_INITIALIZER_LIST( | |
| 52 write_callback_(this, &SocketStream::OnWriteCompleted)), | |
| 53 read_buf_(NULL), | |
| 54 write_buf_(NULL), | |
| 55 current_write_buf_(NULL), | |
| 56 write_buf_offset_(0), | |
| 57 write_buf_size_(0) { | |
| 58 DCHECK(MessageLoop::current()) << | |
| 59 "The current MessageLoop must exist"; | |
| 60 DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) << | |
| 61 "The current MessageLoop must be TYPE_IO"; | |
| 62 DCHECK(delegate_); | |
| 63 } | |
| 64 | |
| 65 SocketStream::~SocketStream() { | |
| 66 DCHECK(!delegate_); | |
| 67 } | |
| 68 | |
| 69 SocketStream::UserData* SocketStream::GetUserData( | |
| 70 const void* key) const { | |
| 71 UserDataMap::const_iterator found = user_data_.find(key); | |
| 72 if (found != user_data_.end()) | |
| 73 return found->second.get(); | |
| 74 return NULL; | |
| 75 } | |
| 76 | |
| 77 void SocketStream::SetUserData(const void* key, UserData* data) { | |
| 78 user_data_[key] = linked_ptr<UserData>(data); | |
| 79 } | |
| 80 | |
| 81 void SocketStream::set_context(URLRequestContext* context) { | |
| 82 context_ = context; | |
| 83 } | |
| 84 | |
| 85 void SocketStream::Connect() { | |
| 86 DCHECK(MessageLoop::current()) << | |
| 87 "The current MessageLoop must exist"; | |
| 88 DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) << | |
| 89 "The current MessageLoop must be TYPE_IO"; | |
| 90 ssl_config_service()->GetSSLConfig(&ssl_config_); | |
| 91 | |
| 92 AddRef(); // Released in Finish() | |
| 93 // Open a connection asynchronously, so that delegate won't be called | |
| 94 // back before returning Connect(). | |
| 95 next_state_ = STATE_RESOLVE_PROXY; | |
| 96 MessageLoop::current()->PostTask( | |
| 97 FROM_HERE, | |
| 98 NewRunnableMethod(this, &SocketStream::DoLoop, OK)); | |
| 99 } | |
| 100 | |
| 101 bool SocketStream::SendData(const char* data, int len) { | |
| 102 DCHECK(MessageLoop::current()) << | |
| 103 "The current MessageLoop must exist"; | |
| 104 DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) << | |
| 105 "The current MessageLoop must be TYPE_IO"; | |
| 106 if (!socket_.get() || !socket_->IsConnected()) | |
| 107 return false; | |
| 108 if (write_buf_) { | |
| 109 int current_amount_send = write_buf_size_ - write_buf_offset_; | |
| 110 for (PendingDataQueue::const_iterator iter = pending_write_bufs_.begin(); | |
| 111 iter != pending_write_bufs_.end(); | |
| 112 ++iter) | |
| 113 current_amount_send += (*iter)->size(); | |
| 114 | |
| 115 current_amount_send += len; | |
| 116 if (current_amount_send > max_pending_send_allowed_) | |
| 117 return false; | |
| 118 | |
| 119 pending_write_bufs_.push_back(new IOBufferWithSize(len)); | |
| 120 memcpy(pending_write_bufs_.back()->data(), data, len); | |
| 121 return true; | |
| 122 } | |
| 123 DCHECK(!current_write_buf_); | |
| 124 write_buf_ = new IOBuffer(len); | |
| 125 memcpy(write_buf_->data(), data, len); | |
| 126 write_buf_size_ = len; | |
| 127 write_buf_offset_ = 0; | |
| 128 // Send pending data asynchronously, so that delegate won't be called | |
| 129 // back before returning SendData(). | |
| 130 MessageLoop::current()->PostTask( | |
| 131 FROM_HERE, | |
| 132 NewRunnableMethod(this, &SocketStream::DoLoop, OK)); | |
| 133 return true; | |
| 134 } | |
| 135 | |
| 136 void SocketStream::Close() { | |
| 137 DCHECK(MessageLoop::current()) << | |
| 138 "The current MessageLoop must exist"; | |
| 139 DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) << | |
| 140 "The current MessageLoop must be TYPE_IO"; | |
| 141 if (!socket_.get()) | |
| 142 return; | |
| 143 if (socket_->IsConnected()) | |
| 144 socket_->Disconnect(); | |
| 145 // Close asynchronously, so that delegate won't be called | |
| 146 // back before returning Close(). | |
| 147 MessageLoop::current()->PostTask( | |
| 148 FROM_HERE, | |
| 149 NewRunnableMethod(this, &SocketStream::DoLoop, OK)); | |
| 150 } | |
| 151 | |
| 152 void SocketStream::DetachDelegate() { | |
| 153 if (!delegate_) | |
| 154 return; | |
| 155 delegate_ = NULL; | |
| 156 Close(); | |
| 157 } | |
| 158 | |
| 159 void SocketStream::Finish() { | |
| 160 DCHECK(MessageLoop::current()) << | |
| 161 "The current MessageLoop must exist"; | |
| 162 DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) << | |
| 163 "The current MessageLoop must be TYPE_IO"; | |
| 164 Delegate* delegate = delegate_; | |
| 165 delegate_ = NULL; | |
| 166 if (delegate) { | |
| 167 delegate->OnClose(this); | |
| 168 Release(); | |
| 169 } | |
| 170 } | |
| 171 | |
| 172 void SocketStream::SetHostResolver(HostResolver* host_resolver) { | |
| 173 DCHECK(host_resolver); | |
| 174 host_resolver_ = host_resolver; | |
| 175 } | |
| 176 | |
| 177 void SocketStream::SetClientSocketFactory( | |
| 178 ClientSocketFactory* factory) { | |
| 179 DCHECK(factory); | |
| 180 factory_ = factory; | |
| 181 } | |
| 182 | |
| 183 void SocketStream::DidEstablishConnection() { | |
| 184 if (!socket_.get() || !socket_->IsConnected()) { | |
| 185 Finish(); | |
| 186 return; | |
| 187 } | |
| 188 next_state_ = STATE_READ_WRITE; | |
| 189 | |
| 190 if (delegate_) | |
| 191 delegate_->OnConnected(this, max_pending_send_allowed_); | |
| 192 | |
| 193 return; | |
| 194 } | |
| 195 | |
| 196 void SocketStream::DidReceiveData(int result) { | |
| 197 DCHECK(read_buf_); | |
| 198 DCHECK(result > 0); | |
| 199 if (!delegate_) | |
| 200 return; | |
| 201 // Notify recevied data to delegate. | |
| 202 delegate_->OnReceivedData(this, read_buf_->data(), result); | |
| 203 read_buf_ = NULL; | |
| 204 } | |
| 205 | |
| 206 void SocketStream::DidSendData(int result) { | |
| 207 current_write_buf_ = NULL; | |
| 208 DCHECK(result > 0); | |
| 209 if (!delegate_) | |
| 210 return; | |
| 211 | |
| 212 delegate_->OnSentData(this, result); | |
| 213 int remaining_size = write_buf_size_ - write_buf_offset_ - result; | |
| 214 if (remaining_size == 0) { | |
| 215 if (!pending_write_bufs_.empty()) { | |
| 216 write_buf_size_ = pending_write_bufs_.front()->size(); | |
| 217 write_buf_ = pending_write_bufs_.front(); | |
| 218 pending_write_bufs_.pop_front(); | |
| 219 } else { | |
| 220 write_buf_size_ = 0; | |
| 221 write_buf_ = NULL; | |
| 222 } | |
| 223 write_buf_offset_ = 0; | |
| 224 } else { | |
| 225 write_buf_offset_ += result; | |
| 226 } | |
| 227 } | |
| 228 | |
| 229 void SocketStream::OnIOCompleted(int result) { | |
| 230 DoLoop(result); | |
| 231 // TODO(ukai): notify error. | |
| 232 } | |
| 233 | |
| 234 void SocketStream::OnReadCompleted(int result) { | |
| 235 // TODO(ukai): notify error. | |
| 236 if (result >= 0 && read_buf_) { | |
| 237 DidReceiveData(result); | |
| 238 result = OK; | |
| 239 } | |
| 240 DoLoop(result); | |
| 241 } | |
| 242 | |
| 243 void SocketStream::OnWriteCompleted(int result) { | |
| 244 // TODO(ukai): notify error. | |
| 245 if (result >= 0 && write_buf_) { | |
| 246 DidSendData(result); | |
| 247 result = OK; | |
| 248 } | |
| 249 DoLoop(result); | |
| 250 } | |
| 251 | |
| 252 int SocketStream::DoLoop(int result) { | |
| 253 if (next_state_ == STATE_NONE) { | |
| 254 Finish(); | |
| 255 return ERR_CONNECTION_CLOSED; | |
| 256 } | |
| 257 | |
| 258 do { | |
| 259 State state = next_state_; | |
| 260 next_state_ = STATE_NONE; | |
| 261 switch (state) { | |
| 262 case STATE_RESOLVE_PROXY: | |
| 263 DCHECK_EQ(OK, result); | |
| 264 result = DoResolveProxy(); | |
| 265 break; | |
| 266 case STATE_RESOLVE_PROXY_COMPLETE: | |
| 267 result = DoResolveProxyComplete(result); | |
| 268 break; | |
| 269 case STATE_RESOLVE_HOST: | |
| 270 DCHECK_EQ(OK, result); | |
| 271 result = DoResolveHost(); | |
| 272 break; | |
| 273 case STATE_RESOLVE_HOST_COMPLETE: | |
| 274 result = DoResolveHostComplete(result); | |
| 275 break; | |
| 276 case STATE_TCP_CONNECT: | |
| 277 DCHECK_EQ(OK, result); | |
| 278 result = DoTcpConnect(); | |
| 279 break; | |
| 280 case STATE_TCP_CONNECT_COMPLETE: | |
| 281 result = DoTcpConnectComplete(result); | |
| 282 break; | |
| 283 case STATE_WRITE_TUNNEL_HEADERS: | |
| 284 DCHECK_EQ(OK, result); | |
| 285 result = DoWriteTunnelHeaders(); | |
| 286 break; | |
| 287 case STATE_WRITE_TUNNEL_HEADERS_COMPLETE: | |
| 288 result = DoWriteTunnelHeadersComplete(result); | |
| 289 break; | |
| 290 case STATE_READ_TUNNEL_HEADERS: | |
| 291 DCHECK_EQ(OK, result); | |
| 292 result = DoReadTunnelHeaders(); | |
| 293 break; | |
| 294 case STATE_READ_TUNNEL_HEADERS_COMPLETE: | |
| 295 result = DoReadTunnelHeadersComplete(result); | |
| 296 break; | |
| 297 case STATE_SOCKS_CONNECT: | |
| 298 DCHECK_EQ(OK, result); | |
| 299 result = DoSOCKSConnect(); | |
| 300 break; | |
| 301 case STATE_SOCKS_CONNECT_COMPLETE: | |
| 302 result = DoSOCKSConnectComplete(result); | |
| 303 break; | |
| 304 case STATE_SSL_CONNECT: | |
| 305 DCHECK_EQ(OK, result); | |
| 306 result = DoSSLConnect(); | |
| 307 break; | |
| 308 case STATE_SSL_CONNECT_COMPLETE: | |
| 309 result = DoSSLConnectComplete(result); | |
| 310 break; | |
| 311 case STATE_READ_WRITE: | |
| 312 result = DoReadWrite(result); | |
| 313 break; | |
| 314 default: | |
| 315 NOTREACHED() << "bad state"; | |
| 316 result = ERR_UNEXPECTED; | |
| 317 break; | |
| 318 } | |
| 319 } while (result != ERR_IO_PENDING && next_state_ != STATE_NONE); | |
| 320 | |
| 321 if (result != ERR_IO_PENDING) | |
| 322 Finish(); | |
| 323 | |
| 324 return result; | |
| 325 } | |
| 326 | |
| 327 int SocketStream::DoResolveProxy() { | |
| 328 DCHECK(!pac_request_); | |
| 329 next_state_ = STATE_RESOLVE_PROXY_COMPLETE; | |
| 330 | |
| 331 return proxy_service()->ResolveProxy( | |
| 332 url_, &proxy_info_, &io_callback_, &pac_request_, NULL); | |
| 333 } | |
| 334 | |
| 335 int SocketStream::DoResolveProxyComplete(int result) { | |
| 336 next_state_ = STATE_RESOLVE_HOST; | |
| 337 | |
| 338 pac_request_ = NULL; | |
| 339 if (result != OK) { | |
| 340 LOG(ERROR) << "Failed to resolve proxy: " << result; | |
| 341 proxy_info_.UseDirect(); | |
| 342 } | |
| 343 | |
| 344 return OK; | |
| 345 } | |
| 346 | |
| 347 int SocketStream::DoResolveHost() { | |
| 348 next_state_ = STATE_RESOLVE_HOST_COMPLETE; | |
| 349 | |
| 350 if (proxy_info_.is_direct()) | |
| 351 proxy_mode_ = kDirectConnection; | |
| 352 else if (proxy_info_.proxy_server().is_socks()) | |
| 353 proxy_mode_ = kSOCKSProxy; | |
| 354 else | |
| 355 proxy_mode_ = kTunnelProxy; | |
| 356 | |
| 357 // Determine the host and port to connect to. | |
| 358 std::string host; | |
| 359 int port; | |
| 360 if (proxy_mode_ != kDirectConnection) { | |
| 361 ProxyServer proxy_server = proxy_info_.proxy_server(); | |
| 362 host = proxy_server.HostNoBrackets(); | |
| 363 port = proxy_server.port(); | |
| 364 } else { | |
| 365 host = url_.HostNoBrackets(); | |
| 366 port = url_.EffectiveIntPort(); | |
| 367 } | |
| 368 | |
| 369 HostResolver::RequestInfo resolve_info(host, port); | |
| 370 | |
| 371 resolver_.reset(new SingleRequestHostResolver(host_resolver_.get())); | |
| 372 return resolver_->Resolve(resolve_info, &addresses_, &io_callback_, NULL); | |
| 373 } | |
| 374 | |
| 375 int SocketStream::DoResolveHostComplete(int result) { | |
| 376 if (result == OK) | |
| 377 next_state_ = STATE_TCP_CONNECT; | |
| 378 return result; | |
| 379 } | |
| 380 | |
| 381 int SocketStream::DoTcpConnect() { | |
| 382 next_state_ = STATE_TCP_CONNECT_COMPLETE; | |
| 383 DCHECK(factory_); | |
| 384 socket_.reset(factory_->CreateTCPClientSocket(addresses_)); | |
| 385 return socket_->Connect(&io_callback_); | |
| 386 } | |
| 387 | |
| 388 int SocketStream::DoTcpConnectComplete(int result) { | |
| 389 if (result != OK) | |
| 390 return result; | |
| 391 | |
| 392 if (proxy_mode_ == kTunnelProxy) | |
| 393 next_state_ = STATE_WRITE_TUNNEL_HEADERS; | |
| 394 else if (proxy_mode_ == kSOCKSProxy) | |
| 395 next_state_ = STATE_SOCKS_CONNECT; | |
| 396 else if (is_secure()) { | |
| 397 next_state_ = STATE_SSL_CONNECT; | |
| 398 } else { | |
| 399 DidEstablishConnection(); | |
| 400 } | |
| 401 return OK; | |
| 402 } | |
| 403 | |
| 404 int SocketStream::DoWriteTunnelHeaders() { | |
| 405 DCHECK_EQ(kTunnelProxy, proxy_mode_); | |
| 406 | |
| 407 next_state_ = STATE_WRITE_TUNNEL_HEADERS_COMPLETE; | |
| 408 | |
| 409 if (!tunnel_request_headers_.get()) { | |
| 410 tunnel_request_headers_ = new RequestHeaders(); | |
| 411 tunnel_request_headers_bytes_sent_ = 0; | |
| 412 } | |
| 413 if (tunnel_request_headers_->headers_.empty()) { | |
| 414 tunnel_request_headers_->headers_ = StringPrintf( | |
| 415 "CONNECT %s HTTP/1.1\r\n" | |
| 416 "Host: %s\r\n" | |
| 417 "Proxy-Connection: keep-alive\r\n", | |
| 418 GetHostAndPort(url_).c_str(), | |
| 419 GetHostAndOptionalPort(url_).c_str()); | |
| 420 // TODO(ukai): set proxy auth if necessary. | |
| 421 tunnel_request_headers_->headers_ += "\r\n"; | |
| 422 } | |
| 423 tunnel_request_headers_->SetDataOffset(tunnel_request_headers_bytes_sent_); | |
| 424 int buf_len = static_cast<int>(tunnel_request_headers_->headers_.size() - | |
| 425 tunnel_request_headers_bytes_sent_); | |
| 426 DCHECK_GT(buf_len, 0); | |
| 427 return socket_->Write(tunnel_request_headers_, buf_len, &io_callback_); | |
| 428 } | |
| 429 | |
| 430 int SocketStream::DoWriteTunnelHeadersComplete(int result) { | |
| 431 DCHECK_EQ(kTunnelProxy, proxy_mode_); | |
| 432 | |
| 433 if (result < 0) | |
| 434 return result; | |
| 435 | |
| 436 tunnel_request_headers_bytes_sent_ += result; | |
| 437 if (tunnel_request_headers_bytes_sent_ < | |
| 438 tunnel_request_headers_->headers_.size()) | |
| 439 next_state_ = STATE_WRITE_TUNNEL_HEADERS; | |
| 440 else | |
| 441 next_state_ = STATE_READ_TUNNEL_HEADERS; | |
| 442 return OK; | |
| 443 } | |
| 444 | |
| 445 int SocketStream::DoReadTunnelHeaders() { | |
| 446 DCHECK_EQ(kTunnelProxy, proxy_mode_); | |
| 447 | |
| 448 next_state_ = STATE_READ_TUNNEL_HEADERS_COMPLETE; | |
| 449 | |
| 450 if (!tunnel_response_headers_.get()) { | |
| 451 tunnel_response_headers_ = new ResponseHeaders(); | |
| 452 tunnel_response_headers_capacity_ = kMaxTunnelResponseHeadersSize; | |
| 453 tunnel_response_headers_->Realloc(tunnel_response_headers_capacity_); | |
| 454 tunnel_response_headers_len_ = 0; | |
| 455 } | |
| 456 | |
| 457 int buf_len = tunnel_response_headers_capacity_ - | |
| 458 tunnel_response_headers_len_; | |
| 459 tunnel_response_headers_->SetDataOffset(tunnel_response_headers_len_); | |
| 460 CHECK(tunnel_response_headers_->data()); | |
| 461 | |
| 462 return socket_->Read(tunnel_response_headers_, buf_len, &io_callback_); | |
| 463 } | |
| 464 | |
| 465 int SocketStream::DoReadTunnelHeadersComplete(int result) { | |
| 466 DCHECK_EQ(kTunnelProxy, proxy_mode_); | |
| 467 | |
| 468 if (result < 0) | |
| 469 return result; | |
| 470 | |
| 471 tunnel_response_headers_len_ += result; | |
| 472 DCHECK(tunnel_response_headers_len_ <= tunnel_response_headers_capacity_); | |
| 473 | |
| 474 int eoh = HttpUtil::LocateEndOfHeaders( | |
| 475 tunnel_response_headers_->headers(), tunnel_response_headers_len_, 0); | |
| 476 if (eoh == -1) { | |
| 477 if (tunnel_response_headers_len_ >= kMaxTunnelResponseHeadersSize) | |
| 478 return ERR_RESPONSE_HEADERS_TOO_BIG; | |
| 479 | |
| 480 next_state_ = STATE_READ_TUNNEL_HEADERS; | |
| 481 return OK; | |
| 482 } | |
| 483 // DidReadResponseHeaders | |
| 484 scoped_refptr<HttpResponseHeaders> headers; | |
| 485 headers = new HttpResponseHeaders( | |
| 486 HttpUtil::AssembleRawHeaders(tunnel_response_headers_->headers(), eoh)); | |
| 487 if (headers->GetParsedHttpVersion() < HttpVersion(1, 0)) { | |
| 488 // Require the "HTTP/1.x" status line. | |
| 489 return ERR_TUNNEL_CONNECTION_FAILED; | |
| 490 } | |
| 491 switch (headers->response_code()) { | |
| 492 case 200: // OK | |
| 493 if (is_secure()) { | |
| 494 DCHECK_EQ(eoh, tunnel_response_headers_len_); | |
| 495 next_state_ = STATE_SSL_CONNECT; | |
| 496 } else { | |
| 497 DidEstablishConnection(); | |
| 498 if ((eoh < tunnel_response_headers_len_) && delegate_) | |
| 499 delegate_->OnReceivedData( | |
| 500 this, tunnel_response_headers_->headers() + eoh, | |
| 501 tunnel_response_headers_len_ - eoh); | |
| 502 } | |
| 503 return OK; | |
| 504 case 407: // Proxy Authentication Required. | |
| 505 // TODO(ukai): handle Proxy Authentication. | |
| 506 break; | |
| 507 default: | |
| 508 break; | |
| 509 } | |
| 510 return ERR_TUNNEL_CONNECTION_FAILED; | |
| 511 } | |
| 512 | |
| 513 int SocketStream::DoSOCKSConnect() { | |
| 514 DCHECK_EQ(kSOCKSProxy, proxy_mode_); | |
| 515 | |
| 516 next_state_ = STATE_SOCKS_CONNECT_COMPLETE; | |
| 517 | |
| 518 ClientSocket* s = socket_.release(); | |
| 519 HostResolver::RequestInfo req_info(url_.HostNoBrackets(), | |
| 520 url_.EffectiveIntPort()); | |
| 521 | |
| 522 if (proxy_info_.proxy_server().scheme() == ProxyServer::SCHEME_SOCKS5) | |
| 523 s = new SOCKS5ClientSocket(s, req_info, host_resolver_.get()); | |
| 524 else | |
| 525 s = new SOCKSClientSocket(s, req_info, host_resolver_.get()); | |
| 526 socket_.reset(s); | |
| 527 return socket_->Connect(&io_callback_); | |
| 528 } | |
| 529 | |
| 530 int SocketStream::DoSOCKSConnectComplete(int result) { | |
| 531 DCHECK_EQ(kSOCKSProxy, proxy_mode_); | |
| 532 | |
| 533 if (result == OK) { | |
| 534 if (is_secure()) | |
| 535 next_state_ = STATE_SSL_CONNECT; | |
| 536 else | |
| 537 DidEstablishConnection(); | |
| 538 } | |
| 539 return result; | |
| 540 } | |
| 541 | |
| 542 int SocketStream::DoSSLConnect() { | |
| 543 DCHECK(factory_); | |
| 544 socket_.reset(factory_->CreateSSLClientSocket( | |
| 545 socket_.release(), url_.HostNoBrackets(), ssl_config_)); | |
| 546 next_state_ = STATE_SSL_CONNECT_COMPLETE; | |
| 547 return socket_->Connect(&io_callback_); | |
| 548 } | |
| 549 | |
| 550 int SocketStream::DoSSLConnectComplete(int result) { | |
| 551 if (IsCertificateError(result)) | |
| 552 result = HandleCertificateError(result); | |
| 553 | |
| 554 if (result == OK) | |
| 555 DidEstablishConnection(); | |
| 556 return result; | |
| 557 } | |
| 558 | |
| 559 int SocketStream::DoReadWrite(int result) { | |
| 560 if (result < OK) { | |
| 561 Finish(); | |
| 562 return result; | |
| 563 } | |
| 564 if (!socket_.get() || !socket_->IsConnected()) { | |
| 565 Finish(); | |
| 566 return ERR_CONNECTION_CLOSED; | |
| 567 } | |
| 568 | |
| 569 next_state_ = STATE_READ_WRITE; | |
| 570 | |
| 571 if (!read_buf_) { | |
| 572 read_buf_ = new IOBuffer(kReadBufferSize); | |
| 573 result = socket_->Read(read_buf_, kReadBufferSize, &read_callback_); | |
| 574 if (result > 0) { | |
| 575 DidReceiveData(result); | |
| 576 result = OK; | |
| 577 } | |
| 578 } | |
| 579 if (write_buf_ && !current_write_buf_) { | |
| 580 current_write_buf_ = new ReusedIOBuffer(write_buf_, write_buf_size_); | |
| 581 current_write_buf_->SetOffset(write_buf_offset_); | |
| 582 result = socket_->Write(current_write_buf_, | |
| 583 write_buf_size_ - write_buf_offset_, | |
| 584 &write_callback_); | |
| 585 if (result > 0) { | |
| 586 DidSendData(result); | |
| 587 result = OK; | |
| 588 } | |
| 589 } | |
| 590 | |
| 591 // We arrived here when Write is performed and finished. | |
| 592 if (result == OK) | |
| 593 return ERR_IO_PENDING; | |
| 594 return result; | |
| 595 } | |
| 596 | |
| 597 int SocketStream::HandleCertificateError(int result) { | |
| 598 // TODO(ukai): handle cert error properly. | |
| 599 switch (result) { | |
| 600 case ERR_CERT_COMMON_NAME_INVALID: | |
| 601 case ERR_CERT_DATE_INVALID: | |
| 602 case ERR_CERT_AUTHORITY_INVALID: | |
| 603 result = OK; | |
| 604 break; | |
| 605 default: | |
| 606 break; | |
| 607 } | |
| 608 return result; | |
| 609 } | |
| 610 | |
| 611 bool SocketStream::is_secure() const { | |
| 612 return url_.SchemeIs("wss"); | |
| 613 } | |
| 614 | |
| 615 SSLConfigService* SocketStream::ssl_config_service() const { | |
| 616 return context_->ssl_config_service(); | |
| 617 } | |
| 618 | |
| 619 ProxyService* SocketStream::proxy_service() const { | |
| 620 return context_->proxy_service(); | |
| 621 } | |
| 622 | |
| 623 } // namespace net | |
| OLD | NEW |