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

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

Issue 2593063003: Add Socket::ReadIfReady() (Closed)
Patch Set: Rebased Created 3 years, 9 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
« no previous file with comments | « net/socket/socket_posix.h ('k') | net/socket/socket_test_util.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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/socket_posix.h" 5 #include "net/socket/socket_posix.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <netinet/in.h> 8 #include <netinet/in.h>
9 #include <sys/socket.h> 9 #include <sys/socket.h>
10 #include <utility> 10 #include <utility>
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 return false; 246 return false;
247 if (errno != EAGAIN && errno != EWOULDBLOCK) 247 if (errno != EAGAIN && errno != EWOULDBLOCK)
248 return false; 248 return false;
249 249
250 return true; 250 return true;
251 } 251 }
252 252
253 int SocketPosix::Read(IOBuffer* buf, 253 int SocketPosix::Read(IOBuffer* buf,
254 int buf_len, 254 int buf_len,
255 const CompletionCallback& callback) { 255 const CompletionCallback& callback) {
256 // Use base::Unretained() is safe here because OnFileCanReadWithoutBlocking()
257 // won't be called if |this| is gone.
258 int rv =
259 ReadIfReady(buf, buf_len,
260 base::Bind(&SocketPosix::RetryRead, base::Unretained(this)));
261 if (rv == ERR_IO_PENDING) {
262 read_buf_ = buf;
263 read_buf_len_ = buf_len;
264 read_callback_ = callback;
265 }
266 return rv;
267 }
268
269 int SocketPosix::ReadIfReady(IOBuffer* buf,
270 int buf_len,
271 const CompletionCallback& callback) {
256 DCHECK(thread_checker_.CalledOnValidThread()); 272 DCHECK(thread_checker_.CalledOnValidThread());
257 DCHECK_NE(kInvalidSocket, socket_fd_); 273 DCHECK_NE(kInvalidSocket, socket_fd_);
258 DCHECK(!waiting_connect_); 274 DCHECK(!waiting_connect_);
259 CHECK(read_callback_.is_null()); 275 CHECK(read_if_ready_callback_.is_null());
260 // Synchronous operation not supported
261 DCHECK(!callback.is_null()); 276 DCHECK(!callback.is_null());
262 DCHECK_LT(0, buf_len); 277 DCHECK_LT(0, buf_len);
263 278
264 int rv = DoRead(buf, buf_len); 279 int rv = DoRead(buf, buf_len);
265 if (rv != ERR_IO_PENDING) 280 if (rv != ERR_IO_PENDING)
266 return rv; 281 return rv;
267 282
268 if (!base::MessageLoopForIO::current()->WatchFileDescriptor( 283 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
269 socket_fd_, true, base::MessageLoopForIO::WATCH_READ, 284 socket_fd_, true, base::MessageLoopForIO::WATCH_READ,
270 &read_socket_watcher_, this)) { 285 &read_socket_watcher_, this)) {
271 PLOG(ERROR) << "WatchFileDescriptor failed on read, errno " << errno; 286 PLOG(ERROR) << "WatchFileDescriptor failed on read, errno " << errno;
272 return MapSystemError(errno); 287 return MapSystemError(errno);
273 } 288 }
274 289
275 read_buf_ = buf; 290 read_if_ready_callback_ = callback;
276 read_buf_len_ = buf_len;
277 read_callback_ = callback;
278 return ERR_IO_PENDING; 291 return ERR_IO_PENDING;
279 } 292 }
280 293
281 int SocketPosix::Write(IOBuffer* buf, 294 int SocketPosix::Write(IOBuffer* buf,
282 int buf_len, 295 int buf_len,
283 const CompletionCallback& callback) { 296 const CompletionCallback& callback) {
284 DCHECK(thread_checker_.CalledOnValidThread()); 297 DCHECK(thread_checker_.CalledOnValidThread());
285 DCHECK_NE(kInvalidSocket, socket_fd_); 298 DCHECK_NE(kInvalidSocket, socket_fd_);
286 DCHECK(!waiting_connect_); 299 DCHECK(!waiting_connect_);
287 CHECK(write_callback_.is_null()); 300 CHECK(write_callback_.is_null());
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 } 381 }
369 } 382 }
370 383
371 void SocketPosix::DetachFromThread() { 384 void SocketPosix::DetachFromThread() {
372 thread_checker_.DetachFromThread(); 385 thread_checker_.DetachFromThread();
373 } 386 }
374 387
375 void SocketPosix::OnFileCanReadWithoutBlocking(int fd) { 388 void SocketPosix::OnFileCanReadWithoutBlocking(int fd) {
376 TRACE_EVENT0(kNetTracingCategory, 389 TRACE_EVENT0(kNetTracingCategory,
377 "SocketPosix::OnFileCanReadWithoutBlocking"); 390 "SocketPosix::OnFileCanReadWithoutBlocking");
378 DCHECK(!accept_callback_.is_null() || !read_callback_.is_null());
379 if (!accept_callback_.is_null()) { 391 if (!accept_callback_.is_null()) {
380 AcceptCompleted(); 392 AcceptCompleted();
381 } else { // !read_callback_.is_null() 393 } else {
394 DCHECK(!read_if_ready_callback_.is_null());
382 ReadCompleted(); 395 ReadCompleted();
383 } 396 }
384 } 397 }
385 398
386 void SocketPosix::OnFileCanWriteWithoutBlocking(int fd) { 399 void SocketPosix::OnFileCanWriteWithoutBlocking(int fd) {
387 DCHECK(!write_callback_.is_null()); 400 DCHECK(!write_callback_.is_null());
388 if (waiting_connect_) { 401 if (waiting_connect_) {
389 ConnectCompleted(); 402 ConnectCompleted();
390 } else { 403 } else {
391 WriteCompleted(); 404 WriteCompleted();
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
446 DCHECK(ok); 459 DCHECK(ok);
447 waiting_connect_ = false; 460 waiting_connect_ = false;
448 base::ResetAndReturn(&write_callback_).Run(rv); 461 base::ResetAndReturn(&write_callback_).Run(rv);
449 } 462 }
450 463
451 int SocketPosix::DoRead(IOBuffer* buf, int buf_len) { 464 int SocketPosix::DoRead(IOBuffer* buf, int buf_len) {
452 int rv = HANDLE_EINTR(read(socket_fd_, buf->data(), buf_len)); 465 int rv = HANDLE_EINTR(read(socket_fd_, buf->data(), buf_len));
453 return rv >= 0 ? rv : MapSystemError(errno); 466 return rv >= 0 ? rv : MapSystemError(errno);
454 } 467 }
455 468
456 void SocketPosix::ReadCompleted() { 469 void SocketPosix::RetryRead(int rv) {
457 int rv = DoRead(read_buf_.get(), read_buf_len_); 470 DCHECK(read_callback_);
458 if (rv == ERR_IO_PENDING) 471 DCHECK(read_buf_);
459 return; 472 DCHECK_LT(0, read_buf_len_);
460 473
461 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); 474 if (rv == OK) {
462 DCHECK(ok); 475 rv = ReadIfReady(
463 read_buf_ = NULL; 476 read_buf_.get(), read_buf_len_,
477 base::Bind(&SocketPosix::RetryRead, base::Unretained(this)));
478 if (rv == ERR_IO_PENDING)
479 return;
480 }
481 read_buf_ = nullptr;
464 read_buf_len_ = 0; 482 read_buf_len_ = 0;
465 base::ResetAndReturn(&read_callback_).Run(rv); 483 base::ResetAndReturn(&read_callback_).Run(rv);
466 } 484 }
467 485
486 void SocketPosix::ReadCompleted() {
487 DCHECK(read_if_ready_callback_);
488
489 bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
490 DCHECK(ok);
491 base::ResetAndReturn(&read_if_ready_callback_).Run(OK);
492 }
493
468 int SocketPosix::DoWrite(IOBuffer* buf, int buf_len) { 494 int SocketPosix::DoWrite(IOBuffer* buf, int buf_len) {
469 #if defined(OS_LINUX) || defined(OS_ANDROID) 495 #if defined(OS_LINUX) || defined(OS_ANDROID)
470 // Disable SIGPIPE for this write. Although Chromium globally disables 496 // Disable SIGPIPE for this write. Although Chromium globally disables
471 // SIGPIPE, the net stack may be used in other consumers which do not do 497 // SIGPIPE, the net stack may be used in other consumers which do not do
472 // this. MSG_NOSIGNAL is a Linux-only API. On OS X, this is a setsockopt on 498 // this. MSG_NOSIGNAL is a Linux-only API. On OS X, this is a setsockopt on
473 // socket creation. 499 // socket creation.
474 int rv = HANDLE_EINTR(send(socket_fd_, buf->data(), buf_len, MSG_NOSIGNAL)); 500 int rv = HANDLE_EINTR(send(socket_fd_, buf->data(), buf_len, MSG_NOSIGNAL));
475 #else 501 #else
476 int rv = HANDLE_EINTR(write(socket_fd_, buf->data(), buf_len)); 502 int rv = HANDLE_EINTR(write(socket_fd_, buf->data(), buf_len));
477 #endif 503 #endif
(...skipping 24 matching lines...) Expand all
502 accept_socket_ = NULL; 528 accept_socket_ = NULL;
503 accept_callback_.Reset(); 529 accept_callback_.Reset();
504 } 530 }
505 531
506 if (!read_callback_.is_null()) { 532 if (!read_callback_.is_null()) {
507 read_buf_ = NULL; 533 read_buf_ = NULL;
508 read_buf_len_ = 0; 534 read_buf_len_ = 0;
509 read_callback_.Reset(); 535 read_callback_.Reset();
510 } 536 }
511 537
538 read_if_ready_callback_.Reset();
539
512 if (!write_callback_.is_null()) { 540 if (!write_callback_.is_null()) {
513 write_buf_ = NULL; 541 write_buf_ = NULL;
514 write_buf_len_ = 0; 542 write_buf_len_ = 0;
515 write_callback_.Reset(); 543 write_callback_.Reset();
516 } 544 }
517 545
518 waiting_connect_ = false; 546 waiting_connect_ = false;
519 peer_address_.reset(); 547 peer_address_.reset();
520 } 548 }
521 549
522 } // namespace net 550 } // namespace net
OLDNEW
« no previous file with comments | « net/socket/socket_posix.h ('k') | net/socket/socket_test_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698