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 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 return false; | 243 return false; |
244 if (errno != EAGAIN && errno != EWOULDBLOCK) | 244 if (errno != EAGAIN && errno != EWOULDBLOCK) |
245 return false; | 245 return false; |
246 | 246 |
247 return true; | 247 return true; |
248 } | 248 } |
249 | 249 |
250 int SocketPosix::Read(IOBuffer* buf, | 250 int SocketPosix::Read(IOBuffer* buf, |
251 int buf_len, | 251 int buf_len, |
252 const CompletionCallback& callback) { | 252 const CompletionCallback& callback) { |
| 253 // Use base::Unretained() is safe here because OnFileCanReadWithoutBlocking() |
| 254 // won't be called if |this| is gone. |
| 255 int rv = ReadIfReady(buf, buf_len, base::Bind(&SocketPosix::RetryRead, |
| 256 base::Unretained(this))); |
| 257 if (rv == ERR_IO_PENDING) { |
| 258 read_buf_ = buf; |
| 259 read_buf_len_ = buf_len; |
| 260 read_callback_ = callback; |
| 261 } |
| 262 return rv; |
| 263 } |
| 264 |
| 265 int SocketPosix::ReadIfReady(IOBuffer* buf, |
| 266 int buf_len, |
| 267 const CompletionCallback& callback) { |
253 DCHECK(thread_checker_.CalledOnValidThread()); | 268 DCHECK(thread_checker_.CalledOnValidThread()); |
254 DCHECK_NE(kInvalidSocket, socket_fd_); | 269 DCHECK_NE(kInvalidSocket, socket_fd_); |
255 DCHECK(!waiting_connect_); | 270 DCHECK(!waiting_connect_); |
256 CHECK(read_callback_.is_null()); | 271 CHECK(read_if_ready_callback_.is_null()); |
257 // Synchronous operation not supported | 272 // Synchronous operation not supported |
258 DCHECK(!callback.is_null()); | 273 DCHECK(!callback.is_null()); |
259 DCHECK_LT(0, buf_len); | 274 DCHECK_LT(0, buf_len); |
260 | 275 |
261 int rv = DoRead(buf, buf_len); | 276 int rv = DoRead(buf, buf_len); |
262 if (rv != ERR_IO_PENDING) | 277 if (rv != ERR_IO_PENDING) |
263 return rv; | 278 return rv; |
264 | 279 |
265 if (!base::MessageLoopForIO::current()->WatchFileDescriptor( | 280 if (!base::MessageLoopForIO::current()->WatchFileDescriptor( |
266 socket_fd_, true, base::MessageLoopForIO::WATCH_READ, | 281 socket_fd_, true, base::MessageLoopForIO::WATCH_READ, |
267 &read_socket_watcher_, this)) { | 282 &read_socket_watcher_, this)) { |
268 PLOG(ERROR) << "WatchFileDescriptor failed on read, errno " << errno; | 283 PLOG(ERROR) << "WatchFileDescriptor failed on read, errno " << errno; |
269 return MapSystemError(errno); | 284 return MapSystemError(errno); |
270 } | 285 } |
271 | 286 |
272 read_buf_ = buf; | 287 read_if_ready_callback_ = callback; |
273 read_buf_len_ = buf_len; | |
274 read_callback_ = callback; | |
275 return ERR_IO_PENDING; | 288 return ERR_IO_PENDING; |
276 } | 289 } |
277 | 290 |
278 int SocketPosix::Write(IOBuffer* buf, | 291 int SocketPosix::Write(IOBuffer* buf, |
279 int buf_len, | 292 int buf_len, |
280 const CompletionCallback& callback) { | 293 const CompletionCallback& callback) { |
281 DCHECK(thread_checker_.CalledOnValidThread()); | 294 DCHECK(thread_checker_.CalledOnValidThread()); |
282 DCHECK_NE(kInvalidSocket, socket_fd_); | 295 DCHECK_NE(kInvalidSocket, socket_fd_); |
283 DCHECK(!waiting_connect_); | 296 DCHECK(!waiting_connect_); |
284 CHECK(write_callback_.is_null()); | 297 CHECK(write_callback_.is_null()); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
365 } | 378 } |
366 } | 379 } |
367 | 380 |
368 void SocketPosix::DetachFromThread() { | 381 void SocketPosix::DetachFromThread() { |
369 thread_checker_.DetachFromThread(); | 382 thread_checker_.DetachFromThread(); |
370 } | 383 } |
371 | 384 |
372 void SocketPosix::OnFileCanReadWithoutBlocking(int fd) { | 385 void SocketPosix::OnFileCanReadWithoutBlocking(int fd) { |
373 TRACE_EVENT0(kNetTracingCategory, | 386 TRACE_EVENT0(kNetTracingCategory, |
374 "SocketPosix::OnFileCanReadWithoutBlocking"); | 387 "SocketPosix::OnFileCanReadWithoutBlocking"); |
375 DCHECK(!accept_callback_.is_null() || !read_callback_.is_null()); | 388 DCHECK(!accept_callback_.is_null() || !read_if_ready_callback_.is_null()); |
376 if (!accept_callback_.is_null()) { | 389 if (!accept_callback_.is_null()) { |
377 AcceptCompleted(); | 390 AcceptCompleted(); |
378 } else { // !read_callback_.is_null() | 391 } else { // !read_if_ready_callback_.is_null() |
379 ReadCompleted(); | 392 ReadCompleted(); |
380 } | 393 } |
381 } | 394 } |
382 | 395 |
383 void SocketPosix::OnFileCanWriteWithoutBlocking(int fd) { | 396 void SocketPosix::OnFileCanWriteWithoutBlocking(int fd) { |
384 DCHECK(!write_callback_.is_null()); | 397 DCHECK(!write_callback_.is_null()); |
385 if (waiting_connect_) { | 398 if (waiting_connect_) { |
386 ConnectCompleted(); | 399 ConnectCompleted(); |
387 } else { | 400 } else { |
388 WriteCompleted(); | 401 WriteCompleted(); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
443 DCHECK(ok); | 456 DCHECK(ok); |
444 waiting_connect_ = false; | 457 waiting_connect_ = false; |
445 base::ResetAndReturn(&write_callback_).Run(rv); | 458 base::ResetAndReturn(&write_callback_).Run(rv); |
446 } | 459 } |
447 | 460 |
448 int SocketPosix::DoRead(IOBuffer* buf, int buf_len) { | 461 int SocketPosix::DoRead(IOBuffer* buf, int buf_len) { |
449 int rv = HANDLE_EINTR(read(socket_fd_, buf->data(), buf_len)); | 462 int rv = HANDLE_EINTR(read(socket_fd_, buf->data(), buf_len)); |
450 return rv >= 0 ? rv : MapSystemError(errno); | 463 return rv >= 0 ? rv : MapSystemError(errno); |
451 } | 464 } |
452 | 465 |
453 void SocketPosix::ReadCompleted() { | 466 void SocketPosix::RetryRead(int rv) { |
454 int rv = DoRead(read_buf_.get(), read_buf_len_); | 467 DCHECK(read_callback_); |
455 if (rv == ERR_IO_PENDING) | 468 DCHECK(read_buf_); |
456 return; | 469 DCHECK_LT(0, read_buf_len_); |
457 | 470 |
458 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); | 471 if (rv == OK) { |
459 DCHECK(ok); | 472 rv = ReadIfReady( |
460 read_buf_ = NULL; | 473 read_buf_.get(), read_buf_len_, |
| 474 base::Bind(&SocketPosix::RetryRead, base::Unretained(this))); |
| 475 if (rv == ERR_IO_PENDING) |
| 476 return; |
| 477 } |
| 478 read_buf_ = nullptr; |
461 read_buf_len_ = 0; | 479 read_buf_len_ = 0; |
462 base::ResetAndReturn(&read_callback_).Run(rv); | 480 base::ResetAndReturn(&read_callback_).Run(rv); |
463 } | 481 } |
464 | 482 |
| 483 void SocketPosix::ReadCompleted() { |
| 484 DCHECK(read_if_ready_callback_); |
| 485 |
| 486 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); |
| 487 DCHECK(ok); |
| 488 base::ResetAndReturn(&read_if_ready_callback_).Run(OK); |
| 489 } |
| 490 |
465 int SocketPosix::DoWrite(IOBuffer* buf, int buf_len) { | 491 int SocketPosix::DoWrite(IOBuffer* buf, int buf_len) { |
466 #if defined(OS_LINUX) || defined(OS_ANDROID) | 492 #if defined(OS_LINUX) || defined(OS_ANDROID) |
467 // Disable SIGPIPE for this write. Although Chromium globally disables | 493 // Disable SIGPIPE for this write. Although Chromium globally disables |
468 // SIGPIPE, the net stack may be used in other consumers which do not do | 494 // 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 | 495 // this. MSG_NOSIGNAL is a Linux-only API. On OS X, this is a setsockopt on |
470 // socket creation. | 496 // socket creation. |
471 int rv = HANDLE_EINTR(send(socket_fd_, buf->data(), buf_len, MSG_NOSIGNAL)); | 497 int rv = HANDLE_EINTR(send(socket_fd_, buf->data(), buf_len, MSG_NOSIGNAL)); |
472 #else | 498 #else |
473 int rv = HANDLE_EINTR(write(socket_fd_, buf->data(), buf_len)); | 499 int rv = HANDLE_EINTR(write(socket_fd_, buf->data(), buf_len)); |
474 #endif | 500 #endif |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
510 write_buf_ = NULL; | 536 write_buf_ = NULL; |
511 write_buf_len_ = 0; | 537 write_buf_len_ = 0; |
512 write_callback_.Reset(); | 538 write_callback_.Reset(); |
513 } | 539 } |
514 | 540 |
515 waiting_connect_ = false; | 541 waiting_connect_ = false; |
516 peer_address_.reset(); | 542 peer_address_.reset(); |
517 } | 543 } |
518 | 544 |
519 } // namespace net | 545 } // namespace net |
OLD | NEW |