Implement NIO.2 multicast options

This commit is contained in:
Trustin Lee 2012-05-30 19:03:45 -07:00
parent 117626e034
commit 67ec4429cc

View File

@ -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<InetAddress> 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);
}