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

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

Issue 2593063003: Add Socket::ReadIfReady() (Closed)
Patch Set: Self Created 3 years, 10 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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 } 55 }
56 } 56 }
57 } 57 }
58 58
59 } // namespace 59 } // namespace
60 60
61 SocketPosix::SocketPosix() 61 SocketPosix::SocketPosix()
62 : socket_fd_(kInvalidSocket), 62 : socket_fd_(kInvalidSocket),
63 read_buf_len_(0), 63 read_buf_len_(0),
64 write_buf_len_(0), 64 write_buf_len_(0),
65 waiting_connect_(false) {} 65 waiting_connect_(false),
66 weak_factory_(this) {}
66 67
67 SocketPosix::~SocketPosix() { 68 SocketPosix::~SocketPosix() {
68 Close(); 69 Close();
69 } 70 }
70 71
71 int SocketPosix::Open(int address_family) { 72 int SocketPosix::Open(int address_family) {
72 DCHECK(thread_checker_.CalledOnValidThread()); 73 DCHECK(thread_checker_.CalledOnValidThread());
73 DCHECK_EQ(kInvalidSocket, socket_fd_); 74 DCHECK_EQ(kInvalidSocket, socket_fd_);
74 DCHECK(address_family == AF_INET || 75 DCHECK(address_family == AF_INET ||
75 address_family == AF_INET6 || 76 address_family == AF_INET6 ||
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 return false; 244 return false;
244 if (errno != EAGAIN && errno != EWOULDBLOCK) 245 if (errno != EAGAIN && errno != EWOULDBLOCK)
245 return false; 246 return false;
246 247
247 return true; 248 return true;
248 } 249 }
249 250
250 int SocketPosix::Read(IOBuffer* buf, 251 int SocketPosix::Read(IOBuffer* buf,
251 int buf_len, 252 int buf_len,
252 const CompletionCallback& callback) { 253 const CompletionCallback& callback) {
254 int rv = ReadIfReady(buf, buf_len, base::Bind(&SocketPosix::RetryRead,
255 weak_factory_.GetWeakPtr()));
davidben 2017/02/10 23:33:48 Do you need a WeakPtr here? Since the callback won
xunjieli 2017/02/13 20:28:18 Done. You are right. I confused this one with the
256 if (rv == ERR_IO_PENDING) {
257 read_buf_ = buf;
258 read_buf_len_ = buf_len;
259 read_callback_ = callback;
260 }
261 return rv;
262 }
263
264 int SocketPosix::ReadIfReady(IOBuffer* buf,
265 int buf_len,
266 const CompletionCallback& callback) {
253 DCHECK(thread_checker_.CalledOnValidThread()); 267 DCHECK(thread_checker_.CalledOnValidThread());
254 DCHECK_NE(kInvalidSocket, socket_fd_); 268 DCHECK_NE(kInvalidSocket, socket_fd_);
255 DCHECK(!waiting_connect_); 269 DCHECK(!waiting_connect_);
256 CHECK(read_callback_.is_null()); 270 CHECK(read_if_ready_callback_.is_null());
257 // Synchronous operation not supported 271 // Synchronous operation not supported
258 DCHECK(!callback.is_null()); 272 DCHECK(!callback.is_null());
259 DCHECK_LT(0, buf_len); 273 DCHECK_LT(0, buf_len);
260 274
261 int rv = DoRead(buf, buf_len); 275 int rv = DoRead(buf, buf_len);
262 if (rv != ERR_IO_PENDING) 276 if (rv != ERR_IO_PENDING)
263 return rv; 277 return rv;
264 278
265 if (!base::MessageLoopForIO::current()->WatchFileDescriptor( 279 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
266 socket_fd_, true, base::MessageLoopForIO::WATCH_READ, 280 socket_fd_, true, base::MessageLoopForIO::WATCH_READ,
267 &read_socket_watcher_, this)) { 281 &read_socket_watcher_, this)) {
268 PLOG(ERROR) << "WatchFileDescriptor failed on read, errno " << errno; 282 PLOG(ERROR) << "WatchFileDescriptor failed on read, errno " << errno;
269 return MapSystemError(errno); 283 return MapSystemError(errno);
270 } 284 }
271 285
272 read_buf_ = buf; 286 read_if_ready_callback_ = callback;
273 read_buf_len_ = buf_len;
274 read_callback_ = callback;
275 return ERR_IO_PENDING; 287 return ERR_IO_PENDING;
276 } 288 }
277 289
278 int SocketPosix::Write(IOBuffer* buf, 290 int SocketPosix::Write(IOBuffer* buf,
279 int buf_len, 291 int buf_len,
280 const CompletionCallback& callback) { 292 const CompletionCallback& callback) {
281 DCHECK(thread_checker_.CalledOnValidThread()); 293 DCHECK(thread_checker_.CalledOnValidThread());
282 DCHECK_NE(kInvalidSocket, socket_fd_); 294 DCHECK_NE(kInvalidSocket, socket_fd_);
283 DCHECK(!waiting_connect_); 295 DCHECK(!waiting_connect_);
284 CHECK(write_callback_.is_null()); 296 CHECK(write_callback_.is_null());
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
365 } 377 }
366 } 378 }
367 379
368 void SocketPosix::DetachFromThread() { 380 void SocketPosix::DetachFromThread() {
369 thread_checker_.DetachFromThread(); 381 thread_checker_.DetachFromThread();
370 } 382 }
371 383
372 void SocketPosix::OnFileCanReadWithoutBlocking(int fd) { 384 void SocketPosix::OnFileCanReadWithoutBlocking(int fd) {
373 TRACE_EVENT0(kNetTracingCategory, 385 TRACE_EVENT0(kNetTracingCategory,
374 "SocketPosix::OnFileCanReadWithoutBlocking"); 386 "SocketPosix::OnFileCanReadWithoutBlocking");
375 DCHECK(!accept_callback_.is_null() || !read_callback_.is_null()); 387 DCHECK(!accept_callback_.is_null() || !read_if_ready_callback_.is_null());
376 if (!accept_callback_.is_null()) { 388 if (!accept_callback_.is_null()) {
377 AcceptCompleted(); 389 AcceptCompleted();
378 } else { // !read_callback_.is_null() 390 } else { // !read_if_ready_callback_.is_null()
379 ReadCompleted(); 391 ReadCompleted();
380 } 392 }
381 } 393 }
382 394
383 void SocketPosix::OnFileCanWriteWithoutBlocking(int fd) { 395 void SocketPosix::OnFileCanWriteWithoutBlocking(int fd) {
384 DCHECK(!write_callback_.is_null()); 396 DCHECK(!write_callback_.is_null());
385 if (waiting_connect_) { 397 if (waiting_connect_) {
386 ConnectCompleted(); 398 ConnectCompleted();
387 } else { 399 } else {
388 WriteCompleted(); 400 WriteCompleted();
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
443 DCHECK(ok); 455 DCHECK(ok);
444 waiting_connect_ = false; 456 waiting_connect_ = false;
445 base::ResetAndReturn(&write_callback_).Run(rv); 457 base::ResetAndReturn(&write_callback_).Run(rv);
446 } 458 }
447 459
448 int SocketPosix::DoRead(IOBuffer* buf, int buf_len) { 460 int SocketPosix::DoRead(IOBuffer* buf, int buf_len) {
449 int rv = HANDLE_EINTR(read(socket_fd_, buf->data(), buf_len)); 461 int rv = HANDLE_EINTR(read(socket_fd_, buf->data(), buf_len));
450 return rv >= 0 ? rv : MapSystemError(errno); 462 return rv >= 0 ? rv : MapSystemError(errno);
451 } 463 }
452 464
453 void SocketPosix::ReadCompleted() { 465 void SocketPosix::RetryRead(int rv) {
454 int rv = DoRead(read_buf_.get(), read_buf_len_); 466 DCHECK(read_callback_);
455 if (rv == ERR_IO_PENDING) 467 DCHECK(read_buf_);
456 return; 468 DCHECK_LT(0, read_buf_len_);
457 469
458 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); 470 if (rv == OK) {
459 DCHECK(ok); 471 rv = ReadIfReady(
460 read_buf_ = NULL; 472 read_buf_.get(), read_buf_len_,
473 base::Bind(&SocketPosix::RetryRead, weak_factory_.GetWeakPtr()));
474 if (rv == ERR_IO_PENDING)
475 return;
476 }
477 read_buf_ = nullptr;
461 read_buf_len_ = 0; 478 read_buf_len_ = 0;
462 base::ResetAndReturn(&read_callback_).Run(rv); 479 base::ResetAndReturn(&read_callback_).Run(rv);
463 } 480 }
464 481
482 void SocketPosix::ReadCompleted() {
483 DCHECK(read_if_ready_callback_);
484
485 bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
486 DCHECK(ok);
487 base::ResetAndReturn(&read_if_ready_callback_).Run(OK);
488 }
489
465 int SocketPosix::DoWrite(IOBuffer* buf, int buf_len) { 490 int SocketPosix::DoWrite(IOBuffer* buf, int buf_len) {
466 #if defined(OS_LINUX) || defined(OS_ANDROID) 491 #if defined(OS_LINUX) || defined(OS_ANDROID)
467 // Disable SIGPIPE for this write. Although Chromium globally disables 492 // Disable SIGPIPE for this write. Although Chromium globally disables
468 // SIGPIPE, the net stack may be used in other consumers which do not do 493 // SIGPIPE, the net stack may be used in other consumers which do not do
469 // this. MSG_NOSIGNAL is a Linux-only API. On OS X, this is a setsockopt on 494 // this. MSG_NOSIGNAL is a Linux-only API. On OS X, this is a setsockopt on
470 // socket creation. 495 // socket creation.
471 int rv = HANDLE_EINTR(send(socket_fd_, buf->data(), buf_len, MSG_NOSIGNAL)); 496 int rv = HANDLE_EINTR(send(socket_fd_, buf->data(), buf_len, MSG_NOSIGNAL));
472 #else 497 #else
473 int rv = HANDLE_EINTR(write(socket_fd_, buf->data(), buf_len)); 498 int rv = HANDLE_EINTR(write(socket_fd_, buf->data(), buf_len));
474 #endif 499 #endif
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
510 write_buf_ = NULL; 535 write_buf_ = NULL;
511 write_buf_len_ = 0; 536 write_buf_len_ = 0;
512 write_callback_.Reset(); 537 write_callback_.Reset();
513 } 538 }
514 539
515 waiting_connect_ = false; 540 waiting_connect_ = false;
516 peer_address_.reset(); 541 peer_address_.reset();
517 } 542 }
518 543
519 } // namespace net 544 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698