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 namespace net { | 35 namespace net { |
| 36 | 36 |
| 37 UDPSocketLibevent::UDPSocketLibevent( | 37 UDPSocketLibevent::UDPSocketLibevent( |
| 38 DatagramSocket::BindType bind_type, | 38 DatagramSocket::BindType bind_type, |
| 39 const RandIntCallback& rand_int_cb, | 39 const RandIntCallback& rand_int_cb, |
| 40 net::NetLog* net_log, | 40 net::NetLog* net_log, |
| 41 const net::NetLog::Source& source) | 41 const net::NetLog::Source& source) |
| 42 : socket_(kInvalidSocket), | 42 : socket_(kInvalidSocket), |
| 43 addr_family_(0), | 43 addr_family_(0), |
| 44 socket_options_(SOCKET_OPTION_MULTICAST_LOOP), | 44 socket_options_(SOCKET_OPTION_MULTICAST_LOOP), |
| 45 multicast_interface_(0), | |
| 45 multicast_time_to_live_(1), | 46 multicast_time_to_live_(1), |
| 46 bind_type_(bind_type), | 47 bind_type_(bind_type), |
| 47 rand_int_cb_(rand_int_cb), | 48 rand_int_cb_(rand_int_cb), |
| 48 read_watcher_(this), | 49 read_watcher_(this), |
| 49 write_watcher_(this), | 50 write_watcher_(this), |
| 50 read_buf_len_(0), | 51 read_buf_len_(0), |
| 51 recv_from_address_(NULL), | 52 recv_from_address_(NULL), |
| 52 write_buf_len_(0), | 53 write_buf_len_(0), |
| 53 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) { | 54 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) { |
| 54 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, | 55 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, |
| (...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 525 &ttl, sizeof(ttl)); | 526 &ttl, sizeof(ttl)); |
| 526 } else { | 527 } else { |
| 527 // Signed interger. -1 to use route default. | 528 // Signed interger. -1 to use route default. |
| 528 int ttl = multicast_time_to_live_; | 529 int ttl = multicast_time_to_live_; |
| 529 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, | 530 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, |
| 530 &ttl, sizeof(ttl)); | 531 &ttl, sizeof(ttl)); |
| 531 } | 532 } |
| 532 if (rv < 0) | 533 if (rv < 0) |
| 533 return MapSystemError(errno); | 534 return MapSystemError(errno); |
| 534 } | 535 } |
| 536 if (multicast_interface_ != 0) { | |
| 537 switch (addr_family_) { | |
| 538 case AF_INET: { | |
| 539 in_addr address; | |
| 540 address.s_addr = htonl(multicast_interface_); | |
|
Noam Samuel
2013/12/02 22:05:54
I know that the 0.x.x.x address convention for num
szym
2013/12/03 07:42:11
In Linux, IP_MULTICAST_IF option has to be one of:
| |
| 541 int rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_IF, | |
| 542 reinterpret_cast<const char*>(&address), | |
| 543 sizeof(address)); | |
| 544 if (rv) | |
| 545 return MapSystemError(errno); | |
| 546 break; | |
| 547 } | |
| 548 case AF_INET6: { | |
| 549 uint32 interface_index = multicast_interface_; | |
| 550 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_IF, | |
| 551 reinterpret_cast<const char*>(&interface_index), | |
| 552 sizeof(interface_index)); | |
| 553 if (rv) | |
| 554 return MapSystemError(errno); | |
| 555 break; | |
| 556 } | |
| 557 default: | |
| 558 NOTREACHED() << "Invalid address family"; | |
| 559 return ERR_ADDRESS_INVALID; | |
| 560 } | |
| 561 } | |
| 535 return OK; | 562 return OK; |
| 536 } | 563 } |
| 537 | 564 |
| 538 int UDPSocketLibevent::DoBind(const IPEndPoint& address) { | 565 int UDPSocketLibevent::DoBind(const IPEndPoint& address) { |
| 539 SockaddrStorage storage; | 566 SockaddrStorage storage; |
| 540 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) | 567 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) |
| 541 return ERR_ADDRESS_INVALID; | 568 return ERR_ADDRESS_INVALID; |
| 542 int rv = bind(socket_, storage.addr, storage.addr_len); | 569 int rv = bind(socket_, storage.addr, storage.addr_len); |
| 543 return rv < 0 ? MapSystemError(errno) : rv; | 570 return rv < 0 ? MapSystemError(errno) : rv; |
| 544 } | 571 } |
| 545 | 572 |
| 546 int UDPSocketLibevent::RandomBind(const IPEndPoint& address) { | 573 int UDPSocketLibevent::RandomBind(const IPEndPoint& address) { |
| 547 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null()); | 574 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null()); |
| 548 | 575 |
| 549 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s. | 576 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s. |
| 550 IPAddressNumber ip(address.address().size()); | 577 IPAddressNumber ip(address.address().size()); |
| 551 | 578 |
| 552 for (int i = 0; i < kBindRetries; ++i) { | 579 for (int i = 0; i < kBindRetries; ++i) { |
| 553 int rv = DoBind(IPEndPoint(ip, rand_int_cb_.Run(kPortStart, kPortEnd))); | 580 int rv = DoBind(IPEndPoint(ip, rand_int_cb_.Run(kPortStart, kPortEnd))); |
| 554 if (rv == OK || rv != ERR_ADDRESS_IN_USE) | 581 if (rv == OK || rv != ERR_ADDRESS_IN_USE) |
| 555 return rv; | 582 return rv; |
| 556 } | 583 } |
| 557 return DoBind(IPEndPoint(ip, 0)); | 584 return DoBind(IPEndPoint(ip, 0)); |
| 558 } | 585 } |
| 559 | 586 |
| 560 int UDPSocketLibevent::JoinGroup(const IPAddressNumber& group_address) const { | 587 int UDPSocketLibevent::JoinGroup(const IPAddressNumber& group_address) { |
| 561 DCHECK(CalledOnValidThread()); | 588 DCHECK(CalledOnValidThread()); |
| 562 if (!is_connected()) | 589 if (!is_connected()) |
| 563 return ERR_SOCKET_NOT_CONNECTED; | 590 return ERR_SOCKET_NOT_CONNECTED; |
| 564 | 591 |
| 565 switch (group_address.size()) { | 592 switch (group_address.size()) { |
| 566 case kIPv4AddressSize: { | 593 case kIPv4AddressSize: { |
| 567 if (addr_family_ != AF_INET) | 594 if (addr_family_ != AF_INET) |
| 568 return ERR_ADDRESS_INVALID; | 595 return ERR_ADDRESS_INVALID; |
| 569 ip_mreq mreq; | 596 ip_mreq mreq; |
| 570 mreq.imr_interface.s_addr = INADDR_ANY; | 597 mreq.imr_interface.s_addr = htonl(multicast_interface_); |
|
Noam Samuel
2013/12/02 22:05:54
Same question
| |
| 571 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize); | 598 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize); |
| 572 int rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP, | 599 int rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP, |
| 573 &mreq, sizeof(mreq)); | 600 &mreq, sizeof(mreq)); |
| 574 if (rv < 0) | 601 if (rv < 0) |
| 575 return MapSystemError(errno); | 602 return MapSystemError(errno); |
| 576 return OK; | 603 return OK; |
| 577 } | 604 } |
| 578 case kIPv6AddressSize: { | 605 case kIPv6AddressSize: { |
| 579 if (addr_family_ != AF_INET6) | 606 if (addr_family_ != AF_INET6) |
| 580 return ERR_ADDRESS_INVALID; | 607 return ERR_ADDRESS_INVALID; |
| 581 ipv6_mreq mreq; | 608 ipv6_mreq mreq; |
| 582 mreq.ipv6mr_interface = 0; // 0 indicates default multicast interface. | 609 mreq.ipv6mr_interface = multicast_interface_; |
| 583 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize); | 610 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize); |
| 584 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_JOIN_GROUP, | 611 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_JOIN_GROUP, |
| 585 &mreq, sizeof(mreq)); | 612 &mreq, sizeof(mreq)); |
| 586 if (rv < 0) | 613 if (rv < 0) |
| 587 return MapSystemError(errno); | 614 return MapSystemError(errno); |
| 588 return OK; | 615 return OK; |
| 589 } | 616 } |
| 590 default: | 617 default: |
| 591 NOTREACHED() << "Invalid address family"; | 618 NOTREACHED() << "Invalid address family"; |
| 592 return ERR_ADDRESS_INVALID; | 619 return ERR_ADDRESS_INVALID; |
| 593 } | 620 } |
| 594 } | 621 } |
| 595 | 622 |
| 596 int UDPSocketLibevent::LeaveGroup(const IPAddressNumber& group_address) const { | 623 int UDPSocketLibevent::LeaveGroup(const IPAddressNumber& group_address) { |
| 597 DCHECK(CalledOnValidThread()); | 624 DCHECK(CalledOnValidThread()); |
| 598 | 625 |
| 599 if (!is_connected()) | 626 if (!is_connected()) |
| 600 return ERR_SOCKET_NOT_CONNECTED; | 627 return ERR_SOCKET_NOT_CONNECTED; |
| 601 | 628 |
| 602 switch (group_address.size()) { | 629 switch (group_address.size()) { |
| 603 case kIPv4AddressSize: { | 630 case kIPv4AddressSize: { |
| 604 if (addr_family_ != AF_INET) | 631 if (addr_family_ != AF_INET) |
| 605 return ERR_ADDRESS_INVALID; | 632 return ERR_ADDRESS_INVALID; |
| 606 ip_mreq mreq; | 633 ip_mreq mreq; |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 623 if (rv < 0) | 650 if (rv < 0) |
| 624 return MapSystemError(errno); | 651 return MapSystemError(errno); |
| 625 return OK; | 652 return OK; |
| 626 } | 653 } |
| 627 default: | 654 default: |
| 628 NOTREACHED() << "Invalid address family"; | 655 NOTREACHED() << "Invalid address family"; |
| 629 return ERR_ADDRESS_INVALID; | 656 return ERR_ADDRESS_INVALID; |
| 630 } | 657 } |
| 631 } | 658 } |
| 632 | 659 |
| 660 int UDPSocketLibevent::SetMulticastInterface(uint32 interface_index) { | |
| 661 DCHECK(CalledOnValidThread()); | |
| 662 if (is_connected()) | |
| 663 return ERR_SOCKET_IS_CONNECTED; | |
| 664 multicast_interface_ = interface_index; | |
| 665 return OK; | |
| 666 } | |
| 667 | |
| 633 int UDPSocketLibevent::SetMulticastTimeToLive(int time_to_live) { | 668 int UDPSocketLibevent::SetMulticastTimeToLive(int time_to_live) { |
| 634 DCHECK(CalledOnValidThread()); | 669 DCHECK(CalledOnValidThread()); |
| 635 if (is_connected()) | 670 if (is_connected()) |
| 636 return ERR_SOCKET_IS_CONNECTED; | 671 return ERR_SOCKET_IS_CONNECTED; |
| 637 | 672 |
| 638 if (time_to_live < 0 || time_to_live > 255) | 673 if (time_to_live < 0 || time_to_live > 255) |
| 639 return ERR_INVALID_ARGUMENT; | 674 return ERR_INVALID_ARGUMENT; |
| 640 multicast_time_to_live_ = time_to_live; | 675 multicast_time_to_live_ = time_to_live; |
| 641 return OK; | 676 return OK; |
| 642 } | 677 } |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 666 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_TCLASS, | 701 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_TCLASS, |
| 667 &dscp_and_ecn, sizeof(dscp_and_ecn)); | 702 &dscp_and_ecn, sizeof(dscp_and_ecn)); |
| 668 } | 703 } |
| 669 if (rv < 0) | 704 if (rv < 0) |
| 670 return MapSystemError(errno); | 705 return MapSystemError(errno); |
| 671 | 706 |
| 672 return OK; | 707 return OK; |
| 673 } | 708 } |
| 674 | 709 |
| 675 } // namespace net | 710 } // namespace net |
| OLD | NEW |