OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |