Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1456)

Side by Side Diff: net/udp/udp_socket_libevent.cc

Issue 99923004: Add support of IP_MULTICAST_IF in UDP sockets. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/udp/udp_socket_libevent.h ('k') | net/udp/udp_socket_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « net/udp/udp_socket_libevent.h ('k') | net/udp/udp_socket_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698