| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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_socket.h" | 5 #include "net/socket/tcp_socket.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <netinet/tcp.h> | 8 #include <netinet/tcp.h> |
| 9 #include <sys/socket.h> | 9 #include <sys/socket.h> |
| 10 | 10 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/files/file_path.h" | 12 #include "base/files/file_path.h" |
| 13 #include "base/files/file_util.h" | 13 #include "base/files/file_util.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/metrics/histogram_macros.h" | 15 #include "base/metrics/histogram_macros.h" |
| 16 #include "base/posix/eintr_wrapper.h" | 16 #include "base/posix/eintr_wrapper.h" |
| 17 #include "base/task_runner_util.h" | 17 #include "base/task_runner_util.h" |
| 18 #include "base/threading/worker_pool.h" | 18 #include "base/threading/worker_pool.h" |
| 19 #include "net/base/address_list.h" | 19 #include "net/base/address_list.h" |
| 20 #include "net/base/connection_type_histograms.h" | 20 #include "net/base/connection_type_histograms.h" |
| 21 #include "net/base/io_buffer.h" | 21 #include "net/base/io_buffer.h" |
| 22 #include "net/base/ip_endpoint.h" | 22 #include "net/base/ip_endpoint.h" |
| 23 #include "net/base/net_errors.h" | 23 #include "net/base/net_errors.h" |
| 24 #include "net/base/net_util.h" | 24 #include "net/base/net_util.h" |
| 25 #include "net/base/network_activity_monitor.h" | 25 #include "net/base/network_activity_monitor.h" |
| 26 #include "net/base/network_change_notifier.h" | 26 #include "net/base/network_change_notifier.h" |
| 27 #include "net/socket/socket_libevent.h" | |
| 28 #include "net/socket/socket_net_log_params.h" | 27 #include "net/socket/socket_net_log_params.h" |
| 28 #include "net/socket/socket_posix.h" |
| 29 | 29 |
| 30 // If we don't have a definition for TCPI_OPT_SYN_DATA, create one. | 30 // If we don't have a definition for TCPI_OPT_SYN_DATA, create one. |
| 31 #ifndef TCPI_OPT_SYN_DATA | 31 #ifndef TCPI_OPT_SYN_DATA |
| 32 #define TCPI_OPT_SYN_DATA 32 | 32 #define TCPI_OPT_SYN_DATA 32 |
| 33 #endif | 33 #endif |
| 34 | 34 |
| 35 namespace net { | 35 namespace net { |
| 36 | 36 |
| 37 namespace { | 37 namespace { |
| 38 | 38 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 void CheckSupportAndMaybeEnableTCPFastOpen(bool user_enabled) { | 139 void CheckSupportAndMaybeEnableTCPFastOpen(bool user_enabled) { |
| 140 #if defined(OS_LINUX) || defined(OS_ANDROID) | 140 #if defined(OS_LINUX) || defined(OS_ANDROID) |
| 141 base::PostTaskAndReplyWithResult( | 141 base::PostTaskAndReplyWithResult( |
| 142 base::WorkerPool::GetTaskRunner(/*task_is_slow=*/false).get(), | 142 base::WorkerPool::GetTaskRunner(/*task_is_slow=*/false).get(), |
| 143 FROM_HERE, | 143 FROM_HERE, |
| 144 base::Bind(SystemSupportsTCPFastOpen), | 144 base::Bind(SystemSupportsTCPFastOpen), |
| 145 base::Bind(RegisterTCPFastOpenIntentAndSupport, user_enabled)); | 145 base::Bind(RegisterTCPFastOpenIntentAndSupport, user_enabled)); |
| 146 #endif | 146 #endif |
| 147 } | 147 } |
| 148 | 148 |
| 149 TCPSocketLibevent::TCPSocketLibevent(NetLog* net_log, | 149 TCPSocketPosix::TCPSocketPosix(NetLog* net_log, const NetLog::Source& source) |
| 150 const NetLog::Source& source) | |
| 151 : use_tcp_fastopen_(false), | 150 : use_tcp_fastopen_(false), |
| 152 tcp_fastopen_write_attempted_(false), | 151 tcp_fastopen_write_attempted_(false), |
| 153 tcp_fastopen_connected_(false), | 152 tcp_fastopen_connected_(false), |
| 154 tcp_fastopen_status_(TCP_FASTOPEN_STATUS_UNKNOWN), | 153 tcp_fastopen_status_(TCP_FASTOPEN_STATUS_UNKNOWN), |
| 155 logging_multiple_connect_attempts_(false), | 154 logging_multiple_connect_attempts_(false), |
| 156 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { | 155 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { |
| 157 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, | 156 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, |
| 158 source.ToEventParametersCallback()); | 157 source.ToEventParametersCallback()); |
| 159 } | 158 } |
| 160 | 159 |
| 161 TCPSocketLibevent::~TCPSocketLibevent() { | 160 TCPSocketPosix::~TCPSocketPosix() { |
| 162 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); | 161 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); |
| 163 Close(); | 162 Close(); |
| 164 } | 163 } |
| 165 | 164 |
| 166 int TCPSocketLibevent::Open(AddressFamily family) { | 165 int TCPSocketPosix::Open(AddressFamily family) { |
| 167 DCHECK(!socket_); | 166 DCHECK(!socket_); |
| 168 socket_.reset(new SocketLibevent); | 167 socket_.reset(new SocketPosix); |
| 169 int rv = socket_->Open(ConvertAddressFamily(family)); | 168 int rv = socket_->Open(ConvertAddressFamily(family)); |
| 170 if (rv != OK) | 169 if (rv != OK) |
| 171 socket_.reset(); | 170 socket_.reset(); |
| 172 return rv; | 171 return rv; |
| 173 } | 172 } |
| 174 | 173 |
| 175 int TCPSocketLibevent::AdoptConnectedSocket(int socket_fd, | 174 int TCPSocketPosix::AdoptConnectedSocket(int socket_fd, |
| 176 const IPEndPoint& peer_address) { | 175 const IPEndPoint& peer_address) { |
| 177 DCHECK(!socket_); | 176 DCHECK(!socket_); |
| 178 | 177 |
| 179 SockaddrStorage storage; | 178 SockaddrStorage storage; |
| 180 if (!peer_address.ToSockAddr(storage.addr, &storage.addr_len) && | 179 if (!peer_address.ToSockAddr(storage.addr, &storage.addr_len) && |
| 181 // For backward compatibility, allows the empty address. | 180 // For backward compatibility, allows the empty address. |
| 182 !(peer_address == IPEndPoint())) { | 181 !(peer_address == IPEndPoint())) { |
| 183 return ERR_ADDRESS_INVALID; | 182 return ERR_ADDRESS_INVALID; |
| 184 } | 183 } |
| 185 | 184 |
| 186 socket_.reset(new SocketLibevent); | 185 socket_.reset(new SocketPosix); |
| 187 int rv = socket_->AdoptConnectedSocket(socket_fd, storage); | 186 int rv = socket_->AdoptConnectedSocket(socket_fd, storage); |
| 188 if (rv != OK) | 187 if (rv != OK) |
| 189 socket_.reset(); | 188 socket_.reset(); |
| 190 return rv; | 189 return rv; |
| 191 } | 190 } |
| 192 | 191 |
| 193 int TCPSocketLibevent::Bind(const IPEndPoint& address) { | 192 int TCPSocketPosix::Bind(const IPEndPoint& address) { |
| 194 DCHECK(socket_); | 193 DCHECK(socket_); |
| 195 | 194 |
| 196 SockaddrStorage storage; | 195 SockaddrStorage storage; |
| 197 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) | 196 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) |
| 198 return ERR_ADDRESS_INVALID; | 197 return ERR_ADDRESS_INVALID; |
| 199 | 198 |
| 200 return socket_->Bind(storage); | 199 return socket_->Bind(storage); |
| 201 } | 200 } |
| 202 | 201 |
| 203 int TCPSocketLibevent::Listen(int backlog) { | 202 int TCPSocketPosix::Listen(int backlog) { |
| 204 DCHECK(socket_); | 203 DCHECK(socket_); |
| 205 return socket_->Listen(backlog); | 204 return socket_->Listen(backlog); |
| 206 } | 205 } |
| 207 | 206 |
| 208 int TCPSocketLibevent::Accept(scoped_ptr<TCPSocketLibevent>* tcp_socket, | 207 int TCPSocketPosix::Accept(scoped_ptr<TCPSocketPosix>* tcp_socket, |
| 209 IPEndPoint* address, | 208 IPEndPoint* address, |
| 210 const CompletionCallback& callback) { | 209 const CompletionCallback& callback) { |
| 211 DCHECK(tcp_socket); | 210 DCHECK(tcp_socket); |
| 212 DCHECK(!callback.is_null()); | 211 DCHECK(!callback.is_null()); |
| 213 DCHECK(socket_); | 212 DCHECK(socket_); |
| 214 DCHECK(!accept_socket_); | 213 DCHECK(!accept_socket_); |
| 215 | 214 |
| 216 net_log_.BeginEvent(NetLog::TYPE_TCP_ACCEPT); | 215 net_log_.BeginEvent(NetLog::TYPE_TCP_ACCEPT); |
| 217 | 216 |
| 218 int rv = socket_->Accept( | 217 int rv = socket_->Accept( |
| 219 &accept_socket_, | 218 &accept_socket_, |
| 220 base::Bind(&TCPSocketLibevent::AcceptCompleted, | 219 base::Bind(&TCPSocketPosix::AcceptCompleted, base::Unretained(this), |
| 221 base::Unretained(this), tcp_socket, address, callback)); | 220 tcp_socket, address, callback)); |
| 222 if (rv != ERR_IO_PENDING) | 221 if (rv != ERR_IO_PENDING) |
| 223 rv = HandleAcceptCompleted(tcp_socket, address, rv); | 222 rv = HandleAcceptCompleted(tcp_socket, address, rv); |
| 224 return rv; | 223 return rv; |
| 225 } | 224 } |
| 226 | 225 |
| 227 int TCPSocketLibevent::Connect(const IPEndPoint& address, | 226 int TCPSocketPosix::Connect(const IPEndPoint& address, |
| 228 const CompletionCallback& callback) { | 227 const CompletionCallback& callback) { |
| 229 DCHECK(socket_); | 228 DCHECK(socket_); |
| 230 | 229 |
| 231 if (!logging_multiple_connect_attempts_) | 230 if (!logging_multiple_connect_attempts_) |
| 232 LogConnectBegin(AddressList(address)); | 231 LogConnectBegin(AddressList(address)); |
| 233 | 232 |
| 234 net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, | 233 net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, |
| 235 CreateNetLogIPEndPointCallback(&address)); | 234 CreateNetLogIPEndPointCallback(&address)); |
| 236 | 235 |
| 237 SockaddrStorage storage; | 236 SockaddrStorage storage; |
| 238 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) | 237 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) |
| 239 return ERR_ADDRESS_INVALID; | 238 return ERR_ADDRESS_INVALID; |
| 240 | 239 |
| 241 if (use_tcp_fastopen_) { | 240 if (use_tcp_fastopen_) { |
| 242 // With TCP FastOpen, we pretend that the socket is connected. | 241 // With TCP FastOpen, we pretend that the socket is connected. |
| 243 DCHECK(!tcp_fastopen_write_attempted_); | 242 DCHECK(!tcp_fastopen_write_attempted_); |
| 244 socket_->SetPeerAddress(storage); | 243 socket_->SetPeerAddress(storage); |
| 245 return OK; | 244 return OK; |
| 246 } | 245 } |
| 247 | 246 |
| 248 int rv = socket_->Connect(storage, | 247 int rv = |
| 249 base::Bind(&TCPSocketLibevent::ConnectCompleted, | 248 socket_->Connect(storage, base::Bind(&TCPSocketPosix::ConnectCompleted, |
| 250 base::Unretained(this), callback)); | 249 base::Unretained(this), callback)); |
| 251 if (rv != ERR_IO_PENDING) | 250 if (rv != ERR_IO_PENDING) |
| 252 rv = HandleConnectCompleted(rv); | 251 rv = HandleConnectCompleted(rv); |
| 253 return rv; | 252 return rv; |
| 254 } | 253 } |
| 255 | 254 |
| 256 bool TCPSocketLibevent::IsConnected() const { | 255 bool TCPSocketPosix::IsConnected() const { |
| 257 if (!socket_) | 256 if (!socket_) |
| 258 return false; | 257 return false; |
| 259 | 258 |
| 260 if (use_tcp_fastopen_ && !tcp_fastopen_write_attempted_ && | 259 if (use_tcp_fastopen_ && !tcp_fastopen_write_attempted_ && |
| 261 socket_->HasPeerAddress()) { | 260 socket_->HasPeerAddress()) { |
| 262 // With TCP FastOpen, we pretend that the socket is connected. | 261 // With TCP FastOpen, we pretend that the socket is connected. |
| 263 // This allows GetPeerAddress() to return peer_address_. | 262 // This allows GetPeerAddress() to return peer_address_. |
| 264 return true; | 263 return true; |
| 265 } | 264 } |
| 266 | 265 |
| 267 return socket_->IsConnected(); | 266 return socket_->IsConnected(); |
| 268 } | 267 } |
| 269 | 268 |
| 270 bool TCPSocketLibevent::IsConnectedAndIdle() const { | 269 bool TCPSocketPosix::IsConnectedAndIdle() const { |
| 271 // TODO(wtc): should we also handle the TCP FastOpen case here, | 270 // TODO(wtc): should we also handle the TCP FastOpen case here, |
| 272 // as we do in IsConnected()? | 271 // as we do in IsConnected()? |
| 273 return socket_ && socket_->IsConnectedAndIdle(); | 272 return socket_ && socket_->IsConnectedAndIdle(); |
| 274 } | 273 } |
| 275 | 274 |
| 276 int TCPSocketLibevent::Read(IOBuffer* buf, | 275 int TCPSocketPosix::Read(IOBuffer* buf, |
| 277 int buf_len, | 276 int buf_len, |
| 278 const CompletionCallback& callback) { | 277 const CompletionCallback& callback) { |
| 279 DCHECK(socket_); | 278 DCHECK(socket_); |
| 280 DCHECK(!callback.is_null()); | 279 DCHECK(!callback.is_null()); |
| 281 | 280 |
| 282 int rv = socket_->Read( | 281 int rv = socket_->Read( |
| 283 buf, buf_len, | 282 buf, buf_len, |
| 284 base::Bind(&TCPSocketLibevent::ReadCompleted, | 283 base::Bind(&TCPSocketPosix::ReadCompleted, |
| 285 // Grab a reference to |buf| so that ReadCompleted() can still | 284 // Grab a reference to |buf| so that ReadCompleted() can still |
| 286 // use it when Read() completes, as otherwise, this transfers | 285 // use it when Read() completes, as otherwise, this transfers |
| 287 // ownership of buf to socket. | 286 // ownership of buf to socket. |
| 288 base::Unretained(this), make_scoped_refptr(buf), callback)); | 287 base::Unretained(this), make_scoped_refptr(buf), callback)); |
| 289 if (rv != ERR_IO_PENDING) | 288 if (rv != ERR_IO_PENDING) |
| 290 rv = HandleReadCompleted(buf, rv); | 289 rv = HandleReadCompleted(buf, rv); |
| 291 return rv; | 290 return rv; |
| 292 } | 291 } |
| 293 | 292 |
| 294 int TCPSocketLibevent::Write(IOBuffer* buf, | 293 int TCPSocketPosix::Write(IOBuffer* buf, |
| 295 int buf_len, | 294 int buf_len, |
| 296 const CompletionCallback& callback) { | 295 const CompletionCallback& callback) { |
| 297 DCHECK(socket_); | 296 DCHECK(socket_); |
| 298 DCHECK(!callback.is_null()); | 297 DCHECK(!callback.is_null()); |
| 299 | 298 |
| 300 CompletionCallback write_callback = | 299 CompletionCallback write_callback = |
| 301 base::Bind(&TCPSocketLibevent::WriteCompleted, | 300 base::Bind(&TCPSocketPosix::WriteCompleted, |
| 302 // Grab a reference to |buf| so that WriteCompleted() can still | 301 // Grab a reference to |buf| so that WriteCompleted() can still |
| 303 // use it when Write() completes, as otherwise, this transfers | 302 // use it when Write() completes, as otherwise, this transfers |
| 304 // ownership of buf to socket. | 303 // ownership of buf to socket. |
| 305 base::Unretained(this), make_scoped_refptr(buf), callback); | 304 base::Unretained(this), make_scoped_refptr(buf), callback); |
| 306 int rv; | 305 int rv; |
| 307 | 306 |
| 308 if (use_tcp_fastopen_ && !tcp_fastopen_write_attempted_) { | 307 if (use_tcp_fastopen_ && !tcp_fastopen_write_attempted_) { |
| 309 rv = TcpFastOpenWrite(buf, buf_len, write_callback); | 308 rv = TcpFastOpenWrite(buf, buf_len, write_callback); |
| 310 } else { | 309 } else { |
| 311 rv = socket_->Write(buf, buf_len, write_callback); | 310 rv = socket_->Write(buf, buf_len, write_callback); |
| 312 } | 311 } |
| 313 | 312 |
| 314 if (rv != ERR_IO_PENDING) | 313 if (rv != ERR_IO_PENDING) |
| 315 rv = HandleWriteCompleted(buf, rv); | 314 rv = HandleWriteCompleted(buf, rv); |
| 316 return rv; | 315 return rv; |
| 317 } | 316 } |
| 318 | 317 |
| 319 int TCPSocketLibevent::GetLocalAddress(IPEndPoint* address) const { | 318 int TCPSocketPosix::GetLocalAddress(IPEndPoint* address) const { |
| 320 DCHECK(address); | 319 DCHECK(address); |
| 321 | 320 |
| 322 if (!socket_) | 321 if (!socket_) |
| 323 return ERR_SOCKET_NOT_CONNECTED; | 322 return ERR_SOCKET_NOT_CONNECTED; |
| 324 | 323 |
| 325 SockaddrStorage storage; | 324 SockaddrStorage storage; |
| 326 int rv = socket_->GetLocalAddress(&storage); | 325 int rv = socket_->GetLocalAddress(&storage); |
| 327 if (rv != OK) | 326 if (rv != OK) |
| 328 return rv; | 327 return rv; |
| 329 | 328 |
| 330 if (!address->FromSockAddr(storage.addr, storage.addr_len)) | 329 if (!address->FromSockAddr(storage.addr, storage.addr_len)) |
| 331 return ERR_ADDRESS_INVALID; | 330 return ERR_ADDRESS_INVALID; |
| 332 | 331 |
| 333 return OK; | 332 return OK; |
| 334 } | 333 } |
| 335 | 334 |
| 336 int TCPSocketLibevent::GetPeerAddress(IPEndPoint* address) const { | 335 int TCPSocketPosix::GetPeerAddress(IPEndPoint* address) const { |
| 337 DCHECK(address); | 336 DCHECK(address); |
| 338 | 337 |
| 339 if (!IsConnected()) | 338 if (!IsConnected()) |
| 340 return ERR_SOCKET_NOT_CONNECTED; | 339 return ERR_SOCKET_NOT_CONNECTED; |
| 341 | 340 |
| 342 SockaddrStorage storage; | 341 SockaddrStorage storage; |
| 343 int rv = socket_->GetPeerAddress(&storage); | 342 int rv = socket_->GetPeerAddress(&storage); |
| 344 if (rv != OK) | 343 if (rv != OK) |
| 345 return rv; | 344 return rv; |
| 346 | 345 |
| 347 if (!address->FromSockAddr(storage.addr, storage.addr_len)) | 346 if (!address->FromSockAddr(storage.addr, storage.addr_len)) |
| 348 return ERR_ADDRESS_INVALID; | 347 return ERR_ADDRESS_INVALID; |
| 349 | 348 |
| 350 return OK; | 349 return OK; |
| 351 } | 350 } |
| 352 | 351 |
| 353 int TCPSocketLibevent::SetDefaultOptionsForServer() { | 352 int TCPSocketPosix::SetDefaultOptionsForServer() { |
| 354 DCHECK(socket_); | 353 DCHECK(socket_); |
| 355 return SetAddressReuse(true); | 354 return SetAddressReuse(true); |
| 356 } | 355 } |
| 357 | 356 |
| 358 void TCPSocketLibevent::SetDefaultOptionsForClient() { | 357 void TCPSocketPosix::SetDefaultOptionsForClient() { |
| 359 DCHECK(socket_); | 358 DCHECK(socket_); |
| 360 | 359 |
| 361 // This mirrors the behaviour on Windows. See the comment in | 360 // This mirrors the behaviour on Windows. See the comment in |
| 362 // tcp_socket_win.cc after searching for "NODELAY". | 361 // tcp_socket_win.cc after searching for "NODELAY". |
| 363 // If SetTCPNoDelay fails, we don't care. | 362 // If SetTCPNoDelay fails, we don't care. |
| 364 SetTCPNoDelay(socket_->socket_fd(), true); | 363 SetTCPNoDelay(socket_->socket_fd(), true); |
| 365 | 364 |
| 366 // TCP keep alive wakes up the radio, which is expensive on mobile. Do not | 365 // TCP keep alive wakes up the radio, which is expensive on mobile. Do not |
| 367 // enable it there. It's useful to prevent TCP middleboxes from timing out | 366 // enable it there. It's useful to prevent TCP middleboxes from timing out |
| 368 // connection mappings. Packets for timed out connection mappings at | 367 // connection mappings. Packets for timed out connection mappings at |
| 369 // middleboxes will either lead to: | 368 // middleboxes will either lead to: |
| 370 // a) Middleboxes sending TCP RSTs. It's up to higher layers to check for this | 369 // a) Middleboxes sending TCP RSTs. It's up to higher layers to check for this |
| 371 // and retry. The HTTP network transaction code does this. | 370 // and retry. The HTTP network transaction code does this. |
| 372 // b) Middleboxes just drop the unrecognized TCP packet. This leads to the TCP | 371 // b) Middleboxes just drop the unrecognized TCP packet. This leads to the TCP |
| 373 // stack retransmitting packets per TCP stack retransmission timeouts, which | 372 // stack retransmitting packets per TCP stack retransmission timeouts, which |
| 374 // are very high (on the order of seconds). Given the number of | 373 // are very high (on the order of seconds). Given the number of |
| 375 // retransmissions required before killing the connection, this can lead to | 374 // retransmissions required before killing the connection, this can lead to |
| 376 // tens of seconds or even minutes of delay, depending on OS. | 375 // tens of seconds or even minutes of delay, depending on OS. |
| 377 #if !defined(OS_ANDROID) && !defined(OS_IOS) | 376 #if !defined(OS_ANDROID) && !defined(OS_IOS) |
| 378 const int kTCPKeepAliveSeconds = 45; | 377 const int kTCPKeepAliveSeconds = 45; |
| 379 | 378 |
| 380 SetTCPKeepAlive(socket_->socket_fd(), true, kTCPKeepAliveSeconds); | 379 SetTCPKeepAlive(socket_->socket_fd(), true, kTCPKeepAliveSeconds); |
| 381 #endif | 380 #endif |
| 382 } | 381 } |
| 383 | 382 |
| 384 int TCPSocketLibevent::SetAddressReuse(bool allow) { | 383 int TCPSocketPosix::SetAddressReuse(bool allow) { |
| 385 DCHECK(socket_); | 384 DCHECK(socket_); |
| 386 | 385 |
| 387 // SO_REUSEADDR is useful for server sockets to bind to a recently unbound | 386 // SO_REUSEADDR is useful for server sockets to bind to a recently unbound |
| 388 // port. When a socket is closed, the end point changes its state to TIME_WAIT | 387 // port. When a socket is closed, the end point changes its state to TIME_WAIT |
| 389 // and wait for 2 MSL (maximum segment lifetime) to ensure the remote peer | 388 // and wait for 2 MSL (maximum segment lifetime) to ensure the remote peer |
| 390 // acknowledges its closure. For server sockets, it is usually safe to | 389 // acknowledges its closure. For server sockets, it is usually safe to |
| 391 // bind to a TIME_WAIT end point immediately, which is a widely adopted | 390 // bind to a TIME_WAIT end point immediately, which is a widely adopted |
| 392 // behavior. | 391 // behavior. |
| 393 // | 392 // |
| 394 // Note that on *nix, SO_REUSEADDR does not enable the TCP socket to bind to | 393 // Note that on *nix, SO_REUSEADDR does not enable the TCP socket to bind to |
| 395 // an end point that is already bound by another socket. To do that one must | 394 // an end point that is already bound by another socket. To do that one must |
| 396 // set SO_REUSEPORT instead. This option is not provided on Linux prior | 395 // set SO_REUSEPORT instead. This option is not provided on Linux prior |
| 397 // to 3.9. | 396 // to 3.9. |
| 398 // | 397 // |
| 399 // SO_REUSEPORT is provided in MacOS X and iOS. | 398 // SO_REUSEPORT is provided in MacOS X and iOS. |
| 400 int boolean_value = allow ? 1 : 0; | 399 int boolean_value = allow ? 1 : 0; |
| 401 int rv = setsockopt(socket_->socket_fd(), SOL_SOCKET, SO_REUSEADDR, | 400 int rv = setsockopt(socket_->socket_fd(), SOL_SOCKET, SO_REUSEADDR, |
| 402 &boolean_value, sizeof(boolean_value)); | 401 &boolean_value, sizeof(boolean_value)); |
| 403 if (rv < 0) | 402 if (rv < 0) |
| 404 return MapSystemError(errno); | 403 return MapSystemError(errno); |
| 405 return OK; | 404 return OK; |
| 406 } | 405 } |
| 407 | 406 |
| 408 int TCPSocketLibevent::SetReceiveBufferSize(int32 size) { | 407 int TCPSocketPosix::SetReceiveBufferSize(int32 size) { |
| 409 DCHECK(socket_); | 408 DCHECK(socket_); |
| 410 int rv = setsockopt(socket_->socket_fd(), SOL_SOCKET, SO_RCVBUF, | 409 int rv = setsockopt(socket_->socket_fd(), SOL_SOCKET, SO_RCVBUF, |
| 411 reinterpret_cast<const char*>(&size), sizeof(size)); | 410 reinterpret_cast<const char*>(&size), sizeof(size)); |
| 412 return (rv == 0) ? OK : MapSystemError(errno); | 411 return (rv == 0) ? OK : MapSystemError(errno); |
| 413 } | 412 } |
| 414 | 413 |
| 415 int TCPSocketLibevent::SetSendBufferSize(int32 size) { | 414 int TCPSocketPosix::SetSendBufferSize(int32 size) { |
| 416 DCHECK(socket_); | 415 DCHECK(socket_); |
| 417 int rv = setsockopt(socket_->socket_fd(), SOL_SOCKET, SO_SNDBUF, | 416 int rv = setsockopt(socket_->socket_fd(), SOL_SOCKET, SO_SNDBUF, |
| 418 reinterpret_cast<const char*>(&size), sizeof(size)); | 417 reinterpret_cast<const char*>(&size), sizeof(size)); |
| 419 return (rv == 0) ? OK : MapSystemError(errno); | 418 return (rv == 0) ? OK : MapSystemError(errno); |
| 420 } | 419 } |
| 421 | 420 |
| 422 bool TCPSocketLibevent::SetKeepAlive(bool enable, int delay) { | 421 bool TCPSocketPosix::SetKeepAlive(bool enable, int delay) { |
| 423 DCHECK(socket_); | 422 DCHECK(socket_); |
| 424 return SetTCPKeepAlive(socket_->socket_fd(), enable, delay); | 423 return SetTCPKeepAlive(socket_->socket_fd(), enable, delay); |
| 425 } | 424 } |
| 426 | 425 |
| 427 bool TCPSocketLibevent::SetNoDelay(bool no_delay) { | 426 bool TCPSocketPosix::SetNoDelay(bool no_delay) { |
| 428 DCHECK(socket_); | 427 DCHECK(socket_); |
| 429 return SetTCPNoDelay(socket_->socket_fd(), no_delay); | 428 return SetTCPNoDelay(socket_->socket_fd(), no_delay); |
| 430 } | 429 } |
| 431 | 430 |
| 432 void TCPSocketLibevent::Close() { | 431 void TCPSocketPosix::Close() { |
| 433 socket_.reset(); | 432 socket_.reset(); |
| 434 | 433 |
| 435 // Record and reset TCP FastOpen state. | 434 // Record and reset TCP FastOpen state. |
| 436 if (tcp_fastopen_write_attempted_ || | 435 if (tcp_fastopen_write_attempted_ || |
| 437 tcp_fastopen_status_ == TCP_FASTOPEN_PREVIOUSLY_FAILED) { | 436 tcp_fastopen_status_ == TCP_FASTOPEN_PREVIOUSLY_FAILED) { |
| 438 UMA_HISTOGRAM_ENUMERATION("Net.TcpFastOpenSocketConnection", | 437 UMA_HISTOGRAM_ENUMERATION("Net.TcpFastOpenSocketConnection", |
| 439 tcp_fastopen_status_, TCP_FASTOPEN_MAX_VALUE); | 438 tcp_fastopen_status_, TCP_FASTOPEN_MAX_VALUE); |
| 440 } | 439 } |
| 441 use_tcp_fastopen_ = false; | 440 use_tcp_fastopen_ = false; |
| 442 tcp_fastopen_connected_ = false; | 441 tcp_fastopen_connected_ = false; |
| 443 tcp_fastopen_write_attempted_ = false; | 442 tcp_fastopen_write_attempted_ = false; |
| 444 tcp_fastopen_status_ = TCP_FASTOPEN_STATUS_UNKNOWN; | 443 tcp_fastopen_status_ = TCP_FASTOPEN_STATUS_UNKNOWN; |
| 445 } | 444 } |
| 446 | 445 |
| 447 bool TCPSocketLibevent::UsingTCPFastOpen() const { | 446 bool TCPSocketPosix::UsingTCPFastOpen() const { |
| 448 return use_tcp_fastopen_; | 447 return use_tcp_fastopen_; |
| 449 } | 448 } |
| 450 | 449 |
| 451 void TCPSocketLibevent::EnableTCPFastOpenIfSupported() { | 450 void TCPSocketPosix::EnableTCPFastOpenIfSupported() { |
| 452 if (!IsTCPFastOpenSupported()) | 451 if (!IsTCPFastOpenSupported()) |
| 453 return; | 452 return; |
| 454 | 453 |
| 455 // Do not enable TCP FastOpen if it had previously failed. | 454 // Do not enable TCP FastOpen if it had previously failed. |
| 456 // This check conservatively avoids middleboxes that may blackhole | 455 // This check conservatively avoids middleboxes that may blackhole |
| 457 // TCP FastOpen SYN+Data packets; on such a failure, subsequent sockets | 456 // TCP FastOpen SYN+Data packets; on such a failure, subsequent sockets |
| 458 // should not use TCP FastOpen. | 457 // should not use TCP FastOpen. |
| 459 if(!g_tcp_fastopen_has_failed) | 458 if(!g_tcp_fastopen_has_failed) |
| 460 use_tcp_fastopen_ = true; | 459 use_tcp_fastopen_ = true; |
| 461 else | 460 else |
| 462 tcp_fastopen_status_ = TCP_FASTOPEN_PREVIOUSLY_FAILED; | 461 tcp_fastopen_status_ = TCP_FASTOPEN_PREVIOUSLY_FAILED; |
| 463 } | 462 } |
| 464 | 463 |
| 465 bool TCPSocketLibevent::IsValid() const { | 464 bool TCPSocketPosix::IsValid() const { |
| 466 return socket_ != NULL && socket_->socket_fd() != kInvalidSocket; | 465 return socket_ != NULL && socket_->socket_fd() != kInvalidSocket; |
| 467 } | 466 } |
| 468 | 467 |
| 469 void TCPSocketLibevent::StartLoggingMultipleConnectAttempts( | 468 void TCPSocketPosix::StartLoggingMultipleConnectAttempts( |
| 470 const AddressList& addresses) { | 469 const AddressList& addresses) { |
| 471 if (!logging_multiple_connect_attempts_) { | 470 if (!logging_multiple_connect_attempts_) { |
| 472 logging_multiple_connect_attempts_ = true; | 471 logging_multiple_connect_attempts_ = true; |
| 473 LogConnectBegin(addresses); | 472 LogConnectBegin(addresses); |
| 474 } else { | 473 } else { |
| 475 NOTREACHED(); | 474 NOTREACHED(); |
| 476 } | 475 } |
| 477 } | 476 } |
| 478 | 477 |
| 479 void TCPSocketLibevent::EndLoggingMultipleConnectAttempts(int net_error) { | 478 void TCPSocketPosix::EndLoggingMultipleConnectAttempts(int net_error) { |
| 480 if (logging_multiple_connect_attempts_) { | 479 if (logging_multiple_connect_attempts_) { |
| 481 LogConnectEnd(net_error); | 480 LogConnectEnd(net_error); |
| 482 logging_multiple_connect_attempts_ = false; | 481 logging_multiple_connect_attempts_ = false; |
| 483 } else { | 482 } else { |
| 484 NOTREACHED(); | 483 NOTREACHED(); |
| 485 } | 484 } |
| 486 } | 485 } |
| 487 | 486 |
| 488 void TCPSocketLibevent::AcceptCompleted( | 487 void TCPSocketPosix::AcceptCompleted(scoped_ptr<TCPSocketPosix>* tcp_socket, |
| 489 scoped_ptr<TCPSocketLibevent>* tcp_socket, | 488 IPEndPoint* address, |
| 490 IPEndPoint* address, | 489 const CompletionCallback& callback, |
| 491 const CompletionCallback& callback, | 490 int rv) { |
| 492 int rv) { | |
| 493 DCHECK_NE(ERR_IO_PENDING, rv); | 491 DCHECK_NE(ERR_IO_PENDING, rv); |
| 494 callback.Run(HandleAcceptCompleted(tcp_socket, address, rv)); | 492 callback.Run(HandleAcceptCompleted(tcp_socket, address, rv)); |
| 495 } | 493 } |
| 496 | 494 |
| 497 int TCPSocketLibevent::HandleAcceptCompleted( | 495 int TCPSocketPosix::HandleAcceptCompleted( |
| 498 scoped_ptr<TCPSocketLibevent>* tcp_socket, | 496 scoped_ptr<TCPSocketPosix>* tcp_socket, |
| 499 IPEndPoint* address, | 497 IPEndPoint* address, |
| 500 int rv) { | 498 int rv) { |
| 501 if (rv == OK) | 499 if (rv == OK) |
| 502 rv = BuildTcpSocketLibevent(tcp_socket, address); | 500 rv = BuildTcpSocketPosix(tcp_socket, address); |
| 503 | 501 |
| 504 if (rv == OK) { | 502 if (rv == OK) { |
| 505 net_log_.EndEvent(NetLog::TYPE_TCP_ACCEPT, | 503 net_log_.EndEvent(NetLog::TYPE_TCP_ACCEPT, |
| 506 CreateNetLogIPEndPointCallback(address)); | 504 CreateNetLogIPEndPointCallback(address)); |
| 507 } else { | 505 } else { |
| 508 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, rv); | 506 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, rv); |
| 509 } | 507 } |
| 510 | 508 |
| 511 return rv; | 509 return rv; |
| 512 } | 510 } |
| 513 | 511 |
| 514 int TCPSocketLibevent::BuildTcpSocketLibevent( | 512 int TCPSocketPosix::BuildTcpSocketPosix(scoped_ptr<TCPSocketPosix>* tcp_socket, |
| 515 scoped_ptr<TCPSocketLibevent>* tcp_socket, | 513 IPEndPoint* address) { |
| 516 IPEndPoint* address) { | |
| 517 DCHECK(accept_socket_); | 514 DCHECK(accept_socket_); |
| 518 | 515 |
| 519 SockaddrStorage storage; | 516 SockaddrStorage storage; |
| 520 if (accept_socket_->GetPeerAddress(&storage) != OK || | 517 if (accept_socket_->GetPeerAddress(&storage) != OK || |
| 521 !address->FromSockAddr(storage.addr, storage.addr_len)) { | 518 !address->FromSockAddr(storage.addr, storage.addr_len)) { |
| 522 accept_socket_.reset(); | 519 accept_socket_.reset(); |
| 523 return ERR_ADDRESS_INVALID; | 520 return ERR_ADDRESS_INVALID; |
| 524 } | 521 } |
| 525 | 522 |
| 526 tcp_socket->reset(new TCPSocketLibevent(net_log_.net_log(), | 523 tcp_socket->reset(new TCPSocketPosix(net_log_.net_log(), net_log_.source())); |
| 527 net_log_.source())); | |
| 528 (*tcp_socket)->socket_.reset(accept_socket_.release()); | 524 (*tcp_socket)->socket_.reset(accept_socket_.release()); |
| 529 return OK; | 525 return OK; |
| 530 } | 526 } |
| 531 | 527 |
| 532 void TCPSocketLibevent::ConnectCompleted(const CompletionCallback& callback, | 528 void TCPSocketPosix::ConnectCompleted(const CompletionCallback& callback, |
| 533 int rv) const { | 529 int rv) const { |
| 534 DCHECK_NE(ERR_IO_PENDING, rv); | 530 DCHECK_NE(ERR_IO_PENDING, rv); |
| 535 callback.Run(HandleConnectCompleted(rv)); | 531 callback.Run(HandleConnectCompleted(rv)); |
| 536 } | 532 } |
| 537 | 533 |
| 538 int TCPSocketLibevent::HandleConnectCompleted(int rv) const { | 534 int TCPSocketPosix::HandleConnectCompleted(int rv) const { |
| 539 // Log the end of this attempt (and any OS error it threw). | 535 // Log the end of this attempt (and any OS error it threw). |
| 540 if (rv != OK) { | 536 if (rv != OK) { |
| 541 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, | 537 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, |
| 542 NetLog::IntegerCallback("os_error", errno)); | 538 NetLog::IntegerCallback("os_error", errno)); |
| 543 } else { | 539 } else { |
| 544 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT); | 540 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT); |
| 545 } | 541 } |
| 546 | 542 |
| 547 // Give a more specific error when the user is offline. | 543 // Give a more specific error when the user is offline. |
| 548 if (rv == ERR_ADDRESS_UNREACHABLE && NetworkChangeNotifier::IsOffline()) | 544 if (rv == ERR_ADDRESS_UNREACHABLE && NetworkChangeNotifier::IsOffline()) |
| 549 rv = ERR_INTERNET_DISCONNECTED; | 545 rv = ERR_INTERNET_DISCONNECTED; |
| 550 | 546 |
| 551 if (!logging_multiple_connect_attempts_) | 547 if (!logging_multiple_connect_attempts_) |
| 552 LogConnectEnd(rv); | 548 LogConnectEnd(rv); |
| 553 | 549 |
| 554 return rv; | 550 return rv; |
| 555 } | 551 } |
| 556 | 552 |
| 557 void TCPSocketLibevent::LogConnectBegin(const AddressList& addresses) const { | 553 void TCPSocketPosix::LogConnectBegin(const AddressList& addresses) const { |
| 558 net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT, | 554 net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT, |
| 559 addresses.CreateNetLogCallback()); | 555 addresses.CreateNetLogCallback()); |
| 560 } | 556 } |
| 561 | 557 |
| 562 void TCPSocketLibevent::LogConnectEnd(int net_error) const { | 558 void TCPSocketPosix::LogConnectEnd(int net_error) const { |
| 563 if (net_error != OK) { | 559 if (net_error != OK) { |
| 564 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, net_error); | 560 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, net_error); |
| 565 return; | 561 return; |
| 566 } | 562 } |
| 567 | 563 |
| 568 UpdateConnectionTypeHistograms(CONNECTION_ANY); | 564 UpdateConnectionTypeHistograms(CONNECTION_ANY); |
| 569 | 565 |
| 570 SockaddrStorage storage; | 566 SockaddrStorage storage; |
| 571 int rv = socket_->GetLocalAddress(&storage); | 567 int rv = socket_->GetLocalAddress(&storage); |
| 572 if (rv != OK) { | 568 if (rv != OK) { |
| 573 PLOG(ERROR) << "GetLocalAddress() [rv: " << rv << "] error: "; | 569 PLOG(ERROR) << "GetLocalAddress() [rv: " << rv << "] error: "; |
| 574 NOTREACHED(); | 570 NOTREACHED(); |
| 575 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, rv); | 571 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, rv); |
| 576 return; | 572 return; |
| 577 } | 573 } |
| 578 | 574 |
| 579 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT, | 575 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT, |
| 580 CreateNetLogSourceAddressCallback(storage.addr, | 576 CreateNetLogSourceAddressCallback(storage.addr, |
| 581 storage.addr_len)); | 577 storage.addr_len)); |
| 582 } | 578 } |
| 583 | 579 |
| 584 void TCPSocketLibevent::ReadCompleted(const scoped_refptr<IOBuffer>& buf, | 580 void TCPSocketPosix::ReadCompleted(const scoped_refptr<IOBuffer>& buf, |
| 585 const CompletionCallback& callback, | 581 const CompletionCallback& callback, |
| 586 int rv) { | 582 int rv) { |
| 587 DCHECK_NE(ERR_IO_PENDING, rv); | 583 DCHECK_NE(ERR_IO_PENDING, rv); |
| 588 callback.Run(HandleReadCompleted(buf.get(), rv)); | 584 callback.Run(HandleReadCompleted(buf.get(), rv)); |
| 589 } | 585 } |
| 590 | 586 |
| 591 int TCPSocketLibevent::HandleReadCompleted(IOBuffer* buf, int rv) { | 587 int TCPSocketPosix::HandleReadCompleted(IOBuffer* buf, int rv) { |
| 592 if (tcp_fastopen_write_attempted_ && !tcp_fastopen_connected_) { | 588 if (tcp_fastopen_write_attempted_ && !tcp_fastopen_connected_) { |
| 593 // A TCP FastOpen connect-with-write was attempted. This read was a | 589 // A TCP FastOpen connect-with-write was attempted. This read was a |
| 594 // subsequent read, which either succeeded or failed. If the read | 590 // subsequent read, which either succeeded or failed. If the read |
| 595 // succeeded, the socket is considered connected via TCP FastOpen. | 591 // succeeded, the socket is considered connected via TCP FastOpen. |
| 596 // If the read failed, TCP FastOpen is (conservatively) turned off for all | 592 // If the read failed, TCP FastOpen is (conservatively) turned off for all |
| 597 // subsequent connections. TCP FastOpen status is recorded in both cases. | 593 // subsequent connections. TCP FastOpen status is recorded in both cases. |
| 598 // TODO (jri): This currently results in conservative behavior, where TCP | 594 // TODO (jri): This currently results in conservative behavior, where TCP |
| 599 // FastOpen is turned off on _any_ error. Implement optimizations, | 595 // FastOpen is turned off on _any_ error. Implement optimizations, |
| 600 // such as turning off TCP FastOpen on more specific errors, and | 596 // such as turning off TCP FastOpen on more specific errors, and |
| 601 // re-attempting TCP FastOpen after a certain amount of time has passed. | 597 // re-attempting TCP FastOpen after a certain amount of time has passed. |
| 602 if (rv >= 0) | 598 if (rv >= 0) |
| 603 tcp_fastopen_connected_ = true; | 599 tcp_fastopen_connected_ = true; |
| 604 else | 600 else |
| 605 g_tcp_fastopen_has_failed = true; | 601 g_tcp_fastopen_has_failed = true; |
| 606 UpdateTCPFastOpenStatusAfterRead(); | 602 UpdateTCPFastOpenStatusAfterRead(); |
| 607 } | 603 } |
| 608 | 604 |
| 609 if (rv < 0) { | 605 if (rv < 0) { |
| 610 net_log_.AddEvent(NetLog::TYPE_SOCKET_READ_ERROR, | 606 net_log_.AddEvent(NetLog::TYPE_SOCKET_READ_ERROR, |
| 611 CreateNetLogSocketErrorCallback(rv, errno)); | 607 CreateNetLogSocketErrorCallback(rv, errno)); |
| 612 return rv; | 608 return rv; |
| 613 } | 609 } |
| 614 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, rv, | 610 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, rv, |
| 615 buf->data()); | 611 buf->data()); |
| 616 NetworkActivityMonitor::GetInstance()->IncrementBytesReceived(rv); | 612 NetworkActivityMonitor::GetInstance()->IncrementBytesReceived(rv); |
| 617 | 613 |
| 618 return rv; | 614 return rv; |
| 619 } | 615 } |
| 620 | 616 |
| 621 void TCPSocketLibevent::WriteCompleted(const scoped_refptr<IOBuffer>& buf, | 617 void TCPSocketPosix::WriteCompleted(const scoped_refptr<IOBuffer>& buf, |
| 622 const CompletionCallback& callback, | 618 const CompletionCallback& callback, |
| 623 int rv) { | 619 int rv) { |
| 624 DCHECK_NE(ERR_IO_PENDING, rv); | 620 DCHECK_NE(ERR_IO_PENDING, rv); |
| 625 callback.Run(HandleWriteCompleted(buf.get(), rv)); | 621 callback.Run(HandleWriteCompleted(buf.get(), rv)); |
| 626 } | 622 } |
| 627 | 623 |
| 628 int TCPSocketLibevent::HandleWriteCompleted(IOBuffer* buf, int rv) { | 624 int TCPSocketPosix::HandleWriteCompleted(IOBuffer* buf, int rv) { |
| 629 if (rv < 0) { | 625 if (rv < 0) { |
| 630 if (tcp_fastopen_write_attempted_ && !tcp_fastopen_connected_) { | 626 if (tcp_fastopen_write_attempted_ && !tcp_fastopen_connected_) { |
| 631 // TCP FastOpen connect-with-write was attempted, and the write failed | 627 // TCP FastOpen connect-with-write was attempted, and the write failed |
| 632 // for unknown reasons. Record status and (conservatively) turn off | 628 // for unknown reasons. Record status and (conservatively) turn off |
| 633 // TCP FastOpen for all subsequent connections. | 629 // TCP FastOpen for all subsequent connections. |
| 634 // TODO (jri): This currently results in conservative behavior, where TCP | 630 // TODO (jri): This currently results in conservative behavior, where TCP |
| 635 // FastOpen is turned off on _any_ error. Implement optimizations, | 631 // FastOpen is turned off on _any_ error. Implement optimizations, |
| 636 // such as turning off TCP FastOpen on more specific errors, and | 632 // such as turning off TCP FastOpen on more specific errors, and |
| 637 // re-attempting TCP FastOpen after a certain amount of time has passed. | 633 // re-attempting TCP FastOpen after a certain amount of time has passed. |
| 638 tcp_fastopen_status_ = TCP_FASTOPEN_ERROR; | 634 tcp_fastopen_status_ = TCP_FASTOPEN_ERROR; |
| 639 g_tcp_fastopen_has_failed = true; | 635 g_tcp_fastopen_has_failed = true; |
| 640 } | 636 } |
| 641 net_log_.AddEvent(NetLog::TYPE_SOCKET_WRITE_ERROR, | 637 net_log_.AddEvent(NetLog::TYPE_SOCKET_WRITE_ERROR, |
| 642 CreateNetLogSocketErrorCallback(rv, errno)); | 638 CreateNetLogSocketErrorCallback(rv, errno)); |
| 643 return rv; | 639 return rv; |
| 644 } | 640 } |
| 645 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, rv, | 641 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, rv, |
| 646 buf->data()); | 642 buf->data()); |
| 647 NetworkActivityMonitor::GetInstance()->IncrementBytesSent(rv); | 643 NetworkActivityMonitor::GetInstance()->IncrementBytesSent(rv); |
| 648 return rv; | 644 return rv; |
| 649 } | 645 } |
| 650 | 646 |
| 651 int TCPSocketLibevent::TcpFastOpenWrite( | 647 int TCPSocketPosix::TcpFastOpenWrite(IOBuffer* buf, |
| 652 IOBuffer* buf, | 648 int buf_len, |
| 653 int buf_len, | 649 const CompletionCallback& callback) { |
| 654 const CompletionCallback& callback) { | |
| 655 SockaddrStorage storage; | 650 SockaddrStorage storage; |
| 656 int rv = socket_->GetPeerAddress(&storage); | 651 int rv = socket_->GetPeerAddress(&storage); |
| 657 if (rv != OK) | 652 if (rv != OK) |
| 658 return rv; | 653 return rv; |
| 659 | 654 |
| 660 int flags = 0x20000000; // Magic flag to enable TCP_FASTOPEN. | 655 int flags = 0x20000000; // Magic flag to enable TCP_FASTOPEN. |
| 661 #if defined(OS_LINUX) || defined(OS_ANDROID) | 656 #if defined(OS_LINUX) || defined(OS_ANDROID) |
| 662 // sendto() will fail with EPIPE when the system doesn't implement TCP | 657 // sendto() will fail with EPIPE when the system doesn't implement TCP |
| 663 // FastOpen, and with EOPNOTSUPP when the system implements TCP FastOpen | 658 // FastOpen, and with EOPNOTSUPP when the system implements TCP FastOpen |
| 664 // but it is disabled. Theoretically these shouldn't happen | 659 // but it is disabled. Theoretically these shouldn't happen |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 703 // turning off TCP FastOpen on more specific errors. | 698 // turning off TCP FastOpen on more specific errors. |
| 704 tcp_fastopen_status_ = TCP_FASTOPEN_ERROR; | 699 tcp_fastopen_status_ = TCP_FASTOPEN_ERROR; |
| 705 g_tcp_fastopen_has_failed = true; | 700 g_tcp_fastopen_has_failed = true; |
| 706 return rv; | 701 return rv; |
| 707 } | 702 } |
| 708 | 703 |
| 709 tcp_fastopen_status_ = TCP_FASTOPEN_SLOW_CONNECT_RETURN; | 704 tcp_fastopen_status_ = TCP_FASTOPEN_SLOW_CONNECT_RETURN; |
| 710 return socket_->WaitForWrite(buf, buf_len, callback); | 705 return socket_->WaitForWrite(buf, buf_len, callback); |
| 711 } | 706 } |
| 712 | 707 |
| 713 void TCPSocketLibevent::UpdateTCPFastOpenStatusAfterRead() { | 708 void TCPSocketPosix::UpdateTCPFastOpenStatusAfterRead() { |
| 714 DCHECK(tcp_fastopen_status_ == TCP_FASTOPEN_FAST_CONNECT_RETURN || | 709 DCHECK(tcp_fastopen_status_ == TCP_FASTOPEN_FAST_CONNECT_RETURN || |
| 715 tcp_fastopen_status_ == TCP_FASTOPEN_SLOW_CONNECT_RETURN); | 710 tcp_fastopen_status_ == TCP_FASTOPEN_SLOW_CONNECT_RETURN); |
| 716 | 711 |
| 717 if (tcp_fastopen_write_attempted_ && !tcp_fastopen_connected_) { | 712 if (tcp_fastopen_write_attempted_ && !tcp_fastopen_connected_) { |
| 718 // TCP FastOpen connect-with-write was attempted, and failed. | 713 // TCP FastOpen connect-with-write was attempted, and failed. |
| 719 tcp_fastopen_status_ = | 714 tcp_fastopen_status_ = |
| 720 (tcp_fastopen_status_ == TCP_FASTOPEN_FAST_CONNECT_RETURN ? | 715 (tcp_fastopen_status_ == TCP_FASTOPEN_FAST_CONNECT_RETURN ? |
| 721 TCP_FASTOPEN_FAST_CONNECT_READ_FAILED : | 716 TCP_FASTOPEN_FAST_CONNECT_READ_FAILED : |
| 722 TCP_FASTOPEN_SLOW_CONNECT_READ_FAILED); | 717 TCP_FASTOPEN_SLOW_CONNECT_READ_FAILED); |
| 723 return; | 718 return; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 744 TCP_FASTOPEN_NO_SYN_DATA_NACK); | 739 TCP_FASTOPEN_NO_SYN_DATA_NACK); |
| 745 } | 740 } |
| 746 } else { | 741 } else { |
| 747 tcp_fastopen_status_ = | 742 tcp_fastopen_status_ = |
| 748 (tcp_fastopen_status_ == TCP_FASTOPEN_FAST_CONNECT_RETURN ? | 743 (tcp_fastopen_status_ == TCP_FASTOPEN_FAST_CONNECT_RETURN ? |
| 749 TCP_FASTOPEN_SYN_DATA_GETSOCKOPT_FAILED : | 744 TCP_FASTOPEN_SYN_DATA_GETSOCKOPT_FAILED : |
| 750 TCP_FASTOPEN_NO_SYN_DATA_GETSOCKOPT_FAILED); | 745 TCP_FASTOPEN_NO_SYN_DATA_GETSOCKOPT_FAILED); |
| 751 } | 746 } |
| 752 } | 747 } |
| 753 | 748 |
| 754 bool TCPSocketLibevent::GetEstimatedRoundTripTime( | 749 bool TCPSocketPosix::GetEstimatedRoundTripTime(base::TimeDelta* out_rtt) const { |
| 755 base::TimeDelta* out_rtt) const { | |
| 756 DCHECK(out_rtt); | 750 DCHECK(out_rtt); |
| 757 if (!socket_) | 751 if (!socket_) |
| 758 return false; | 752 return false; |
| 759 | 753 |
| 760 #if defined(TCP_INFO) | 754 #if defined(TCP_INFO) |
| 761 tcp_info info; | 755 tcp_info info; |
| 762 if (GetTcpInfo(socket_->socket_fd(), &info)) { | 756 if (GetTcpInfo(socket_->socket_fd(), &info)) { |
| 763 // tcpi_rtt is zero when the kernel doesn't have an RTT estimate, | 757 // tcpi_rtt is zero when the kernel doesn't have an RTT estimate, |
| 764 // and possibly in other cases such as connections to localhost. | 758 // and possibly in other cases such as connections to localhost. |
| 765 if (info.tcpi_rtt > 0) { | 759 if (info.tcpi_rtt > 0) { |
| 766 *out_rtt = base::TimeDelta::FromMicroseconds(info.tcpi_rtt); | 760 *out_rtt = base::TimeDelta::FromMicroseconds(info.tcpi_rtt); |
| 767 return true; | 761 return true; |
| 768 } | 762 } |
| 769 } | 763 } |
| 770 #endif // defined(TCP_INFO) | 764 #endif // defined(TCP_INFO) |
| 771 return false; | 765 return false; |
| 772 } | 766 } |
| 773 | 767 |
| 774 } // namespace net | 768 } // namespace net |
| OLD | NEW |