1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.channel.socket;
17
18 import io.netty.buffer.ByteBufAllocator;
19 import io.netty.channel.ChannelException;
20 import io.netty.channel.ChannelOption;
21 import io.netty.channel.DefaultChannelConfig;
22 import io.netty.channel.FixedRecvByteBufAllocator;
23 import io.netty.channel.MessageSizeEstimator;
24 import io.netty.channel.RecvByteBufAllocator;
25 import io.netty.util.internal.PlatformDependent;
26 import io.netty.util.internal.logging.InternalLogger;
27 import io.netty.util.internal.logging.InternalLoggerFactory;
28
29 import java.io.IOException;
30 import java.net.DatagramSocket;
31 import java.net.InetAddress;
32 import java.net.MulticastSocket;
33 import java.net.NetworkInterface;
34 import java.net.SocketException;
35 import java.util.Map;
36
37 import static io.netty.channel.ChannelOption.*;
38
39
40
41
42 public class DefaultDatagramChannelConfig extends DefaultChannelConfig implements DatagramChannelConfig {
43
44 private static final InternalLogger logger = InternalLoggerFactory.getInstance(DefaultDatagramChannelConfig.class);
45
46 private static final RecvByteBufAllocator DEFAULT_RCVBUF_ALLOCATOR = new FixedRecvByteBufAllocator(2048);
47
48 private final DatagramSocket javaSocket;
49 private volatile boolean activeOnOpen;
50
51
52
53
54 public DefaultDatagramChannelConfig(DatagramChannel channel, DatagramSocket javaSocket) {
55 super(channel);
56 if (javaSocket == null) {
57 throw new NullPointerException("javaSocket");
58 }
59 this.javaSocket = javaSocket;
60 setRecvByteBufAllocator(DEFAULT_RCVBUF_ALLOCATOR);
61 }
62
63 protected final DatagramSocket javaSocket() {
64 return javaSocket;
65 }
66
67 @Override
68 @SuppressWarnings("deprecation")
69 public Map<ChannelOption<?>, Object> getOptions() {
70 return getOptions(
71 super.getOptions(),
72 SO_BROADCAST, SO_RCVBUF, SO_SNDBUF, SO_REUSEADDR, IP_MULTICAST_LOOP_DISABLED,
73 IP_MULTICAST_ADDR, IP_MULTICAST_IF, IP_MULTICAST_TTL, IP_TOS, DATAGRAM_CHANNEL_ACTIVE_ON_REGISTRATION);
74 }
75
76 @Override
77 @SuppressWarnings({ "unchecked", "deprecation" })
78 public <T> T getOption(ChannelOption<T> option) {
79 if (option == SO_BROADCAST) {
80 return (T) Boolean.valueOf(isBroadcast());
81 }
82 if (option == SO_RCVBUF) {
83 return (T) Integer.valueOf(getReceiveBufferSize());
84 }
85 if (option == SO_SNDBUF) {
86 return (T) Integer.valueOf(getSendBufferSize());
87 }
88 if (option == SO_REUSEADDR) {
89 return (T) Boolean.valueOf(isReuseAddress());
90 }
91 if (option == IP_MULTICAST_LOOP_DISABLED) {
92 return (T) Boolean.valueOf(isLoopbackModeDisabled());
93 }
94 if (option == IP_MULTICAST_ADDR) {
95 return (T) getInterface();
96 }
97 if (option == IP_MULTICAST_IF) {
98 return (T) getNetworkInterface();
99 }
100 if (option == IP_MULTICAST_TTL) {
101 return (T) Integer.valueOf(getTimeToLive());
102 }
103 if (option == IP_TOS) {
104 return (T) Integer.valueOf(getTrafficClass());
105 }
106 if (option == DATAGRAM_CHANNEL_ACTIVE_ON_REGISTRATION) {
107 return (T) Boolean.valueOf(activeOnOpen);
108 }
109 return super.getOption(option);
110 }
111
112 @Override
113 @SuppressWarnings("deprecation")
114 public <T> boolean setOption(ChannelOption<T> option, T value) {
115 validate(option, value);
116
117 if (option == SO_BROADCAST) {
118 setBroadcast((Boolean) value);
119 } else if (option == SO_RCVBUF) {
120 setReceiveBufferSize((Integer) value);
121 } else if (option == SO_SNDBUF) {
122 setSendBufferSize((Integer) value);
123 } else if (option == SO_REUSEADDR) {
124 setReuseAddress((Boolean) value);
125 } else if (option == IP_MULTICAST_LOOP_DISABLED) {
126 setLoopbackModeDisabled((Boolean) value);
127 } else if (option == IP_MULTICAST_ADDR) {
128 setInterface((InetAddress) value);
129 } else if (option == IP_MULTICAST_IF) {
130 setNetworkInterface((NetworkInterface) value);
131 } else if (option == IP_MULTICAST_TTL) {
132 setTimeToLive((Integer) value);
133 } else if (option == IP_TOS) {
134 setTrafficClass((Integer) value);
135 } else if (option == DATAGRAM_CHANNEL_ACTIVE_ON_REGISTRATION) {
136 setActiveOnOpen((Boolean) value);
137 } else {
138 return super.setOption(option, value);
139 }
140
141 return true;
142 }
143
144 private void setActiveOnOpen(boolean activeOnOpen) {
145 if (channel.isRegistered()) {
146 throw new IllegalStateException("Can only changed before channel was registered");
147 }
148 this.activeOnOpen = activeOnOpen;
149 }
150 @Override
151 public boolean isBroadcast() {
152 try {
153 return javaSocket.getBroadcast();
154 } catch (SocketException e) {
155 throw new ChannelException(e);
156 }
157 }
158
159 @Override
160 public DatagramChannelConfig setBroadcast(boolean broadcast) {
161 try {
162
163 if (broadcast &&
164 !javaSocket.getLocalAddress().isAnyLocalAddress() &&
165 !PlatformDependent.isWindows() && !PlatformDependent.maybeSuperUser()) {
166
167
168 logger.warn(
169 "A non-root user can't receive a broadcast packet if the socket " +
170 "is not bound to a wildcard address; setting the SO_BROADCAST flag " +
171 "anyway as requested on the socket which is bound to " +
172 javaSocket.getLocalSocketAddress() + '.');
173 }
174
175 javaSocket.setBroadcast(broadcast);
176 } catch (SocketException e) {
177 throw new ChannelException(e);
178 }
179 return this;
180 }
181
182 @Override
183 public InetAddress getInterface() {
184 if (javaSocket instanceof MulticastSocket) {
185 try {
186 return ((MulticastSocket) javaSocket).getInterface();
187 } catch (SocketException e) {
188 throw new ChannelException(e);
189 }
190 } else {
191 throw new UnsupportedOperationException();
192 }
193 }
194
195 @Override
196 public DatagramChannelConfig setInterface(InetAddress interfaceAddress) {
197 if (javaSocket instanceof MulticastSocket) {
198 try {
199 ((MulticastSocket) javaSocket).setInterface(interfaceAddress);
200 } catch (SocketException e) {
201 throw new ChannelException(e);
202 }
203 } else {
204 throw new UnsupportedOperationException();
205 }
206 return this;
207 }
208
209 @Override
210 public boolean isLoopbackModeDisabled() {
211 if (javaSocket instanceof MulticastSocket) {
212 try {
213 return ((MulticastSocket) javaSocket).getLoopbackMode();
214 } catch (SocketException e) {
215 throw new ChannelException(e);
216 }
217 } else {
218 throw new UnsupportedOperationException();
219 }
220 }
221
222 @Override
223 public DatagramChannelConfig setLoopbackModeDisabled(boolean loopbackModeDisabled) {
224 if (javaSocket instanceof MulticastSocket) {
225 try {
226 ((MulticastSocket) javaSocket).setLoopbackMode(loopbackModeDisabled);
227 } catch (SocketException e) {
228 throw new ChannelException(e);
229 }
230 } else {
231 throw new UnsupportedOperationException();
232 }
233 return this;
234 }
235
236 @Override
237 public NetworkInterface getNetworkInterface() {
238 if (javaSocket instanceof MulticastSocket) {
239 try {
240 return ((MulticastSocket) javaSocket).getNetworkInterface();
241 } catch (SocketException e) {
242 throw new ChannelException(e);
243 }
244 } else {
245 throw new UnsupportedOperationException();
246 }
247 }
248
249 @Override
250 public DatagramChannelConfig setNetworkInterface(NetworkInterface networkInterface) {
251 if (javaSocket instanceof MulticastSocket) {
252 try {
253 ((MulticastSocket) javaSocket).setNetworkInterface(networkInterface);
254 } catch (SocketException e) {
255 throw new ChannelException(e);
256 }
257 } else {
258 throw new UnsupportedOperationException();
259 }
260 return this;
261 }
262
263 @Override
264 public boolean isReuseAddress() {
265 try {
266 return javaSocket.getReuseAddress();
267 } catch (SocketException e) {
268 throw new ChannelException(e);
269 }
270 }
271
272 @Override
273 public DatagramChannelConfig setReuseAddress(boolean reuseAddress) {
274 try {
275 javaSocket.setReuseAddress(reuseAddress);
276 } catch (SocketException e) {
277 throw new ChannelException(e);
278 }
279 return this;
280 }
281
282 @Override
283 public int getReceiveBufferSize() {
284 try {
285 return javaSocket.getReceiveBufferSize();
286 } catch (SocketException e) {
287 throw new ChannelException(e);
288 }
289 }
290
291 @Override
292 public DatagramChannelConfig setReceiveBufferSize(int receiveBufferSize) {
293 try {
294 javaSocket.setReceiveBufferSize(receiveBufferSize);
295 } catch (SocketException e) {
296 throw new ChannelException(e);
297 }
298 return this;
299 }
300
301 @Override
302 public int getSendBufferSize() {
303 try {
304 return javaSocket.getSendBufferSize();
305 } catch (SocketException e) {
306 throw new ChannelException(e);
307 }
308 }
309
310 @Override
311 public DatagramChannelConfig setSendBufferSize(int sendBufferSize) {
312 try {
313 javaSocket.setSendBufferSize(sendBufferSize);
314 } catch (SocketException e) {
315 throw new ChannelException(e);
316 }
317 return this;
318 }
319
320 @Override
321 public int getTimeToLive() {
322 if (javaSocket instanceof MulticastSocket) {
323 try {
324 return ((MulticastSocket) javaSocket).getTimeToLive();
325 } catch (IOException e) {
326 throw new ChannelException(e);
327 }
328 } else {
329 throw new UnsupportedOperationException();
330 }
331 }
332
333 @Override
334 public DatagramChannelConfig setTimeToLive(int ttl) {
335 if (javaSocket instanceof MulticastSocket) {
336 try {
337 ((MulticastSocket) javaSocket).setTimeToLive(ttl);
338 } catch (IOException e) {
339 throw new ChannelException(e);
340 }
341 } else {
342 throw new UnsupportedOperationException();
343 }
344 return this;
345 }
346
347 @Override
348 public int getTrafficClass() {
349 try {
350 return javaSocket.getTrafficClass();
351 } catch (SocketException e) {
352 throw new ChannelException(e);
353 }
354 }
355
356 @Override
357 public DatagramChannelConfig setTrafficClass(int trafficClass) {
358 try {
359 javaSocket.setTrafficClass(trafficClass);
360 } catch (SocketException e) {
361 throw new ChannelException(e);
362 }
363 return this;
364 }
365
366 @Override
367 public DatagramChannelConfig setWriteSpinCount(int writeSpinCount) {
368 super.setWriteSpinCount(writeSpinCount);
369 return this;
370 }
371
372 @Override
373 public DatagramChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis) {
374 super.setConnectTimeoutMillis(connectTimeoutMillis);
375 return this;
376 }
377
378 @Override
379 public DatagramChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead) {
380 super.setMaxMessagesPerRead(maxMessagesPerRead);
381 return this;
382 }
383
384 @Override
385 public DatagramChannelConfig setAllocator(ByteBufAllocator allocator) {
386 super.setAllocator(allocator);
387 return this;
388 }
389
390 @Override
391 public DatagramChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator) {
392 super.setRecvByteBufAllocator(allocator);
393 return this;
394 }
395
396 @Override
397 public DatagramChannelConfig setAutoRead(boolean autoRead) {
398 super.setAutoRead(autoRead);
399 return this;
400 }
401
402 @Override
403 public DatagramChannelConfig setAutoClose(boolean autoClose) {
404 super.setAutoClose(autoClose);
405 return this;
406 }
407
408 @Override
409 public DatagramChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) {
410 super.setWriteBufferHighWaterMark(writeBufferHighWaterMark);
411 return this;
412 }
413
414 @Override
415 public DatagramChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) {
416 super.setWriteBufferLowWaterMark(writeBufferLowWaterMark);
417 return this;
418 }
419
420 @Override
421 public DatagramChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator) {
422 super.setMessageSizeEstimator(estimator);
423 return this;
424 }
425 }