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