| OLD | NEW |
| 1 // Copyright (c) 2010 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.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> |
| 12 #if defined(OS_POSIX) | 12 #if defined(OS_POSIX) |
| 13 #include <netinet/in.h> | 13 #include <netinet/in.h> |
| 14 #endif | 14 #endif |
| 15 | 15 |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 113 const net::NetLog::Source& source) | 113 const net::NetLog::Source& source) |
| 114 : socket_(kInvalidSocket), | 114 : socket_(kInvalidSocket), |
| 115 addresses_(addresses), | 115 addresses_(addresses), |
| 116 current_ai_(NULL), | 116 current_ai_(NULL), |
| 117 read_watcher_(this), | 117 read_watcher_(this), |
| 118 write_watcher_(this), | 118 write_watcher_(this), |
| 119 read_callback_(NULL), | 119 read_callback_(NULL), |
| 120 write_callback_(NULL), | 120 write_callback_(NULL), |
| 121 next_connect_state_(CONNECT_STATE_NONE), | 121 next_connect_state_(CONNECT_STATE_NONE), |
| 122 connect_os_error_(0), | 122 connect_os_error_(0), |
| 123 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { | 123 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)), |
| 124 use_tcp_fastopen_(false), |
| 125 tcp_fastopen_connected_(false) { |
| 124 scoped_refptr<NetLog::EventParameters> params; | 126 scoped_refptr<NetLog::EventParameters> params; |
| 125 if (source.is_valid()) | 127 if (source.is_valid()) |
| 126 params = new NetLogSourceParameter("source_dependency", source); | 128 params = new NetLogSourceParameter("source_dependency", source); |
| 127 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, params); | 129 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, params); |
| 130 |
| 131 if (is_tcp_fastopen_enabled()) |
| 132 use_tcp_fastopen_ = true; |
| 128 } | 133 } |
| 129 | 134 |
| 130 TCPClientSocketLibevent::~TCPClientSocketLibevent() { | 135 TCPClientSocketLibevent::~TCPClientSocketLibevent() { |
| 131 Disconnect(); | 136 Disconnect(); |
| 132 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE, NULL); | 137 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE, NULL); |
| 133 } | 138 } |
| 134 | 139 |
| 135 int TCPClientSocketLibevent::Connect(CompletionCallback* callback) { | 140 int TCPClientSocketLibevent::Connect(CompletionCallback* callback) { |
| 136 DCHECK(CalledOnValidThread()); | 141 DCHECK(CalledOnValidThread()); |
| 137 | 142 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 "address", NetAddressToStringWithPort(current_ai_))); | 204 "address", NetAddressToStringWithPort(current_ai_))); |
| 200 | 205 |
| 201 next_connect_state_ = CONNECT_STATE_CONNECT_COMPLETE; | 206 next_connect_state_ = CONNECT_STATE_CONNECT_COMPLETE; |
| 202 | 207 |
| 203 // Create a non-blocking socket. | 208 // Create a non-blocking socket. |
| 204 connect_os_error_ = CreateSocket(current_ai_); | 209 connect_os_error_ = CreateSocket(current_ai_); |
| 205 if (connect_os_error_) | 210 if (connect_os_error_) |
| 206 return MapPosixError(connect_os_error_); | 211 return MapPosixError(connect_os_error_); |
| 207 | 212 |
| 208 // Connect the socket. | 213 // Connect the socket. |
| 209 if (!HANDLE_EINTR(connect(socket_, current_ai_->ai_addr, | 214 if (!use_tcp_fastopen_) { |
| 210 static_cast<int>(current_ai_->ai_addrlen)))) { | 215 if (!HANDLE_EINTR(connect(socket_, current_ai_->ai_addr, |
| 211 // Connected without waiting! | 216 static_cast<int>(current_ai_->ai_addrlen)))) { |
| 217 // Connected without waiting! |
| 218 return OK; |
| 219 } |
| 220 } else { |
| 221 // With TCP FastOpen, we pretend that the socket is connected. |
| 222 DCHECK(!tcp_fastopen_connected_); |
| 212 return OK; | 223 return OK; |
| 213 } | 224 } |
| 214 | 225 |
| 215 // Check if the connect() failed synchronously. | 226 // Check if the connect() failed synchronously. |
| 216 connect_os_error_ = errno; | 227 connect_os_error_ = errno; |
| 217 if (connect_os_error_ != EINPROGRESS) | 228 if (connect_os_error_ != EINPROGRESS) |
| 218 return MapConnectError(connect_os_error_); | 229 return MapConnectError(connect_os_error_); |
| 219 | 230 |
| 220 // Otherwise the connect() is going to complete asynchronously, so watch | 231 // Otherwise the connect() is going to complete asynchronously, so watch |
| 221 // for its completion. | 232 // for its completion. |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 358 int buf_len, | 369 int buf_len, |
| 359 CompletionCallback* callback) { | 370 CompletionCallback* callback) { |
| 360 DCHECK(CalledOnValidThread()); | 371 DCHECK(CalledOnValidThread()); |
| 361 DCHECK_NE(kInvalidSocket, socket_); | 372 DCHECK_NE(kInvalidSocket, socket_); |
| 362 DCHECK(!waiting_connect()); | 373 DCHECK(!waiting_connect()); |
| 363 DCHECK(!write_callback_); | 374 DCHECK(!write_callback_); |
| 364 // Synchronous operation not supported | 375 // Synchronous operation not supported |
| 365 DCHECK(callback); | 376 DCHECK(callback); |
| 366 DCHECK_GT(buf_len, 0); | 377 DCHECK_GT(buf_len, 0); |
| 367 | 378 |
| 368 int nwrite = HANDLE_EINTR(write(socket_, buf->data(), buf_len)); | 379 int nwrite = InternalWrite(buf, buf_len); |
| 369 if (nwrite >= 0) { | 380 if (nwrite >= 0) { |
| 370 static base::StatsCounter write_bytes("tcp.write_bytes"); | 381 static base::StatsCounter write_bytes("tcp.write_bytes"); |
| 371 write_bytes.Add(nwrite); | 382 write_bytes.Add(nwrite); |
| 372 if (nwrite > 0) | 383 if (nwrite > 0) |
| 373 use_history_.set_was_used_to_convey_data(); | 384 use_history_.set_was_used_to_convey_data(); |
| 374 LogByteTransfer( | 385 LogByteTransfer( |
| 375 net_log_, NetLog::TYPE_SOCKET_BYTES_SENT, nwrite, buf->data()); | 386 net_log_, NetLog::TYPE_SOCKET_BYTES_SENT, nwrite, buf->data()); |
| 376 return nwrite; | 387 return nwrite; |
| 377 } | 388 } |
| 378 if (errno != EAGAIN && errno != EWOULDBLOCK) | 389 if (errno != EAGAIN && errno != EWOULDBLOCK) |
| 379 return MapPosixError(errno); | 390 return MapPosixError(errno); |
| 380 | 391 |
| 381 if (!MessageLoopForIO::current()->WatchFileDescriptor( | 392 if (!MessageLoopForIO::current()->WatchFileDescriptor( |
| 382 socket_, true, MessageLoopForIO::WATCH_WRITE, | 393 socket_, true, MessageLoopForIO::WATCH_WRITE, |
| 383 &write_socket_watcher_, &write_watcher_)) { | 394 &write_socket_watcher_, &write_watcher_)) { |
| 384 DVLOG(1) << "WatchFileDescriptor failed on write, errno " << errno; | 395 DVLOG(1) << "WatchFileDescriptor failed on write, errno " << errno; |
| 385 return MapPosixError(errno); | 396 return MapPosixError(errno); |
| 386 } | 397 } |
| 387 | 398 |
| 388 write_buf_ = buf; | 399 write_buf_ = buf; |
| 389 write_buf_len_ = buf_len; | 400 write_buf_len_ = buf_len; |
| 390 write_callback_ = callback; | 401 write_callback_ = callback; |
| 391 return ERR_IO_PENDING; | 402 return ERR_IO_PENDING; |
| 392 } | 403 } |
| 393 | 404 |
| 405 int TCPClientSocketLibevent::InternalWrite(IOBuffer* buf, int buf_len) { |
| 406 int nwrite; |
| 407 if (use_tcp_fastopen_ && !tcp_fastopen_connected_) { |
| 408 // We have a limited amount of data to send in the SYN packet. |
| 409 int kMaxFastOpenSendLength = 1420; |
| 410 |
| 411 buf_len = std::min(kMaxFastOpenSendLength, buf_len); |
| 412 |
| 413 int flags = 0x20000000; // Magic flag to enable TCP_FASTOPEN |
| 414 nwrite = HANDLE_EINTR(sendto(socket_, |
| 415 buf->data(), |
| 416 buf_len, |
| 417 flags, |
| 418 current_ai_->ai_addr, |
| 419 static_cast<int>(current_ai_->ai_addrlen))); |
| 420 tcp_fastopen_connected_ = true; |
| 421 |
| 422 if (nwrite < 0) { |
| 423 // Non-blocking mode is returning EINPROGRESS rather than EAGAIN. |
| 424 if (errno == EINPROGRESS) |
| 425 errno = EAGAIN; |
| 426 |
| 427 // Unlike "normal" nonblocking sockets, the data is already queued, |
| 428 // so tell the app that we've consumed it. |
| 429 return buf_len; |
| 430 } |
| 431 } else { |
| 432 nwrite = HANDLE_EINTR(write(socket_, buf->data(), buf_len)); |
| 433 } |
| 434 return nwrite; |
| 435 } |
| 436 |
| 394 bool TCPClientSocketLibevent::SetReceiveBufferSize(int32 size) { | 437 bool TCPClientSocketLibevent::SetReceiveBufferSize(int32 size) { |
| 395 DCHECK(CalledOnValidThread()); | 438 DCHECK(CalledOnValidThread()); |
| 396 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, | 439 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, |
| 397 reinterpret_cast<const char*>(&size), | 440 reinterpret_cast<const char*>(&size), |
| 398 sizeof(size)); | 441 sizeof(size)); |
| 399 DCHECK(!rv) << "Could not set socket receive buffer size: " << errno; | 442 DCHECK(!rv) << "Could not set socket receive buffer size: " << errno; |
| 400 return rv == 0; | 443 return rv == 0; |
| 401 } | 444 } |
| 402 | 445 |
| 403 bool TCPClientSocketLibevent::SetSendBufferSize(int32 size) { | 446 bool TCPClientSocketLibevent::SetSendBufferSize(int32 size) { |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 546 } | 589 } |
| 547 | 590 |
| 548 void TCPClientSocketLibevent::SetOmniboxSpeculation() { | 591 void TCPClientSocketLibevent::SetOmniboxSpeculation() { |
| 549 use_history_.set_omnibox_speculation(); | 592 use_history_.set_omnibox_speculation(); |
| 550 } | 593 } |
| 551 | 594 |
| 552 bool TCPClientSocketLibevent::WasEverUsed() const { | 595 bool TCPClientSocketLibevent::WasEverUsed() const { |
| 553 return use_history_.was_used_to_convey_data(); | 596 return use_history_.was_used_to_convey_data(); |
| 554 } | 597 } |
| 555 | 598 |
| 599 bool TCPClientSocketLibevent::UsingTCPFastOpen() const { |
| 600 return use_tcp_fastopen_; |
| 601 } |
| 602 |
| 556 } // namespace net | 603 } // namespace net |
| OLD | NEW |