1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.channel.socket.nio;
17
18 import io.netty.channel.ChannelException;
19 import io.netty.channel.socket.DatagramChannelConfig;
20 import io.netty.channel.socket.DefaultDatagramChannelConfig;
21 import io.netty.util.internal.PlatformDependent;
22 import io.netty.util.internal.SocketUtils;
23
24 import java.lang.reflect.Method;
25 import java.net.InetAddress;
26 import java.net.NetworkInterface;
27 import java.net.SocketException;
28 import java.nio.channels.DatagramChannel;
29 import java.util.Enumeration;
30
31
32
33
34 class NioDatagramChannelConfig extends DefaultDatagramChannelConfig {
35
36 private static final Object IP_MULTICAST_TTL;
37 private static final Object IP_MULTICAST_IF;
38 private static final Object IP_MULTICAST_LOOP;
39 private static final Method GET_OPTION;
40 private static final Method SET_OPTION;
41
42 static {
43 ClassLoader classLoader = PlatformDependent.getClassLoader(DatagramChannel.class);
44 Class<?> socketOptionType = null;
45 try {
46 socketOptionType = Class.forName("java.net.SocketOption", true, classLoader);
47 } catch (Exception e) {
48
49 }
50 Class<?> stdSocketOptionType = null;
51 try {
52 stdSocketOptionType = Class.forName("java.net.StandardSocketOptions", true, classLoader);
53 } catch (Exception e) {
54
55 }
56
57 Object ipMulticastTtl = null;
58 Object ipMulticastIf = null;
59 Object ipMulticastLoop = null;
60 Method getOption = null;
61 Method setOption = null;
62 if (socketOptionType != null) {
63 try {
64 ipMulticastTtl = stdSocketOptionType.getDeclaredField("IP_MULTICAST_TTL").get(null);
65 } catch (Exception e) {
66 throw new Error("cannot locate the IP_MULTICAST_TTL field", e);
67 }
68
69 try {
70 ipMulticastIf = stdSocketOptionType.getDeclaredField("IP_MULTICAST_IF").get(null);
71 } catch (Exception e) {
72 throw new Error("cannot locate the IP_MULTICAST_IF field", e);
73 }
74
75 try {
76 ipMulticastLoop = stdSocketOptionType.getDeclaredField("IP_MULTICAST_LOOP").get(null);
77 } catch (Exception e) {
78 throw new Error("cannot locate the IP_MULTICAST_LOOP field", e);
79 }
80
81 Class<?> networkChannelClass = null;
82 try {
83 networkChannelClass = Class.forName("java.nio.channels.NetworkChannel", true, classLoader);
84 } catch (Throwable ignore) {
85
86 }
87
88 if (networkChannelClass == null) {
89 getOption = null;
90 setOption = null;
91 } else {
92 try {
93 getOption = networkChannelClass.getDeclaredMethod("getOption", socketOptionType);
94 } catch (Exception e) {
95 throw new Error("cannot locate the getOption() method", e);
96 }
97
98 try {
99 setOption = networkChannelClass.getDeclaredMethod("setOption", socketOptionType, Object.class);
100 } catch (Exception e) {
101 throw new Error("cannot locate the setOption() method", e);
102 }
103 }
104 }
105 IP_MULTICAST_TTL = ipMulticastTtl;
106 IP_MULTICAST_IF = ipMulticastIf;
107 IP_MULTICAST_LOOP = ipMulticastLoop;
108 GET_OPTION = getOption;
109 SET_OPTION = setOption;
110 }
111
112 private final DatagramChannel javaChannel;
113
114 NioDatagramChannelConfig(NioDatagramChannel channel, DatagramChannel javaChannel) {
115 super(channel, javaChannel.socket());
116 this.javaChannel = javaChannel;
117 }
118
119 @Override
120 public int getTimeToLive() {
121 return (Integer) getOption0(IP_MULTICAST_TTL);
122 }
123
124 @Override
125 public DatagramChannelConfig setTimeToLive(int ttl) {
126 setOption0(IP_MULTICAST_TTL, ttl);
127 return this;
128 }
129
130 @Override
131 public InetAddress getInterface() {
132 NetworkInterface inf = getNetworkInterface();
133 if (inf == null) {
134 return null;
135 } else {
136 Enumeration<InetAddress> addresses = SocketUtils.addressesFromNetworkInterface(inf);
137 if (addresses.hasMoreElements()) {
138 return addresses.nextElement();
139 }
140 return null;
141 }
142 }
143
144 @Override
145 public DatagramChannelConfig setInterface(InetAddress interfaceAddress) {
146 try {
147 setNetworkInterface(NetworkInterface.getByInetAddress(interfaceAddress));
148 } catch (SocketException e) {
149 throw new ChannelException(e);
150 }
151 return this;
152 }
153
154 @Override
155 public NetworkInterface getNetworkInterface() {
156 return (NetworkInterface) getOption0(IP_MULTICAST_IF);
157 }
158
159 @Override
160 public DatagramChannelConfig setNetworkInterface(NetworkInterface networkInterface) {
161 setOption0(IP_MULTICAST_IF, networkInterface);
162 return this;
163 }
164
165 @Override
166 public boolean isLoopbackModeDisabled() {
167 return (Boolean) getOption0(IP_MULTICAST_LOOP);
168 }
169
170 @Override
171 public DatagramChannelConfig setLoopbackModeDisabled(boolean loopbackModeDisabled) {
172 setOption0(IP_MULTICAST_LOOP, loopbackModeDisabled);
173 return this;
174 }
175
176 @Override
177 public DatagramChannelConfig setAutoRead(boolean autoRead) {
178 super.setAutoRead(autoRead);
179 return this;
180 }
181
182 @Override
183 protected void autoReadCleared() {
184 ((NioDatagramChannel) channel).setReadPending(false);
185 }
186
187 private Object getOption0(Object option) {
188 if (GET_OPTION == null) {
189 throw new UnsupportedOperationException();
190 } else {
191 try {
192 return GET_OPTION.invoke(javaChannel, option);
193 } catch (Exception e) {
194 throw new ChannelException(e);
195 }
196 }
197 }
198
199 private void setOption0(Object option, Object value) {
200 if (SET_OPTION == null) {
201 throw new UnsupportedOperationException();
202 } else {
203 try {
204 SET_OPTION.invoke(javaChannel, option, value);
205 } catch (Exception e) {
206 throw new ChannelException(e);
207 }
208 }
209 }
210 }