OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 #include <algorithm> | 7 #include <algorithm> |
8 #include <cstring> | 8 #include <cstring> |
9 #include <cstdlib> | 9 #include <cstdlib> |
10 | 10 |
11 #include "base/basictypes.h" | 11 #include "base/basictypes.h" |
12 #include "base/bind.h" | 12 #include "base/bind.h" |
13 #include "base/compiler_specific.h" | 13 #include "base/compiler_specific.h" |
14 #include "base/logging.h" | 14 #include "base/logging.h" |
15 #include "base/message_loop.h" | 15 #include "base/message_loop.h" |
16 #include "jingle/notifier/base/resolving_client_socket_factory.h" | 16 #include "jingle/notifier/base/resolving_client_socket_factory.h" |
17 #include "net/base/address_list.h" | 17 #include "net/base/address_list.h" |
18 #include "net/base/host_port_pair.h" | 18 #include "net/base/host_port_pair.h" |
19 #include "net/base/io_buffer.h" | 19 #include "net/base/io_buffer.h" |
20 #include "net/base/net_util.h" | 20 #include "net/base/net_util.h" |
21 #include "net/base/ssl_config_service.h" | 21 #include "net/base/ssl_config_service.h" |
22 #include "net/socket/client_socket_factory.h" | |
23 #include "net/socket/client_socket_handle.h" | 22 #include "net/socket/client_socket_handle.h" |
24 #include "net/socket/ssl_client_socket.h" | 23 #include "net/socket/ssl_client_socket.h" |
25 #include "net/socket/tcp_client_socket.h" | 24 #include "net/socket/tcp_client_socket.h" |
26 #include "talk/base/socketaddress.h" | 25 #include "talk/base/socketaddress.h" |
27 | 26 |
28 namespace notifier { | 27 namespace notifier { |
29 | 28 |
30 ChromeAsyncSocket::ChromeAsyncSocket( | 29 ChromeAsyncSocket::ChromeAsyncSocket( |
31 ResolvingClientSocketFactory* client_socket_factory, | 30 ResolvingClientSocketFactory* resolving_client_socket_factory, |
32 size_t read_buf_size, | 31 size_t read_buf_size, |
33 size_t write_buf_size) | 32 size_t write_buf_size) |
34 : client_socket_factory_(client_socket_factory), | 33 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), |
| 34 resolving_client_socket_factory_(resolving_client_socket_factory), |
35 state_(STATE_CLOSED), | 35 state_(STATE_CLOSED), |
36 error_(ERROR_NONE), | 36 error_(ERROR_NONE), |
37 net_error_(net::OK), | 37 net_error_(net::OK), |
38 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), | |
39 read_state_(IDLE), | 38 read_state_(IDLE), |
40 read_buf_(new net::IOBufferWithSize(read_buf_size)), | 39 read_buf_(new net::IOBufferWithSize(read_buf_size)), |
41 read_start_(0U), | 40 read_start_(0U), |
42 read_end_(0U), | 41 read_end_(0U), |
43 write_state_(IDLE), | 42 write_state_(IDLE), |
44 write_buf_(new net::IOBufferWithSize(write_buf_size)), | 43 write_buf_(new net::IOBufferWithSize(write_buf_size)), |
45 write_end_(0U) { | 44 write_end_(0U) { |
46 DCHECK(client_socket_factory_.get()); | 45 DCHECK(resolving_client_socket_factory_.get()); |
47 DCHECK_GT(read_buf_size, 0U); | 46 DCHECK_GT(read_buf_size, 0U); |
48 DCHECK_GT(write_buf_size, 0U); | 47 DCHECK_GT(write_buf_size, 0U); |
49 } | 48 } |
50 | 49 |
51 ChromeAsyncSocket::~ChromeAsyncSocket() {} | 50 ChromeAsyncSocket::~ChromeAsyncSocket() {} |
52 | 51 |
53 ChromeAsyncSocket::State ChromeAsyncSocket::state() { | 52 ChromeAsyncSocket::State ChromeAsyncSocket::state() { |
54 return state_; | 53 return state_; |
55 } | 54 } |
56 | 55 |
(...skipping 27 matching lines...) Expand all Loading... |
84 } | 83 } |
85 | 84 |
86 // STATE_CLOSED -> STATE_CONNECTING | 85 // STATE_CLOSED -> STATE_CONNECTING |
87 | 86 |
88 bool ChromeAsyncSocket::Connect(const talk_base::SocketAddress& address) { | 87 bool ChromeAsyncSocket::Connect(const talk_base::SocketAddress& address) { |
89 if (state_ != STATE_CLOSED) { | 88 if (state_ != STATE_CLOSED) { |
90 LOG(DFATAL) << "Connect() called on non-closed socket"; | 89 LOG(DFATAL) << "Connect() called on non-closed socket"; |
91 DoNonNetError(ERROR_WRONGSTATE); | 90 DoNonNetError(ERROR_WRONGSTATE); |
92 return false; | 91 return false; |
93 } | 92 } |
94 // We can't work with an empty hostname and IP address. | 93 if (address.hostname().empty() || address.port() == 0) { |
95 if (address.hostname().empty() && (address.ip() == 0)) { | |
96 DoNonNetError(ERROR_DNS); | 94 DoNonNetError(ERROR_DNS); |
97 return false; | 95 return false; |
98 } | 96 } |
99 | 97 |
100 DCHECK_EQ(state_, buzz::AsyncSocket::STATE_CLOSED); | 98 DCHECK_EQ(state_, buzz::AsyncSocket::STATE_CLOSED); |
101 DCHECK_EQ(read_state_, IDLE); | 99 DCHECK_EQ(read_state_, IDLE); |
102 DCHECK_EQ(write_state_, IDLE); | 100 DCHECK_EQ(write_state_, IDLE); |
103 | 101 |
104 state_ = STATE_CONNECTING; | 102 state_ = STATE_CONNECTING; |
105 | 103 |
106 DCHECK_EQ(false, weak_factory_.HasWeakPtrs()); | 104 DCHECK(!weak_ptr_factory_.HasWeakPtrs()); |
| 105 weak_ptr_factory_.InvalidateWeakPtrs(); |
107 | 106 |
108 net::HostPortPair dest_host_port_pair(address.IPAsString(), address.port()); | 107 net::HostPortPair dest_host_port_pair(address.hostname(), address.port()); |
109 | 108 |
110 transport_socket_.reset( | 109 transport_socket_.reset( |
111 client_socket_factory_->CreateTransportClientSocket( | 110 resolving_client_socket_factory_->CreateTransportClientSocket( |
112 dest_host_port_pair)); | 111 dest_host_port_pair)); |
113 int status = transport_socket_->Connect( | 112 int status = transport_socket_->Connect( |
114 base::Bind(&ChromeAsyncSocket::ProcessConnectDone, | 113 base::Bind(&ChromeAsyncSocket::ProcessConnectDone, |
115 base::Unretained(this))); | 114 weak_ptr_factory_.GetWeakPtr())); |
116 if (status != net::ERR_IO_PENDING) { | 115 if (status != net::ERR_IO_PENDING) { |
117 // We defer execution of ProcessConnectDone instead of calling it | 116 // We defer execution of ProcessConnectDone instead of calling it |
118 // directly here as the caller may not expect an error/close to | 117 // directly here as the caller may not expect an error/close to |
119 // happen here. This is okay, as from the caller's point of view, | 118 // happen here. This is okay, as from the caller's point of view, |
120 // the connect always happens asynchronously. | 119 // the connect always happens asynchronously. |
121 MessageLoop* message_loop = MessageLoop::current(); | 120 MessageLoop* message_loop = MessageLoop::current(); |
122 CHECK(message_loop); | 121 CHECK(message_loop); |
123 message_loop->PostTask(FROM_HERE, | 122 message_loop->PostTask( |
124 base::Bind(&ChromeAsyncSocket::ProcessConnectDone, | 123 FROM_HERE, |
125 weak_factory_.GetWeakPtr(), status)); | 124 base::Bind(&ChromeAsyncSocket::ProcessConnectDone, |
| 125 weak_ptr_factory_.GetWeakPtr(), status)); |
126 } | 126 } |
127 return true; | 127 return true; |
128 } | 128 } |
129 | 129 |
130 // STATE_CONNECTING -> STATE_OPEN | 130 // STATE_CONNECTING -> STATE_OPEN |
131 // read_state_ == IDLE -> read_state_ == POSTED (via PostDoRead()) | 131 // read_state_ == IDLE -> read_state_ == POSTED (via PostDoRead()) |
132 | 132 |
133 void ChromeAsyncSocket::ProcessConnectDone(int status) { | 133 void ChromeAsyncSocket::ProcessConnectDone(int status) { |
134 DCHECK_NE(status, net::ERR_IO_PENDING); | 134 DCHECK_NE(status, net::ERR_IO_PENDING); |
135 DCHECK_EQ(read_state_, IDLE); | 135 DCHECK_EQ(read_state_, IDLE); |
(...skipping 15 matching lines...) Expand all Loading... |
151 | 151 |
152 void ChromeAsyncSocket::PostDoRead() { | 152 void ChromeAsyncSocket::PostDoRead() { |
153 DCHECK(IsOpen()); | 153 DCHECK(IsOpen()); |
154 DCHECK_EQ(read_state_, IDLE); | 154 DCHECK_EQ(read_state_, IDLE); |
155 DCHECK_EQ(read_start_, 0U); | 155 DCHECK_EQ(read_start_, 0U); |
156 DCHECK_EQ(read_end_, 0U); | 156 DCHECK_EQ(read_end_, 0U); |
157 MessageLoop* message_loop = MessageLoop::current(); | 157 MessageLoop* message_loop = MessageLoop::current(); |
158 CHECK(message_loop); | 158 CHECK(message_loop); |
159 message_loop->PostTask( | 159 message_loop->PostTask( |
160 FROM_HERE, | 160 FROM_HERE, |
161 base::Bind(&ChromeAsyncSocket::DoRead, weak_factory_.GetWeakPtr())); | 161 base::Bind(&ChromeAsyncSocket::DoRead, |
| 162 weak_ptr_factory_.GetWeakPtr())); |
162 read_state_ = POSTED; | 163 read_state_ = POSTED; |
163 } | 164 } |
164 | 165 |
165 // read_state_ == POSTED -> read_state_ == PENDING | 166 // read_state_ == POSTED -> read_state_ == PENDING |
166 | 167 |
167 void ChromeAsyncSocket::DoRead() { | 168 void ChromeAsyncSocket::DoRead() { |
168 DCHECK(IsOpen()); | 169 DCHECK(IsOpen()); |
169 DCHECK_EQ(read_state_, POSTED); | 170 DCHECK_EQ(read_state_, POSTED); |
170 DCHECK_EQ(read_start_, 0U); | 171 DCHECK_EQ(read_start_, 0U); |
171 DCHECK_EQ(read_end_, 0U); | 172 DCHECK_EQ(read_end_, 0U); |
172 // Once we call Read(), we cannot call StartTls() until the read | 173 // Once we call Read(), we cannot call StartTls() until the read |
173 // finishes. This is okay, as StartTls() is called only from a read | 174 // finishes. This is okay, as StartTls() is called only from a read |
174 // handler (i.e., after a read finishes and before another read is | 175 // handler (i.e., after a read finishes and before another read is |
175 // done). | 176 // done). |
176 int status = | 177 int status = |
177 transport_socket_->Read( | 178 transport_socket_->Read( |
178 read_buf_.get(), read_buf_->size(), | 179 read_buf_.get(), read_buf_->size(), |
179 base::Bind(&ChromeAsyncSocket::ProcessReadDone, | 180 base::Bind(&ChromeAsyncSocket::ProcessReadDone, |
180 base::Unretained(this))); | 181 weak_ptr_factory_.GetWeakPtr())); |
181 read_state_ = PENDING; | 182 read_state_ = PENDING; |
182 if (status != net::ERR_IO_PENDING) { | 183 if (status != net::ERR_IO_PENDING) { |
183 ProcessReadDone(status); | 184 ProcessReadDone(status); |
184 } | 185 } |
185 } | 186 } |
186 | 187 |
187 // read_state_ == PENDING -> read_state_ == IDLE | 188 // read_state_ == PENDING -> read_state_ == IDLE |
188 | 189 |
189 void ChromeAsyncSocket::ProcessReadDone(int status) { | 190 void ChromeAsyncSocket::ProcessReadDone(int status) { |
190 DCHECK_NE(status, net::ERR_IO_PENDING); | 191 DCHECK_NE(status, net::ERR_IO_PENDING); |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
284 // write_state_ == IDLE -> write_state_ == POSTED | 285 // write_state_ == IDLE -> write_state_ == POSTED |
285 | 286 |
286 void ChromeAsyncSocket::PostDoWrite() { | 287 void ChromeAsyncSocket::PostDoWrite() { |
287 DCHECK(IsOpen()); | 288 DCHECK(IsOpen()); |
288 DCHECK_EQ(write_state_, IDLE); | 289 DCHECK_EQ(write_state_, IDLE); |
289 DCHECK_GT(write_end_, 0U); | 290 DCHECK_GT(write_end_, 0U); |
290 MessageLoop* message_loop = MessageLoop::current(); | 291 MessageLoop* message_loop = MessageLoop::current(); |
291 CHECK(message_loop); | 292 CHECK(message_loop); |
292 message_loop->PostTask( | 293 message_loop->PostTask( |
293 FROM_HERE, | 294 FROM_HERE, |
294 base::Bind(&ChromeAsyncSocket::DoWrite, weak_factory_.GetWeakPtr())); | 295 base::Bind(&ChromeAsyncSocket::DoWrite, |
| 296 weak_ptr_factory_.GetWeakPtr())); |
295 write_state_ = POSTED; | 297 write_state_ = POSTED; |
296 } | 298 } |
297 | 299 |
298 // write_state_ == POSTED -> write_state_ == PENDING | 300 // write_state_ == POSTED -> write_state_ == PENDING |
299 | 301 |
300 void ChromeAsyncSocket::DoWrite() { | 302 void ChromeAsyncSocket::DoWrite() { |
301 DCHECK(IsOpen()); | 303 DCHECK(IsOpen()); |
302 DCHECK_EQ(write_state_, POSTED); | 304 DCHECK_EQ(write_state_, POSTED); |
303 DCHECK_GT(write_end_, 0U); | 305 DCHECK_GT(write_end_, 0U); |
304 // Once we call Write(), we cannot call StartTls() until the write | 306 // Once we call Write(), we cannot call StartTls() until the write |
305 // finishes. This is okay, as StartTls() is called only after we | 307 // finishes. This is okay, as StartTls() is called only after we |
306 // have received a reply to a message we sent to the server and | 308 // have received a reply to a message we sent to the server and |
307 // before we send the next message. | 309 // before we send the next message. |
308 int status = | 310 int status = |
309 transport_socket_->Write( | 311 transport_socket_->Write( |
310 write_buf_.get(), write_end_, | 312 write_buf_.get(), write_end_, |
311 base::Bind(&ChromeAsyncSocket::ProcessWriteDone, | 313 base::Bind(&ChromeAsyncSocket::ProcessWriteDone, |
312 base::Unretained(this))); | 314 weak_ptr_factory_.GetWeakPtr())); |
313 write_state_ = PENDING; | 315 write_state_ = PENDING; |
314 if (status != net::ERR_IO_PENDING) { | 316 if (status != net::ERR_IO_PENDING) { |
315 ProcessWriteDone(status); | 317 ProcessWriteDone(status); |
316 } | 318 } |
317 } | 319 } |
318 | 320 |
319 // write_state_ == PENDING -> write_state_ == IDLE or POSTED (the | 321 // write_state_ == PENDING -> write_state_ == IDLE or POSTED (the |
320 // latter via PostDoWrite()) | 322 // latter via PostDoWrite()) |
321 | 323 |
322 void ChromeAsyncSocket::ProcessWriteDone(int status) { | 324 void ChromeAsyncSocket::ProcessWriteDone(int status) { |
(...skipping 30 matching lines...) Expand all Loading... |
353 // * -> STATE_CLOSED | 355 // * -> STATE_CLOSED |
354 | 356 |
355 bool ChromeAsyncSocket::Close() { | 357 bool ChromeAsyncSocket::Close() { |
356 DoClose(); | 358 DoClose(); |
357 return true; | 359 return true; |
358 } | 360 } |
359 | 361 |
360 // (not STATE_CLOSED) -> STATE_CLOSED | 362 // (not STATE_CLOSED) -> STATE_CLOSED |
361 | 363 |
362 void ChromeAsyncSocket::DoClose() { | 364 void ChromeAsyncSocket::DoClose() { |
363 weak_factory_.InvalidateWeakPtrs(); | 365 weak_ptr_factory_.InvalidateWeakPtrs(); |
364 if (transport_socket_.get()) { | 366 if (transport_socket_.get()) { |
365 transport_socket_->Disconnect(); | 367 transport_socket_->Disconnect(); |
366 } | 368 } |
367 transport_socket_.reset(); | 369 transport_socket_.reset(); |
368 read_state_ = IDLE; | 370 read_state_ = IDLE; |
369 read_start_ = 0U; | 371 read_start_ = 0U; |
370 read_end_ = 0U; | 372 read_end_ = 0U; |
371 write_state_ = IDLE; | 373 write_state_ = IDLE; |
372 write_end_ = 0U; | 374 write_end_ = 0U; |
373 if (state_ != STATE_CLOSED) { | 375 if (state_ != STATE_CLOSED) { |
(...skipping 16 matching lines...) Expand all Loading... |
390 return false; | 392 return false; |
391 } | 393 } |
392 | 394 |
393 state_ = STATE_TLS_CONNECTING; | 395 state_ = STATE_TLS_CONNECTING; |
394 read_state_ = IDLE; | 396 read_state_ = IDLE; |
395 read_start_ = 0U; | 397 read_start_ = 0U; |
396 read_end_ = 0U; | 398 read_end_ = 0U; |
397 DCHECK_EQ(write_end_, 0U); | 399 DCHECK_EQ(write_end_, 0U); |
398 | 400 |
399 // Clear out any posted DoRead() tasks. | 401 // Clear out any posted DoRead() tasks. |
400 weak_factory_.InvalidateWeakPtrs(); | 402 weak_ptr_factory_.InvalidateWeakPtrs(); |
401 | 403 |
402 DCHECK(transport_socket_.get()); | 404 DCHECK(transport_socket_.get()); |
403 net::ClientSocketHandle* socket_handle = new net::ClientSocketHandle(); | 405 scoped_ptr<net::ClientSocketHandle> socket_handle( |
| 406 new net::ClientSocketHandle()); |
404 socket_handle->set_socket(transport_socket_.release()); | 407 socket_handle->set_socket(transport_socket_.release()); |
405 transport_socket_.reset( | 408 transport_socket_.reset( |
406 client_socket_factory_->CreateSSLClientSocket( | 409 resolving_client_socket_factory_->CreateSSLClientSocket( |
407 socket_handle, net::HostPortPair(domain_name, 443))); | 410 socket_handle.release(), net::HostPortPair(domain_name, 443))); |
408 int status = transport_socket_->Connect( | 411 int status = transport_socket_->Connect( |
409 base::Bind(&ChromeAsyncSocket::ProcessSSLConnectDone, | 412 base::Bind(&ChromeAsyncSocket::ProcessSSLConnectDone, |
410 base::Unretained(this))); | 413 weak_ptr_factory_.GetWeakPtr())); |
411 if (status != net::ERR_IO_PENDING) { | 414 if (status != net::ERR_IO_PENDING) { |
412 MessageLoop* message_loop = MessageLoop::current(); | 415 MessageLoop* message_loop = MessageLoop::current(); |
413 CHECK(message_loop); | 416 CHECK(message_loop); |
414 message_loop->PostTask(FROM_HERE, | 417 message_loop->PostTask( |
415 base::Bind(&ChromeAsyncSocket::ProcessSSLConnectDone, | 418 FROM_HERE, |
416 weak_factory_.GetWeakPtr(), status)); | 419 base::Bind(&ChromeAsyncSocket::ProcessSSLConnectDone, |
| 420 weak_ptr_factory_.GetWeakPtr(), status)); |
417 } | 421 } |
418 return true; | 422 return true; |
419 } | 423 } |
420 | 424 |
421 // STATE_TLS_CONNECTING -> STATE_TLS_OPEN | 425 // STATE_TLS_CONNECTING -> STATE_TLS_OPEN |
422 // read_state_ == IDLE -> read_state_ == POSTED (via PostDoRead()) | 426 // read_state_ == IDLE -> read_state_ == POSTED (via PostDoRead()) |
423 // (maybe) write_state_ == IDLE -> write_state_ == POSTED (via | 427 // (maybe) write_state_ == IDLE -> write_state_ == POSTED (via |
424 // PostDoWrite()) | 428 // PostDoWrite()) |
425 | 429 |
426 void ChromeAsyncSocket::ProcessSSLConnectDone(int status) { | 430 void ChromeAsyncSocket::ProcessSSLConnectDone(int status) { |
(...skipping 10 matching lines...) Expand all Loading... |
437 } | 441 } |
438 state_ = STATE_TLS_OPEN; | 442 state_ = STATE_TLS_OPEN; |
439 PostDoRead(); | 443 PostDoRead(); |
440 if (write_end_ > 0U) { | 444 if (write_end_ > 0U) { |
441 PostDoWrite(); | 445 PostDoWrite(); |
442 } | 446 } |
443 SignalSSLConnected(); | 447 SignalSSLConnected(); |
444 } | 448 } |
445 | 449 |
446 } // namespace notifier | 450 } // namespace notifier |
OLD | NEW |