diff options
-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 | ||||
-rw-r--r-- | csharp/src/Ice/Network.cs | 115 | ||||
-rw-r--r-- | csharp/src/Ice/UdpTransceiver.cs | 12 | ||||
-rw-r--r-- | java-compat/src/Ice/src/main/java/IceInternal/Network.java | 82 | ||||
-rw-r--r-- | java-compat/src/Ice/src/main/java/IceInternal/UdpTransceiver.java | 12 | ||||
-rw-r--r-- | java/src/Ice/src/main/java/com/zeroc/IceInternal/Network.java | 82 | ||||
-rw-r--r-- | java/src/Ice/src/main/java/com/zeroc/IceInternal/UdpTransceiver.java | 12 |
9 files changed, 292 insertions, 130 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()) { diff --git a/csharp/src/Ice/Network.cs b/csharp/src/Ice/Network.cs index 2d410d6a944..be375cc0526 100644 --- a/csharp/src/Ice/Network.cs +++ b/csharp/src/Ice/Network.cs @@ -456,40 +456,39 @@ namespace IceInternal { try { - int protocolSupport = group.AddressFamily == AddressFamily.InterNetwork ? EnableIPv4 : EnableIPv6; - List<string> interfaces = getHostsForEndpointExpand(iface, protocolSupport, true); - if(interfaces.Count == 0) - { - interfaces.Add(iface); - } - foreach(string intf in interfaces) + var indexes = new HashSet<int>(); + foreach(string intf in getInterfacesForMulticast(iface, group)) { int index = getInterfaceIndex(intf, group.AddressFamily); - if(group.AddressFamily == AddressFamily.InterNetwork) + if(!indexes.Contains(index)) { - MulticastOption option; - if(index == -1) - { - option = new MulticastOption(group); - } - else + indexes.Add(index); + if(group.AddressFamily == AddressFamily.InterNetwork) { - option = new MulticastOption(group, index); - } - s.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, option); - } - else - { - IPv6MulticastOption option; - if(index == -1) - { - option = new IPv6MulticastOption(group); + MulticastOption option; + if(index == -1) + { + option = new MulticastOption(group); + } + else + { + option = new MulticastOption(group, index); + } + s.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, option); } else { - option = new IPv6MulticastOption(group, index); + IPv6MulticastOption option; + if(index == -1) + { + option = new IPv6MulticastOption(group); + } + else + { + option = new IPv6MulticastOption(group, index); + } + s.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.AddMembership, option); } - s.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.AddMembership, option); } } } @@ -936,23 +935,9 @@ namespace IceInternal public static List<string> getHostsForEndpointExpand(string host, int protocol, bool includeLoopback) { - bool wildcard = host.Length == 0; - bool ipv4Wildcard = false; - if(!wildcard) - { - try - { - IPAddress addr = IPAddress.Parse(host); - ipv4Wildcard = addr.Equals(IPAddress.Any); - wildcard = ipv4Wildcard || addr.Equals(IPAddress.IPv6Any); - } - catch(Exception) - { - } - } - List<string> hosts = new List<string>(); - if(wildcard) + bool ipv4Wildcard = false; + if(isWildcard(host, out ipv4Wildcard)) { IPAddress[] addrs = getLocalAddresses(ipv4Wildcard ? EnableIPv4 : protocol, includeLoopback); foreach(IPAddress a in addrs) @@ -966,6 +951,26 @@ namespace IceInternal return hosts; } + public static List<string> getInterfacesForMulticast(string intf, IPAddress group) + { + List<string> interfaces = new List<string>(); + bool ipv4Wildcard = false; + int protocol = group.AddressFamily == AddressFamily.InterNetwork ? EnableIPv4 : EnableIPv6; + if(isWildcard(intf, out ipv4Wildcard)) + { + IPAddress[] addrs = getLocalAddresses(ipv4Wildcard ? EnableIPv4 : protocol, true); + foreach(IPAddress a in addrs) + { + interfaces.Add(a.ToString()); + } + } + if(interfaces.Count == 0) + { + interfaces.Add(intf); + } + return interfaces; + } + public static string fdToString(Socket socket, NetworkProxy proxy, EndPoint target) { try @@ -1181,6 +1186,32 @@ namespace IceInternal return addr; } + private static bool + isWildcard(string address, out bool ipv4Wildcard) + { + ipv4Wildcard = false; + if(address.Length == 0) + { + return true; + } + + try + { + IPAddress addr = IPAddress.Parse(address); + if(addr.Equals(IPAddress.Any)) + { + ipv4Wildcard = true; + return true; + } + return addr.Equals(IPAddress.IPv6Any); + } + catch(Exception) + { + } + + return false; + } + public static bool addressEquals(EndPoint addr1, EndPoint addr2) { diff --git a/csharp/src/Ice/UdpTransceiver.cs b/csharp/src/Ice/UdpTransceiver.cs index 05f569c7b40..00a5e0d10dc 100644 --- a/csharp/src/Ice/UdpTransceiver.cs +++ b/csharp/src/Ice/UdpTransceiver.cs @@ -652,11 +652,15 @@ namespace IceInternal public string toDetailedString() { StringBuilder s = new StringBuilder(ToString()); - string addr = _mcastAddr != null ? _mcastInterface : Network.endpointAddressToString(_addr); - List<string> intfs = Network.getHostsForEndpointExpand(addr, _instance.protocolSupport(), true); - if(_mcastAddr != null && intfs.Count == 0) + List<string> intfs; + if(_mcastAddr == null) { - intfs.Add(_mcastInterface); + intfs = Network.getHostsForEndpointExpand(Network.endpointAddressToString(_addr), + _instance.protocolSupport(), true); + } + else + { + intfs = Network.getInterfacesForMulticast(_mcastInterface, _mcastAddr.Address); } if(intfs.Count != 0) { diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Network.java b/java-compat/src/Ice/src/main/java/IceInternal/Network.java index 7ee1da0cf58..9a96429a68c 100644 --- a/java-compat/src/Ice/src/main/java/IceInternal/Network.java +++ b/java-compat/src/Ice/src/main/java/IceInternal/Network.java @@ -297,14 +297,15 @@ public final class Network { try { - java.util.List<String> interfaces = getHostsForEndpointExpand(intf, getProtocolSupport(group), true); - if(interfaces.isEmpty()) + java.util.Set<java.net.NetworkInterface> interfaces = new java.util.HashSet<>(); + for(String address : getInterfacesForMulticast(intf, group)) { - interfaces.add(intf); - } - for(String intf2 : interfaces) - { - fd.join(group.getAddress(), getInterface(intf2)); + java.net.NetworkInterface intf2 = getInterface(address); + if(!interfaces.contains(intf2)) + { + interfaces.add(intf2); + fd.join(group.getAddress(), intf2); + } } } catch(Exception ex) @@ -1021,24 +1022,8 @@ public final class Network public static java.util.ArrayList<String> getHostsForEndpointExpand(String host, int protocolSupport, boolean includeLoopback) { - boolean wildcard = (host == null || host.length() == 0); - if(!wildcard) - { - try - { - wildcard = java.net.InetAddress.getByName(host).isAnyLocalAddress(); - } - catch(java.net.UnknownHostException ex) - { - } - catch(java.lang.SecurityException ex) - { - throw new Ice.SocketException(ex); - } - } - java.util.ArrayList<String> hosts = new java.util.ArrayList<String>(); - if(wildcard) + if(isWildcard(host)) { java.util.ArrayList<java.net.InetAddress> addrs = getLocalAddresses(protocolSupport); for(java.net.InetAddress addr : addrs) @@ -1069,6 +1054,34 @@ public final class Network return hosts; } + public static java.util.ArrayList<String> + getInterfacesForMulticast(String intf, java.net.InetSocketAddress mcastAddr) + { + int protocolSupport = getProtocolSupport(mcastAddr); + java.util.ArrayList<String> interfaces = new java.util.ArrayList<>(); + if(isWildcard(intf)) + { + java.util.ArrayList<java.net.InetAddress> addrs = getLocalAddresses(protocolSupport); + for(java.net.InetAddress addr : addrs) + { + interfaces.add(addr.getHostAddress()); + } + if(protocolSupport != EnableIPv6) + { + interfaces.add("127.0.0.1"); + } + if(protocolSupport != EnableIPv4) + { + interfaces.add("0:0:0:0:0:0:0:1"); + } + } + if(interfaces.isEmpty()) + { + interfaces.add(intf); + } + return interfaces; + } + public static void setTcpBufSize(java.nio.channels.SocketChannel socket, ProtocolInstance instance) { @@ -1402,6 +1415,27 @@ public final class Network return addr; } + private static boolean + isWildcard(String host) + { + if(host == null || host.length() == 0) + { + return true; + } + try + { + return java.net.InetAddress.getByName(host).isAnyLocalAddress(); + } + catch(java.net.UnknownHostException ex) + { + } + catch(java.lang.SecurityException ex) + { + throw new Ice.SocketException(ex); + } + return false; + } + static class IPAddressComparator implements java.util.Comparator<java.net.InetSocketAddress> { IPAddressComparator(boolean ipv6) diff --git a/java-compat/src/Ice/src/main/java/IceInternal/UdpTransceiver.java b/java-compat/src/Ice/src/main/java/IceInternal/UdpTransceiver.java index fe6f67d295e..f6fceb03c6a 100644 --- a/java-compat/src/Ice/src/main/java/IceInternal/UdpTransceiver.java +++ b/java-compat/src/Ice/src/main/java/IceInternal/UdpTransceiver.java @@ -282,11 +282,15 @@ final class UdpTransceiver implements Transceiver public String toDetailedString() { StringBuilder s = new StringBuilder(toString()); - String addr = _mcastAddr != null ? _mcastInterface : _addr.getAddress().getHostAddress(); - java.util.List<String> intfs = Network.getHostsForEndpointExpand(addr, _instance.protocolSupport(), true); - if(_mcastAddr != null && intfs.isEmpty()) + java.util.List<String> intfs; + if(_mcastAddr == null) { - intfs.add(_mcastInterface); + intfs = Network.getHostsForEndpointExpand(_addr.getAddress().getHostAddress(), _instance.protocolSupport(), + true); + } + else + { + intfs = Network.getInterfacesForMulticast(_mcastInterface, _mcastAddr); } if(!intfs.isEmpty()) { diff --git a/java/src/Ice/src/main/java/com/zeroc/IceInternal/Network.java b/java/src/Ice/src/main/java/com/zeroc/IceInternal/Network.java index 9a0a8a72538..acbba6dccf2 100644 --- a/java/src/Ice/src/main/java/com/zeroc/IceInternal/Network.java +++ b/java/src/Ice/src/main/java/com/zeroc/IceInternal/Network.java @@ -302,14 +302,15 @@ public final class Network { try { - java.util.List<String> interfaces = getHostsForEndpointExpand(intf, getProtocolSupport(group), true); - if(interfaces.isEmpty()) + java.util.Set<java.net.NetworkInterface> interfaces = new java.util.HashSet<>(); + for(String address : getInterfacesForMulticast(intf, group)) { - interfaces.add(intf); - } - for(String intf2 : interfaces) - { - fd.join(group.getAddress(), getInterface(intf2)); + java.net.NetworkInterface intf2 = getInterface(address); + if(!interfaces.contains(intf2)) + { + interfaces.add(intf2); + fd.join(group.getAddress(), intf2); + } } } catch(Exception ex) @@ -1026,24 +1027,8 @@ public final class Network public static java.util.ArrayList<String> getHostsForEndpointExpand(String host, int protocolSupport, boolean includeLoopback) { - boolean wildcard = (host == null || host.length() == 0); - if(!wildcard) - { - try - { - wildcard = java.net.InetAddress.getByName(host).isAnyLocalAddress(); - } - catch(java.net.UnknownHostException ex) - { - } - catch(java.lang.SecurityException ex) - { - throw new SocketException(ex); - } - } - java.util.ArrayList<String> hosts = new java.util.ArrayList<>(); - if(wildcard) + if(isWildcard(host)) { java.util.ArrayList<java.net.InetAddress> addrs = getLocalAddresses(protocolSupport); for(java.net.InetAddress addr : addrs) @@ -1074,6 +1059,34 @@ public final class Network return hosts; } + public static java.util.ArrayList<String> + getInterfacesForMulticast(String intf, java.net.InetSocketAddress mcastAddr) + { + int protocolSupport = getProtocolSupport(mcastAddr); + java.util.ArrayList<String> interfaces = new java.util.ArrayList<>(); + if(isWildcard(intf)) + { + java.util.ArrayList<java.net.InetAddress> addrs = getLocalAddresses(protocolSupport); + for(java.net.InetAddress addr : addrs) + { + interfaces.add(addr.getHostAddress()); + } + if(protocolSupport != EnableIPv6) + { + interfaces.add("127.0.0.1"); + } + if(protocolSupport != EnableIPv4) + { + interfaces.add("0:0:0:0:0:0:0:1"); + } + } + if(interfaces.isEmpty()) + { + interfaces.add(intf); + } + return interfaces; + } + public static void setTcpBufSize(java.nio.channels.SocketChannel socket, ProtocolInstance instance) { @@ -1407,6 +1420,27 @@ public final class Network return addr; } + private static boolean + isWildcard(String host) + { + if(host == null || host.length() == 0) + { + return true; + } + try + { + return java.net.InetAddress.getByName(host).isAnyLocalAddress(); + } + catch(java.net.UnknownHostException ex) + { + } + catch(java.lang.SecurityException ex) + { + throw new SocketException(ex); + } + return false; + } + static class IPAddressComparator implements java.util.Comparator<java.net.InetSocketAddress> { IPAddressComparator(boolean ipv6) diff --git a/java/src/Ice/src/main/java/com/zeroc/IceInternal/UdpTransceiver.java b/java/src/Ice/src/main/java/com/zeroc/IceInternal/UdpTransceiver.java index 885e0cb9175..fd3b2834853 100644 --- a/java/src/Ice/src/main/java/com/zeroc/IceInternal/UdpTransceiver.java +++ b/java/src/Ice/src/main/java/com/zeroc/IceInternal/UdpTransceiver.java @@ -282,11 +282,15 @@ final class UdpTransceiver implements Transceiver public String toDetailedString() { StringBuilder s = new StringBuilder(toString()); - String addr = _mcastAddr != null ? _mcastInterface : _addr.getAddress().getHostAddress(); - java.util.List<String> intfs = Network.getHostsForEndpointExpand(addr, _instance.protocolSupport(), true); - if(_mcastAddr != null && intfs.isEmpty()) + java.util.List<String> intfs; + if(_mcastAddr == null) { - intfs.add(_mcastInterface); + intfs = Network.getHostsForEndpointExpand(_addr.getAddress().getHostAddress(), _instance.protocolSupport(), + true); + } + else + { + intfs = Network.getInterfacesForMulticast(_mcastInterface, _mcastAddr); } if(!intfs.isEmpty()) { |