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 |