summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES3
-rw-r--r--cpp/src/Ice/UdpTransceiver.cpp27
-rw-r--r--demoscript/Ice/multicast.py21
-rw-r--r--java/src/IceInternal/UdpTransceiver.java50
-rwxr-xr-xscripts/TestUtil.py5
5 files changed, 61 insertions, 45 deletions
diff --git a/CHANGES b/CHANGES
index 7e39f910f82..d9b57de8769 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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))