Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(373)

Side by Side Diff: jingle/notifier/base/chrome_async_socket.cc

Issue 6833031: Changed the jingle network code in ChromeAsyncSocket to use the client socket pool. This also all... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Lint fix Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "jingle/notifier/base/chrome_async_socket.h" 5 #include "jingle/notifier/base/chrome_async_socket.h"
6 6
7 #if defined(OS_WIN) 7 #if defined(OS_WIN)
8 #include <winsock2.h> 8 #include <winsock2.h>
9 #elif defined(OS_POSIX) 9 #elif defined(OS_POSIX)
10 #include <arpa/inet.h> 10 #include <arpa/inet.h>
11 #endif 11 #endif
12 12
13 #include <algorithm> 13 #include <algorithm>
14 #include <cstring> 14 #include <cstring>
15 #include <cstdlib> 15 #include <cstdlib>
16 16
17 #include "base/basictypes.h" 17 #include "base/basictypes.h"
18 #include "base/compiler_specific.h" 18 #include "base/compiler_specific.h"
19 #include "base/logging.h" 19 #include "base/logging.h"
20 #include "base/message_loop.h" 20 #include "base/message_loop.h"
21 #include "jingle/notifier/base/fake_ssl_client_socket.h"
21 #include "net/base/address_list.h" 22 #include "net/base/address_list.h"
22 #include "net/base/host_port_pair.h" 23 #include "net/base/host_port_pair.h"
23 #include "net/base/io_buffer.h" 24 #include "net/base/io_buffer.h"
24 #include "net/base/net_util.h" 25 #include "net/base/net_util.h"
25 #include "net/base/ssl_config_service.h" 26 #include "net/base/ssl_config_service.h"
26 #include "net/base/sys_addrinfo.h" 27 #include "net/base/sys_addrinfo.h"
28 #include "net/http/http_network_session.h"
27 #include "net/socket/client_socket_factory.h" 29 #include "net/socket/client_socket_factory.h"
30 #include "net/socket/client_socket_handle.h"
31 #include "net/socket/client_socket_pool_manager.h"
28 #include "net/socket/ssl_client_socket.h" 32 #include "net/socket/ssl_client_socket.h"
29 #include "net/socket/tcp_client_socket.h" 33 #include "net/socket/tcp_client_socket.h"
34 #include "net/url_request/url_request_context.h"
35 #include "net/url_request/url_request_context_getter.h"
30 #include "talk/base/socketaddress.h" 36 #include "talk/base/socketaddress.h"
31 37
32 namespace notifier { 38 namespace notifier {
33 39
34 ChromeAsyncSocket::ChromeAsyncSocket( 40 ChromeAsyncSocket::ChromeAsyncSocket(
35 net::ClientSocketFactory* client_socket_factory,
36 const net::SSLConfig& ssl_config, 41 const net::SSLConfig& ssl_config,
37 net::CertVerifier* cert_verifier, 42 const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
akalin 2011/04/13 20:49:32 It seems to me that a socket shouldn't need to kno
sanjeevr 2011/04/13 21:20:21 This is not straightforward. Basically there is co
43 bool use_fake_ssl_client_socket,
38 size_t read_buf_size, 44 size_t read_buf_size,
39 size_t write_buf_size, 45 size_t write_buf_size,
40 net::NetLog* net_log) 46 net::NetLog* net_log)
41 : connect_callback_(ALLOW_THIS_IN_INITIALIZER_LIST(this), 47 : proxy_resolve_callback_(ALLOW_THIS_IN_INITIALIZER_LIST(this),
48 &ChromeAsyncSocket::ProcessProxyResolveDone),
49 connect_callback_(ALLOW_THIS_IN_INITIALIZER_LIST(this),
42 &ChromeAsyncSocket::ProcessConnectDone), 50 &ChromeAsyncSocket::ProcessConnectDone),
43 read_callback_(ALLOW_THIS_IN_INITIALIZER_LIST(this), 51 read_callback_(ALLOW_THIS_IN_INITIALIZER_LIST(this),
44 &ChromeAsyncSocket::ProcessReadDone), 52 &ChromeAsyncSocket::ProcessReadDone),
45 write_callback_(ALLOW_THIS_IN_INITIALIZER_LIST(this), 53 write_callback_(ALLOW_THIS_IN_INITIALIZER_LIST(this),
46 &ChromeAsyncSocket::ProcessWriteDone), 54 &ChromeAsyncSocket::ProcessWriteDone),
47 ssl_connect_callback_(ALLOW_THIS_IN_INITIALIZER_LIST(this), 55 ssl_connect_callback_(ALLOW_THIS_IN_INITIALIZER_LIST(this),
48 &ChromeAsyncSocket::ProcessSSLConnectDone), 56 &ChromeAsyncSocket::ProcessSSLConnectDone),
49 client_socket_factory_(client_socket_factory), 57 fake_ssl_handshake_callback_(ALLOW_THIS_IN_INITIALIZER_LIST(this),
akalin 2011/04/13 20:49:32 i don't think ChromeAsyncSocket should know anythi
sanjeevr 2011/04/13 21:20:21 Yes, we can supply this layer externally.
58 &ChromeAsyncSocket::ProcessFakeSSLHandshakeDone),
50 ssl_config_(ssl_config), 59 ssl_config_(ssl_config),
51 cert_verifier_(cert_verifier), 60 request_context_getter_(request_context_getter),
61 use_fake_ssl_client_socket_(use_fake_ssl_client_socket),
52 bound_net_log_( 62 bound_net_log_(
53 net::BoundNetLog::Make(net_log, net::NetLog::SOURCE_SOCKET)), 63 net::BoundNetLog::Make(net_log, net::NetLog::SOURCE_SOCKET)),
54 state_(STATE_CLOSED), 64 state_(STATE_CLOSED),
55 error_(ERROR_NONE), 65 error_(ERROR_NONE),
56 net_error_(net::OK), 66 net_error_(net::OK),
57 scoped_runnable_method_factory_( 67 scoped_runnable_method_factory_(
58 ALLOW_THIS_IN_INITIALIZER_LIST(this)), 68 ALLOW_THIS_IN_INITIALIZER_LIST(this)),
69 pac_request_(NULL),
70 tried_direct_connect_fallback_(false),
59 read_state_(IDLE), 71 read_state_(IDLE),
60 read_buf_(new net::IOBufferWithSize(read_buf_size)), 72 read_buf_(new net::IOBufferWithSize(read_buf_size)),
61 read_start_(0U), 73 read_start_(0U),
62 read_end_(0U), 74 read_end_(0U),
63 write_state_(IDLE), 75 write_state_(IDLE),
64 write_buf_(new net::IOBufferWithSize(write_buf_size)), 76 write_buf_(new net::IOBufferWithSize(write_buf_size)),
65 write_end_(0U) { 77 write_end_(0U) {
66 DCHECK(client_socket_factory_.get()); 78 DCHECK(request_context_getter_.get());
67 DCHECK_GT(read_buf_size, 0U); 79 DCHECK_GT(read_buf_size, 0U);
68 DCHECK_GT(write_buf_size, 0U); 80 DCHECK_GT(write_buf_size, 0U);
81 net::HttpNetworkSession::Params session_params;
akalin 2011/04/13 20:49:32 It seems to me that you can at least construct the
sanjeevr 2011/04/13 21:20:21 This is also doable (though it is almost the same
82 session_params.host_resolver =
83 request_context_getter_->GetURLRequestContext()->host_resolver();
84 session_params.cert_verifier =
85 request_context_getter_->GetURLRequestContext()->cert_verifier();
86 session_params.dnsrr_resolver =
87 request_context_getter_->GetURLRequestContext()->dnsrr_resolver();
88 session_params.proxy_service =
89 request_context_getter_->GetURLRequestContext()->proxy_service();
90 session_params.ssl_config_service =
91 request_context_getter_->GetURLRequestContext()->ssl_config_service();
92 session_params.http_auth_handler_factory =
93 request_context_getter_->GetURLRequestContext()->
94 http_auth_handler_factory();
95 network_session_ = new net::HttpNetworkSession(session_params);
69 } 96 }
70 97
71 ChromeAsyncSocket::~ChromeAsyncSocket() {} 98 ChromeAsyncSocket::~ChromeAsyncSocket() {}
72 99
73 ChromeAsyncSocket::State ChromeAsyncSocket::state() { 100 ChromeAsyncSocket::State ChromeAsyncSocket::state() {
74 return state_; 101 return state_;
75 } 102 }
76 103
77 ChromeAsyncSocket::Error ChromeAsyncSocket::error() { 104 ChromeAsyncSocket::Error ChromeAsyncSocket::error() {
78 return error_; 105 return error_;
(...skipping 17 matching lines...) Expand all
96 void ChromeAsyncSocket::DoNetError(net::Error net_error) { 123 void ChromeAsyncSocket::DoNetError(net::Error net_error) {
97 error_ = ERROR_WINSOCK; 124 error_ = ERROR_WINSOCK;
98 net_error_ = net_error; 125 net_error_ = net_error;
99 } 126 }
100 127
101 void ChromeAsyncSocket::DoNetErrorFromStatus(int status) { 128 void ChromeAsyncSocket::DoNetErrorFromStatus(int status) {
102 DCHECK_LT(status, net::OK); 129 DCHECK_LT(status, net::OK);
103 DoNetError(static_cast<net::Error>(status)); 130 DoNetError(static_cast<net::Error>(status));
104 } 131 }
105 132
133 // STATE_CLOSED -> STATE_CONNECTING
134 bool ChromeAsyncSocket::Connect(const talk_base::SocketAddress& address) {
135 // Bypass for unit-tests.
136 if (client_socket_factory_.get())
137 return ConnectUsingFactory(address);
138
139 if (state_ != STATE_CLOSED) {
140 LOG(DFATAL) << "Connect() called on non-closed socket";
141 DoNonNetError(ERROR_WRONGSTATE);
142 return false;
143 }
144
145 // We can't work with an empty hostname and IP address.
146 if (address.hostname().empty() && (address.ip() == 0)) {
147 DoNonNetError(ERROR_DNS);
148 return false;
149 }
150
151
152 DCHECK_EQ(state_, buzz::AsyncSocket::STATE_CLOSED);
153 DCHECK_EQ(read_state_, IDLE);
154 DCHECK_EQ(write_state_, IDLE);
155
156 state_ = STATE_CONNECTING;
157
158 DCHECK(scoped_runnable_method_factory_.empty());
159 scoped_runnable_method_factory_.RevokeAll();
160
161 // First we try and resolve the proxy.
162 dest_host_port_pair_ =
163 net::HostPortPair(address.IPAsString(), address.port());
164
165 GURL url = GURL("http://" + dest_host_port_pair_.ToString());
166 int status = request_context_getter_->GetURLRequestContext()->
167 proxy_service()->ResolveProxy(url,
168 &proxy_info_,
169 &proxy_resolve_callback_,
170 &pac_request_,
171 bound_net_log_);
172 if (status != net::ERR_IO_PENDING) {
173 ProcessProxyResolveDone(status);
174 }
175 return true;
176 }
177
106 namespace { 178 namespace {
107 179
108 // Takes a 32-bit integer in host byte order and converts it to a 180 // Takes a 32-bit integer in host byte order and converts it to a
109 // net::IPAddressNumber. 181 // net::IPAddressNumber.
110 net::IPAddressNumber Uint32ToIPAddressNumber(uint32 ip) { 182 net::IPAddressNumber Uint32ToIPAddressNumber(uint32 ip) {
111 uint32 ip_nbo = htonl(ip); 183 uint32 ip_nbo = htonl(ip);
112 const unsigned char* const ip_start = 184 const unsigned char* const ip_start =
113 reinterpret_cast<const unsigned char*>(&ip_nbo); 185 reinterpret_cast<const unsigned char*>(&ip_nbo);
114 return net::IPAddressNumber(ip_start, ip_start + (sizeof ip_nbo)); 186 return net::IPAddressNumber(ip_start, ip_start + (sizeof ip_nbo));
115 } 187 }
116 188
117 net::AddressList SocketAddressToAddressList( 189 net::AddressList SocketAddressToAddressList(
118 const talk_base::SocketAddress& address) { 190 const talk_base::SocketAddress& address) {
119 DCHECK_NE(address.ip(), 0U); 191 DCHECK_NE(address.ip(), 0U);
120 return net::AddressList(Uint32ToIPAddressNumber(address.ip()), 192 return net::AddressList(Uint32ToIPAddressNumber(address.ip()),
121 address.port(), false); 193 address.port(), false);
122 } 194 }
123 195
124 } // namespace 196 } // namespace
125 197
126 // STATE_CLOSED -> STATE_CONNECTING 198 bool ChromeAsyncSocket::ConnectUsingFactory(
127 199 const talk_base::SocketAddress& address) {
128 bool ChromeAsyncSocket::Connect(const talk_base::SocketAddress& address) {
129 if (state_ != STATE_CLOSED) { 200 if (state_ != STATE_CLOSED) {
130 LOG(DFATAL) << "Connect() called on non-closed socket"; 201 LOG(DFATAL) << "Connect() called on non-closed socket";
131 DoNonNetError(ERROR_WRONGSTATE); 202 DoNonNetError(ERROR_WRONGSTATE);
132 return false; 203 return false;
133 } 204 }
205
134 if (address.ip() == 0) { 206 if (address.ip() == 0) {
135 DoNonNetError(ERROR_DNS); 207 DoNonNetError(ERROR_DNS);
136 return false; 208 return false;
137 } 209 }
138 210
139 DCHECK_EQ(state_, buzz::AsyncSocket::STATE_CLOSED); 211 DCHECK_EQ(state_, buzz::AsyncSocket::STATE_CLOSED);
140 DCHECK_EQ(read_state_, IDLE); 212 DCHECK_EQ(read_state_, IDLE);
141 DCHECK_EQ(write_state_, IDLE); 213 DCHECK_EQ(write_state_, IDLE);
142 214
143 state_ = STATE_CONNECTING; 215 state_ = STATE_CONNECTING;
144 216
145 DCHECK(scoped_runnable_method_factory_.empty()); 217 DCHECK(scoped_runnable_method_factory_.empty());
146 scoped_runnable_method_factory_.RevokeAll(); 218 scoped_runnable_method_factory_.RevokeAll();
147 219
148 net::AddressList address_list = SocketAddressToAddressList(address); 220 net::AddressList address_list = SocketAddressToAddressList(address);
149 transport_socket_.reset( 221 net::ClientSocket* transport_socket =
150 client_socket_factory_->CreateTransportClientSocket( 222 client_socket_factory_->CreateTransportClientSocket(
151 address_list, bound_net_log_.net_log(), net::NetLog::Source())); 223 address_list, bound_net_log_.net_log(), net::NetLog::Source());
152 int status = transport_socket_->Connect(&connect_callback_); 224 int status = transport_socket->Connect(&connect_callback_);
225 connection_.reset(new net::ClientSocketHandle);
226 connection_->set_socket(transport_socket);
153 if (status != net::ERR_IO_PENDING) { 227 if (status != net::ERR_IO_PENDING) {
154 // We defer execution of ProcessConnectDone instead of calling it 228 // We defer execution of ProcessConnectDone instead of calling it
155 // directly here as the caller may not expect an error/close to 229 // directly here as the caller may not expect an error/close to
156 // happen here. This is okay, as from the caller's point of view, 230 // happen here. This is okay, as from the caller's point of view,
157 // the connect always happens asynchronously. 231 // the connect always happens asynchronously.
158 MessageLoop* message_loop = MessageLoop::current(); 232 MessageLoop* message_loop = MessageLoop::current();
159 CHECK(message_loop); 233 CHECK(message_loop);
160 message_loop->PostTask( 234 message_loop->PostTask(
161 FROM_HERE, 235 FROM_HERE,
162 scoped_runnable_method_factory_.NewRunnableMethod( 236 scoped_runnable_method_factory_.NewRunnableMethod(
163 &ChromeAsyncSocket::ProcessConnectDone, status)); 237 &ChromeAsyncSocket::ProcessConnectDone, status));
164 } 238 }
165 return true; 239 return true;
166 } 240 }
167 241
242
243 void ChromeAsyncSocket::ProcessProxyResolveDone(int status) {
244 DCHECK_NE(status, net::ERR_IO_PENDING);
245 DCHECK_EQ(read_state_, IDLE);
246 DCHECK_EQ(write_state_, IDLE);
247 DCHECK_EQ(state_, STATE_CONNECTING);
248 if (status == net::OK) {
249 // Remove unsupported proxies from the list.
250 proxy_info_.RemoveProxiesWithoutScheme(
251 net::ProxyServer::SCHEME_DIRECT |
252 net::ProxyServer::SCHEME_HTTP | net::ProxyServer::SCHEME_HTTPS |
253 net::ProxyServer::SCHEME_SOCKS4 | net::ProxyServer::SCHEME_SOCKS5);
254
255 if (proxy_info_.is_empty()) {
256 // No proxies/direct to choose from. This happens when we don't support
257 // any of the proxies in the returned list.
258 status = net::ERR_NO_SUPPORTED_PROXIES;
259 }
260 }
261
262 // Since we are faking the URL, it is possible that no proxies match our URL.
263 // Try falling back to a direct connection if we have not tried that before.
264 if (status != net::OK) {
265 if (!tried_direct_connect_fallback_) {
266 tried_direct_connect_fallback_ = true;
267 proxy_info_.UseDirect();
268 } else {
269 DoNetErrorFromStatus(status);
270 DoClose();
271 return;
272 }
273 }
274
275 connection_.reset(new net::ClientSocketHandle);
akalin 2011/04/13 20:49:32 Yeah this part is weird. Shouldn't we use a socke
sanjeevr 2011/04/13 21:20:21 We are not creating the socket ourselves. InitSock
276 // Now that we have resolved the proxy, we need to connect.
277 status = net::ClientSocketPoolManager::InitSocketHandleForRawConnect(
278 dest_host_port_pair_,
279 network_session_.get(),
280 proxy_info_,
281 ssl_config_,
282 ssl_config_,
283 bound_net_log_,
284 connection_.get(),
285 &connect_callback_);
286 if (status != net::ERR_IO_PENDING) {
287 // We defer execution of ProcessConnectDone instead of calling it
288 // directly here as the caller may not expect an error/close to
289 // happen here. This is okay, as from the caller's point of view,
290 // the connect always happens asynchronously.
291 MessageLoop* message_loop = MessageLoop::current();
292 CHECK(message_loop);
293 message_loop->PostTask(
294 FROM_HERE,
295 scoped_runnable_method_factory_.NewRunnableMethod(
296 &ChromeAsyncSocket::ProcessConnectDone, status));
297 }
298 }
299
168 // STATE_CONNECTING -> STATE_OPEN 300 // STATE_CONNECTING -> STATE_OPEN
169 // read_state_ == IDLE -> read_state_ == POSTED (via PostDoRead()) 301 // read_state_ == IDLE -> read_state_ == POSTED (via PostDoRead())
170 302
171 void ChromeAsyncSocket::ProcessConnectDone(int status) { 303 void ChromeAsyncSocket::ProcessConnectDone(int status) {
172 DCHECK_NE(status, net::ERR_IO_PENDING); 304 DCHECK_NE(status, net::ERR_IO_PENDING);
173 DCHECK_EQ(read_state_, IDLE); 305 DCHECK_EQ(read_state_, IDLE);
174 DCHECK_EQ(write_state_, IDLE); 306 DCHECK_EQ(write_state_, IDLE);
175 DCHECK_EQ(state_, STATE_CONNECTING); 307 DCHECK_EQ(state_, STATE_CONNECTING);
176 if (status != net::OK) { 308 if (status != net::OK) {
309 // If the connection fails, try another proxy.
310 if (!client_socket_factory_.get())
311 status = ReconsiderProxyAfterError(status);
312 if ((status != net::OK) && (status != net::ERR_IO_PENDING)) {
313 // If no more proxies to try, we are done.
314 DoNetErrorFromStatus(status);
315 DoClose();
316 }
317 return;
318 }
319 // If we need to use a fake handshake, process that now.
320 if (use_fake_ssl_client_socket_) {
321 net::ClientSocket* fake_ssl_socket =
322 new FakeSSLClientSocket(connection_.release());
323 connection_.reset(new net::ClientSocketHandle);
324 connection_->set_socket(fake_ssl_socket);
325 status = fake_ssl_socket->Connect(&fake_ssl_handshake_callback_);
326 if (status != net::ERR_IO_PENDING)
327 ProcessFakeSSLHandshakeDone(status);
328 } else {
329 state_ = STATE_OPEN;
330 PostDoRead();
331 // Write buffer should be empty.
332 DCHECK_EQ(write_end_, 0U);
333 SignalConnected();
334 }
335 }
336
337 // STATE_CONNECTING -> STATE_OPEN
338 // read_state_ == IDLE -> read_state_ == POSTED (via PostDoRead())
339
340 void ChromeAsyncSocket::ProcessFakeSSLHandshakeDone(int status) {
341 DCHECK_NE(status, net::ERR_IO_PENDING);
342 DCHECK_EQ(read_state_, IDLE);
343 DCHECK_EQ(write_state_, IDLE);
344 DCHECK_EQ(state_, STATE_CONNECTING);
345 if (status != net::OK) {
177 DoNetErrorFromStatus(status); 346 DoNetErrorFromStatus(status);
178 DoClose(); 347 DoClose();
179 return; 348 return;
180 } 349 }
181 state_ = STATE_OPEN; 350 state_ = STATE_OPEN;
182 PostDoRead(); 351 PostDoRead();
183 // Write buffer should be empty. 352 // Write buffer should be empty.
184 DCHECK_EQ(write_end_, 0U); 353 DCHECK_EQ(write_end_, 0U);
185 SignalConnected(); 354 SignalConnected();
186 } 355 }
(...skipping 18 matching lines...) Expand all
205 374
206 void ChromeAsyncSocket::DoRead() { 375 void ChromeAsyncSocket::DoRead() {
207 DCHECK(IsOpen()); 376 DCHECK(IsOpen());
208 DCHECK_EQ(read_state_, POSTED); 377 DCHECK_EQ(read_state_, POSTED);
209 DCHECK_EQ(read_start_, 0U); 378 DCHECK_EQ(read_start_, 0U);
210 DCHECK_EQ(read_end_, 0U); 379 DCHECK_EQ(read_end_, 0U);
211 // Once we call Read(), we cannot call StartTls() until the read 380 // Once we call Read(), we cannot call StartTls() until the read
212 // finishes. This is okay, as StartTls() is called only from a read 381 // finishes. This is okay, as StartTls() is called only from a read
213 // handler (i.e., after a read finishes and before another read is 382 // handler (i.e., after a read finishes and before another read is
214 // done). 383 // done).
215 int status = 384 int status = connection_->socket()->Read(
216 transport_socket_->Read( 385 read_buf_.get(), read_buf_->size(), &read_callback_);
217 read_buf_.get(), read_buf_->size(), &read_callback_);
218 read_state_ = PENDING; 386 read_state_ = PENDING;
219 if (status != net::ERR_IO_PENDING) { 387 if (status != net::ERR_IO_PENDING) {
220 ProcessReadDone(status); 388 ProcessReadDone(status);
221 } 389 }
222 } 390 }
223 391
224 // read_state_ == PENDING -> read_state_ == IDLE 392 // read_state_ == PENDING -> read_state_ == IDLE
225 393
226 void ChromeAsyncSocket::ProcessReadDone(int status) { 394 void ChromeAsyncSocket::ProcessReadDone(int status) {
227 DCHECK_NE(status, net::ERR_IO_PENDING); 395 DCHECK_NE(status, net::ERR_IO_PENDING);
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
336 // write_state_ == POSTED -> write_state_ == PENDING 504 // write_state_ == POSTED -> write_state_ == PENDING
337 505
338 void ChromeAsyncSocket::DoWrite() { 506 void ChromeAsyncSocket::DoWrite() {
339 DCHECK(IsOpen()); 507 DCHECK(IsOpen());
340 DCHECK_EQ(write_state_, POSTED); 508 DCHECK_EQ(write_state_, POSTED);
341 DCHECK_GT(write_end_, 0U); 509 DCHECK_GT(write_end_, 0U);
342 // Once we call Write(), we cannot call StartTls() until the write 510 // Once we call Write(), we cannot call StartTls() until the write
343 // finishes. This is okay, as StartTls() is called only after we 511 // finishes. This is okay, as StartTls() is called only after we
344 // have received a reply to a message we sent to the server and 512 // have received a reply to a message we sent to the server and
345 // before we send the next message. 513 // before we send the next message.
346 int status = 514 int status = connection_->socket()->Write(
347 transport_socket_->Write( 515 write_buf_.get(), write_end_, &write_callback_);
348 write_buf_.get(), write_end_, &write_callback_);
349 write_state_ = PENDING; 516 write_state_ = PENDING;
350 if (status != net::ERR_IO_PENDING) { 517 if (status != net::ERR_IO_PENDING) {
351 ProcessWriteDone(status); 518 ProcessWriteDone(status);
352 } 519 }
353 } 520 }
354 521
355 // write_state_ == PENDING -> write_state_ == IDLE or POSTED (the 522 // write_state_ == PENDING -> write_state_ == IDLE or POSTED (the
356 // latter via PostDoWrite()) 523 // latter via PostDoWrite())
357 524
358 void ChromeAsyncSocket::ProcessWriteDone(int status) { 525 void ChromeAsyncSocket::ProcessWriteDone(int status) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
390 557
391 bool ChromeAsyncSocket::Close() { 558 bool ChromeAsyncSocket::Close() {
392 DoClose(); 559 DoClose();
393 return true; 560 return true;
394 } 561 }
395 562
396 // (not STATE_CLOSED) -> STATE_CLOSED 563 // (not STATE_CLOSED) -> STATE_CLOSED
397 564
398 void ChromeAsyncSocket::DoClose() { 565 void ChromeAsyncSocket::DoClose() {
399 scoped_runnable_method_factory_.RevokeAll(); 566 scoped_runnable_method_factory_.RevokeAll();
400 if (transport_socket_.get()) { 567 // Disconnect the socket.
401 transport_socket_->Disconnect(); 568 if (connection_.get() && connection_->socket())
402 } 569 connection_->socket()->Disconnect();
403 transport_socket_.reset(); 570 connection_.reset();
404 read_state_ = IDLE; 571 read_state_ = IDLE;
405 read_start_ = 0U; 572 read_start_ = 0U;
406 read_end_ = 0U; 573 read_end_ = 0U;
407 write_state_ = IDLE; 574 write_state_ = IDLE;
408 write_end_ = 0U; 575 write_end_ = 0U;
409 if (state_ != STATE_CLOSED) { 576 if (state_ != STATE_CLOSED) {
410 state_ = STATE_CLOSED; 577 state_ = STATE_CLOSED;
411 SignalClosed(); 578 SignalClosed();
412 } 579 }
413 // Reset error variables after SignalClosed() so slots connected 580 // Reset error variables after SignalClosed() so slots connected
(...skipping 14 matching lines...) Expand all
428 595
429 state_ = STATE_TLS_CONNECTING; 596 state_ = STATE_TLS_CONNECTING;
430 read_state_ = IDLE; 597 read_state_ = IDLE;
431 read_start_ = 0U; 598 read_start_ = 0U;
432 read_end_ = 0U; 599 read_end_ = 0U;
433 DCHECK_EQ(write_end_, 0U); 600 DCHECK_EQ(write_end_, 0U);
434 601
435 // Clear out any posted DoRead() tasks. 602 // Clear out any posted DoRead() tasks.
436 scoped_runnable_method_factory_.RevokeAll(); 603 scoped_runnable_method_factory_.RevokeAll();
437 604
438 DCHECK(transport_socket_.get()); 605 net::ClientSocketFactory* factory =
439 transport_socket_.reset( 606 client_socket_factory_.get() ? client_socket_factory_.get()
440 client_socket_factory_->CreateSSLClientSocket( 607 : net::ClientSocketFactory::GetDefaultFactory();
441 transport_socket_.release(), net::HostPortPair(domain_name, 443), 608
442 ssl_config_, NULL /* ssl_host_info */, 609 DCHECK(connection_.get());
443 cert_verifier_)); 610 net::ClientSocket* ssl_socket = factory->CreateSSLClientSocket(
444 int status = transport_socket_->Connect(&ssl_connect_callback_); 611 connection_.release(), net::HostPortPair(domain_name, 443),
612 ssl_config_, NULL /* ssl_host_info */,
613 request_context_getter_->GetURLRequestContext()->cert_verifier(),
614 NULL);
615 connection_.reset(new net::ClientSocketHandle);
616 connection_->set_socket(ssl_socket);
617
618 int status = ssl_socket->Connect(&ssl_connect_callback_);
445 if (status != net::ERR_IO_PENDING) { 619 if (status != net::ERR_IO_PENDING) {
446 MessageLoop* message_loop = MessageLoop::current(); 620 MessageLoop* message_loop = MessageLoop::current();
447 CHECK(message_loop); 621 CHECK(message_loop);
448 message_loop->PostTask( 622 message_loop->PostTask(
449 FROM_HERE, 623 FROM_HERE,
450 scoped_runnable_method_factory_.NewRunnableMethod( 624 scoped_runnable_method_factory_.NewRunnableMethod(
451 &ChromeAsyncSocket::ProcessSSLConnectDone, status)); 625 &ChromeAsyncSocket::ProcessSSLConnectDone, status));
452 } 626 }
453 return true; 627 return true;
454 } 628 }
(...skipping 16 matching lines...) Expand all
471 return; 645 return;
472 } 646 }
473 state_ = STATE_TLS_OPEN; 647 state_ = STATE_TLS_OPEN;
474 PostDoRead(); 648 PostDoRead();
475 if (write_end_ > 0U) { 649 if (write_end_ > 0U) {
476 PostDoWrite(); 650 PostDoWrite();
477 } 651 }
478 SignalSSLConnected(); 652 SignalSSLConnected();
479 } 653 }
480 654
655 // TODO(sanjeevr): This has largely been copied from
656 // HttpStreamFactoryImpl::Job::ReconsiderProxyAfterError. This should be
657 // refactored into some common place.
658 int ChromeAsyncSocket::ReconsiderProxyAfterError(int error) {
659 DCHECK(!pac_request_);
660 // A failure to resolve the hostname or any error related to establishing a
661 // TCP connection could be grounds for trying a new proxy configuration.
662 //
663 // Why do this when a hostname cannot be resolved? Some URLs only make sense
664 // to proxy servers. The hostname in those URLs might fail to resolve if we
665 // are still using a non-proxy config. We need to check if a proxy config
666 // now exists that corresponds to a proxy server that could load the URL.
667 //
668 switch (error) {
669 case net::ERR_PROXY_CONNECTION_FAILED:
670 case net::ERR_NAME_NOT_RESOLVED:
671 case net::ERR_INTERNET_DISCONNECTED:
672 case net::ERR_ADDRESS_UNREACHABLE:
673 case net::ERR_CONNECTION_CLOSED:
674 case net::ERR_CONNECTION_RESET:
675 case net::ERR_CONNECTION_REFUSED:
676 case net::ERR_CONNECTION_ABORTED:
677 case net::ERR_TIMED_OUT:
678 case net::ERR_TUNNEL_CONNECTION_FAILED:
679 case net::ERR_SOCKS_CONNECTION_FAILED:
680 break;
681 case net::ERR_SOCKS_CONNECTION_HOST_UNREACHABLE:
682 // Remap the SOCKS-specific "host unreachable" error to a more
683 // generic error code (this way consumers like the link doctor
684 // know to substitute their error page).
685 //
686 // Note that if the host resolving was done by the SOCSK5 proxy, we can't
687 // differentiate between a proxy-side "host not found" versus a proxy-side
688 // "address unreachable" error, and will report both of these failures as
689 // ERR_ADDRESS_UNREACHABLE.
690 return net::ERR_ADDRESS_UNREACHABLE;
691 default:
692 return error;
693 }
694
695 if (proxy_info_.is_https() && ssl_config_.send_client_cert) {
696 network_session_->ssl_client_auth_cache()->Remove(
697 proxy_info_.proxy_server().host_port_pair().ToString());
698 }
699
700 GURL url = GURL("http://" + dest_host_port_pair_.ToString());
701 int rv = network_session_->proxy_service()->ReconsiderProxyAfterError(
702 url, &proxy_info_, &proxy_resolve_callback_, &pac_request_,
703 bound_net_log_);
704 if (rv == net::OK || rv == net::ERR_IO_PENDING) {
705 // If the error was during connection setup, there is no socket to
706 // disconnect.
707 if (connection_->socket())
708 connection_->socket()->Disconnect();
709 connection_->Reset();
710 } else {
711 // If ReconsiderProxyAfterError() failed synchronously, it means
712 // there was nothing left to fall-back to, so fail the transaction
713 // with the last connection error we got.
714 rv = error;
715 }
716
717 // We either have new proxy info or there was an error in falling back.
718 // In both cases we want to post ProcessProxyResolveDone (in the error case
719 // we might still want to fall back a direct connection).
720 if (rv != net::ERR_IO_PENDING) {
721 MessageLoop* message_loop = MessageLoop::current();
722 CHECK(message_loop);
723 message_loop->PostTask(
724 FROM_HERE,
725 scoped_runnable_method_factory_.NewRunnableMethod(
726 &ChromeAsyncSocket::ProcessProxyResolveDone, rv));
727 }
728 return rv;
729 }
730
481 } // namespace notifier 731 } // namespace notifier
OLDNEW
« no previous file with comments | « jingle/notifier/base/chrome_async_socket.h ('k') | jingle/notifier/base/chrome_async_socket_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698