diff options
author | Benoit Foucher <benoit@zeroc.com> | 2017-01-23 15:39:06 +0100 |
---|---|---|
committer | Benoit Foucher <benoit@zeroc.com> | 2017-01-23 15:39:06 +0100 |
commit | 91bdb2c1b221a5ddcb6d9ec28e41ee1beffd5508 (patch) | |
tree | 021d4d7f93712e5ea29542f88470401a4955ba27 /cpp/src/Ice | |
parent | Fixed ICE-7517 - Objective-C build failure (diff) | |
download | ice-91bdb2c1b221a5ddcb6d9ec28e41ee1beffd5508.tar.bz2 ice-91bdb2c1b221a5ddcb6d9ec28e41ee1beffd5508.tar.xz ice-91bdb2c1b221a5ddcb6d9ec28e41ee1beffd5508.zip |
Fixed multicast to also listen on link-locap IPv6 addressees
Diffstat (limited to 'cpp/src/Ice')
-rwxr-xr-x | cpp/src/Ice/Network.cpp | 95 | ||||
-rwxr-xr-x | cpp/src/Ice/Network.h | 1 | ||||
-rwxr-xr-x | cpp/src/Ice/UdpTransceiver.cpp | 11 |
3 files changed, 79 insertions, 28 deletions
diff --git a/cpp/src/Ice/Network.cpp b/cpp/src/Ice/Network.cpp index e98aa790f22..10c4739cb72 100755 --- a/cpp/src/Ice/Network.cpp +++ b/cpp/src/Ice/Network.cpp @@ -513,31 +513,45 @@ isWildcard(const string& host, ProtocolSupport protocol, bool& ipv4) } int -getInterfaceIndex(const string& name) +getInterfaceIndex(const string& intf) { - if(name.empty()) + if(intf.empty()) { return 0; } - int index = -1; + string name; + bool isAddr; + in6_addr addr; + string::size_type pos = intf.find("%"); + if(pos != string::npos) + { + // + // If it's a link-local address, use the zone indice. + // + isAddr = false; + name = intf.substr(pos + 1); + } + else + { + // + // Then check if it's an IPv6 address. If it's an address we'll + // look for the interface index by address. + // + isAddr = inet_pton(AF_INET6, intf.c_str(), &addr) > 0; + name = intf; + } // - // First check if index + // Check if index // + int index = -1; istringstream p(name); if((p >> index) && p.eof()) { return index; } - // - // Then check if it's an IPv6 address. If it's an address we'll - // look for the interface index by address. - // - in6_addr addr; - bool isAddr = inet_pton(AF_INET6, name.c_str(), &addr) > 0; - #ifdef _WIN32 IP_ADAPTER_ADDRESSES addrs; ULONG buflen = 0; @@ -1627,8 +1641,7 @@ IceInternal::getHostsForEndpointExpand(const string& host, ProtocolSupport proto HostName^ h = it->Current; if(h->IPInformation != nullptr && h->IPInformation->NetworkAdapter != nullptr) { - hosts.push_back(wstringToString(h->CanonicalName->Data(), - getProcessStringConverter())); + hosts.push_back(wstringToString(h->CanonicalName->Data(), getProcessStringConverter())); } } if(includeLoopback) @@ -1645,6 +1658,18 @@ IceInternal::getHostsForEndpointExpand(const string& host, ProtocolSupport proto } return hosts; } + +vector<string> +IceInternal::getInterfacesForMulticast(const string& interface, const Address& mcastAddr) +{ + int protocolSupport = getProtocolSupport(mcastAddr); + vector<string> interfaces = getHostsForEndpointExpand(interface, protocolSupport, true); + if(interfaces.empty()) + { + interfaces.push_back(interface); + } + return interfaces; +} #else vector<string> IceInternal::getHostsForEndpointExpand(const string& host, ProtocolSupport protocolSupport, bool includeLoopback) @@ -1669,6 +1694,27 @@ IceInternal::getHostsForEndpointExpand(const string& host, ProtocolSupport proto } return hosts; // An empty host list indicates to just use the given host. } + +vector<string> +IceInternal::getInterfacesForMulticast(const string& interface, const Address& mcastAddr) +{ + ProtocolSupport protocolSupport = getProtocolSupport(mcastAddr); + vector<string> interfaces; + bool ipv4Wildcard = false; + if(isWildcard(interface, protocolSupport, ipv4Wildcard)) + { + vector<Address> addrs = getLocalAddresses(ipv4Wildcard ? EnableIPv4 : protocolSupport, true); + for(vector<Address>::const_iterator p = addrs.begin(); p != addrs.end(); ++p) + { + interfaces.push_back(inetAddrToString(*p)); // We keep link local addresses for multicast + } + } + if(interfaces.empty()) + { + interfaces.push_back(interface); + } + return interfaces; +} #endif string @@ -2019,15 +2065,11 @@ IceInternal::getRecvBufferSize(SOCKET fd) void IceInternal::setMcastGroup(SOCKET fd, const Address& group, const string& intf) { - vector<string> interfaces = getHostsForEndpointExpand(intf, getProtocolSupport(group), true); - if(interfaces.empty()) - { - interfaces.push_back(intf); - } - + vector<string> interfaces = getInterfacesForMulticast(intf, group); + set<int> indexes; for(vector<string>::const_iterator p = interfaces.begin(); p != interfaces.end(); ++p) { - int rc; + int rc = 0; if(group.saStorage.ss_family == AF_INET) { struct ip_mreq mreq; @@ -2037,10 +2079,15 @@ IceInternal::setMcastGroup(SOCKET fd, const Address& group, const string& intf) } else { - struct ipv6_mreq mreq; - mreq.ipv6mr_multiaddr = group.saIn6.sin6_addr; - mreq.ipv6mr_interface = getInterfaceIndex(*p); - rc = setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, reinterpret_cast<char*>(&mreq), int(sizeof(mreq))); + int index = getInterfaceIndex(*p); + if(indexes.find(index) == indexes.end()) // Don't join twice the same interface (if it has multiple IPs) + { + indexes.insert(index); + struct ipv6_mreq mreq; + mreq.ipv6mr_multiaddr = group.saIn6.sin6_addr; + mreq.ipv6mr_interface = index; + rc = setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, reinterpret_cast<char*>(&mreq), int(sizeof(mreq))); + } } if(rc == SOCKET_ERROR) { diff --git a/cpp/src/Ice/Network.h b/cpp/src/Ice/Network.h index 788470f2708..ccf05b74663 100755 --- a/cpp/src/Ice/Network.h +++ b/cpp/src/Ice/Network.h @@ -284,6 +284,7 @@ ICE_API std::string addressesToString(const Address&, const Address&, bool); ICE_API bool isAddressValid(const Address&); ICE_API std::vector<std::string> getHostsForEndpointExpand(const std::string&, ProtocolSupport, bool); +ICE_API std::vector<std::string> getInterfacesForMulticast(const std::string&, const Address&); ICE_API std::string inetAddrToString(const Address&); ICE_API int getPort(const Address&); diff --git a/cpp/src/Ice/UdpTransceiver.cpp b/cpp/src/Ice/UdpTransceiver.cpp index b4f5520c184..9d32c38938e 100755 --- a/cpp/src/Ice/UdpTransceiver.cpp +++ b/cpp/src/Ice/UdpTransceiver.cpp @@ -771,11 +771,14 @@ IceInternal::UdpTransceiver::toDetailedString() const { ostringstream os; os << toString(); - string addr = isAddressValid(_mcastAddr) ? _mcastInterface : inetAddrToString(_addr); - vector<string> intfs = getHostsForEndpointExpand(addr, _instance->protocolSupport(), true); - if(isAddressValid(_mcastAddr) && intfs.empty()) + vector<string> intfs; + if(isAddressValid(_mcastAddr)) + { + intfs = getInterfacesForMulticast(_mcastInterface, _mcastAddr); + } + else { - intfs.push_back(_mcastInterface); + intfs = getHostsForEndpointExpand(inetAddrToString(_addr), _instance->protocolSupport(), true); } if(!intfs.empty()) { |