diff options
-rw-r--r-- | CHANGES | 3 | ||||
-rw-r--r-- | cpp/src/Ice/UdpTransceiver.cpp | 27 | ||||
-rw-r--r-- | demoscript/Ice/multicast.py | 21 | ||||
-rw-r--r-- | java/src/IceInternal/UdpTransceiver.java | 50 | ||||
-rwxr-xr-x | scripts/TestUtil.py | 5 |
5 files changed, 61 insertions, 45 deletions
@@ -27,6 +27,9 @@ Changes since version 3.4.2 General Changes =============== +- Fixed bug where the UDP client endpoint --interface option would be + ignored on some platforms (Windows and OS X). + - IceGrid now enables active connection management for its object adapters to allow client connections to be closed automatically when inactive. diff --git a/cpp/src/Ice/UdpTransceiver.cpp b/cpp/src/Ice/UdpTransceiver.cpp index 581f7527960..46e9478e91e 100644 --- a/cpp/src/Ice/UdpTransceiver.cpp +++ b/cpp/src/Ice/UdpTransceiver.cpp @@ -871,6 +871,22 @@ IceInternal::UdpTransceiver::UdpTransceiver(const InstancePtr& instance, _peerAddr.ss_family = AF_UNSPEC; // Not initialized yet. // + // NOTE: setting the multicast interface before performing the + // connect is important for some OS such as OS X. + // + if(isMulticast(_addr)) + { + if(mcastInterface.length() > 0) + { + setMcastInterface(_fd, mcastInterface, _addr); + } + if(mcastTtl != -1) + { + setMcastTtl(_fd, mcastTtl, _addr); + } + } + + // // In general, connecting a datagram socket should be non-blocking as this just setups // the default destination address for the socket. However, on some OS, connect sometime // returns EWOULDBLOCK. If that's the case, we keep the state as StateNeedConnect. This @@ -890,17 +906,6 @@ IceInternal::UdpTransceiver::UdpTransceiver(const InstancePtr& instance, }); #endif - if(isMulticast(_addr)) - { - if(mcastInterface.length() > 0) - { - setMcastInterface(_fd, mcastInterface, _addr); - } - if(mcastTtl != -1) - { - setMcastTtl(_fd, mcastTtl, _addr); - } - } #ifdef ICE_USE_IOCP // diff --git a/demoscript/Ice/multicast.py b/demoscript/Ice/multicast.py index 17905d1d048..d1f84d3698a 100644 --- a/demoscript/Ice/multicast.py +++ b/demoscript/Ice/multicast.py @@ -64,12 +64,19 @@ def run(clientCmd, serverCmd): runDemo(clientCmd, serverCmd) print("ok") - if Util.getMapping() == "java" and Util.isWin32(): - sys.stdout.write("skipping testing multicast discovery (IPv6) under Windows...") + sys.stdout.write("testing multicast discovery (IPv6)... ") + sys.stdout.flush() + + # + # On OS X, using the interface-local address doesn't work, the client fails with + # a "Host not reachable" error, instead we use a link-local address with on loopback. + # + if Util.isDarwin(): + endpoint = 'udp -h \\"ff02::1:1\\" -p 10000 --interface \\"lo0\\"' else: - sys.stdout.write("testing multicast discovery (IPv6)... ") - sys.stdout.flush() - serverCmd += ' --Ice.IPv6=1 --Discover.Endpoints="udp -h \\"ff01::1:1\\" -p 10000"' - clientCmd += ' --Ice.IPv6=1 --Discover.Proxy="discover:udp -h \\"ff01::1:1\\" -p 10000"' - runDemo(clientCmd, serverCmd) + endpoint = 'udp -h \\"ff01::1:1\\" -p 10000' + serverCmd += ' --Ice.IPv6=1 --Discover.Endpoints="%s"' % (endpoint) + clientCmd += ' --Ice.IPv6=1 --Discover.Proxy="discover:%s"' % (endpoint) + + runDemo(clientCmd, serverCmd) print("ok") diff --git a/java/src/IceInternal/UdpTransceiver.java b/java/src/IceInternal/UdpTransceiver.java index d7de10b223a..989a1907187 100644 --- a/java/src/IceInternal/UdpTransceiver.java +++ b/java/src/IceInternal/UdpTransceiver.java @@ -300,12 +300,16 @@ final class UdpTransceiver implements Transceiver _fd = Network.createUdpSocket(_addr); setBufSize(instance); Network.setBlock(_fd, false); - Network.doConnect(_fd, _addr); - _state = StateConnected; // We're connected now + // + // NOTE: setting the multicast interface before performing the + // connect is important for some OS such as OS X. + // if(_addr.getAddress().isMulticastAddress()) { configureMulticast(null, mcastInterface, mcastTtl); } + Network.doConnect(_fd, _addr); + _state = StateConnected; // We're connected now if(_traceLevels.network >= 1) { @@ -482,12 +486,13 @@ final class UdpTransceiver implements Transceiver // // The NIO classes before JDK 1.7 do not support multicast, at least not directly. - // This method works around that limitation by using reflection to configure the file descriptor - // of a DatagramChannel for multicast operation. Specifically, an instance of - // java.net.PlainDatagramSocketImpl is use to (temporarily) wrap the channel's file descriptor. + // This method works around that limitation by using reflection to configure the + // file descriptor of a DatagramChannel for multicast operation. Specifically, an + // instance of java.net.PlainDatagramSocketImpl is use to (temporarily) wrap the + // channel's file descriptor. // - // In recent JDK versions greater or equal to JDK 1.7 we use the new added MulticastChannel via - // reflection, so the code still compile with older JDK versions that doesn't support. + // If using JDK >= 1.7 we use the new added MulticastChannel via reflection to allow + // compilation with older JDK versions. // private void configureMulticast(java.net.InetSocketAddress group, String interfaceAddr, int ttl) @@ -551,6 +556,9 @@ final class UdpTransceiver implements Transceiver if(group != null) { + // + // Join multicast group. + // Class<?>[] types; Object[] args; if(socketImpl == null) @@ -561,8 +569,7 @@ final class UdpTransceiver implements Transceiver boolean join = false; if(intf != null) { - args = new Object[]{ group.getAddress(), intf }; - m.invoke(_fd, args); + m.invoke(_fd, new Object[] { group.getAddress(), intf }); join = true; } else @@ -598,9 +605,7 @@ final class UdpTransceiver implements Transceiver if(hasProtocolAddress) { - args = new Object[]{ - group.getAddress(), iface }; - m.invoke(_fd, args); + m.invoke(_fd, new Object[] { group.getAddress(), iface }); join = true; } } @@ -635,6 +640,10 @@ final class UdpTransceiver implements Transceiver } else if(intf != null) { + // + // Otherwise, set the multicast interface if specified. + // + Class<?>[] types = new Class<?>[]{ Integer.TYPE, Object.class }; if(socketImpl == null) { @@ -642,10 +651,9 @@ final class UdpTransceiver implements Transceiver Class<?> standardSocketOptions = Util.findClass("java.net.StandardSocketOptions", null); m = _fd.getClass().getDeclaredMethod("setOption", new Class<?>[]{socketOption, Object.class}); m.setAccessible(true); - java.lang.reflect.Field ipMulticastIf = standardSocketOptions.getDeclaredField("IP_MULTICAST_IF"); - ipMulticastIf.setAccessible(true); - Object[] args = new Object[]{ ipMulticastIf.get(null), intf }; - m.invoke(_fd, args); + java.lang.reflect.Field ipMcastIf = standardSocketOptions.getDeclaredField("IP_MULTICAST_IF"); + ipMcastIf.setAccessible(true); + m.invoke(_fd, new Object[]{ ipMcastIf.get(null), intf }); } else { @@ -671,18 +679,16 @@ final class UdpTransceiver implements Transceiver Class<?> standardSocketOptions = Util.findClass("java.net.StandardSocketOptions", null); m = _fd.getClass().getDeclaredMethod("setOption", new Class<?>[]{socketOption, Object.class}); m.setAccessible(true); - java.lang.reflect.Field ipMulticastIf = standardSocketOptions.getDeclaredField("IP_MULTICAST_TTL"); - ipMulticastIf.setAccessible(true); - Object[] args = new Object[]{ ipMulticastIf.get(null), ttl }; - m.invoke(_fd, args); + java.lang.reflect.Field ipMcastTtl = standardSocketOptions.getDeclaredField("IP_MULTICAST_TTL"); + ipMcastTtl.setAccessible(true); + m.invoke(_fd, new Object[]{ ipMcastTtl.get(null), ttl }); } else { Class<?>[] types = new Class<?>[]{ Integer.TYPE }; m = java.net.DatagramSocketImpl.class.getDeclaredMethod("setTimeToLive", types); m.setAccessible(true); - Object[] args = new Object[]{ Integer.valueOf(ttl) }; - m.invoke(socketImpl, args); + m.invoke(socketImpl, new Object[]{ Integer.valueOf(ttl) }); } } } diff --git a/scripts/TestUtil.py b/scripts/TestUtil.py index 95a92d1e0c6..67d3be026cd 100755 --- a/scripts/TestUtil.py +++ b/scripts/TestUtil.py @@ -1752,11 +1752,6 @@ def runTests(start, expanded, num = 0, script = False): print("%s*** test not supported with IceSSL%s" % (prefix, suffix)) continue - # If this is java and we're running ipv6 under windows then skip. - if isWin32() and i.find(os.path.join("java","test")) != -1 and args.find("ipv6") != -1: - print("%s*** test not supported under windows%s" % (prefix, suffix)) - continue - # Skip tests not supported by valgrind if args.find("valgrind") != -1 and ("novalgrind" in config or args.find("ssl") != -1): print("%s*** test not supported with valgrind%s" % (prefix, suffix)) |