Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/udp/udp_socket_libevent.h" | 5 #include "net/udp/udp_socket_libevent.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <netdb.h> | 9 #include <netdb.h> |
| 10 #include <sys/socket.h> | 10 #include <sys/socket.h> |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 35 | 35 |
| 36 namespace net { | 36 namespace net { |
| 37 | 37 |
| 38 UDPSocketLibevent::UDPSocketLibevent( | 38 UDPSocketLibevent::UDPSocketLibevent( |
| 39 DatagramSocket::BindType bind_type, | 39 DatagramSocket::BindType bind_type, |
| 40 const RandIntCallback& rand_int_cb, | 40 const RandIntCallback& rand_int_cb, |
| 41 net::NetLog* net_log, | 41 net::NetLog* net_log, |
| 42 const net::NetLog::Source& source) | 42 const net::NetLog::Source& source) |
| 43 : socket_(kInvalidSocket), | 43 : socket_(kInvalidSocket), |
| 44 socket_options_(0), | 44 socket_options_(0), |
| 45 multicast_time_to_live_(1), | |
| 46 multicast_loopback_mode_(true), | |
| 45 bind_type_(bind_type), | 47 bind_type_(bind_type), |
| 46 rand_int_cb_(rand_int_cb), | 48 rand_int_cb_(rand_int_cb), |
| 47 read_watcher_(this), | 49 read_watcher_(this), |
| 48 write_watcher_(this), | 50 write_watcher_(this), |
| 49 read_buf_len_(0), | 51 read_buf_len_(0), |
| 50 recv_from_address_(NULL), | 52 recv_from_address_(NULL), |
| 51 write_buf_len_(0), | 53 write_buf_len_(0), |
| 52 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) { | 54 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) { |
| 53 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, | 55 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, |
| 54 source.ToEventParametersCallback()); | 56 source.ToEventParametersCallback()); |
| (...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 356 CreateNetLogUDPDataTranferCallback( | 358 CreateNetLogUDPDataTranferCallback( |
| 357 result, bytes, | 359 result, bytes, |
| 358 is_address_valid ? &address : NULL)); | 360 is_address_valid ? &address : NULL)); |
| 359 } | 361 } |
| 360 | 362 |
| 361 base::StatsCounter read_bytes("udp.read_bytes"); | 363 base::StatsCounter read_bytes("udp.read_bytes"); |
| 362 read_bytes.Add(result); | 364 read_bytes.Add(result); |
| 363 } | 365 } |
| 364 | 366 |
| 365 int UDPSocketLibevent::CreateSocket(const IPEndPoint& address) { | 367 int UDPSocketLibevent::CreateSocket(const IPEndPoint& address) { |
| 366 socket_ = socket(address.GetSockAddrFamily(), SOCK_DGRAM, 0); | 368 sock_addr_family_ = address.GetSockAddrFamily(); |
| 369 socket_ = socket(sock_addr_family_, SOCK_DGRAM, 0); | |
| 367 if (socket_ == kInvalidSocket) | 370 if (socket_ == kInvalidSocket) |
| 368 return MapSystemError(errno); | 371 return MapSystemError(errno); |
| 369 if (SetNonBlocking(socket_)) { | 372 if (SetNonBlocking(socket_)) { |
| 370 const int err = MapSystemError(errno); | 373 const int err = MapSystemError(errno); |
| 371 Close(); | 374 Close(); |
| 372 return err; | 375 return err; |
| 373 } | 376 } |
| 374 return OK; | 377 return OK; |
| 375 } | 378 } |
| 376 | 379 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 469 return MapSystemError(errno); | 472 return MapSystemError(errno); |
| 470 } | 473 } |
| 471 if (socket_options_ & SOCKET_OPTION_BROADCAST) { | 474 if (socket_options_ & SOCKET_OPTION_BROADCAST) { |
| 472 int rv; | 475 int rv; |
| 473 #if defined(OS_MACOSX) | 476 #if defined(OS_MACOSX) |
| 474 // SO_REUSEPORT on OSX permits multiple processes to each receive | 477 // SO_REUSEPORT on OSX permits multiple processes to each receive |
| 475 // UDP multicast or broadcast datagrams destined for the bound | 478 // UDP multicast or broadcast datagrams destined for the bound |
| 476 // port. | 479 // port. |
| 477 rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEPORT, &true_value, | 480 rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEPORT, &true_value, |
| 478 sizeof(true_value)); | 481 sizeof(true_value)); |
| 479 if (rv < 0) | 482 #else |
| 480 return MapSystemError(errno); | 483 rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &true_value, |
|
mmenke
2013/04/12 21:07:41
Why get rid of this?
Bei Zhang
2013/04/15 22:30:26
I simply moved this out side of the #if to elimina
| |
| 484 sizeof(true_value)); | |
|
mmenke
2013/04/12 21:07:41
I don't think we need to do this twice on platform
Bei Zhang
2013/04/15 22:30:26
Done.
| |
| 481 #endif // defined(OS_MACOSX) | 485 #endif // defined(OS_MACOSX) |
| 482 rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &true_value, | 486 rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &true_value, |
| 483 sizeof(true_value)); | 487 sizeof(true_value)); |
| 484 if (rv < 0) | 488 if (rv < 0) |
| 485 return MapSystemError(errno); | 489 return MapSystemError(errno); |
| 486 } | 490 } |
| 491 if (multicast_time_to_live_ != 1) { | |
| 492 int rv = SetMulticastTimeToLive(multicast_time_to_live_); | |
| 493 if (rv != OK) | |
| 494 return rv; | |
| 495 } | |
| 496 if (!multicast_loopback_mode_) { | |
| 497 int rv = SetMulticastLoopbackMode(multicast_loopback_mode_); | |
| 498 if (rv != OK) | |
| 499 return rv; | |
| 500 } | |
| 487 return OK; | 501 return OK; |
| 488 } | 502 } |
| 489 | 503 |
| 490 int UDPSocketLibevent::DoBind(const IPEndPoint& address) { | 504 int UDPSocketLibevent::DoBind(const IPEndPoint& address) { |
| 491 SockaddrStorage storage; | 505 SockaddrStorage storage; |
| 492 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) | 506 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) |
| 493 return ERR_UNEXPECTED; | 507 return ERR_UNEXPECTED; |
| 494 int rv = bind(socket_, storage.addr, storage.addr_len); | 508 int rv = bind(socket_, storage.addr, storage.addr_len); |
| 495 return rv < 0 ? MapSystemError(errno) : rv; | 509 return rv < 0 ? MapSystemError(errno) : rv; |
| 496 } | 510 } |
| 497 | 511 |
| 498 int UDPSocketLibevent::RandomBind(const IPEndPoint& address) { | 512 int UDPSocketLibevent::RandomBind(const IPEndPoint& address) { |
| 499 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null()); | 513 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null()); |
| 500 | 514 |
| 501 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s. | 515 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s. |
| 502 IPAddressNumber ip(address.address().size()); | 516 IPAddressNumber ip(address.address().size()); |
| 503 | 517 |
| 504 for (int i = 0; i < kBindRetries; ++i) { | 518 for (int i = 0; i < kBindRetries; ++i) { |
| 505 int rv = DoBind(IPEndPoint(ip, rand_int_cb_.Run(kPortStart, kPortEnd))); | 519 int rv = DoBind(IPEndPoint(ip, rand_int_cb_.Run(kPortStart, kPortEnd))); |
| 506 if (rv == OK || rv != ERR_ADDRESS_IN_USE) | 520 if (rv == OK || rv != ERR_ADDRESS_IN_USE) |
| 507 return rv; | 521 return rv; |
| 508 } | 522 } |
| 509 return DoBind(IPEndPoint(ip, 0)); | 523 return DoBind(IPEndPoint(ip, 0)); |
| 510 } | 524 } |
| 511 | 525 |
| 526 int UDPSocketLibevent::JoinGroup( | |
| 527 const net::IPAddressNumber& group_address) const { | |
| 528 DCHECK(CalledOnValidThread()); | |
| 529 DCHECK(is_connected()); | |
| 530 | |
| 531 int rv = -1; | |
| 532 switch(group_address.size()) { | |
|
mmenke
2013/04/12 21:07:41
Space after switch.
Bei Zhang
2013/04/15 22:30:26
Done.
| |
| 533 case kIPv4AddressSize: { | |
| 534 if (sock_addr_family_ != AF_INET) { | |
| 535 return ERR_ADDRESS_INVALID; | |
| 536 } | |
|
mmenke
2013/04/12 21:07:41
Braces are generally discouraged in single line if
Bei Zhang
2013/04/15 22:30:26
Done.
| |
| 537 ip_mreq mreq; | |
| 538 memset(&mreq, 0, sizeof(mreq)); | |
| 539 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize); | |
| 540 rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP, | |
| 541 &mreq, sizeof(mreq)); | |
| 542 break; | |
| 543 } | |
| 544 case kIPv6AddressSize: { | |
| 545 if (sock_addr_family_ != AF_INET6) { | |
| 546 return ERR_ADDRESS_INVALID; | |
| 547 } | |
| 548 ipv6_mreq mreq; | |
| 549 memset(&mreq, 0, sizeof(mreq)); | |
| 550 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize); | |
| 551 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_JOIN_GROUP, | |
| 552 &mreq, sizeof(mreq)); | |
| 553 break; | |
| 554 } | |
| 555 } | |
| 556 | |
| 557 return MapSystemError(rv); | |
| 558 } | |
| 559 | |
| 560 int UDPSocketLibevent::LeaveGroup( | |
| 561 const net::IPAddressNumber& group_address) const { | |
| 562 DCHECK(CalledOnValidThread()); | |
| 563 DCHECK(is_connected()); | |
| 564 | |
| 565 int rv = -1; | |
| 566 switch(group_address.size()) { | |
| 567 case kIPv4AddressSize: { | |
| 568 if (sock_addr_family_ != AF_INET) { | |
| 569 return ERR_ADDRESS_INVALID; | |
| 570 } | |
| 571 ip_mreq mreq; | |
| 572 memset(&mreq, 0, sizeof(mreq)); | |
| 573 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize); | |
| 574 rv = setsockopt(socket_, IPPROTO_IP, IP_DROP_MEMBERSHIP, | |
| 575 &mreq, sizeof(mreq)); | |
|
mmenke
2013/04/12 21:07:41
Fix indent.
Bei Zhang
2013/04/15 22:30:26
Done.
| |
| 576 break; | |
| 577 } | |
| 578 case kIPv6AddressSize: { | |
| 579 if (sock_addr_family_ != AF_INET6) { | |
| 580 return ERR_ADDRESS_INVALID; | |
| 581 } | |
| 582 ipv6_mreq mreq; | |
| 583 memset(&mreq, 0, sizeof(mreq)); | |
| 584 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize); | |
| 585 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_LEAVE_GROUP, | |
| 586 &mreq, sizeof(mreq)); | |
|
mmenke
2013/04/12 21:07:41
Fix indent.
Bei Zhang
2013/04/15 22:30:26
Done.
| |
| 587 break; | |
| 588 } | |
| 589 } | |
| 590 | |
| 591 return MapSystemError(rv); | |
| 592 } | |
| 593 | |
| 594 int UDPSocketLibevent::SetMulticastTimeToLive(int timeToLive) { | |
|
mmenke
2013/04/12 21:07:41
Rename, per comment in header.
Bei Zhang
2013/04/15 22:30:26
Done.
| |
| 595 DCHECK(CalledOnValidThread()); | |
| 596 if (timeToLive < 0 || timeToLive > 255) { | |
| 597 return ERR_INVALID_ARGUMENT; | |
| 598 } | |
| 599 if(is_connected()) { | |
|
mmenke
2013/04/12 21:07:41
Space after if.
Bei Zhang
2013/04/15 22:30:26
Done.
| |
| 600 uint8 ttl = timeToLive; | |
| 601 int ip_family = sock_addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; | |
| 602 return MapSystemError(setsockopt(socket_, | |
| 603 ip_family, | |
| 604 IP_MULTICAST_TTL, | |
| 605 &ttl, sizeof(ttl))); | |
| 606 } else { | |
| 607 multicast_time_to_live_ = timeToLive; | |
| 608 return OK; | |
| 609 } | |
| 610 } | |
| 611 | |
| 612 int UDPSocketLibevent::SetMulticastLoopbackMode(bool loopback) { | |
| 613 DCHECK(CalledOnValidThread()); | |
| 614 if(is_connected()) { | |
|
mmenke
2013/04/12 21:07:41
Space after if.
Bei Zhang
2013/04/15 22:30:26
Done.
| |
| 615 uint8 loop = loopback; | |
| 616 int ip_family = sock_addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; | |
| 617 return MapSystemError(setsockopt(socket_, | |
| 618 ip_family, | |
| 619 IP_MULTICAST_LOOP, | |
| 620 &loop, sizeof(loop))); | |
| 621 } else { | |
| 622 multicast_loopback_mode_ = loopback; | |
| 623 return OK; | |
| 624 } | |
| 625 } | |
| 512 } // namespace net | 626 } // namespace net |
| OLD | NEW |