From 67ec4429ccc34c3933f2b3d5881e9ddda2c531de Mon Sep 17 00:00:00 2001 From: Trustin Lee Date: Wed, 30 May 2012 19:03:45 -0700 Subject: [PATCH] Implement NIO.2 multicast options --- .../socket/nio/NioDatagramChannelConfig.java | 80 ++++++++++++++++++- 1 file changed, 76 insertions(+), 4 deletions(-) diff --git a/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannelConfig.java b/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannelConfig.java index e89624bc23..112100da74 100644 --- a/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannelConfig.java +++ b/transport/src/main/java/io/netty/channel/socket/nio/NioDatagramChannelConfig.java @@ -20,15 +20,20 @@ import io.netty.channel.socket.DefaultDatagramChannelConfig; import io.netty.util.internal.DetectionUtil; import java.lang.reflect.Method; +import java.net.InetAddress; import java.net.NetworkInterface; +import java.net.SocketException; import java.nio.channels.DatagramChannel; +import java.util.Enumeration; /** * The default {@link NioSocketChannelConfig} implementation. */ class NioDatagramChannelConfig extends DefaultDatagramChannelConfig { + private static final Object IP_MULTICAST_TTL; private static final Object IP_MULTICAST_IF; + private static final Object IP_MULTICAST_LOOP; private static final Method GET_OPTION; private static final Method SET_OPTION; @@ -41,16 +46,30 @@ class NioDatagramChannelConfig extends DefaultDatagramChannelConfig { // Not Java 7+ } + Object ipMulticastTtl = null; Object ipMulticastIf = null; + Object ipMulticastLoop = null; Method getOption = null; Method setOption = null; if (socketOptionType != null) { + try { + ipMulticastIf = Class.forName("java.net.StandardSocketOptions", true, classLoader).getDeclaredField("IP_MULTICAST_TTL").get(null); + } catch (Exception e) { + throw new Error("cannot locate the IP_MULTICAST_TTL field", e); + } + try { ipMulticastIf = Class.forName("java.net.StandardSocketOptions", true, classLoader).getDeclaredField("IP_MULTICAST_IF").get(null); } catch (Exception e) { throw new Error("cannot locate the IP_MULTICAST_IF field", e); } + try { + ipMulticastIf = Class.forName("java.net.StandardSocketOptions", true, classLoader).getDeclaredField("IP_MULTICAST_LOOP").get(null); + } catch (Exception e) { + throw new Error("cannot locate the IP_MULTICAST_LOOP field", e); + } + try { getOption = DatagramChannel.class.getDeclaredMethod("getOption", socketOptionType); } catch (Exception e) { @@ -63,7 +82,9 @@ class NioDatagramChannelConfig extends DefaultDatagramChannelConfig { throw new Error("cannot locate the setOption() method", e); } } + IP_MULTICAST_TTL = ipMulticastTtl; IP_MULTICAST_IF = ipMulticastIf; + IP_MULTICAST_LOOP = ipMulticastLoop; GET_OPTION = getOption; SET_OPTION = setOption; } @@ -75,26 +96,77 @@ class NioDatagramChannelConfig extends DefaultDatagramChannelConfig { this.channel = channel; } + @Override + public int getTimeToLive() { + return (Integer) getOption0(IP_MULTICAST_TTL); + } + + @Override + public void setTimeToLive(int ttl) { + setOption0(IP_MULTICAST_TTL, ttl); + } + + @Override + public InetAddress getInterface() { + NetworkInterface inf = getNetworkInterface(); + if (inf == null) { + return null; + } else { + Enumeration addresses = inf.getInetAddresses(); + if (addresses.hasMoreElements()) { + return addresses.nextElement(); + } + return null; + } + } + + @Override + public void setInterface(InetAddress interfaceAddress) { + try { + setNetworkInterface(NetworkInterface.getByInetAddress(interfaceAddress)); + } catch (SocketException e) { + throw new ChannelException(e); + } + } + + @Override + public NetworkInterface getNetworkInterface() { + return (NetworkInterface) getOption0(IP_MULTICAST_IF); + } + @Override public void setNetworkInterface(NetworkInterface networkInterface) { + setOption0(IP_MULTICAST_IF, networkInterface); + } + + @Override + public boolean isLoopbackModeDisabled() { + return (Boolean) getOption0(IP_MULTICAST_LOOP); + } + + @Override + public void setLoopbackModeDisabled(boolean loopbackModeDisabled) { + setOption0(IP_MULTICAST_LOOP, loopbackModeDisabled); + } + + private Object getOption0(Object option) { if (DetectionUtil.javaVersion() < 7) { throw new UnsupportedOperationException(); } else { try { - SET_OPTION.invoke(channel, IP_MULTICAST_IF, networkInterface); + return GET_OPTION.invoke(channel, option); } catch (Exception e) { throw new ChannelException(e); } } } - @Override - public NetworkInterface getNetworkInterface() { + private void setOption0(Object option, Object value) { if (DetectionUtil.javaVersion() < 7) { throw new UnsupportedOperationException(); } else { try { - return (NetworkInterface) GET_OPTION.invoke(channel, IP_MULTICAST_IF); + SET_OPTION.invoke(channel, option, value); } catch (Exception e) { throw new ChannelException(e); }