Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(159)

Side by Side Diff: net/socket/tcp_socket_libevent.cc

Issue 348803003: Refactor tcp socket and unix domain socket. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed comments and fixed unittests for chrome os. Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 <fcntl.h>
9 #include <netdb.h>
10 #include <netinet/in.h>
11 #include <netinet/tcp.h> 8 #include <netinet/tcp.h>
12 #include <sys/socket.h> 9 #include <sys/socket.h>
13 10
14 #include "base/callback_helpers.h" 11 #include "base/bind.h"
15 #include "base/logging.h" 12 #include "base/logging.h"
16 #include "base/metrics/histogram.h" 13 #include "base/metrics/histogram.h"
17 #include "base/metrics/stats_counters.h" 14 #include "base/metrics/stats_counters.h"
18 #include "base/posix/eintr_wrapper.h" 15 #include "base/posix/eintr_wrapper.h"
19 #include "build/build_config.h"
20 #include "net/base/address_list.h" 16 #include "net/base/address_list.h"
21 #include "net/base/connection_type_histograms.h" 17 #include "net/base/connection_type_histograms.h"
22 #include "net/base/io_buffer.h" 18 #include "net/base/io_buffer.h"
23 #include "net/base/ip_endpoint.h" 19 #include "net/base/ip_endpoint.h"
24 #include "net/base/net_errors.h" 20 #include "net/base/net_errors.h"
25 #include "net/base/net_util.h" 21 #include "net/base/net_util.h"
26 #include "net/base/network_change_notifier.h" 22 #include "net/base/network_change_notifier.h"
23 #include "net/socket/socket_libevent.h"
27 #include "net/socket/socket_net_log_params.h" 24 #include "net/socket/socket_net_log_params.h"
28 25
29 // If we don't have a definition for TCPI_OPT_SYN_DATA, create one. 26 // If we don't have a definition for TCPI_OPT_SYN_DATA, create one.
30 #ifndef TCPI_OPT_SYN_DATA 27 #ifndef TCPI_OPT_SYN_DATA
31 #define TCPI_OPT_SYN_DATA 32 28 #define TCPI_OPT_SYN_DATA 32
32 #endif 29 #endif
33 30
34 namespace net { 31 namespace net {
35 32
36 namespace { 33 namespace {
(...skipping 28 matching lines...) Expand all
65 } 62 }
66 // Set seconds between TCP keep alives. 63 // Set seconds between TCP keep alives.
67 if (setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &delay, sizeof(delay))) { 64 if (setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &delay, sizeof(delay))) {
68 PLOG(ERROR) << "Failed to set TCP_KEEPINTVL on fd: " << fd; 65 PLOG(ERROR) << "Failed to set TCP_KEEPINTVL on fd: " << fd;
69 return false; 66 return false;
70 } 67 }
71 #endif 68 #endif
72 return true; 69 return true;
73 } 70 }
74 71
75 int MapAcceptError(int os_error) {
76 switch (os_error) {
77 // If the client aborts the connection before the server calls accept,
78 // POSIX specifies accept should fail with ECONNABORTED. The server can
79 // ignore the error and just call accept again, so we map the error to
80 // ERR_IO_PENDING. See UNIX Network Programming, Vol. 1, 3rd Ed., Sec.
81 // 5.11, "Connection Abort before accept Returns".
82 case ECONNABORTED:
83 return ERR_IO_PENDING;
84 default:
85 return MapSystemError(os_error);
86 }
87 }
88
89 int MapConnectError(int os_error) {
90 switch (os_error) {
91 case EACCES:
92 return ERR_NETWORK_ACCESS_DENIED;
93 case ETIMEDOUT:
94 return ERR_CONNECTION_TIMED_OUT;
95 default: {
96 int net_error = MapSystemError(os_error);
97 if (net_error == ERR_FAILED)
98 return ERR_CONNECTION_FAILED; // More specific than ERR_FAILED.
99
100 // Give a more specific error when the user is offline.
101 if (net_error == ERR_ADDRESS_UNREACHABLE &&
102 NetworkChangeNotifier::IsOffline()) {
103 return ERR_INTERNET_DISCONNECTED;
104 }
105 return net_error;
106 }
107 }
108 }
109
110 } // namespace 72 } // namespace
111 73
112 //----------------------------------------------------------------------------- 74 //-----------------------------------------------------------------------------
113 75
114 TCPSocketLibevent::Watcher::Watcher(
115 const base::Closure& read_ready_callback,
116 const base::Closure& write_ready_callback)
117 : read_ready_callback_(read_ready_callback),
118 write_ready_callback_(write_ready_callback) {
119 }
120
121 TCPSocketLibevent::Watcher::~Watcher() {
122 }
123
124 void TCPSocketLibevent::Watcher::OnFileCanReadWithoutBlocking(int /* fd */) {
125 if (!read_ready_callback_.is_null())
126 read_ready_callback_.Run();
127 else
128 NOTREACHED();
129 }
130
131 void TCPSocketLibevent::Watcher::OnFileCanWriteWithoutBlocking(int /* fd */) {
132 if (!write_ready_callback_.is_null())
133 write_ready_callback_.Run();
134 else
135 NOTREACHED();
136 }
137
138 TCPSocketLibevent::TCPSocketLibevent(NetLog* net_log, 76 TCPSocketLibevent::TCPSocketLibevent(NetLog* net_log,
139 const NetLog::Source& source) 77 const NetLog::Source& source)
140 : socket_(kInvalidSocket), 78 : use_tcp_fastopen_(IsTCPFastOpenEnabled()),
141 accept_watcher_(base::Bind(&TCPSocketLibevent::DidCompleteAccept,
142 base::Unretained(this)),
143 base::Closure()),
144 accept_socket_(NULL),
145 accept_address_(NULL),
146 read_watcher_(base::Bind(&TCPSocketLibevent::DidCompleteRead,
147 base::Unretained(this)),
148 base::Closure()),
149 write_watcher_(base::Closure(),
150 base::Bind(&TCPSocketLibevent::DidCompleteConnectOrWrite,
151 base::Unretained(this))),
152 read_buf_len_(0),
153 write_buf_len_(0),
154 use_tcp_fastopen_(IsTCPFastOpenEnabled()),
155 tcp_fastopen_connected_(false), 79 tcp_fastopen_connected_(false),
156 fast_open_status_(FAST_OPEN_STATUS_UNKNOWN), 80 fast_open_status_(FAST_OPEN_STATUS_UNKNOWN),
157 waiting_connect_(false),
158 connect_os_error_(0),
159 logging_multiple_connect_attempts_(false), 81 logging_multiple_connect_attempts_(false),
160 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { 82 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) {
161 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, 83 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE,
162 source.ToEventParametersCallback()); 84 source.ToEventParametersCallback());
163 } 85 }
164 86
165 TCPSocketLibevent::~TCPSocketLibevent() { 87 TCPSocketLibevent::~TCPSocketLibevent() {
166 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); 88 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE);
167 if (tcp_fastopen_connected_) { 89 if (tcp_fastopen_connected_) {
168 UMA_HISTOGRAM_ENUMERATION("Net.TcpFastOpenSocketConnection", 90 UMA_HISTOGRAM_ENUMERATION("Net.TcpFastOpenSocketConnection",
169 fast_open_status_, FAST_OPEN_MAX_VALUE); 91 fast_open_status_, FAST_OPEN_MAX_VALUE);
170 } 92 }
171 Close();
172 } 93 }
173 94
174 int TCPSocketLibevent::Open(AddressFamily family) { 95 int TCPSocketLibevent::Open(AddressFamily family) {
175 DCHECK(CalledOnValidThread()); 96 DCHECK(!socket_);
176 DCHECK_EQ(socket_, kInvalidSocket); 97 socket_.reset(new SocketLibevent);
98 return socket_->Open(ConvertAddressFamily(family));
99 }
177 100
178 socket_ = CreatePlatformSocket(ConvertAddressFamily(family), SOCK_STREAM, 101 int TCPSocketLibevent::AdoptConnectedSocket(int socket_fd,
179 IPPROTO_TCP); 102 const IPEndPoint& peer_address) {
180 if (socket_ < 0) { 103 DCHECK(!socket_);
181 PLOG(ERROR) << "CreatePlatformSocket() returned an error"; 104
182 return MapSystemError(errno); 105 SockaddrStorage storage;
106 if (!peer_address.ToSockAddr(storage.addr, &storage.addr_len) &&
107 // For backward compatibility, allows the empty address.
108 !(peer_address == IPEndPoint())) {
109 return ERR_ADDRESS_INVALID;
183 } 110 }
184 111
185 if (SetNonBlocking(socket_)) { 112 socket_.reset(new SocketLibevent);
186 int result = MapSystemError(errno); 113 return socket_->AdoptConnectedSocket(socket_fd, storage);
187 Close();
188 return result;
189 }
190
191 return OK;
192 }
193
194 int TCPSocketLibevent::AdoptConnectedSocket(int socket,
195 const IPEndPoint& peer_address) {
196 DCHECK(CalledOnValidThread());
197 DCHECK_EQ(socket_, kInvalidSocket);
198
199 socket_ = socket;
200
201 if (SetNonBlocking(socket_)) {
202 int result = MapSystemError(errno);
203 Close();
204 return result;
205 }
206
207 peer_address_.reset(new IPEndPoint(peer_address));
208
209 return OK;
210 } 114 }
211 115
212 int TCPSocketLibevent::Bind(const IPEndPoint& address) { 116 int TCPSocketLibevent::Bind(const IPEndPoint& address) {
213 DCHECK(CalledOnValidThread()); 117 DCHECK(socket_);
214 DCHECK_NE(socket_, kInvalidSocket);
215 118
216 SockaddrStorage storage; 119 SockaddrStorage storage;
217 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) 120 if (!address.ToSockAddr(storage.addr, &storage.addr_len))
218 return ERR_ADDRESS_INVALID; 121 return ERR_ADDRESS_INVALID;
219 122
220 int result = bind(socket_, storage.addr, storage.addr_len); 123 return socket_->Bind(storage);
221 if (result < 0) {
222 PLOG(ERROR) << "bind() returned an error";
223 return MapSystemError(errno);
224 }
225
226 return OK;
227 } 124 }
228 125
229 int TCPSocketLibevent::Listen(int backlog) { 126 int TCPSocketLibevent::Listen(int backlog) {
230 DCHECK(CalledOnValidThread()); 127 DCHECK(socket_);
231 DCHECK_GT(backlog, 0); 128 return socket_->Listen(backlog);
232 DCHECK_NE(socket_, kInvalidSocket);
233
234 int result = listen(socket_, backlog);
235 if (result < 0) {
236 PLOG(ERROR) << "listen() returned an error";
237 return MapSystemError(errno);
238 }
239
240 return OK;
241 } 129 }
242 130
243 int TCPSocketLibevent::Accept(scoped_ptr<TCPSocketLibevent>* socket, 131 int TCPSocketLibevent::Accept(scoped_ptr<TCPSocketLibevent>* tcp_socket,
244 IPEndPoint* address, 132 IPEndPoint* address,
245 const CompletionCallback& callback) { 133 const CompletionCallback& callback) {
246 DCHECK(CalledOnValidThread()); 134 DCHECK(tcp_socket);
247 DCHECK(socket);
248 DCHECK(address);
249 DCHECK(!callback.is_null()); 135 DCHECK(!callback.is_null());
250 DCHECK(accept_callback_.is_null()); 136 DCHECK(socket_);
137 DCHECK(!accept_socket_);
251 138
252 net_log_.BeginEvent(NetLog::TYPE_TCP_ACCEPT); 139 net_log_.BeginEvent(NetLog::TYPE_TCP_ACCEPT);
253 140
254 int result = AcceptInternal(socket, address); 141 int rv = socket_->Accept(
255 142 &accept_socket_,
256 if (result == ERR_IO_PENDING) { 143 base::Bind(&TCPSocketLibevent::AcceptCompleted,
257 if (!base::MessageLoopForIO::current()->WatchFileDescriptor( 144 base::Unretained(this), tcp_socket, address, callback));
258 socket_, true, base::MessageLoopForIO::WATCH_READ, 145 if (rv != ERR_IO_PENDING)
259 &accept_socket_watcher_, &accept_watcher_)) { 146 rv = HandleAcceptCompleted(tcp_socket, address, rv);
260 PLOG(ERROR) << "WatchFileDescriptor failed on read"; 147 return rv;
261 return MapSystemError(errno);
262 }
263
264 accept_socket_ = socket;
265 accept_address_ = address;
266 accept_callback_ = callback;
267 }
268
269 return result;
270 } 148 }
271 149
272 int TCPSocketLibevent::Connect(const IPEndPoint& address, 150 int TCPSocketLibevent::Connect(const IPEndPoint& address,
273 const CompletionCallback& callback) { 151 const CompletionCallback& callback) {
274 DCHECK(CalledOnValidThread()); 152 DCHECK(socket_);
275 DCHECK_NE(socket_, kInvalidSocket);
276 DCHECK(!waiting_connect_);
277
278 // |peer_address_| will be non-NULL if Connect() has been called. Unless
279 // Close() is called to reset the internal state, a second call to Connect()
280 // is not allowed.
281 // Please note that we don't allow a second Connect() even if the previous
282 // Connect() has failed. Connecting the same |socket_| again after a
283 // connection attempt failed results in unspecified behavior according to
284 // POSIX.
285 DCHECK(!peer_address_);
286 153
287 if (!logging_multiple_connect_attempts_) 154 if (!logging_multiple_connect_attempts_)
288 LogConnectBegin(AddressList(address)); 155 LogConnectBegin(AddressList(address));
289 156
290 peer_address_.reset(new IPEndPoint(address)); 157 net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT,
158 CreateNetLogIPEndPointCallback(&address));
291 159
292 int rv = DoConnect(); 160 SockaddrStorage storage;
293 if (rv == ERR_IO_PENDING) { 161 if (!address.ToSockAddr(storage.addr, &storage.addr_len))
294 // Synchronous operation not supported. 162 return ERR_ADDRESS_INVALID;
295 DCHECK(!callback.is_null()); 163
296 write_callback_ = callback; 164 if (use_tcp_fastopen_) {
297 waiting_connect_ = true; 165 // With TCP FastOpen, we pretend that the socket is connected.
298 } else { 166 DCHECK(!tcp_fastopen_connected_);
299 DoConnectComplete(rv); 167 socket_->SetPeerAddress(storage);
168 return OK;
300 } 169 }
301 170
171 int rv = socket_->Connect(storage,
172 base::Bind(&TCPSocketLibevent::ConnectCompleted,
173 base::Unretained(this), callback));
174 if (rv != ERR_IO_PENDING)
175 rv = HandleConnectCompleted(rv);
302 return rv; 176 return rv;
303 } 177 }
304 178
305 bool TCPSocketLibevent::IsConnected() const { 179 bool TCPSocketLibevent::IsConnected() const {
306 DCHECK(CalledOnValidThread()); 180 if (!socket_)
307
308 if (socket_ == kInvalidSocket || waiting_connect_)
309 return false; 181 return false;
310 182
311 if (use_tcp_fastopen_ && !tcp_fastopen_connected_ && peer_address_) { 183 if (use_tcp_fastopen_ && !tcp_fastopen_connected_ &&
184 socket_->HasPeerAddress()) {
312 // With TCP FastOpen, we pretend that the socket is connected. 185 // With TCP FastOpen, we pretend that the socket is connected.
313 // This allows GetPeerAddress() to return peer_address_. 186 // This allows GetPeerAddress() to return peer_address_.
314 return true; 187 return true;
315 } 188 }
316 189
317 // Check if connection is alive. 190 return socket_->IsConnected();
318 char c;
319 int rv = HANDLE_EINTR(recv(socket_, &c, 1, MSG_PEEK));
320 if (rv == 0)
321 return false;
322 if (rv == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
323 return false;
324
325 return true;
326 } 191 }
327 192
328 bool TCPSocketLibevent::IsConnectedAndIdle() const { 193 bool TCPSocketLibevent::IsConnectedAndIdle() const {
329 DCHECK(CalledOnValidThread());
330
331 if (socket_ == kInvalidSocket || waiting_connect_)
332 return false;
333
334 // TODO(wtc): should we also handle the TCP FastOpen case here, 194 // TODO(wtc): should we also handle the TCP FastOpen case here,
335 // as we do in IsConnected()? 195 // as we do in IsConnected()?
336 196 return socket_ && socket_->IsConnectedAndIdle();
337 // Check if connection is alive and we haven't received any data
338 // unexpectedly.
339 char c;
340 int rv = HANDLE_EINTR(recv(socket_, &c, 1, MSG_PEEK));
341 if (rv >= 0)
342 return false;
343 if (errno != EAGAIN && errno != EWOULDBLOCK)
344 return false;
345
346 return true;
347 } 197 }
348 198
349 int TCPSocketLibevent::Read(IOBuffer* buf, 199 int TCPSocketLibevent::Read(IOBuffer* buf,
350 int buf_len, 200 int buf_len,
351 const CompletionCallback& callback) { 201 const CompletionCallback& callback) {
352 DCHECK(CalledOnValidThread()); 202 DCHECK(socket_);
353 DCHECK_NE(kInvalidSocket, socket_);
354 DCHECK(!waiting_connect_);
355 DCHECK(read_callback_.is_null());
356 // Synchronous operation not supported
357 DCHECK(!callback.is_null()); 203 DCHECK(!callback.is_null());
358 DCHECK_GT(buf_len, 0);
359 204
360 int nread = HANDLE_EINTR(read(socket_, buf->data(), buf_len)); 205 int rv = socket_->Read(
361 if (nread >= 0) { 206 buf, buf_len,
362 base::StatsCounter read_bytes("tcp.read_bytes"); 207 base::Bind(&TCPSocketLibevent::ReadCompleted,
363 read_bytes.Add(nread); 208 base::Unretained(this), base::Unretained(buf), callback));
364 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, nread, 209 if (rv != ERR_IO_PENDING)
365 buf->data()); 210 rv = HandleReadCompleted(buf, rv);
366 RecordFastOpenStatus(); 211 return rv;
367 return nread;
368 }
369 if (errno != EAGAIN && errno != EWOULDBLOCK) {
370 int net_error = MapSystemError(errno);
371 net_log_.AddEvent(NetLog::TYPE_SOCKET_READ_ERROR,
372 CreateNetLogSocketErrorCallback(net_error, errno));
373 return net_error;
374 }
375
376 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
377 socket_, true, base::MessageLoopForIO::WATCH_READ,
378 &read_socket_watcher_, &read_watcher_)) {
379 DVLOG(1) << "WatchFileDescriptor failed on read, errno " << errno;
380 return MapSystemError(errno);
381 }
382
383 read_buf_ = buf;
384 read_buf_len_ = buf_len;
385 read_callback_ = callback;
386 return ERR_IO_PENDING;
387 } 212 }
388 213
389 int TCPSocketLibevent::Write(IOBuffer* buf, 214 int TCPSocketLibevent::Write(IOBuffer* buf,
390 int buf_len, 215 int buf_len,
391 const CompletionCallback& callback) { 216 const CompletionCallback& callback) {
392 DCHECK(CalledOnValidThread()); 217 DCHECK(socket_);
393 DCHECK_NE(kInvalidSocket, socket_);
394 DCHECK(!waiting_connect_);
395 DCHECK(write_callback_.is_null());
396 // Synchronous operation not supported
397 DCHECK(!callback.is_null()); 218 DCHECK(!callback.is_null());
398 DCHECK_GT(buf_len, 0);
399 219
400 int nwrite = InternalWrite(buf, buf_len); 220 CompletionCallback write_callback =
401 if (nwrite >= 0) { 221 base::Bind(&TCPSocketLibevent::WriteCompleted,
402 base::StatsCounter write_bytes("tcp.write_bytes"); 222 base::Unretained(this), base::Unretained(buf), callback);
403 write_bytes.Add(nwrite); 223 int rv;
404 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, nwrite, 224 if (use_tcp_fastopen_ && !tcp_fastopen_connected_) {
405 buf->data()); 225 rv = TcpFastOpenWrite(buf, buf_len, write_callback);
406 return nwrite; 226 } else {
407 } 227 rv = socket_->Write(buf, buf_len, write_callback);
408 if (errno != EAGAIN && errno != EWOULDBLOCK) {
409 int net_error = MapSystemError(errno);
410 net_log_.AddEvent(NetLog::TYPE_SOCKET_WRITE_ERROR,
411 CreateNetLogSocketErrorCallback(net_error, errno));
412 return net_error;
413 } 228 }
414 229
415 if (!base::MessageLoopForIO::current()->WatchFileDescriptor( 230 if (rv != ERR_IO_PENDING)
416 socket_, true, base::MessageLoopForIO::WATCH_WRITE, 231 rv = HandleWriteCompleted(buf, rv);
417 &write_socket_watcher_, &write_watcher_)) { 232 return rv;
418 DVLOG(1) << "WatchFileDescriptor failed on write, errno " << errno;
419 return MapSystemError(errno);
420 }
421
422 write_buf_ = buf;
423 write_buf_len_ = buf_len;
424 write_callback_ = callback;
425 return ERR_IO_PENDING;
426 } 233 }
427 234
428 int TCPSocketLibevent::GetLocalAddress(IPEndPoint* address) const { 235 int TCPSocketLibevent::GetLocalAddress(IPEndPoint* address) const {
429 DCHECK(CalledOnValidThread());
430 DCHECK(address); 236 DCHECK(address);
431 237
238 if (!socket_)
239 return ERR_SOCKET_NOT_CONNECTED;
240
432 SockaddrStorage storage; 241 SockaddrStorage storage;
433 if (getsockname(socket_, storage.addr, &storage.addr_len) < 0) 242 int rv = socket_->GetLocalAddress(&storage);
434 return MapSystemError(errno); 243 if (rv != OK)
244 return rv;
245
435 if (!address->FromSockAddr(storage.addr, storage.addr_len)) 246 if (!address->FromSockAddr(storage.addr, storage.addr_len))
436 return ERR_ADDRESS_INVALID; 247 return ERR_ADDRESS_INVALID;
437 248
438 return OK; 249 return OK;
439 } 250 }
440 251
441 int TCPSocketLibevent::GetPeerAddress(IPEndPoint* address) const { 252 int TCPSocketLibevent::GetPeerAddress(IPEndPoint* address) const {
442 DCHECK(CalledOnValidThread());
443 DCHECK(address); 253 DCHECK(address);
254
444 if (!IsConnected()) 255 if (!IsConnected())
445 return ERR_SOCKET_NOT_CONNECTED; 256 return ERR_SOCKET_NOT_CONNECTED;
446 *address = *peer_address_; 257
258 SockaddrStorage storage;
259 int rv = socket_->GetPeerAddress(&storage);
260 if (rv != OK)
261 return rv;
262
263 if (!address->FromSockAddr(storage.addr, storage.addr_len))
264 return ERR_ADDRESS_INVALID;
265
447 return OK; 266 return OK;
448 } 267 }
449 268
450 int TCPSocketLibevent::SetDefaultOptionsForServer() { 269 int TCPSocketLibevent::SetDefaultOptionsForServer() {
451 DCHECK(CalledOnValidThread()); 270 DCHECK(socket_);
452 return SetAddressReuse(true); 271 return SetAddressReuse(true);
453 } 272 }
454 273
455 void TCPSocketLibevent::SetDefaultOptionsForClient() { 274 void TCPSocketLibevent::SetDefaultOptionsForClient() {
456 DCHECK(CalledOnValidThread()); 275 DCHECK(socket_);
457 276
458 // This mirrors the behaviour on Windows. See the comment in 277 // This mirrors the behaviour on Windows. See the comment in
459 // tcp_socket_win.cc after searching for "NODELAY". 278 // tcp_socket_win.cc after searching for "NODELAY".
460 SetTCPNoDelay(socket_, true); // If SetTCPNoDelay fails, we don't care. 279 // If SetTCPNoDelay fails, we don't care.
280 SetTCPNoDelay(socket_->socket_fd(), true);
461 281
462 // TCP keep alive wakes up the radio, which is expensive on mobile. Do not 282 // TCP keep alive wakes up the radio, which is expensive on mobile. Do not
463 // enable it there. It's useful to prevent TCP middleboxes from timing out 283 // enable it there. It's useful to prevent TCP middleboxes from timing out
464 // connection mappings. Packets for timed out connection mappings at 284 // connection mappings. Packets for timed out connection mappings at
465 // middleboxes will either lead to: 285 // middleboxes will either lead to:
466 // a) Middleboxes sending TCP RSTs. It's up to higher layers to check for this 286 // a) Middleboxes sending TCP RSTs. It's up to higher layers to check for this
467 // and retry. The HTTP network transaction code does this. 287 // and retry. The HTTP network transaction code does this.
468 // b) Middleboxes just drop the unrecognized TCP packet. This leads to the TCP 288 // b) Middleboxes just drop the unrecognized TCP packet. This leads to the TCP
469 // stack retransmitting packets per TCP stack retransmission timeouts, which 289 // stack retransmitting packets per TCP stack retransmission timeouts, which
470 // are very high (on the order of seconds). Given the number of 290 // are very high (on the order of seconds). Given the number of
471 // retransmissions required before killing the connection, this can lead to 291 // retransmissions required before killing the connection, this can lead to
472 // tens of seconds or even minutes of delay, depending on OS. 292 // tens of seconds or even minutes of delay, depending on OS.
473 #if !defined(OS_ANDROID) && !defined(OS_IOS) 293 #if !defined(OS_ANDROID) && !defined(OS_IOS)
474 const int kTCPKeepAliveSeconds = 45; 294 const int kTCPKeepAliveSeconds = 45;
475 295
476 SetTCPKeepAlive(socket_, true, kTCPKeepAliveSeconds); 296 SetTCPKeepAlive(socket_->socket_fd(), true, kTCPKeepAliveSeconds);
477 #endif 297 #endif
478 } 298 }
479 299
480 int TCPSocketLibevent::SetAddressReuse(bool allow) { 300 int TCPSocketLibevent::SetAddressReuse(bool allow) {
481 DCHECK(CalledOnValidThread()); 301 DCHECK(socket_);
482 302
483 // SO_REUSEADDR is useful for server sockets to bind to a recently unbound 303 // SO_REUSEADDR is useful for server sockets to bind to a recently unbound
484 // port. When a socket is closed, the end point changes its state to TIME_WAIT 304 // port. When a socket is closed, the end point changes its state to TIME_WAIT
485 // and wait for 2 MSL (maximum segment lifetime) to ensure the remote peer 305 // and wait for 2 MSL (maximum segment lifetime) to ensure the remote peer
486 // acknowledges its closure. For server sockets, it is usually safe to 306 // acknowledges its closure. For server sockets, it is usually safe to
487 // bind to a TIME_WAIT end point immediately, which is a widely adopted 307 // bind to a TIME_WAIT end point immediately, which is a widely adopted
488 // behavior. 308 // behavior.
489 // 309 //
490 // Note that on *nix, SO_REUSEADDR does not enable the TCP socket to bind to 310 // Note that on *nix, SO_REUSEADDR does not enable the TCP socket to bind to
491 // an end point that is already bound by another socket. To do that one must 311 // an end point that is already bound by another socket. To do that one must
492 // set SO_REUSEPORT instead. This option is not provided on Linux prior 312 // set SO_REUSEPORT instead. This option is not provided on Linux prior
493 // to 3.9. 313 // to 3.9.
494 // 314 //
495 // SO_REUSEPORT is provided in MacOS X and iOS. 315 // SO_REUSEPORT is provided in MacOS X and iOS.
496 int boolean_value = allow ? 1 : 0; 316 int boolean_value = allow ? 1 : 0;
497 int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &boolean_value, 317 int rv = setsockopt(socket_->socket_fd(), SOL_SOCKET, SO_REUSEADDR,
498 sizeof(boolean_value)); 318 &boolean_value, sizeof(boolean_value));
499 if (rv < 0) 319 if (rv < 0)
500 return MapSystemError(errno); 320 return MapSystemError(errno);
501 return OK; 321 return OK;
502 } 322 }
503 323
504 int TCPSocketLibevent::SetReceiveBufferSize(int32 size) { 324 int TCPSocketLibevent::SetReceiveBufferSize(int32 size) {
505 DCHECK(CalledOnValidThread()); 325 DCHECK(socket_);
506 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, 326 int rv = setsockopt(socket_->socket_fd(), SOL_SOCKET, SO_RCVBUF,
507 reinterpret_cast<const char*>(&size), sizeof(size)); 327 reinterpret_cast<const char*>(&size), sizeof(size));
508 return (rv == 0) ? OK : MapSystemError(errno); 328 return (rv == 0) ? OK : MapSystemError(errno);
509 } 329 }
510 330
511 int TCPSocketLibevent::SetSendBufferSize(int32 size) { 331 int TCPSocketLibevent::SetSendBufferSize(int32 size) {
512 DCHECK(CalledOnValidThread()); 332 DCHECK(socket_);
513 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, 333 int rv = setsockopt(socket_->socket_fd(), SOL_SOCKET, SO_SNDBUF,
514 reinterpret_cast<const char*>(&size), sizeof(size)); 334 reinterpret_cast<const char*>(&size), sizeof(size));
515 return (rv == 0) ? OK : MapSystemError(errno); 335 return (rv == 0) ? OK : MapSystemError(errno);
516 } 336 }
517 337
518 bool TCPSocketLibevent::SetKeepAlive(bool enable, int delay) { 338 bool TCPSocketLibevent::SetKeepAlive(bool enable, int delay) {
519 DCHECK(CalledOnValidThread()); 339 DCHECK(socket_);
520 return SetTCPKeepAlive(socket_, enable, delay); 340 return SetTCPKeepAlive(socket_->socket_fd(), enable, delay);
521 } 341 }
522 342
523 bool TCPSocketLibevent::SetNoDelay(bool no_delay) { 343 bool TCPSocketLibevent::SetNoDelay(bool no_delay) {
524 DCHECK(CalledOnValidThread()); 344 DCHECK(socket_);
525 return SetTCPNoDelay(socket_, no_delay); 345 return SetTCPNoDelay(socket_->socket_fd(), no_delay);
526 } 346 }
527 347
528 void TCPSocketLibevent::Close() { 348 void TCPSocketLibevent::Close() {
529 DCHECK(CalledOnValidThread()); 349 socket_.reset();
530
531 bool ok = accept_socket_watcher_.StopWatchingFileDescriptor();
532 DCHECK(ok);
533 ok = read_socket_watcher_.StopWatchingFileDescriptor();
534 DCHECK(ok);
535 ok = write_socket_watcher_.StopWatchingFileDescriptor();
536 DCHECK(ok);
537
538 if (socket_ != kInvalidSocket) {
539 if (IGNORE_EINTR(close(socket_)) < 0)
540 PLOG(ERROR) << "close";
541 socket_ = kInvalidSocket;
542 }
543
544 if (!accept_callback_.is_null()) {
545 accept_socket_ = NULL;
546 accept_address_ = NULL;
547 accept_callback_.Reset();
548 }
549
550 if (!read_callback_.is_null()) {
551 read_buf_ = NULL;
552 read_buf_len_ = 0;
553 read_callback_.Reset();
554 }
555
556 if (!write_callback_.is_null()) {
557 write_buf_ = NULL;
558 write_buf_len_ = 0;
559 write_callback_.Reset();
560 }
561
562 tcp_fastopen_connected_ = false; 350 tcp_fastopen_connected_ = false;
563 fast_open_status_ = FAST_OPEN_STATUS_UNKNOWN; 351 fast_open_status_ = FAST_OPEN_STATUS_UNKNOWN;
564 waiting_connect_ = false;
565 peer_address_.reset();
566 connect_os_error_ = 0;
567 } 352 }
568 353
569 bool TCPSocketLibevent::UsingTCPFastOpen() const { 354 bool TCPSocketLibevent::UsingTCPFastOpen() const {
570 return use_tcp_fastopen_; 355 return use_tcp_fastopen_;
571 } 356 }
572 357
573 void TCPSocketLibevent::StartLoggingMultipleConnectAttempts( 358 void TCPSocketLibevent::StartLoggingMultipleConnectAttempts(
574 const AddressList& addresses) { 359 const AddressList& addresses) {
575 if (!logging_multiple_connect_attempts_) { 360 if (!logging_multiple_connect_attempts_) {
576 logging_multiple_connect_attempts_ = true; 361 logging_multiple_connect_attempts_ = true;
577 LogConnectBegin(addresses); 362 LogConnectBegin(addresses);
578 } else { 363 } else {
579 NOTREACHED(); 364 NOTREACHED();
580 } 365 }
581 } 366 }
582 367
583 void TCPSocketLibevent::EndLoggingMultipleConnectAttempts(int net_error) { 368 void TCPSocketLibevent::EndLoggingMultipleConnectAttempts(int net_error) {
584 if (logging_multiple_connect_attempts_) { 369 if (logging_multiple_connect_attempts_) {
585 LogConnectEnd(net_error); 370 LogConnectEnd(net_error);
586 logging_multiple_connect_attempts_ = false; 371 logging_multiple_connect_attempts_ = false;
587 } else { 372 } else {
588 NOTREACHED(); 373 NOTREACHED();
589 } 374 }
590 } 375 }
591 376
592 int TCPSocketLibevent::AcceptInternal(scoped_ptr<TCPSocketLibevent>* socket, 377 void TCPSocketLibevent::AcceptCompleted(
593 IPEndPoint* address) { 378 scoped_ptr<TCPSocketLibevent>* tcp_socket,
379 IPEndPoint* address,
380 const CompletionCallback& callback,
381 int rv) {
382 DCHECK_NE(ERR_IO_PENDING, rv);
383 callback.Run(HandleAcceptCompleted(tcp_socket, address, rv));
384 }
385
386 int TCPSocketLibevent::HandleAcceptCompleted(
387 scoped_ptr<TCPSocketLibevent>* tcp_socket,
388 IPEndPoint* address,
389 int rv) {
390 if (rv == OK)
391 rv = BuildTcpSocketLibevent(tcp_socket, address);
392
393 if (rv != OK && rv != ERR_IO_PENDING)
394 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, rv);
395
396 return rv;
397 }
398
399 int TCPSocketLibevent::BuildTcpSocketLibevent(
400 scoped_ptr<TCPSocketLibevent>* tcp_socket,
401 IPEndPoint* address) {
402 DCHECK(accept_socket_);
403
594 SockaddrStorage storage; 404 SockaddrStorage storage;
595 int new_socket = HANDLE_EINTR(accept(socket_, 405 if (accept_socket_->GetPeerAddress(&storage) != OK ||
596 storage.addr, 406 !address->FromSockAddr(storage.addr, storage.addr_len)) {
597 &storage.addr_len)); 407 accept_socket_.reset();
598 if (new_socket < 0) { 408 return ERR_ADDRESS_INVALID;
599 int net_error = MapAcceptError(errno);
600 if (net_error != ERR_IO_PENDING)
601 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, net_error);
602 return net_error;
603 } 409 }
604 410
605 IPEndPoint ip_end_point; 411 tcp_socket->reset(new TCPSocketLibevent(net_log_.net_log(),
606 if (!ip_end_point.FromSockAddr(storage.addr, storage.addr_len)) { 412 net_log_.source()));
607 NOTREACHED(); 413 (*tcp_socket)->socket_.reset(accept_socket_.release());
608 if (IGNORE_EINTR(close(new_socket)) < 0)
609 PLOG(ERROR) << "close";
610 int net_error = ERR_ADDRESS_INVALID;
611 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, net_error);
612 return net_error;
613 }
614 scoped_ptr<TCPSocketLibevent> tcp_socket(new TCPSocketLibevent(
615 net_log_.net_log(), net_log_.source()));
616 int adopt_result = tcp_socket->AdoptConnectedSocket(new_socket, ip_end_point);
617 if (adopt_result != OK) {
618 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, adopt_result);
619 return adopt_result;
620 }
621 *socket = tcp_socket.Pass();
622 *address = ip_end_point;
623 net_log_.EndEvent(NetLog::TYPE_TCP_ACCEPT, 414 net_log_.EndEvent(NetLog::TYPE_TCP_ACCEPT,
624 CreateNetLogIPEndPointCallback(&ip_end_point)); 415 CreateNetLogIPEndPointCallback(address));
mmenke 2014/06/30 18:26:51 Think we should move this up to HandleAcceptComple
byungchul 2014/06/30 19:38:35 Done.
625 return OK; 416 return OK;
626 } 417 }
627 418
628 int TCPSocketLibevent::DoConnect() { 419 void TCPSocketLibevent::ConnectCompleted(const CompletionCallback& callback,
629 DCHECK_EQ(0, connect_os_error_); 420 int rv) const {
630 421 DCHECK_NE(ERR_IO_PENDING, rv);
631 net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, 422 callback.Run(HandleConnectCompleted(rv));
632 CreateNetLogIPEndPointCallback(peer_address_.get()));
633
634 // Connect the socket.
635 if (!use_tcp_fastopen_) {
636 SockaddrStorage storage;
637 if (!peer_address_->ToSockAddr(storage.addr, &storage.addr_len))
638 return ERR_ADDRESS_INVALID;
639
640 if (!HANDLE_EINTR(connect(socket_, storage.addr, storage.addr_len))) {
641 // Connected without waiting!
642 return OK;
643 }
644 } else {
645 // With TCP FastOpen, we pretend that the socket is connected.
646 DCHECK(!tcp_fastopen_connected_);
647 return OK;
648 }
649
650 // Check if the connect() failed synchronously.
651 connect_os_error_ = errno;
652 if (connect_os_error_ != EINPROGRESS)
653 return MapConnectError(connect_os_error_);
654
655 // Otherwise the connect() is going to complete asynchronously, so watch
656 // for its completion.
657 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
658 socket_, true, base::MessageLoopForIO::WATCH_WRITE,
659 &write_socket_watcher_, &write_watcher_)) {
660 connect_os_error_ = errno;
661 DVLOG(1) << "WatchFileDescriptor failed: " << connect_os_error_;
662 return MapSystemError(connect_os_error_);
663 }
664
665 return ERR_IO_PENDING;
666 } 423 }
667 424
668 void TCPSocketLibevent::DoConnectComplete(int result) { 425 int TCPSocketLibevent::HandleConnectCompleted(int rv) const {
669 // Log the end of this attempt (and any OS error it threw). 426 // Log the end of this attempt (and any OS error it threw).
670 int os_error = connect_os_error_; 427 int os_error = errno;
mmenke 2014/06/30 18:26:51 This imposes a non-obvious constraint on SocketLib
mmenke 2014/06/30 18:26:51 nit: Can just inline this below.
byungchul 2014/06/30 19:38:35 Done.
byungchul 2014/06/30 19:38:35 Done.
671 connect_os_error_ = 0; 428 if (rv != OK) {
672 if (result != OK) {
673 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, 429 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT,
674 NetLog::IntegerCallback("os_error", os_error)); 430 NetLog::IntegerCallback("os_error", os_error));
675 } else { 431 } else {
676 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT); 432 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT);
677 } 433 }
678 434
435 // Give a more specific error when the user is offline.
436 if (rv == ERR_ADDRESS_UNREACHABLE && NetworkChangeNotifier::IsOffline())
437 rv = ERR_INTERNET_DISCONNECTED;
438
679 if (!logging_multiple_connect_attempts_) 439 if (!logging_multiple_connect_attempts_)
680 LogConnectEnd(result); 440 LogConnectEnd(rv);
441
442 return rv;
681 } 443 }
682 444
683 void TCPSocketLibevent::LogConnectBegin(const AddressList& addresses) { 445 void TCPSocketLibevent::LogConnectBegin(const AddressList& addresses) const {
684 base::StatsCounter connects("tcp.connect"); 446 base::StatsCounter connects("tcp.connect");
685 connects.Increment(); 447 connects.Increment();
686 448
687 net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT, 449 net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT,
688 addresses.CreateNetLogCallback()); 450 addresses.CreateNetLogCallback());
689 } 451 }
690 452
691 void TCPSocketLibevent::LogConnectEnd(int net_error) { 453 void TCPSocketLibevent::LogConnectEnd(int net_error) const {
692 if (net_error == OK)
693 UpdateConnectionTypeHistograms(CONNECTION_ANY);
694
695 if (net_error != OK) { 454 if (net_error != OK) {
696 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, net_error); 455 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, net_error);
697 return; 456 return;
698 } 457 }
699 458
459 UpdateConnectionTypeHistograms(CONNECTION_ANY);
460
700 SockaddrStorage storage; 461 SockaddrStorage storage;
701 int rv = getsockname(socket_, storage.addr, &storage.addr_len); 462 int rv = socket_->GetLocalAddress(&storage);
702 if (rv != 0) { 463 if (rv != OK) {
703 PLOG(ERROR) << "getsockname() [rv: " << rv << "] error: "; 464 PLOG(ERROR) << "GetLocalAddress() [rv: " << rv << "] error: ";
704 NOTREACHED(); 465 NOTREACHED();
705 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, rv); 466 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, rv);
706 return; 467 return;
707 } 468 }
708 469
709 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT, 470 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT,
710 CreateNetLogSourceAddressCallback(storage.addr, 471 CreateNetLogSourceAddressCallback(storage.addr,
711 storage.addr_len)); 472 storage.addr_len));
712 } 473 }
713 474
714 void TCPSocketLibevent::DidCompleteRead() { 475 void TCPSocketLibevent::ReadCompleted(IOBuffer* buf,
715 RecordFastOpenStatus(); 476 const CompletionCallback& callback,
716 if (read_callback_.is_null()) 477 int rv) {
717 return; 478 DCHECK_NE(ERR_IO_PENDING, rv);
479 callback.Run(HandleReadCompleted(buf, rv));
480 }
718 481
719 int bytes_transferred; 482 int TCPSocketLibevent::HandleReadCompleted(IOBuffer* buf, int rv) {
720 bytes_transferred = HANDLE_EINTR(read(socket_, read_buf_->data(), 483 if (rv < 0) {
721 read_buf_len_)); 484 net_log_.AddEvent(NetLog::TYPE_SOCKET_READ_ERROR,
722 485 CreateNetLogSocketErrorCallback(rv, errno));
723 int result; 486 return rv;
724 if (bytes_transferred >= 0) {
725 result = bytes_transferred;
726 base::StatsCounter read_bytes("tcp.read_bytes");
727 read_bytes.Add(bytes_transferred);
728 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, result,
729 read_buf_->data());
730 } else {
731 result = MapSystemError(errno);
732 if (result != ERR_IO_PENDING) {
733 net_log_.AddEvent(NetLog::TYPE_SOCKET_READ_ERROR,
734 CreateNetLogSocketErrorCallback(result, errno));
735 }
736 } 487 }
737 488
738 if (result != ERR_IO_PENDING) { 489 base::StatsCounter read_bytes("tcp.read_bytes");
739 read_buf_ = NULL; 490 read_bytes.Add(rv);
740 read_buf_len_ = 0; 491 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, rv,
741 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); 492 buf->data());
742 DCHECK(ok); 493 RecordFastOpenStatus();
mmenke 2014/06/30 18:26:51 We used to call this regardless of failure, succes
byungchul 2014/06/30 19:38:35 Not sure if it should be called at error as well.
Randy Smith (Not in Mondays) 2014/07/07 19:46:41 Arggh. My read of the code (memory isn't clear) i
byungchul 2014/07/07 21:10:26 Modified to call RecordFastOpenStatus() as before,
743 base::ResetAndReturn(&read_callback_).Run(result); 494 return rv;
744 }
745 } 495 }
746 496
747 void TCPSocketLibevent::DidCompleteWrite() { 497 void TCPSocketLibevent::WriteCompleted(IOBuffer* buf,
748 if (write_callback_.is_null()) 498 const CompletionCallback& callback,
749 return; 499 int rv) const {
500 DCHECK_NE(ERR_IO_PENDING, rv);
501 callback.Run(HandleWriteCompleted(buf, rv));
502 }
750 503
751 int bytes_transferred; 504 int TCPSocketLibevent::HandleWriteCompleted(IOBuffer* buf, int rv) const {
752 bytes_transferred = HANDLE_EINTR(write(socket_, write_buf_->data(), 505 if (rv < 0) {
753 write_buf_len_)); 506 net_log_.AddEvent(NetLog::TYPE_SOCKET_WRITE_ERROR,
754 507 CreateNetLogSocketErrorCallback(rv, errno));
755 int result; 508 return rv;
756 if (bytes_transferred >= 0) {
757 result = bytes_transferred;
758 base::StatsCounter write_bytes("tcp.write_bytes");
759 write_bytes.Add(bytes_transferred);
760 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, result,
761 write_buf_->data());
762 } else {
763 result = MapSystemError(errno);
764 if (result != ERR_IO_PENDING) {
765 net_log_.AddEvent(NetLog::TYPE_SOCKET_WRITE_ERROR,
766 CreateNetLogSocketErrorCallback(result, errno));
767 }
768 } 509 }
769 510
770 if (result != ERR_IO_PENDING) { 511 base::StatsCounter write_bytes("tcp.write_bytes");
771 write_buf_ = NULL; 512 write_bytes.Add(rv);
772 write_buf_len_ = 0; 513 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, rv,
773 write_socket_watcher_.StopWatchingFileDescriptor(); 514 buf->data());
774 base::ResetAndReturn(&write_callback_).Run(result); 515 return rv;
775 }
776 } 516 }
777 517
778 void TCPSocketLibevent::DidCompleteConnect() { 518 int TCPSocketLibevent::TcpFastOpenWrite(
779 DCHECK(waiting_connect_); 519 IOBuffer* buf,
520 int buf_len,
521 const CompletionCallback& callback) {
522 SockaddrStorage storage;
523 int rv = socket_->GetPeerAddress(&storage);
524 if (rv != OK)
525 return rv;
780 526
781 // Get the error that connect() completed with. 527 int flags = 0x20000000; // Magic flag to enable TCP_FASTOPEN.
mmenke 2014/06/30 18:26:51 nit: 2 spaces before comment (Know the old code h
byungchul 2014/06/30 19:38:35 Done.
782 int os_error = 0; 528 #if defined(OS_LINUX)
783 socklen_t len = sizeof(os_error); 529 // sendto() will fail with EPIPE when the system doesn't support TCP Fast
784 if (getsockopt(socket_, SOL_SOCKET, SO_ERROR, &os_error, &len) < 0) 530 // Open. Theoretically that shouldn't happen since the caller should check
785 os_error = errno; 531 // for system support on startup, but users may dynamically disable TCP Fast
532 // Open via sysctl.
533 flags |= MSG_NOSIGNAL;
534 #endif // defined(OS_LINUX)
535 rv = HANDLE_EINTR(sendto(socket_->socket_fd(),
536 buf->data(),
537 buf_len,
538 flags,
539 storage.addr,
540 storage.addr_len));
541 tcp_fastopen_connected_ = true;
786 542
787 int result = MapConnectError(os_error); 543 if (rv >= 0) {
788 connect_os_error_ = os_error; 544 fast_open_status_ = FAST_OPEN_FAST_CONNECT_RETURN;
789 if (result != ERR_IO_PENDING) { 545 return rv;
790 DoConnectComplete(result);
791 waiting_connect_ = false;
792 write_socket_watcher_.StopWatchingFileDescriptor();
793 base::ResetAndReturn(&write_callback_).Run(result);
794 } 546 }
795 }
796 547
797 void TCPSocketLibevent::DidCompleteConnectOrWrite() { 548 DCHECK_NE(EPIPE, errno);
798 if (waiting_connect_)
799 DidCompleteConnect();
800 else
801 DidCompleteWrite();
802 }
803 549
804 void TCPSocketLibevent::DidCompleteAccept() { 550 // If errno == EINPROGRESS, that means the kernel didn't have a cookie
805 DCHECK(CalledOnValidThread()); 551 // and would block. The kernel is internally doing a connect() though.
552 // Remap EINPROGRESS to EAGAIN so we treat this the same as our other
553 // asynchronous cases. Note that the user buffer has not been copied to
554 // kernel space.
555 if (errno == EINPROGRESS) {
556 rv = ERR_IO_PENDING;
557 } else {
558 rv = MapSystemError(errno);
559 }
806 560
807 int result = AcceptInternal(accept_socket_, accept_address_); 561 if (rv != ERR_IO_PENDING) {
808 if (result != ERR_IO_PENDING) { 562 fast_open_status_ = FAST_OPEN_ERROR;
809 accept_socket_ = NULL; 563 return rv;
810 accept_address_ = NULL;
811 bool ok = accept_socket_watcher_.StopWatchingFileDescriptor();
812 DCHECK(ok);
813 CompletionCallback callback = accept_callback_;
814 accept_callback_.Reset();
815 callback.Run(result);
816 } 564 }
817 }
818 565
819 int TCPSocketLibevent::InternalWrite(IOBuffer* buf, int buf_len) { 566 fast_open_status_ = FAST_OPEN_SLOW_CONNECT_RETURN;
820 int nwrite; 567 return socket_->WaitForWrite(buf, buf_len, callback);
821 if (use_tcp_fastopen_ && !tcp_fastopen_connected_) {
822 SockaddrStorage storage;
823 if (!peer_address_->ToSockAddr(storage.addr, &storage.addr_len)) {
824 // Set errno to EADDRNOTAVAIL so that MapSystemError will map it to
825 // ERR_ADDRESS_INVALID later.
826 errno = EADDRNOTAVAIL;
827 return -1;
828 }
829
830 int flags = 0x20000000; // Magic flag to enable TCP_FASTOPEN.
831 #if defined(OS_LINUX)
832 // sendto() will fail with EPIPE when the system doesn't support TCP Fast
833 // Open. Theoretically that shouldn't happen since the caller should check
834 // for system support on startup, but users may dynamically disable TCP Fast
835 // Open via sysctl.
836 flags |= MSG_NOSIGNAL;
837 #endif // defined(OS_LINUX)
838 nwrite = HANDLE_EINTR(sendto(socket_,
839 buf->data(),
840 buf_len,
841 flags,
842 storage.addr,
843 storage.addr_len));
844 tcp_fastopen_connected_ = true;
845
846 if (nwrite < 0) {
847 DCHECK_NE(EPIPE, errno);
848
849 // If errno == EINPROGRESS, that means the kernel didn't have a cookie
850 // and would block. The kernel is internally doing a connect() though.
851 // Remap EINPROGRESS to EAGAIN so we treat this the same as our other
852 // asynchronous cases. Note that the user buffer has not been copied to
853 // kernel space.
854 if (errno == EINPROGRESS) {
855 errno = EAGAIN;
856 fast_open_status_ = FAST_OPEN_SLOW_CONNECT_RETURN;
857 } else {
858 fast_open_status_ = FAST_OPEN_ERROR;
859 }
860 } else {
861 fast_open_status_ = FAST_OPEN_FAST_CONNECT_RETURN;
862 }
863 } else {
864 nwrite = HANDLE_EINTR(write(socket_, buf->data(), buf_len));
865 }
866 return nwrite;
867 } 568 }
868 569
869 void TCPSocketLibevent::RecordFastOpenStatus() { 570 void TCPSocketLibevent::RecordFastOpenStatus() {
870 if (use_tcp_fastopen_ && 571 if (use_tcp_fastopen_ &&
871 (fast_open_status_ == FAST_OPEN_FAST_CONNECT_RETURN || 572 (fast_open_status_ == FAST_OPEN_FAST_CONNECT_RETURN ||
872 fast_open_status_ == FAST_OPEN_SLOW_CONNECT_RETURN)) { 573 fast_open_status_ == FAST_OPEN_SLOW_CONNECT_RETURN)) {
873 DCHECK_NE(FAST_OPEN_STATUS_UNKNOWN, fast_open_status_); 574 DCHECK_NE(FAST_OPEN_STATUS_UNKNOWN, fast_open_status_);
874 bool getsockopt_success(false); 575 bool getsockopt_success(false);
875 bool server_acked_data(false); 576 bool server_acked_data(false);
876 #if defined(TCP_INFO) 577 #if defined(TCP_INFO)
877 // Probe to see the if the socket used TCP Fast Open. 578 // Probe to see the if the socket used TCP Fast Open.
878 tcp_info info; 579 tcp_info info;
879 socklen_t info_len = sizeof(tcp_info); 580 socklen_t info_len = sizeof(tcp_info);
880 getsockopt_success = 581 getsockopt_success =
881 getsockopt(socket_, IPPROTO_TCP, TCP_INFO, &info, &info_len) == 0 && 582 getsockopt(socket_->socket_fd(), IPPROTO_TCP, TCP_INFO,
583 &info, &info_len) == 0 &&
882 info_len == sizeof(tcp_info); 584 info_len == sizeof(tcp_info);
883 server_acked_data = getsockopt_success && 585 server_acked_data = getsockopt_success &&
884 (info.tcpi_options & TCPI_OPT_SYN_DATA); 586 (info.tcpi_options & TCPI_OPT_SYN_DATA);
885 #endif 587 #endif
886 if (getsockopt_success) { 588 if (getsockopt_success) {
887 if (fast_open_status_ == FAST_OPEN_FAST_CONNECT_RETURN) { 589 if (fast_open_status_ == FAST_OPEN_FAST_CONNECT_RETURN) {
888 fast_open_status_ = (server_acked_data ? FAST_OPEN_SYN_DATA_ACK : 590 fast_open_status_ = (server_acked_data ? FAST_OPEN_SYN_DATA_ACK :
889 FAST_OPEN_SYN_DATA_NACK); 591 FAST_OPEN_SYN_DATA_NACK);
890 } else { 592 } else {
891 fast_open_status_ = (server_acked_data ? FAST_OPEN_NO_SYN_DATA_ACK : 593 fast_open_status_ = (server_acked_data ? FAST_OPEN_NO_SYN_DATA_ACK :
892 FAST_OPEN_NO_SYN_DATA_NACK); 594 FAST_OPEN_NO_SYN_DATA_NACK);
893 } 595 }
894 } else { 596 } else {
895 fast_open_status_ = (fast_open_status_ == FAST_OPEN_FAST_CONNECT_RETURN ? 597 fast_open_status_ = (fast_open_status_ == FAST_OPEN_FAST_CONNECT_RETURN ?
896 FAST_OPEN_SYN_DATA_FAILED : 598 FAST_OPEN_SYN_DATA_FAILED :
897 FAST_OPEN_NO_SYN_DATA_FAILED); 599 FAST_OPEN_NO_SYN_DATA_FAILED);
898 } 600 }
899 } 601 }
900 } 602 }
901 603
902 } // namespace net 604 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698