View Javadoc
1   /*
2    * Copyright 2016 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.channel.kqueue;
17  
18  import io.netty.buffer.ByteBufAllocator;
19  import io.netty.channel.ChannelException;
20  import io.netty.channel.ChannelOption;
21  import io.netty.channel.FixedRecvByteBufAllocator;
22  import io.netty.channel.MessageSizeEstimator;
23  import io.netty.channel.RecvByteBufAllocator;
24  import io.netty.channel.WriteBufferWaterMark;
25  import io.netty.channel.socket.DatagramChannelConfig;
26  import io.netty.util.internal.UnstableApi;
27  
28  import java.io.IOException;
29  import java.net.InetAddress;
30  import java.net.NetworkInterface;
31  import java.util.Map;
32  
33  import static io.netty.channel.ChannelOption.DATAGRAM_CHANNEL_ACTIVE_ON_REGISTRATION;
34  import static io.netty.channel.ChannelOption.IP_MULTICAST_ADDR;
35  import static io.netty.channel.ChannelOption.IP_MULTICAST_IF;
36  import static io.netty.channel.ChannelOption.IP_MULTICAST_LOOP_DISABLED;
37  import static io.netty.channel.ChannelOption.IP_MULTICAST_TTL;
38  import static io.netty.channel.ChannelOption.IP_TOS;
39  import static io.netty.channel.ChannelOption.SO_BROADCAST;
40  import static io.netty.channel.ChannelOption.SO_RCVBUF;
41  import static io.netty.channel.ChannelOption.SO_REUSEADDR;
42  import static io.netty.channel.ChannelOption.SO_SNDBUF;
43  import static io.netty.channel.unix.UnixChannelOption.SO_REUSEPORT;
44  
45  @UnstableApi
46  public final class KQueueDatagramChannelConfig extends KQueueChannelConfig implements DatagramChannelConfig {
47      private static final RecvByteBufAllocator DEFAULT_RCVBUF_ALLOCATOR = new FixedRecvByteBufAllocator(2048);
48      private final KQueueDatagramChannel datagramChannel;
49      private boolean activeOnOpen;
50  
51      KQueueDatagramChannelConfig(KQueueDatagramChannel channel) {
52          super(channel);
53          this.datagramChannel = channel;
54          setRecvByteBufAllocator(DEFAULT_RCVBUF_ALLOCATOR);
55      }
56  
57      @Override
58      @SuppressWarnings("deprecation")
59      public Map<ChannelOption<?>, Object> getOptions() {
60          return getOptions(
61                  super.getOptions(),
62                  SO_BROADCAST, SO_RCVBUF, SO_SNDBUF, SO_REUSEADDR, IP_MULTICAST_LOOP_DISABLED,
63                  IP_MULTICAST_ADDR, IP_MULTICAST_IF, IP_MULTICAST_TTL,
64                  IP_TOS, DATAGRAM_CHANNEL_ACTIVE_ON_REGISTRATION, SO_REUSEPORT);
65      }
66  
67      @SuppressWarnings({ "unchecked", "deprecation" })
68      @Override
69      public <T> T getOption(ChannelOption<T> option) {
70          if (option == SO_BROADCAST) {
71              return (T) Boolean.valueOf(isBroadcast());
72          }
73          if (option == SO_RCVBUF) {
74              return (T) Integer.valueOf(getReceiveBufferSize());
75          }
76          if (option == SO_SNDBUF) {
77              return (T) Integer.valueOf(getSendBufferSize());
78          }
79          if (option == SO_REUSEADDR) {
80              return (T) Boolean.valueOf(isReuseAddress());
81          }
82          if (option == IP_MULTICAST_LOOP_DISABLED) {
83              return (T) Boolean.valueOf(isLoopbackModeDisabled());
84          }
85          if (option == IP_MULTICAST_ADDR) {
86              return (T) getInterface();
87          }
88          if (option == IP_MULTICAST_IF) {
89              return (T) getNetworkInterface();
90          }
91          if (option == IP_MULTICAST_TTL) {
92              return (T) Integer.valueOf(getTimeToLive());
93          }
94          if (option == IP_TOS) {
95              return (T) Integer.valueOf(getTrafficClass());
96          }
97          if (option == DATAGRAM_CHANNEL_ACTIVE_ON_REGISTRATION) {
98              return (T) Boolean.valueOf(activeOnOpen);
99          }
100         if (option == SO_REUSEPORT) {
101             return (T) Boolean.valueOf(isReusePort());
102         }
103         return super.getOption(option);
104     }
105 
106     @Override
107     @SuppressWarnings("deprecation")
108     public <T> boolean setOption(ChannelOption<T> option, T value) {
109         validate(option, value);
110 
111         if (option == SO_BROADCAST) {
112             setBroadcast((Boolean) value);
113         } else if (option == SO_RCVBUF) {
114             setReceiveBufferSize((Integer) value);
115         } else if (option == SO_SNDBUF) {
116             setSendBufferSize((Integer) value);
117         } else if (option == SO_REUSEADDR) {
118             setReuseAddress((Boolean) value);
119         } else if (option == IP_MULTICAST_LOOP_DISABLED) {
120             setLoopbackModeDisabled((Boolean) value);
121         } else if (option == IP_MULTICAST_ADDR) {
122             setInterface((InetAddress) value);
123         } else if (option == IP_MULTICAST_IF) {
124             setNetworkInterface((NetworkInterface) value);
125         } else if (option == IP_MULTICAST_TTL) {
126             setTimeToLive((Integer) value);
127         } else if (option == IP_TOS) {
128             setTrafficClass((Integer) value);
129         } else if (option == DATAGRAM_CHANNEL_ACTIVE_ON_REGISTRATION) {
130             setActiveOnOpen((Boolean) value);
131         } else if (option == SO_REUSEPORT) {
132             setReusePort((Boolean) value);
133         } else {
134             return super.setOption(option, value);
135         }
136 
137         return true;
138     }
139 
140     private void setActiveOnOpen(boolean activeOnOpen) {
141         if (channel.isRegistered()) {
142             throw new IllegalStateException("Can only changed before channel was registered");
143         }
144         this.activeOnOpen = activeOnOpen;
145     }
146 
147     boolean getActiveOnOpen() {
148         return activeOnOpen;
149     }
150 
151     /**
152      * Returns {@code true} if the SO_REUSEPORT option is set.
153      */
154     public boolean isReusePort() {
155         try {
156             return datagramChannel.socket.isReusePort();
157         } catch (IOException e) {
158             throw new ChannelException(e);
159         }
160     }
161 
162     /**
163      * Set the SO_REUSEPORT option on the underlying Channel. This will allow to bind multiple
164      * {@link KQueueSocketChannel}s to the same port and so accept connections with multiple threads.
165      *
166      * Be aware this method needs be called before {@link KQueueDatagramChannel#bind(java.net.SocketAddress)} to have
167      * any affect.
168      */
169     public KQueueDatagramChannelConfig setReusePort(boolean reusePort) {
170         try {
171             datagramChannel.socket.setReusePort(reusePort);
172             return this;
173         } catch (IOException e) {
174             throw new ChannelException(e);
175         }
176     }
177 
178     @Override
179     public KQueueDatagramChannelConfig setRcvAllocTransportProvidesGuess(boolean transportProvidesGuess) {
180         super.setRcvAllocTransportProvidesGuess(transportProvidesGuess);
181         return this;
182     }
183 
184     @Override
185     public KQueueDatagramChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator) {
186         super.setMessageSizeEstimator(estimator);
187         return this;
188     }
189 
190     @Override
191     @Deprecated
192     public KQueueDatagramChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) {
193         super.setWriteBufferLowWaterMark(writeBufferLowWaterMark);
194         return this;
195     }
196 
197     @Override
198     @Deprecated
199     public KQueueDatagramChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) {
200         super.setWriteBufferHighWaterMark(writeBufferHighWaterMark);
201         return this;
202     }
203 
204     @Override
205     public KQueueDatagramChannelConfig setWriteBufferWaterMark(WriteBufferWaterMark writeBufferWaterMark) {
206         super.setWriteBufferWaterMark(writeBufferWaterMark);
207         return this;
208     }
209 
210     @Override
211     public KQueueDatagramChannelConfig setAutoClose(boolean autoClose) {
212         super.setAutoClose(autoClose);
213         return this;
214     }
215 
216     @Override
217     public KQueueDatagramChannelConfig setAutoRead(boolean autoRead) {
218         super.setAutoRead(autoRead);
219         return this;
220     }
221 
222     @Override
223     public KQueueDatagramChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator) {
224         super.setRecvByteBufAllocator(allocator);
225         return this;
226     }
227 
228     @Override
229     public KQueueDatagramChannelConfig setWriteSpinCount(int writeSpinCount) {
230         super.setWriteSpinCount(writeSpinCount);
231         return this;
232     }
233 
234     @Override
235     public KQueueDatagramChannelConfig setAllocator(ByteBufAllocator allocator) {
236         super.setAllocator(allocator);
237         return this;
238     }
239 
240     @Override
241     public KQueueDatagramChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis) {
242         super.setConnectTimeoutMillis(connectTimeoutMillis);
243         return this;
244     }
245 
246     @Override
247     @Deprecated
248     public KQueueDatagramChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead) {
249         super.setMaxMessagesPerRead(maxMessagesPerRead);
250         return this;
251     }
252 
253     @Override
254     public int getSendBufferSize() {
255         try {
256             return datagramChannel.socket.getSendBufferSize();
257         } catch (IOException e) {
258             throw new ChannelException(e);
259         }
260     }
261 
262     @Override
263     public KQueueDatagramChannelConfig setSendBufferSize(int sendBufferSize) {
264         try {
265             datagramChannel.socket.setSendBufferSize(sendBufferSize);
266             return this;
267         } catch (IOException e) {
268             throw new ChannelException(e);
269         }
270     }
271 
272     @Override
273     public int getReceiveBufferSize() {
274         try {
275             return datagramChannel.socket.getReceiveBufferSize();
276         } catch (IOException e) {
277             throw new ChannelException(e);
278         }
279     }
280 
281     @Override
282     public KQueueDatagramChannelConfig setReceiveBufferSize(int receiveBufferSize) {
283         try {
284             datagramChannel.socket.setReceiveBufferSize(receiveBufferSize);
285             return this;
286         } catch (IOException e) {
287             throw new ChannelException(e);
288         }
289     }
290 
291     @Override
292     public int getTrafficClass() {
293         try {
294             return datagramChannel.socket.getTrafficClass();
295         } catch (IOException e) {
296             throw new ChannelException(e);
297         }
298     }
299 
300     @Override
301     public KQueueDatagramChannelConfig setTrafficClass(int trafficClass) {
302         try {
303             datagramChannel.socket.setTrafficClass(trafficClass);
304             return this;
305         } catch (IOException e) {
306             throw new ChannelException(e);
307         }
308     }
309 
310     @Override
311     public boolean isReuseAddress() {
312         try {
313             return datagramChannel.socket.isReuseAddress();
314         } catch (IOException e) {
315             throw new ChannelException(e);
316         }
317     }
318 
319     @Override
320     public KQueueDatagramChannelConfig setReuseAddress(boolean reuseAddress) {
321         try {
322             datagramChannel.socket.setReuseAddress(reuseAddress);
323             return this;
324         } catch (IOException e) {
325             throw new ChannelException(e);
326         }
327     }
328 
329     @Override
330     public boolean isBroadcast() {
331         try {
332             return datagramChannel.socket.isBroadcast();
333         } catch (IOException e) {
334             throw new ChannelException(e);
335         }
336     }
337 
338     @Override
339     public KQueueDatagramChannelConfig setBroadcast(boolean broadcast) {
340         try {
341             datagramChannel.socket.setBroadcast(broadcast);
342             return this;
343         } catch (IOException e) {
344             throw new ChannelException(e);
345         }
346     }
347 
348     @Override
349     public boolean isLoopbackModeDisabled() {
350         return false;
351     }
352 
353     @Override
354     public DatagramChannelConfig setLoopbackModeDisabled(boolean loopbackModeDisabled) {
355         throw new UnsupportedOperationException("Multicast not supported");
356     }
357 
358     @Override
359     public int getTimeToLive() {
360         return -1;
361     }
362 
363     @Override
364     public KQueueDatagramChannelConfig setTimeToLive(int ttl) {
365         throw new UnsupportedOperationException("Multicast not supported");
366     }
367 
368     @Override
369     public InetAddress getInterface() {
370         return null;
371     }
372 
373     @Override
374     public KQueueDatagramChannelConfig setInterface(InetAddress interfaceAddress) {
375         throw new UnsupportedOperationException("Multicast not supported");
376     }
377 
378     @Override
379     public NetworkInterface getNetworkInterface() {
380         return null;
381     }
382 
383     @Override
384     public KQueueDatagramChannelConfig setNetworkInterface(NetworkInterface networkInterface) {
385         throw new UnsupportedOperationException("Multicast not supported");
386     }
387 }