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

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

Issue 2593063003: Add Socket::ReadIfReady() (Closed)
Patch Set: self review. remove unused include 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
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 276 // Synchronous operation not supported
Bence 2017/03/03 16:33:41 What does this comment mean? Could it be removed?
xunjieli 2017/03/03 19:41:05 Done. Removed. I think having a callback as a requ
261 DCHECK(!callback.is_null()); 277 DCHECK(!callback.is_null());
262 DCHECK_LT(0, buf_len); 278 DCHECK_LT(0, buf_len);
263 279
264 int rv = DoRead(buf, buf_len); 280 int rv = DoRead(buf, buf_len);
265 if (rv != ERR_IO_PENDING) 281 if (rv != ERR_IO_PENDING)
266 return rv; 282 return rv;
267 283
268 if (!base::MessageLoopForIO::current()->WatchFileDescriptor( 284 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
269 socket_fd_, true, base::MessageLoopForIO::WATCH_READ, 285 socket_fd_, true, base::MessageLoopForIO::WATCH_READ,
270 &read_socket_watcher_, this)) { 286 &read_socket_watcher_, this)) {
271 PLOG(ERROR) << "WatchFileDescriptor failed on read, errno " << errno; 287 PLOG(ERROR) << "WatchFileDescriptor failed on read, errno " << errno;
272 return MapSystemError(errno); 288 return MapSystemError(errno);
273 } 289 }
274 290
275 read_buf_ = buf; 291 read_if_ready_callback_ = callback;
276 read_buf_len_ = buf_len;
277 read_callback_ = callback;
278 return ERR_IO_PENDING; 292 return ERR_IO_PENDING;
279 } 293 }
280 294
281 int SocketPosix::Write(IOBuffer* buf, 295 int SocketPosix::Write(IOBuffer* buf,
282 int buf_len, 296 int buf_len,
283 const CompletionCallback& callback) { 297 const CompletionCallback& callback) {
284 DCHECK(thread_checker_.CalledOnValidThread()); 298 DCHECK(thread_checker_.CalledOnValidThread());
285 DCHECK_NE(kInvalidSocket, socket_fd_); 299 DCHECK_NE(kInvalidSocket, socket_fd_);
286 DCHECK(!waiting_connect_); 300 DCHECK(!waiting_connect_);
287 CHECK(write_callback_.is_null()); 301 CHECK(write_callback_.is_null());
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 } 382 }
369 } 383 }
370 384
371 void SocketPosix::DetachFromThread() { 385 void SocketPosix::DetachFromThread() {
372 thread_checker_.DetachFromThread(); 386 thread_checker_.DetachFromThread();
373 } 387 }
374 388
375 void SocketPosix::OnFileCanReadWithoutBlocking(int fd) { 389 void SocketPosix::OnFileCanReadWithoutBlocking(int fd) {
376 TRACE_EVENT0(kNetTracingCategory, 390 TRACE_EVENT0(kNetTracingCategory,
377 "SocketPosix::OnFileCanReadWithoutBlocking"); 391 "SocketPosix::OnFileCanReadWithoutBlocking");
378 DCHECK(!accept_callback_.is_null() || !read_callback_.is_null()); 392 DCHECK(!accept_callback_.is_null() || !read_if_ready_callback_.is_null());
379 if (!accept_callback_.is_null()) { 393 if (!accept_callback_.is_null()) {
380 AcceptCompleted(); 394 AcceptCompleted();
381 } else { // !read_callback_.is_null() 395 } else { // !read_if_ready_callback_.is_null()
Bence 2017/03/03 16:33:41 Optional: remove this comment, remove DCHECK from
xunjieli 2017/03/03 19:41:05 Done.
382 ReadCompleted(); 396 ReadCompleted();
383 } 397 }
384 } 398 }
385 399
386 void SocketPosix::OnFileCanWriteWithoutBlocking(int fd) { 400 void SocketPosix::OnFileCanWriteWithoutBlocking(int fd) {
387 DCHECK(!write_callback_.is_null()); 401 DCHECK(!write_callback_.is_null());
388 if (waiting_connect_) { 402 if (waiting_connect_) {
389 ConnectCompleted(); 403 ConnectCompleted();
390 } else { 404 } else {
391 WriteCompleted(); 405 WriteCompleted();
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
446 DCHECK(ok); 460 DCHECK(ok);
447 waiting_connect_ = false; 461 waiting_connect_ = false;
448 base::ResetAndReturn(&write_callback_).Run(rv); 462 base::ResetAndReturn(&write_callback_).Run(rv);
449 } 463 }
450 464
451 int SocketPosix::DoRead(IOBuffer* buf, int buf_len) { 465 int SocketPosix::DoRead(IOBuffer* buf, int buf_len) {
452 int rv = HANDLE_EINTR(read(socket_fd_, buf->data(), buf_len)); 466 int rv = HANDLE_EINTR(read(socket_fd_, buf->data(), buf_len));
453 return rv >= 0 ? rv : MapSystemError(errno); 467 return rv >= 0 ? rv : MapSystemError(errno);
454 } 468 }
455 469
456 void SocketPosix::ReadCompleted() { 470 void SocketPosix::RetryRead(int rv) {
457 int rv = DoRead(read_buf_.get(), read_buf_len_); 471 DCHECK(read_callback_);
458 if (rv == ERR_IO_PENDING) 472 DCHECK(read_buf_);
459 return; 473 DCHECK_LT(0, read_buf_len_);
460 474
461 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); 475 if (rv == OK) {
462 DCHECK(ok); 476 rv = ReadIfReady(
463 read_buf_ = NULL; 477 read_buf_.get(), read_buf_len_,
478 base::Bind(&SocketPosix::RetryRead, base::Unretained(this)));
479 if (rv == ERR_IO_PENDING)
480 return;
481 }
482 read_buf_ = nullptr;
464 read_buf_len_ = 0; 483 read_buf_len_ = 0;
465 base::ResetAndReturn(&read_callback_).Run(rv); 484 base::ResetAndReturn(&read_callback_).Run(rv);
466 } 485 }
467 486
487 void SocketPosix::ReadCompleted() {
488 DCHECK(read_if_ready_callback_);
489
490 bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
491 DCHECK(ok);
492 base::ResetAndReturn(&read_if_ready_callback_).Run(OK);
493 }
494
468 int SocketPosix::DoWrite(IOBuffer* buf, int buf_len) { 495 int SocketPosix::DoWrite(IOBuffer* buf, int buf_len) {
469 #if defined(OS_LINUX) || defined(OS_ANDROID) 496 #if defined(OS_LINUX) || defined(OS_ANDROID)
470 // Disable SIGPIPE for this write. Although Chromium globally disables 497 // Disable SIGPIPE for this write. Although Chromium globally disables
471 // SIGPIPE, the net stack may be used in other consumers which do not do 498 // 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 499 // this. MSG_NOSIGNAL is a Linux-only API. On OS X, this is a setsockopt on
473 // socket creation. 500 // socket creation.
474 int rv = HANDLE_EINTR(send(socket_fd_, buf->data(), buf_len, MSG_NOSIGNAL)); 501 int rv = HANDLE_EINTR(send(socket_fd_, buf->data(), buf_len, MSG_NOSIGNAL));
475 #else 502 #else
476 int rv = HANDLE_EINTR(write(socket_fd_, buf->data(), buf_len)); 503 int rv = HANDLE_EINTR(write(socket_fd_, buf->data(), buf_len));
477 #endif 504 #endif
(...skipping 18 matching lines...) Expand all
496 ok = read_socket_watcher_.StopWatchingFileDescriptor(); 523 ok = read_socket_watcher_.StopWatchingFileDescriptor();
497 DCHECK(ok); 524 DCHECK(ok);
498 ok = write_socket_watcher_.StopWatchingFileDescriptor(); 525 ok = write_socket_watcher_.StopWatchingFileDescriptor();
499 DCHECK(ok); 526 DCHECK(ok);
500 527
501 if (!accept_callback_.is_null()) { 528 if (!accept_callback_.is_null()) {
502 accept_socket_ = NULL; 529 accept_socket_ = NULL;
503 accept_callback_.Reset(); 530 accept_callback_.Reset();
504 } 531 }
505 532
506 if (!read_callback_.is_null()) { 533 if (!read_callback_.is_null()) {
Bence 2017/03/03 16:33:41 I am wondering if |read_if_ready_callback_| would
xunjieli 2017/03/03 19:41:06 Done. Good point.
507 read_buf_ = NULL; 534 read_buf_ = NULL;
508 read_buf_len_ = 0; 535 read_buf_len_ = 0;
509 read_callback_.Reset(); 536 read_callback_.Reset();
510 } 537 }
511 538
512 if (!write_callback_.is_null()) { 539 if (!write_callback_.is_null()) {
513 write_buf_ = NULL; 540 write_buf_ = NULL;
514 write_buf_len_ = 0; 541 write_buf_len_ = 0;
515 write_callback_.Reset(); 542 write_callback_.Reset();
516 } 543 }
517 544
518 waiting_connect_ = false; 545 waiting_connect_ = false;
519 peer_address_.reset(); 546 peer_address_.reset();
520 } 547 }
521 548
522 } // namespace net 549 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698