• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
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 
13 #include "base/compiler_specific.h"
14 #include "base/logging.h"
15 #include "base/message_loop.h"
16 #include "base/string_util.h"
17 #include "base/stringprintf.h"
18 #include "base/utf_string_conversions.h"
19 #include "net/base/auth.h"
20 #include "net/base/host_resolver.h"
21 #include "net/base/io_buffer.h"
22 #include "net/base/net_errors.h"
23 #include "net/base/net_util.h"
24 #include "net/http/http_auth_handler_factory.h"
25 #include "net/http/http_request_info.h"
26 #include "net/http/http_response_headers.h"
27 #include "net/http/http_util.h"
28 #include "net/socket/client_socket_factory.h"
29 #include "net/socket/socks5_client_socket.h"
30 #include "net/socket/socks_client_socket.h"
31 #include "net/socket/ssl_client_socket.h"
32 #include "net/socket/tcp_client_socket.h"
33 #include "net/socket_stream/socket_stream_metrics.h"
34 #include "net/url_request/url_request.h"
35 
36 static const int kMaxPendingSendAllowed = 32768;  // 32 kilobytes.
37 static const int kReadBufferSize = 4096;
38 
39 namespace net {
40 
ResponseHeaders()41 SocketStream::ResponseHeaders::ResponseHeaders() : IOBuffer() {}
42 
Realloc(size_t new_size)43 void SocketStream::ResponseHeaders::Realloc(size_t new_size) {
44   headers_.reset(static_cast<char*>(realloc(headers_.release(), new_size)));
45 }
46 
~ResponseHeaders()47 SocketStream::ResponseHeaders::~ResponseHeaders() { data_ = NULL; }
48 
SocketStream(const GURL & url,Delegate * delegate)49 SocketStream::SocketStream(const GURL& url, Delegate* delegate)
50     : delegate_(delegate),
51       url_(url),
52       max_pending_send_allowed_(kMaxPendingSendAllowed),
53       next_state_(STATE_NONE),
54       host_resolver_(NULL),
55       cert_verifier_(NULL),
56       http_auth_handler_factory_(NULL),
57       factory_(ClientSocketFactory::GetDefaultFactory()),
58       proxy_mode_(kDirectConnection),
59       proxy_url_(url),
60       pac_request_(NULL),
61       ALLOW_THIS_IN_INITIALIZER_LIST(
62           io_callback_(this, &SocketStream::OnIOCompleted)),
63       ALLOW_THIS_IN_INITIALIZER_LIST(
64           read_callback_(this, &SocketStream::OnReadCompleted)),
65       ALLOW_THIS_IN_INITIALIZER_LIST(
66           write_callback_(this, &SocketStream::OnWriteCompleted)),
67       read_buf_(NULL),
68       write_buf_(NULL),
69       current_write_buf_(NULL),
70       write_buf_offset_(0),
71       write_buf_size_(0),
72       closing_(false),
73       server_closed_(false),
74       metrics_(new SocketStreamMetrics(url)) {
75   DCHECK(MessageLoop::current()) <<
76       "The current MessageLoop must exist";
77   DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) <<
78       "The current MessageLoop must be TYPE_IO";
79   DCHECK(delegate_);
80 }
81 
GetUserData(const void * key) const82 SocketStream::UserData* SocketStream::GetUserData(
83     const void* key) const {
84   UserDataMap::const_iterator found = user_data_.find(key);
85   if (found != user_data_.end())
86     return found->second.get();
87   return NULL;
88 }
89 
SetUserData(const void * key,UserData * data)90 void SocketStream::SetUserData(const void* key, UserData* data) {
91   user_data_[key] = linked_ptr<UserData>(data);
92 }
93 
is_secure() const94 bool SocketStream::is_secure() const {
95   return url_.SchemeIs("wss");
96 }
97 
set_context(URLRequestContext * context)98 void SocketStream::set_context(URLRequestContext* context) {
99   scoped_refptr<URLRequestContext> prev_context = context_;
100 
101   context_ = context;
102 
103   if (prev_context != context) {
104     if (prev_context && pac_request_) {
105       prev_context->proxy_service()->CancelPacRequest(pac_request_);
106       pac_request_ = NULL;
107     }
108 
109     net_log_.EndEvent(NetLog::TYPE_REQUEST_ALIVE, NULL);
110     net_log_ = BoundNetLog();
111 
112     if (context) {
113       net_log_ = BoundNetLog::Make(
114           context->net_log(),
115           NetLog::SOURCE_SOCKET_STREAM);
116 
117       net_log_.BeginEvent(NetLog::TYPE_REQUEST_ALIVE, NULL);
118     }
119   }
120 
121   if (context_) {
122     host_resolver_ = context_->host_resolver();
123     cert_verifier_ = context_->cert_verifier();
124     http_auth_handler_factory_ = context_->http_auth_handler_factory();
125   }
126 }
127 
Connect()128 void SocketStream::Connect() {
129   DCHECK(MessageLoop::current()) <<
130       "The current MessageLoop must exist";
131   DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) <<
132       "The current MessageLoop must be TYPE_IO";
133   if (context_)
134     ssl_config_service()->GetSSLConfig(&ssl_config_);
135   DCHECK_EQ(next_state_, STATE_NONE);
136 
137   AddRef();  // Released in Finish()
138   // Open a connection asynchronously, so that delegate won't be called
139   // back before returning Connect().
140   next_state_ = STATE_RESOLVE_PROXY;
141   net_log_.BeginEvent(
142       NetLog::TYPE_SOCKET_STREAM_CONNECT,
143       make_scoped_refptr(
144           new NetLogStringParameter("url", url_.possibly_invalid_spec())));
145   MessageLoop::current()->PostTask(
146       FROM_HERE,
147       NewRunnableMethod(this, &SocketStream::DoLoop, OK));
148 }
149 
SendData(const char * data,int len)150 bool SocketStream::SendData(const char* data, int len) {
151   DCHECK(MessageLoop::current()) <<
152       "The current MessageLoop must exist";
153   DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) <<
154       "The current MessageLoop must be TYPE_IO";
155   if (!socket_.get() || !socket_->IsConnected() || next_state_ == STATE_NONE)
156     return false;
157   if (write_buf_) {
158     int current_amount_send = write_buf_size_ - write_buf_offset_;
159     for (PendingDataQueue::const_iterator iter = pending_write_bufs_.begin();
160          iter != pending_write_bufs_.end();
161          ++iter)
162       current_amount_send += (*iter)->size();
163 
164     current_amount_send += len;
165     if (current_amount_send > max_pending_send_allowed_)
166       return false;
167 
168     pending_write_bufs_.push_back(make_scoped_refptr(
169         new IOBufferWithSize(len)));
170     memcpy(pending_write_bufs_.back()->data(), data, len);
171     return true;
172   }
173   DCHECK(!current_write_buf_);
174   write_buf_ = new IOBuffer(len);
175   memcpy(write_buf_->data(), data, len);
176   write_buf_size_ = len;
177   write_buf_offset_ = 0;
178   // Send pending data asynchronously, so that delegate won't be called
179   // back before returning SendData().
180   MessageLoop::current()->PostTask(
181       FROM_HERE,
182       NewRunnableMethod(this, &SocketStream::DoLoop, OK));
183   return true;
184 }
185 
Close()186 void SocketStream::Close() {
187   DCHECK(MessageLoop::current()) <<
188       "The current MessageLoop must exist";
189   DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) <<
190       "The current MessageLoop must be TYPE_IO";
191   // If next_state_ is STATE_NONE, the socket was not opened, or already
192   // closed.  So, return immediately.
193   // Otherwise, it might call Finish() more than once, so breaks balance
194   // of AddRef() and Release() in Connect() and Finish(), respectively.
195   if (next_state_ == STATE_NONE)
196     return;
197   MessageLoop::current()->PostTask(
198       FROM_HERE,
199       NewRunnableMethod(this, &SocketStream::DoClose));
200 }
201 
RestartWithAuth(const string16 & username,const string16 & password)202 void SocketStream::RestartWithAuth(
203     const string16& username, const string16& password) {
204   DCHECK(MessageLoop::current()) <<
205       "The current MessageLoop must exist";
206   DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) <<
207       "The current MessageLoop must be TYPE_IO";
208   DCHECK(auth_handler_.get());
209   if (!socket_.get()) {
210     LOG(ERROR) << "Socket is closed before restarting with auth.";
211     return;
212   }
213 
214   if (auth_identity_.invalid) {
215     // Update the username/password.
216     auth_identity_.source = HttpAuth::IDENT_SRC_EXTERNAL;
217     auth_identity_.invalid = false;
218     auth_identity_.username = username;
219     auth_identity_.password = password;
220   }
221 
222   MessageLoop::current()->PostTask(
223       FROM_HERE,
224       NewRunnableMethod(this, &SocketStream::DoRestartWithAuth));
225 }
226 
DetachDelegate()227 void SocketStream::DetachDelegate() {
228   if (!delegate_)
229     return;
230   delegate_ = NULL;
231   net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL);
232   // We don't need to send pending data when client detach the delegate.
233   pending_write_bufs_.clear();
234   Close();
235 }
236 
SetHostResolver(HostResolver * host_resolver)237 void SocketStream::SetHostResolver(HostResolver* host_resolver) {
238   DCHECK(host_resolver);
239   host_resolver_ = host_resolver;
240 }
241 
SetClientSocketFactory(ClientSocketFactory * factory)242 void SocketStream::SetClientSocketFactory(
243     ClientSocketFactory* factory) {
244   DCHECK(factory);
245   factory_ = factory;
246 }
247 
~SocketStream()248 SocketStream::~SocketStream() {
249   set_context(NULL);
250   DCHECK(!delegate_);
251   DCHECK(!pac_request_);
252 }
253 
CopyAddrInfo(struct addrinfo * head)254 void SocketStream::CopyAddrInfo(struct addrinfo* head) {
255   addresses_.Copy(head, true);
256 }
257 
DoClose()258 void SocketStream::DoClose() {
259   closing_ = true;
260   // If next_state_ is STATE_TCP_CONNECT, it's waiting other socket establishing
261   // connection.  If next_state_ is STATE_AUTH_REQUIRED, it's waiting for
262   // restarting.  In these states, we'll close the SocketStream now.
263   if (next_state_ == STATE_TCP_CONNECT || next_state_ == STATE_AUTH_REQUIRED) {
264     DoLoop(ERR_ABORTED);
265     return;
266   }
267   // If next_state_ is STATE_READ_WRITE, we'll run DoLoop and close
268   // the SocketStream.
269   // If it's writing now, we should defer the closing after the current
270   // writing is completed.
271   if (next_state_ == STATE_READ_WRITE && !current_write_buf_)
272     DoLoop(ERR_ABORTED);
273 
274   // In other next_state_, we'll wait for callback of other APIs, such as
275   // ResolveProxy().
276 }
277 
Finish(int result)278 void SocketStream::Finish(int result) {
279   DCHECK(MessageLoop::current()) <<
280       "The current MessageLoop must exist";
281   DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) <<
282       "The current MessageLoop must be TYPE_IO";
283   DCHECK_LE(result, OK);
284   if (result == OK)
285     result = ERR_CONNECTION_CLOSED;
286   DCHECK_EQ(next_state_, STATE_NONE);
287   DVLOG(1) << "Finish result=" << ErrorToString(result);
288   if (delegate_)
289     delegate_->OnError(this, result);
290 
291   metrics_->OnClose();
292   Delegate* delegate = delegate_;
293   delegate_ = NULL;
294   if (delegate) {
295     delegate->OnClose(this);
296   }
297   Release();
298 }
299 
DidEstablishConnection()300 int SocketStream::DidEstablishConnection() {
301   if (!socket_.get() || !socket_->IsConnected()) {
302     next_state_ = STATE_CLOSE;
303     return ERR_CONNECTION_FAILED;
304   }
305   next_state_ = STATE_READ_WRITE;
306   metrics_->OnConnected();
307 
308   net_log_.EndEvent(NetLog::TYPE_SOCKET_STREAM_CONNECT, NULL);
309   if (delegate_)
310     delegate_->OnConnected(this, max_pending_send_allowed_);
311 
312   return OK;
313 }
314 
DidReceiveData(int result)315 int SocketStream::DidReceiveData(int result) {
316   DCHECK(read_buf_);
317   DCHECK_GT(result, 0);
318   net_log_.AddEvent(NetLog::TYPE_SOCKET_STREAM_RECEIVED, NULL);
319   int len = result;
320   metrics_->OnRead(len);
321   if (delegate_) {
322     // Notify recevied data to delegate.
323     delegate_->OnReceivedData(this, read_buf_->data(), len);
324   }
325   read_buf_ = NULL;
326   return OK;
327 }
328 
DidSendData(int result)329 int SocketStream::DidSendData(int result) {
330   DCHECK_GT(result, 0);
331   net_log_.AddEvent(NetLog::TYPE_SOCKET_STREAM_SENT, NULL);
332   int len = result;
333   metrics_->OnWrite(len);
334   current_write_buf_ = NULL;
335   if (delegate_)
336     delegate_->OnSentData(this, len);
337 
338   int remaining_size = write_buf_size_ - write_buf_offset_ - len;
339   if (remaining_size == 0) {
340     if (!pending_write_bufs_.empty()) {
341       write_buf_size_ = pending_write_bufs_.front()->size();
342       write_buf_ = pending_write_bufs_.front();
343       pending_write_bufs_.pop_front();
344     } else {
345       write_buf_size_ = 0;
346       write_buf_ = NULL;
347     }
348     write_buf_offset_ = 0;
349   } else {
350     write_buf_offset_ += len;
351   }
352   return OK;
353 }
354 
OnIOCompleted(int result)355 void SocketStream::OnIOCompleted(int result) {
356   DoLoop(result);
357 }
358 
OnReadCompleted(int result)359 void SocketStream::OnReadCompleted(int result) {
360   if (result == 0) {
361     // 0 indicates end-of-file, so socket was closed.
362     // Don't close the socket if it's still writing.
363     server_closed_ = true;
364   } else if (result > 0 && read_buf_) {
365     result = DidReceiveData(result);
366   }
367   DoLoop(result);
368 }
369 
OnWriteCompleted(int result)370 void SocketStream::OnWriteCompleted(int result) {
371   if (result >= 0 && write_buf_) {
372     result = DidSendData(result);
373   }
374   DoLoop(result);
375 }
376 
DoLoop(int result)377 void SocketStream::DoLoop(int result) {
378   // If context was not set, close immediately.
379   if (!context_)
380     next_state_ = STATE_CLOSE;
381 
382   if (next_state_ == STATE_NONE)
383     return;
384 
385   do {
386     State state = next_state_;
387     next_state_ = STATE_NONE;
388     switch (state) {
389       case STATE_RESOLVE_PROXY:
390         DCHECK_EQ(OK, result);
391         result = DoResolveProxy();
392         break;
393       case STATE_RESOLVE_PROXY_COMPLETE:
394         result = DoResolveProxyComplete(result);
395         break;
396       case STATE_RESOLVE_HOST:
397         DCHECK_EQ(OK, result);
398         result = DoResolveHost();
399         break;
400       case STATE_RESOLVE_HOST_COMPLETE:
401         result = DoResolveHostComplete(result);
402         break;
403       case STATE_TCP_CONNECT:
404         result = DoTcpConnect(result);
405         break;
406       case STATE_TCP_CONNECT_COMPLETE:
407         result = DoTcpConnectComplete(result);
408         break;
409       case STATE_WRITE_TUNNEL_HEADERS:
410         DCHECK_EQ(OK, result);
411         result = DoWriteTunnelHeaders();
412         break;
413       case STATE_WRITE_TUNNEL_HEADERS_COMPLETE:
414         result = DoWriteTunnelHeadersComplete(result);
415         break;
416       case STATE_READ_TUNNEL_HEADERS:
417         DCHECK_EQ(OK, result);
418         result = DoReadTunnelHeaders();
419         break;
420       case STATE_READ_TUNNEL_HEADERS_COMPLETE:
421         result = DoReadTunnelHeadersComplete(result);
422         break;
423       case STATE_SOCKS_CONNECT:
424         DCHECK_EQ(OK, result);
425         result = DoSOCKSConnect();
426         break;
427       case STATE_SOCKS_CONNECT_COMPLETE:
428         result = DoSOCKSConnectComplete(result);
429         break;
430       case STATE_SSL_CONNECT:
431         DCHECK_EQ(OK, result);
432         result = DoSSLConnect();
433         break;
434       case STATE_SSL_CONNECT_COMPLETE:
435         result = DoSSLConnectComplete(result);
436         break;
437       case STATE_READ_WRITE:
438         result = DoReadWrite(result);
439         break;
440       case STATE_AUTH_REQUIRED:
441         // It might be called when DoClose is called while waiting in
442         // STATE_AUTH_REQUIRED.
443         Finish(result);
444         return;
445       case STATE_CLOSE:
446         DCHECK_LE(result, OK);
447         Finish(result);
448         return;
449       default:
450         NOTREACHED() << "bad state " << state;
451         Finish(result);
452         return;
453     }
454     // If the connection is not established yet and had actual errors,
455     // close the connection.
456     if (state != STATE_READ_WRITE && result < ERR_IO_PENDING) {
457       DCHECK_EQ(next_state_, STATE_CLOSE);
458       net_log_.EndEventWithNetErrorCode(
459           NetLog::TYPE_SOCKET_STREAM_CONNECT, result);
460     }
461   } while (result != ERR_IO_PENDING);
462 }
463 
DoResolveProxy()464 int SocketStream::DoResolveProxy() {
465   DCHECK(!pac_request_);
466   next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
467 
468   if (!proxy_url_.is_valid()) {
469     next_state_ = STATE_CLOSE;
470     return ERR_INVALID_ARGUMENT;
471   }
472 
473   return proxy_service()->ResolveProxy(
474       proxy_url_, &proxy_info_, &io_callback_, &pac_request_, net_log_);
475 }
476 
DoResolveProxyComplete(int result)477 int SocketStream::DoResolveProxyComplete(int result) {
478   pac_request_ = NULL;
479   if (result != OK) {
480     LOG(ERROR) << "Failed to resolve proxy: " << result;
481     if (delegate_)
482       delegate_->OnError(this, result);
483     proxy_info_.UseDirect();
484   }
485   if (proxy_info_.is_direct()) {
486     // If proxy was not found for original URL (i.e. websocket URL),
487     // try again with https URL, like Safari implementation.
488     // Note that we don't want to use http proxy, because we'll use tunnel
489     // proxy using CONNECT method, which is used by https proxy.
490     if (!proxy_url_.SchemeIs("https")) {
491       const std::string scheme = "https";
492       GURL::Replacements repl;
493       repl.SetSchemeStr(scheme);
494       proxy_url_ = url_.ReplaceComponents(repl);
495       DVLOG(1) << "Try https proxy: " << proxy_url_;
496       next_state_ = STATE_RESOLVE_PROXY;
497       return OK;
498     }
499   }
500 
501   if (proxy_info_.is_empty()) {
502     // No proxies/direct to choose from. This happens when we don't support any
503     // of the proxies in the returned list.
504     return ERR_NO_SUPPORTED_PROXIES;
505   }
506 
507   next_state_ = STATE_RESOLVE_HOST;
508   return OK;
509 }
510 
DoResolveHost()511 int SocketStream::DoResolveHost() {
512   next_state_ = STATE_RESOLVE_HOST_COMPLETE;
513 
514   DCHECK(!proxy_info_.is_empty());
515   if (proxy_info_.is_direct())
516     proxy_mode_ = kDirectConnection;
517   else if (proxy_info_.proxy_server().is_socks())
518     proxy_mode_ = kSOCKSProxy;
519   else
520     proxy_mode_ = kTunnelProxy;
521 
522   // Determine the host and port to connect to.
523   HostPortPair host_port_pair;
524   if (proxy_mode_ != kDirectConnection) {
525     host_port_pair = proxy_info_.proxy_server().host_port_pair();
526   } else {
527     host_port_pair = HostPortPair::FromURL(url_);
528   }
529 
530   HostResolver::RequestInfo resolve_info(host_port_pair);
531 
532   DCHECK(host_resolver_);
533   resolver_.reset(new SingleRequestHostResolver(host_resolver_));
534   return resolver_->Resolve(resolve_info, &addresses_, &io_callback_,
535                             net_log_);
536 }
537 
DoResolveHostComplete(int result)538 int SocketStream::DoResolveHostComplete(int result) {
539   if (result == OK && delegate_) {
540     next_state_ = STATE_TCP_CONNECT;
541     result = delegate_->OnStartOpenConnection(this, &io_callback_);
542     if (result == ERR_IO_PENDING)
543       metrics_->OnWaitConnection();
544   } else {
545     next_state_ = STATE_CLOSE;
546   }
547   // TODO(ukai): if error occured, reconsider proxy after error.
548   return result;
549 }
550 
DoTcpConnect(int result)551 int SocketStream::DoTcpConnect(int result) {
552   if (result != OK) {
553     next_state_ = STATE_CLOSE;
554     return result;
555   }
556   next_state_ = STATE_TCP_CONNECT_COMPLETE;
557   DCHECK(factory_);
558   socket_.reset(factory_->CreateTransportClientSocket(addresses_,
559                                                       net_log_.net_log(),
560                                                       net_log_.source()));
561   metrics_->OnStartConnection();
562   return socket_->Connect(&io_callback_);
563 }
564 
DoTcpConnectComplete(int result)565 int SocketStream::DoTcpConnectComplete(int result) {
566   // TODO(ukai): if error occured, reconsider proxy after error.
567   if (result != OK) {
568     next_state_ = STATE_CLOSE;
569     return result;
570   }
571 
572   if (proxy_mode_ == kTunnelProxy)
573     next_state_ = STATE_WRITE_TUNNEL_HEADERS;
574   else if (proxy_mode_ == kSOCKSProxy)
575     next_state_ = STATE_SOCKS_CONNECT;
576   else if (is_secure()) {
577     next_state_ = STATE_SSL_CONNECT;
578   } else {
579     result = DidEstablishConnection();
580   }
581   return result;
582 }
583 
DoWriteTunnelHeaders()584 int SocketStream::DoWriteTunnelHeaders() {
585   DCHECK_EQ(kTunnelProxy, proxy_mode_);
586 
587   next_state_ = STATE_WRITE_TUNNEL_HEADERS_COMPLETE;
588 
589   if (!tunnel_request_headers_.get()) {
590     metrics_->OnTunnelProxy();
591     tunnel_request_headers_ = new RequestHeaders();
592     tunnel_request_headers_bytes_sent_ = 0;
593   }
594   if (tunnel_request_headers_->headers_.empty()) {
595     std::string authorization_headers;
596 
597     if (!auth_handler_.get()) {
598       // Do preemptive authentication.
599       HttpAuthCache::Entry* entry = auth_cache_.LookupByPath(
600           ProxyAuthOrigin(), std::string());
601       if (entry) {
602         scoped_ptr<HttpAuthHandler> handler_preemptive;
603         int rv_create = http_auth_handler_factory_->
604             CreatePreemptiveAuthHandlerFromString(
605                 entry->auth_challenge(), HttpAuth::AUTH_PROXY,
606                 ProxyAuthOrigin(), entry->IncrementNonceCount(),
607                 net_log_, &handler_preemptive);
608         if (rv_create == OK) {
609           auth_identity_.source = HttpAuth::IDENT_SRC_PATH_LOOKUP;
610           auth_identity_.invalid = false;
611           auth_identity_.username = entry->username();
612           auth_identity_.password = entry->password();
613           auth_handler_.swap(handler_preemptive);
614         }
615       }
616     }
617 
618     // Support basic authentication scheme only, because we don't have
619     // HttpRequestInfo.
620     // TODO(ukai): Add support other authentication scheme.
621     if (auth_handler_.get() &&
622         auth_handler_->auth_scheme() == HttpAuth::AUTH_SCHEME_BASIC) {
623       HttpRequestInfo request_info;
624       std::string auth_token;
625       int rv = auth_handler_->GenerateAuthToken(
626           &auth_identity_.username,
627           &auth_identity_.password,
628           &request_info,
629           NULL,
630           &auth_token);
631       // TODO(cbentzel): Support async auth handlers.
632       DCHECK_NE(ERR_IO_PENDING, rv);
633       if (rv != OK)
634         return rv;
635       authorization_headers.append(
636           HttpAuth::GetAuthorizationHeaderName(HttpAuth::AUTH_PROXY) +
637           ": " + auth_token + "\r\n");
638     }
639 
640     tunnel_request_headers_->headers_ = base::StringPrintf(
641         "CONNECT %s HTTP/1.1\r\n"
642         "Host: %s\r\n"
643         "Proxy-Connection: keep-alive\r\n",
644         GetHostAndPort(url_).c_str(),
645         GetHostAndOptionalPort(url_).c_str());
646     if (!authorization_headers.empty())
647       tunnel_request_headers_->headers_ += authorization_headers;
648     tunnel_request_headers_->headers_ += "\r\n";
649   }
650   tunnel_request_headers_->SetDataOffset(tunnel_request_headers_bytes_sent_);
651   int buf_len = static_cast<int>(tunnel_request_headers_->headers_.size() -
652                                  tunnel_request_headers_bytes_sent_);
653   DCHECK_GT(buf_len, 0);
654   return socket_->Write(tunnel_request_headers_, buf_len, &io_callback_);
655 }
656 
DoWriteTunnelHeadersComplete(int result)657 int SocketStream::DoWriteTunnelHeadersComplete(int result) {
658   DCHECK_EQ(kTunnelProxy, proxy_mode_);
659 
660   if (result < 0) {
661     next_state_ = STATE_CLOSE;
662     return result;
663   }
664 
665   tunnel_request_headers_bytes_sent_ += result;
666   if (tunnel_request_headers_bytes_sent_ <
667       tunnel_request_headers_->headers_.size())
668     next_state_ = STATE_WRITE_TUNNEL_HEADERS;
669   else
670     next_state_ = STATE_READ_TUNNEL_HEADERS;
671   return OK;
672 }
673 
DoReadTunnelHeaders()674 int SocketStream::DoReadTunnelHeaders() {
675   DCHECK_EQ(kTunnelProxy, proxy_mode_);
676 
677   next_state_ = STATE_READ_TUNNEL_HEADERS_COMPLETE;
678 
679   if (!tunnel_response_headers_.get()) {
680     tunnel_response_headers_ = new ResponseHeaders();
681     tunnel_response_headers_capacity_ = kMaxTunnelResponseHeadersSize;
682     tunnel_response_headers_->Realloc(tunnel_response_headers_capacity_);
683     tunnel_response_headers_len_ = 0;
684   }
685 
686   int buf_len = tunnel_response_headers_capacity_ -
687       tunnel_response_headers_len_;
688   tunnel_response_headers_->SetDataOffset(tunnel_response_headers_len_);
689   CHECK(tunnel_response_headers_->data());
690 
691   return socket_->Read(tunnel_response_headers_, buf_len, &io_callback_);
692 }
693 
DoReadTunnelHeadersComplete(int result)694 int SocketStream::DoReadTunnelHeadersComplete(int result) {
695   DCHECK_EQ(kTunnelProxy, proxy_mode_);
696 
697   if (result < 0) {
698     next_state_ = STATE_CLOSE;
699     return result;
700   }
701 
702   if (result == 0) {
703     // 0 indicates end-of-file, so socket was closed.
704     next_state_ = STATE_CLOSE;
705     return ERR_CONNECTION_CLOSED;
706   }
707 
708   tunnel_response_headers_len_ += result;
709   DCHECK(tunnel_response_headers_len_ <= tunnel_response_headers_capacity_);
710 
711   int eoh = HttpUtil::LocateEndOfHeaders(
712       tunnel_response_headers_->headers(), tunnel_response_headers_len_, 0);
713   if (eoh == -1) {
714     if (tunnel_response_headers_len_ >= kMaxTunnelResponseHeadersSize) {
715       next_state_ = STATE_CLOSE;
716       return ERR_RESPONSE_HEADERS_TOO_BIG;
717     }
718 
719     next_state_ = STATE_READ_TUNNEL_HEADERS;
720     return OK;
721   }
722   // DidReadResponseHeaders
723   scoped_refptr<HttpResponseHeaders> headers;
724   headers = new HttpResponseHeaders(
725       HttpUtil::AssembleRawHeaders(tunnel_response_headers_->headers(), eoh));
726   if (headers->GetParsedHttpVersion() < HttpVersion(1, 0)) {
727     // Require the "HTTP/1.x" status line.
728     next_state_ = STATE_CLOSE;
729     return ERR_TUNNEL_CONNECTION_FAILED;
730   }
731   switch (headers->response_code()) {
732     case 200:  // OK
733       if (is_secure()) {
734         DCHECK_EQ(eoh, tunnel_response_headers_len_);
735         next_state_ = STATE_SSL_CONNECT;
736       } else {
737         result = DidEstablishConnection();
738         if (result < 0) {
739           next_state_ = STATE_CLOSE;
740           return result;
741         }
742         if ((eoh < tunnel_response_headers_len_) && delegate_)
743           delegate_->OnReceivedData(
744               this, tunnel_response_headers_->headers() + eoh,
745               tunnel_response_headers_len_ - eoh);
746       }
747       return OK;
748     case 407:  // Proxy Authentication Required.
749       result = HandleAuthChallenge(headers.get());
750       if (result == ERR_PROXY_AUTH_UNSUPPORTED &&
751           auth_handler_.get() && delegate_) {
752         DCHECK(!proxy_info_.is_empty());
753         auth_info_ = new AuthChallengeInfo;
754         auth_info_->is_proxy = true;
755         auth_info_->host_and_port =
756             ASCIIToWide(proxy_info_.proxy_server().host_port_pair().ToString());
757         auth_info_->scheme = ASCIIToWide(
758             HttpAuth::SchemeToString(auth_handler_->auth_scheme()));
759         auth_info_->realm = ASCIIToWide(auth_handler_->realm());
760         // Wait until RestartWithAuth or Close is called.
761         MessageLoop::current()->PostTask(
762             FROM_HERE,
763             NewRunnableMethod(this, &SocketStream::DoAuthRequired));
764         next_state_ = STATE_AUTH_REQUIRED;
765         return ERR_IO_PENDING;
766       }
767     default:
768       break;
769   }
770   next_state_ = STATE_CLOSE;
771   return ERR_TUNNEL_CONNECTION_FAILED;
772 }
773 
DoSOCKSConnect()774 int SocketStream::DoSOCKSConnect() {
775   DCHECK_EQ(kSOCKSProxy, proxy_mode_);
776 
777   next_state_ = STATE_SOCKS_CONNECT_COMPLETE;
778 
779   ClientSocket* s = socket_.release();
780   HostResolver::RequestInfo req_info(HostPortPair::FromURL(url_));
781 
782   DCHECK(!proxy_info_.is_empty());
783   if (proxy_info_.proxy_server().scheme() == ProxyServer::SCHEME_SOCKS5)
784     s = new SOCKS5ClientSocket(s, req_info);
785   else
786     s = new SOCKSClientSocket(s, req_info, host_resolver_);
787   socket_.reset(s);
788   metrics_->OnSOCKSProxy();
789   return socket_->Connect(&io_callback_);
790 }
791 
DoSOCKSConnectComplete(int result)792 int SocketStream::DoSOCKSConnectComplete(int result) {
793   DCHECK_EQ(kSOCKSProxy, proxy_mode_);
794 
795   if (result == OK) {
796     if (is_secure())
797       next_state_ = STATE_SSL_CONNECT;
798     else
799       result = DidEstablishConnection();
800   } else {
801     next_state_ = STATE_CLOSE;
802   }
803   return result;
804 }
805 
DoSSLConnect()806 int SocketStream::DoSSLConnect() {
807   DCHECK(factory_);
808   // TODO(agl): look into plumbing SSLHostInfo here.
809   socket_.reset(factory_->CreateSSLClientSocket(socket_.release(),
810                                                 HostPortPair::FromURL(url_),
811                                                 ssl_config_,
812                                                 NULL /* ssl_host_info */,
813                                                 cert_verifier_));
814   next_state_ = STATE_SSL_CONNECT_COMPLETE;
815   metrics_->OnSSLConnection();
816   return socket_->Connect(&io_callback_);
817 }
818 
DoSSLConnectComplete(int result)819 int SocketStream::DoSSLConnectComplete(int result) {
820   if (IsCertificateError(result)) {
821     if (socket_->IsConnectedAndIdle()) {
822       result = HandleCertificateError(result);
823     } else {
824       // SSLClientSocket for Mac will report socket is not connected,
825       // if it returns cert verification error.  It didn't perform
826       // SSLHandshake yet.
827       // So, we should restart establishing connection with the
828       // certificate in allowed bad certificates in |ssl_config_|.
829       // See also net/http/http_network_transaction.cc
830       //  HandleCertificateError() and RestartIgnoringLastError().
831       SSLClientSocket* ssl_socket =
832         reinterpret_cast<SSLClientSocket*>(socket_.get());
833       SSLInfo ssl_info;
834       ssl_socket->GetSSLInfo(&ssl_info);
835       if (ssl_config_.IsAllowedBadCert(ssl_info.cert)) {
836         // If we already have the certificate in the set of allowed bad
837         // certificates, we did try it and failed again, so we should not
838         // retry again: the connection should fail at last.
839         next_state_ = STATE_CLOSE;
840         return result;
841       }
842       // Add the bad certificate to the set of allowed certificates in the
843       // SSL config object.
844       SSLConfig::CertAndStatus bad_cert;
845       bad_cert.cert = ssl_info.cert;
846       bad_cert.cert_status = ssl_info.cert_status;
847       ssl_config_.allowed_bad_certs.push_back(bad_cert);
848       // Restart connection ignoring the bad certificate.
849       socket_->Disconnect();
850       socket_.reset();
851       next_state_ = STATE_TCP_CONNECT;
852       return OK;
853     }
854   }
855 
856   if (result == OK)
857     result = DidEstablishConnection();
858   else
859     next_state_ = STATE_CLOSE;
860   return result;
861 }
862 
DoReadWrite(int result)863 int SocketStream::DoReadWrite(int result) {
864   if (result < OK) {
865     next_state_ = STATE_CLOSE;
866     return result;
867   }
868   if (!socket_.get() || !socket_->IsConnected()) {
869     next_state_ = STATE_CLOSE;
870     return ERR_CONNECTION_CLOSED;
871   }
872 
873   // If client has requested close(), and there's nothing to write, then
874   // let's close the socket.
875   // We don't care about receiving data after the socket is closed.
876   if (closing_ && !write_buf_ && pending_write_bufs_.empty()) {
877     socket_->Disconnect();
878     next_state_ = STATE_CLOSE;
879     return OK;
880   }
881 
882   next_state_ = STATE_READ_WRITE;
883 
884   // If server already closed the socket, we don't try to read.
885   if (!server_closed_) {
886     if (!read_buf_) {
887       // No read pending and server didn't close the socket.
888       read_buf_ = new IOBuffer(kReadBufferSize);
889       result = socket_->Read(read_buf_, kReadBufferSize, &read_callback_);
890       if (result > 0) {
891         return DidReceiveData(result);
892       } else if (result == 0) {
893         // 0 indicates end-of-file, so socket was closed.
894         next_state_ = STATE_CLOSE;
895         server_closed_ = true;
896         return ERR_CONNECTION_CLOSED;
897       }
898       // If read is pending, try write as well.
899       // Otherwise, return the result and do next loop (to close the
900       // connection).
901       if (result != ERR_IO_PENDING) {
902         next_state_ = STATE_CLOSE;
903         server_closed_ = true;
904         return result;
905       }
906     }
907     // Read is pending.
908     DCHECK(read_buf_);
909   }
910 
911   if (write_buf_ && !current_write_buf_) {
912     // No write pending.
913     current_write_buf_ = new DrainableIOBuffer(write_buf_, write_buf_size_);
914     current_write_buf_->SetOffset(write_buf_offset_);
915     result = socket_->Write(current_write_buf_,
916                             current_write_buf_->BytesRemaining(),
917                             &write_callback_);
918     if (result > 0) {
919       return DidSendData(result);
920     }
921     // If write is not pending, return the result and do next loop (to close
922     // the connection).
923     if (result != 0 && result != ERR_IO_PENDING) {
924       next_state_ = STATE_CLOSE;
925       return result;
926     }
927     return result;
928   }
929 
930   // We arrived here when both operation is pending.
931   return ERR_IO_PENDING;
932 }
933 
ProxyAuthOrigin() const934 GURL SocketStream::ProxyAuthOrigin() const {
935   DCHECK(!proxy_info_.is_empty());
936   return GURL("http://" +
937               proxy_info_.proxy_server().host_port_pair().ToString());
938 }
939 
HandleAuthChallenge(const HttpResponseHeaders * headers)940 int SocketStream::HandleAuthChallenge(const HttpResponseHeaders* headers) {
941   GURL auth_origin(ProxyAuthOrigin());
942 
943   VLOG(1) << "The proxy " << auth_origin << " requested auth";
944 
945   // TODO(cbentzel): Since SocketStream only suppports basic authentication
946   // right now, another challenge is always treated as a rejection.
947   // Ultimately this should be converted to use HttpAuthController like the
948   // HttpNetworkTransaction has.
949   if (auth_handler_.get() && !auth_identity_.invalid) {
950     if (auth_identity_.source != HttpAuth::IDENT_SRC_PATH_LOOKUP)
951       auth_cache_.Remove(auth_origin,
952                          auth_handler_->realm(),
953                          auth_handler_->auth_scheme(),
954                          auth_identity_.username,
955                          auth_identity_.password);
956     auth_handler_.reset();
957     auth_identity_ = HttpAuth::Identity();
958   }
959 
960   auth_identity_.invalid = true;
961   std::set<HttpAuth::Scheme> disabled_schemes;
962   HttpAuth::ChooseBestChallenge(http_auth_handler_factory_, headers,
963                                 HttpAuth::AUTH_PROXY,
964                                 auth_origin, disabled_schemes,
965                                 net_log_, &auth_handler_);
966   if (!auth_handler_.get()) {
967     LOG(ERROR) << "Can't perform auth to the proxy " << auth_origin;
968     return ERR_TUNNEL_CONNECTION_FAILED;
969   }
970   if (auth_handler_->NeedsIdentity()) {
971     // We only support basic authentication scheme now.
972     // TODO(ukai): Support other authentication scheme.
973     HttpAuthCache::Entry* entry = auth_cache_.Lookup(
974         auth_origin, auth_handler_->realm(), HttpAuth::AUTH_SCHEME_BASIC);
975     if (entry) {
976       auth_identity_.source = HttpAuth::IDENT_SRC_REALM_LOOKUP;
977       auth_identity_.invalid = false;
978       auth_identity_.username = entry->username();
979       auth_identity_.password = entry->password();
980       // Restart with auth info.
981     }
982     return ERR_PROXY_AUTH_UNSUPPORTED;
983   } else {
984     auth_identity_.invalid = false;
985   }
986   return ERR_TUNNEL_CONNECTION_FAILED;
987 }
988 
DoAuthRequired()989 void SocketStream::DoAuthRequired() {
990   if (delegate_ && auth_info_.get())
991     delegate_->OnAuthRequired(this, auth_info_.get());
992   else
993     DoLoop(ERR_UNEXPECTED);
994 }
995 
DoRestartWithAuth()996 void SocketStream::DoRestartWithAuth() {
997   DCHECK_EQ(next_state_, STATE_AUTH_REQUIRED);
998   auth_cache_.Add(ProxyAuthOrigin(),
999                   auth_handler_->realm(),
1000                   auth_handler_->auth_scheme(),
1001                   auth_handler_->challenge(),
1002                   auth_identity_.username,
1003                   auth_identity_.password,
1004                   std::string());
1005 
1006   tunnel_request_headers_ = NULL;
1007   tunnel_request_headers_bytes_sent_ = 0;
1008   tunnel_response_headers_ = NULL;
1009   tunnel_response_headers_capacity_ = 0;
1010   tunnel_response_headers_len_ = 0;
1011 
1012   next_state_ = STATE_TCP_CONNECT;
1013   DoLoop(OK);
1014 }
1015 
HandleCertificateError(int result)1016 int SocketStream::HandleCertificateError(int result) {
1017   // TODO(ukai): handle cert error properly.
1018   switch (result) {
1019     case ERR_CERT_COMMON_NAME_INVALID:
1020     case ERR_CERT_DATE_INVALID:
1021     case ERR_CERT_AUTHORITY_INVALID:
1022       result = OK;
1023       break;
1024     default:
1025       break;
1026   }
1027   return result;
1028 }
1029 
ssl_config_service() const1030 SSLConfigService* SocketStream::ssl_config_service() const {
1031   return context_->ssl_config_service();
1032 }
1033 
proxy_service() const1034 ProxyService* SocketStream::proxy_service() const {
1035   return context_->proxy_service();
1036 }
1037 
1038 }  // namespace net
1039