OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "net/socket/tcp_client_socket_libevent.h" | 5 #include "net/socket/tcp_client_socket_libevent.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <fcntl.h> | 8 #include <fcntl.h> |
9 #include <netdb.h> | 9 #include <netdb.h> |
10 #include <sys/socket.h> | 10 #include <sys/socket.h> |
11 #include <netinet/tcp.h> | 11 #include <netinet/tcp.h> |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
115 return true; | 115 return true; |
116 default: | 116 default: |
117 return false; | 117 return false; |
118 } | 118 } |
119 } | 119 } |
120 | 120 |
121 } // namespace | 121 } // namespace |
122 | 122 |
123 //----------------------------------------------------------------------------- | 123 //----------------------------------------------------------------------------- |
124 | 124 |
125 TCPClientSocketLibevent::TCPClientSocketLibevent(const AddressList& addresses) | 125 TCPClientSocketLibevent::TCPClientSocketLibevent(const AddressList& addresses, |
| 126 net::NetLog* net_log) |
126 : socket_(kInvalidSocket), | 127 : socket_(kInvalidSocket), |
127 addresses_(addresses), | 128 addresses_(addresses), |
128 current_ai_(addresses_.head()), | 129 current_ai_(addresses_.head()), |
129 waiting_connect_(false), | 130 waiting_connect_(false), |
130 read_watcher_(this), | 131 read_watcher_(this), |
131 write_watcher_(this), | 132 write_watcher_(this), |
132 read_callback_(NULL), | 133 read_callback_(NULL), |
133 write_callback_(NULL) { | 134 write_callback_(NULL), |
| 135 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { |
134 } | 136 } |
135 | 137 |
136 TCPClientSocketLibevent::~TCPClientSocketLibevent() { | 138 TCPClientSocketLibevent::~TCPClientSocketLibevent() { |
137 Disconnect(); | 139 Disconnect(); |
| 140 net_log_.AddEvent(NetLog::TYPE_TCP_SOCKET_DONE); |
138 } | 141 } |
139 | 142 |
140 int TCPClientSocketLibevent::Connect(CompletionCallback* callback, | 143 int TCPClientSocketLibevent::Connect(CompletionCallback* callback) { |
141 const BoundNetLog& net_log) { | |
142 // If already connected, then just return OK. | 144 // If already connected, then just return OK. |
143 if (socket_ != kInvalidSocket) | 145 if (socket_ != kInvalidSocket) |
144 return OK; | 146 return OK; |
145 | 147 |
146 DCHECK(!waiting_connect_); | 148 DCHECK(!waiting_connect_); |
147 DCHECK(!net_log_.net_log()); | |
148 | 149 |
149 TRACE_EVENT_BEGIN("socket.connect", this, ""); | 150 TRACE_EVENT_BEGIN("socket.connect", this, ""); |
150 | 151 |
151 net_log.BeginEvent(NetLog::TYPE_TCP_CONNECT); | 152 net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT); |
152 | 153 |
153 int rv = DoConnect(); | 154 int rv = DoConnect(); |
154 | 155 |
155 if (rv == ERR_IO_PENDING) { | 156 if (rv == ERR_IO_PENDING) { |
156 // Synchronous operation not supported. | 157 // Synchronous operation not supported. |
157 DCHECK(callback); | 158 DCHECK(callback); |
158 | 159 |
159 net_log_ = net_log; | |
160 waiting_connect_ = true; | 160 waiting_connect_ = true; |
161 write_callback_ = callback; | 161 write_callback_ = callback; |
162 } else { | 162 } else { |
163 TRACE_EVENT_END("socket.connect", this, ""); | 163 TRACE_EVENT_END("socket.connect", this, ""); |
164 net_log.EndEvent(NetLog::TYPE_TCP_CONNECT); | 164 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT); |
165 } | 165 } |
166 | 166 |
167 return rv; | 167 return rv; |
168 } | 168 } |
169 | 169 |
170 int TCPClientSocketLibevent::DoConnect() { | 170 int TCPClientSocketLibevent::DoConnect() { |
171 while (true) { | 171 while (true) { |
172 DCHECK(current_ai_); | 172 DCHECK(current_ai_); |
173 | 173 |
174 int rv = CreateSocket(current_ai_); | 174 int rv = CreateSocket(current_ai_); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 DCHECK(!waiting_connect_); | 270 DCHECK(!waiting_connect_); |
271 DCHECK(!read_callback_); | 271 DCHECK(!read_callback_); |
272 // Synchronous operation not supported | 272 // Synchronous operation not supported |
273 DCHECK(callback); | 273 DCHECK(callback); |
274 DCHECK_GT(buf_len, 0); | 274 DCHECK_GT(buf_len, 0); |
275 | 275 |
276 TRACE_EVENT_BEGIN("socket.read", this, ""); | 276 TRACE_EVENT_BEGIN("socket.read", this, ""); |
277 int nread = HANDLE_EINTR(read(socket_, buf->data(), buf_len)); | 277 int nread = HANDLE_EINTR(read(socket_, buf->data(), buf_len)); |
278 if (nread >= 0) { | 278 if (nread >= 0) { |
279 TRACE_EVENT_END("socket.read", this, StringPrintf("%d bytes", nread)); | 279 TRACE_EVENT_END("socket.read", this, StringPrintf("%d bytes", nread)); |
| 280 net_log_.AddEventWithInteger(NetLog::TYPE_SOCKET_BYTES_RECEIVED, nread); |
280 return nread; | 281 return nread; |
281 } | 282 } |
282 if (errno != EAGAIN && errno != EWOULDBLOCK) { | 283 if (errno != EAGAIN && errno != EWOULDBLOCK) { |
283 DLOG(INFO) << "read failed, errno " << errno; | 284 DLOG(INFO) << "read failed, errno " << errno; |
284 return MapPosixError(errno); | 285 return MapPosixError(errno); |
285 } | 286 } |
286 | 287 |
287 if (!MessageLoopForIO::current()->WatchFileDescriptor( | 288 if (!MessageLoopForIO::current()->WatchFileDescriptor( |
288 socket_, true, MessageLoopForIO::WATCH_READ, | 289 socket_, true, MessageLoopForIO::WATCH_READ, |
289 &read_socket_watcher_, &read_watcher_)) { | 290 &read_socket_watcher_, &read_watcher_)) { |
(...skipping 14 matching lines...) Expand all Loading... |
304 DCHECK(!waiting_connect_); | 305 DCHECK(!waiting_connect_); |
305 DCHECK(!write_callback_); | 306 DCHECK(!write_callback_); |
306 // Synchronous operation not supported | 307 // Synchronous operation not supported |
307 DCHECK(callback); | 308 DCHECK(callback); |
308 DCHECK_GT(buf_len, 0); | 309 DCHECK_GT(buf_len, 0); |
309 | 310 |
310 TRACE_EVENT_BEGIN("socket.write", this, ""); | 311 TRACE_EVENT_BEGIN("socket.write", this, ""); |
311 int nwrite = HANDLE_EINTR(write(socket_, buf->data(), buf_len)); | 312 int nwrite = HANDLE_EINTR(write(socket_, buf->data(), buf_len)); |
312 if (nwrite >= 0) { | 313 if (nwrite >= 0) { |
313 TRACE_EVENT_END("socket.write", this, StringPrintf("%d bytes", nwrite)); | 314 TRACE_EVENT_END("socket.write", this, StringPrintf("%d bytes", nwrite)); |
| 315 net_log_.AddEventWithInteger(NetLog::TYPE_SOCKET_BYTES_SENT, nwrite); |
314 return nwrite; | 316 return nwrite; |
315 } | 317 } |
316 if (errno != EAGAIN && errno != EWOULDBLOCK) | 318 if (errno != EAGAIN && errno != EWOULDBLOCK) |
317 return MapPosixError(errno); | 319 return MapPosixError(errno); |
318 | 320 |
319 if (!MessageLoopForIO::current()->WatchFileDescriptor( | 321 if (!MessageLoopForIO::current()->WatchFileDescriptor( |
320 socket_, true, MessageLoopForIO::WATCH_WRITE, | 322 socket_, true, MessageLoopForIO::WATCH_WRITE, |
321 &write_socket_watcher_, &write_watcher_)) { | 323 &write_socket_watcher_, &write_watcher_)) { |
322 DLOG(INFO) << "WatchFileDescriptor failed on write, errno " << errno; | 324 DLOG(INFO) << "WatchFileDescriptor failed on write, errno " << errno; |
323 return MapPosixError(errno); | 325 return MapPosixError(errno); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
396 os_error = errno; | 398 os_error = errno; |
397 | 399 |
398 if (os_error == EINPROGRESS || os_error == EALREADY) { | 400 if (os_error == EINPROGRESS || os_error == EALREADY) { |
399 NOTREACHED(); // This indicates a bug in libevent or our code. | 401 NOTREACHED(); // This indicates a bug in libevent or our code. |
400 result = ERR_IO_PENDING; | 402 result = ERR_IO_PENDING; |
401 } else if (current_ai_->ai_next && ShouldTryNextAddress(os_error)) { | 403 } else if (current_ai_->ai_next && ShouldTryNextAddress(os_error)) { |
402 // This address failed, try next one in list. | 404 // This address failed, try next one in list. |
403 const addrinfo* next = current_ai_->ai_next; | 405 const addrinfo* next = current_ai_->ai_next; |
404 Disconnect(); | 406 Disconnect(); |
405 current_ai_ = next; | 407 current_ai_ = next; |
406 BoundNetLog net_log = net_log_; | |
407 net_log_ = BoundNetLog(); | |
408 TRACE_EVENT_END("socket.connect", this, ""); | 408 TRACE_EVENT_END("socket.connect", this, ""); |
409 net_log.EndEvent(NetLog::TYPE_TCP_CONNECT); | 409 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT); |
410 result = Connect(write_callback_, net_log); | 410 result = Connect(write_callback_); |
411 } else { | 411 } else { |
412 result = MapConnectError(os_error); | 412 result = MapConnectError(os_error); |
413 bool ok = write_socket_watcher_.StopWatchingFileDescriptor(); | 413 bool ok = write_socket_watcher_.StopWatchingFileDescriptor(); |
414 DCHECK(ok); | 414 DCHECK(ok); |
415 waiting_connect_ = false; | 415 waiting_connect_ = false; |
416 TRACE_EVENT_END("socket.connect", this, ""); | 416 TRACE_EVENT_END("socket.connect", this, ""); |
417 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT); | 417 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT); |
418 net_log_ = BoundNetLog(); | |
419 } | 418 } |
420 | 419 |
421 if (result != ERR_IO_PENDING) { | 420 if (result != ERR_IO_PENDING) { |
422 DoWriteCallback(result); | 421 DoWriteCallback(result); |
423 } | 422 } |
424 } | 423 } |
425 | 424 |
426 void TCPClientSocketLibevent::DidCompleteRead() { | 425 void TCPClientSocketLibevent::DidCompleteRead() { |
427 int bytes_transferred; | 426 int bytes_transferred; |
428 bytes_transferred = HANDLE_EINTR(read(socket_, read_buf_->data(), | 427 bytes_transferred = HANDLE_EINTR(read(socket_, read_buf_->data(), |
429 read_buf_len_)); | 428 read_buf_len_)); |
430 | 429 |
431 int result; | 430 int result; |
432 if (bytes_transferred >= 0) { | 431 if (bytes_transferred >= 0) { |
433 TRACE_EVENT_END("socket.read", this, | 432 TRACE_EVENT_END("socket.read", this, |
434 StringPrintf("%d bytes", bytes_transferred)); | 433 StringPrintf("%d bytes", bytes_transferred)); |
435 result = bytes_transferred; | 434 result = bytes_transferred; |
| 435 net_log_.AddEventWithInteger(NetLog::TYPE_SOCKET_BYTES_RECEIVED, result); |
436 } else { | 436 } else { |
437 result = MapPosixError(errno); | 437 result = MapPosixError(errno); |
438 } | 438 } |
439 | 439 |
440 if (result != ERR_IO_PENDING) { | 440 if (result != ERR_IO_PENDING) { |
441 read_buf_ = NULL; | 441 read_buf_ = NULL; |
442 read_buf_len_ = 0; | 442 read_buf_len_ = 0; |
443 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); | 443 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); |
444 DCHECK(ok); | 444 DCHECK(ok); |
445 DoReadCallback(result); | 445 DoReadCallback(result); |
446 } | 446 } |
447 } | 447 } |
448 | 448 |
449 void TCPClientSocketLibevent::DidCompleteWrite() { | 449 void TCPClientSocketLibevent::DidCompleteWrite() { |
450 int bytes_transferred; | 450 int bytes_transferred; |
451 bytes_transferred = HANDLE_EINTR(write(socket_, write_buf_->data(), | 451 bytes_transferred = HANDLE_EINTR(write(socket_, write_buf_->data(), |
452 write_buf_len_)); | 452 write_buf_len_)); |
453 | 453 |
454 int result; | 454 int result; |
455 if (bytes_transferred >= 0) { | 455 if (bytes_transferred >= 0) { |
456 result = bytes_transferred; | 456 result = bytes_transferred; |
457 TRACE_EVENT_END("socket.write", this, | 457 TRACE_EVENT_END("socket.write", this, |
458 StringPrintf("%d bytes", bytes_transferred)); | 458 StringPrintf("%d bytes", bytes_transferred)); |
| 459 net_log_.AddEventWithInteger(NetLog::TYPE_SOCKET_BYTES_SENT, result); |
459 } else { | 460 } else { |
460 result = MapPosixError(errno); | 461 result = MapPosixError(errno); |
461 } | 462 } |
462 | 463 |
463 if (result != ERR_IO_PENDING) { | 464 if (result != ERR_IO_PENDING) { |
464 write_buf_ = NULL; | 465 write_buf_ = NULL; |
465 write_buf_len_ = 0; | 466 write_buf_len_ = 0; |
466 write_socket_watcher_.StopWatchingFileDescriptor(); | 467 write_socket_watcher_.StopWatchingFileDescriptor(); |
467 DoWriteCallback(result); | 468 DoWriteCallback(result); |
468 } | 469 } |
469 } | 470 } |
470 | 471 |
471 int TCPClientSocketLibevent::GetPeerAddress(AddressList* address) const { | 472 int TCPClientSocketLibevent::GetPeerAddress(AddressList* address) const { |
472 DCHECK(address); | 473 DCHECK(address); |
473 if (!current_ai_) | 474 if (!current_ai_) |
474 return ERR_UNEXPECTED; | 475 return ERR_UNEXPECTED; |
475 address->Copy(current_ai_, false); | 476 address->Copy(current_ai_, false); |
476 return OK; | 477 return OK; |
477 } | 478 } |
478 | 479 |
479 } // namespace net | 480 } // namespace net |
OLD | NEW |