| 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 |