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    *   https://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 boolean activeOnOpen;
49  
50      KQueueDatagramChannelConfig(KQueueDatagramChannel channel) {
51          super(channel);
52          setRecvByteBufAllocator(DEFAULT_RCVBUF_ALLOCATOR);
53      }
54  
55      @Override
56      @SuppressWarnings("deprecation")
57      public Map<ChannelOption<?>, Object> getOptions() {
58          return getOptions(
59                  super.getOptions(),
60                  SO_BROADCAST, SO_RCVBUF, SO_SNDBUF, SO_REUSEADDR, IP_MULTICAST_LOOP_DISABLED,
61                  IP_MULTICAST_ADDR, IP_MULTICAST_IF, IP_MULTICAST_TTL,
62                  IP_TOS, DATAGRAM_CHANNEL_ACTIVE_ON_REGISTRATION, SO_REUSEPORT);
63      }
64  
65      @SuppressWarnings({ "unchecked", "deprecation" })
66      @Override
67      public <T> T getOption(ChannelOption<T> option) {
68          if (option == SO_BROADCAST) {
69              return (T) Boolean.valueOf(isBroadcast());
70          }
71          if (option == SO_RCVBUF) {
72              return (T) Integer.valueOf(getReceiveBufferSize());
73          }
74          if (option == SO_SNDBUF) {
75              return (T) Integer.valueOf(getSendBufferSize());
76          }
77          if (option == SO_REUSEADDR) {
78              return (T) Boolean.valueOf(isReuseAddress());
79          }
80          if (option == IP_MULTICAST_LOOP_DISABLED) {
81              return (T) Boolean.valueOf(isLoopbackModeDisabled());
82          }
83          if (option == IP_MULTICAST_ADDR) {
84              return (T) getInterface();
85          }
86          if (option == IP_MULTICAST_IF) {
87              return (T) getNetworkInterface();
88          }
89          if (option == IP_MULTICAST_TTL) {
90              return (T) Integer.valueOf(getTimeToLive());
91          }
92          if (option == IP_TOS) {
93              return (T) Integer.valueOf(getTrafficClass());
94          }
95          if (option == DATAGRAM_CHANNEL_ACTIVE_ON_REGISTRATION) {
96              return (T) Boolean.valueOf(activeOnOpen);
97          }
98          if (option == SO_REUSEPORT) {
99              return (T) Boolean.valueOf(isReusePort());
100         }
101         return super.getOption(option);
102     }
103 
104     @Override
105     @SuppressWarnings("deprecation")
106     public <T> boolean setOption(ChannelOption<T> option, T value) {
107         validate(option, value);
108 
109         if (option == SO_BROADCAST) {
110             setBroadcast((Boolean) value);
111         } else if (option == SO_RCVBUF) {
112             setReceiveBufferSize((Integer) value);
113         } else if (option == SO_SNDBUF) {
114             setSendBufferSize((Integer) value);
115         } else if (option == SO_REUSEADDR) {
116             setReuseAddress((Boolean) value);
117         } else if (option == IP_MULTICAST_LOOP_DISABLED) {
118             setLoopbackModeDisabled((Boolean) value);
119         } else if (option == IP_MULTICAST_ADDR) {
120             setInterface((InetAddress) value);
121         } else if (option == IP_MULTICAST_IF) {
122             setNetworkInterface((NetworkInterface) value);
123         } else if (option == IP_MULTICAST_TTL) {
124             setTimeToLive((Integer) value);
125         } else if (option == IP_TOS) {
126             setTrafficClass((Integer) value);
127         } else if (option == DATAGRAM_CHANNEL_ACTIVE_ON_REGISTRATION) {
128             setActiveOnOpen((Boolean) value);
129         } else if (option == SO_REUSEPORT) {
130             setReusePort((Boolean) value);
131         } else {
132             return super.setOption(option, value);
133         }
134 
135         return true;
136     }
137 
138     private void setActiveOnOpen(boolean activeOnOpen) {
139         if (channel.isRegistered()) {
140             throw new IllegalStateException("Can only changed before channel was registered");
141         }
142         this.activeOnOpen = activeOnOpen;
143     }
144 
145     boolean getActiveOnOpen() {
146         return activeOnOpen;
147     }
148 
149     /**
150      * Returns {@code true} if the SO_REUSEPORT option is set.
151      */
152     public boolean isReusePort() {
153         try {
154             return ((KQueueDatagramChannel) channel).socket.isReusePort();
155         } catch (IOException e) {
156             throw new ChannelException(e);
157         }
158     }
159 
160     /**
161      * Set the SO_REUSEPORT option on the underlying Channel. This will allow to bind multiple
162      * {@link KQueueSocketChannel}s to the same port and so accept connections with multiple threads.
163      *
164      * Be aware this method needs be called before {@link KQueueDatagramChannel#bind(java.net.SocketAddress)} to have
165      * any affect.
166      */
167     public KQueueDatagramChannelConfig setReusePort(boolean reusePort) {
168         try {
169             ((KQueueDatagramChannel) channel).socket.setReusePort(reusePort);
170             return this;
171         } catch (IOException e) {
172             throw new ChannelException(e);
173         }
174     }
175 
176     @Override
177     public KQueueDatagramChannelConfig setRcvAllocTransportProvidesGuess(boolean transportProvidesGuess) {
178         super.setRcvAllocTransportProvidesGuess(transportProvidesGuess);
179         return this;
180     }
181 
182     @Override
183     public KQueueDatagramChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator) {
184         super.setMessageSizeEstimator(estimator);
185         return this;
186     }
187 
188     @Override
189     @Deprecated
190     public KQueueDatagramChannelConfig setWriteBufferLowWaterMark(int writeBufferLowWaterMark) {
191         super.setWriteBufferLowWaterMark(writeBufferLowWaterMark);
192         return this;
193     }
194 
195     @Override
196     @Deprecated
197     public KQueueDatagramChannelConfig setWriteBufferHighWaterMark(int writeBufferHighWaterMark) {
198         super.setWriteBufferHighWaterMark(writeBufferHighWaterMark);
199         return this;
200     }
201 
202     @Override
203     public KQueueDatagramChannelConfig setWriteBufferWaterMark(WriteBufferWaterMark writeBufferWaterMark) {
204         super.setWriteBufferWaterMark(writeBufferWaterMark);
205         return this;
206     }
207 
208     @Override
209     public KQueueDatagramChannelConfig setAutoClose(boolean autoClose) {
210         super.setAutoClose(autoClose);
211         return this;
212     }
213 
214     @Override
215     public KQueueDatagramChannelConfig setAutoRead(boolean autoRead) {
216         super.setAutoRead(autoRead);
217         return this;
218     }
219 
220     @Override
221     public KQueueDatagramChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator) {
222         super.setRecvByteBufAllocator(allocator);
223         return this;
224     }
225 
226     @Override
227     public KQueueDatagramChannelConfig setWriteSpinCount(int writeSpinCount) {
228         super.setWriteSpinCount(writeSpinCount);
229         return this;
230     }
231 
232     @Override
233     public KQueueDatagramChannelConfig setAllocator(ByteBufAllocator allocator) {
234         super.setAllocator(allocator);
235         return this;
236     }
237 
238     @Override
239     public KQueueDatagramChannelConfig setConnectTimeoutMillis(int connectTimeoutMillis) {
240         super.setConnectTimeoutMillis(connectTimeoutMillis);
241         return this;
242     }
243 
244     @Override
245     @Deprecated
246     public KQueueDatagramChannelConfig setMaxMessagesPerRead(int maxMessagesPerRead) {
247         super.setMaxMessagesPerRead(maxMessagesPerRead);
248         return this;
249     }
250 
251     @Override
252     public int getSendBufferSize() {
253         try {
254             return ((KQueueDatagramChannel) channel).socket.getSendBufferSize();
255         } catch (IOException e) {
256             throw new ChannelException(e);
257         }
258     }
259 
260     @Override
261     public KQueueDatagramChannelConfig setSendBufferSize(int sendBufferSize) {
262         try {
263             ((KQueueDatagramChannel) channel).socket.setSendBufferSize(sendBufferSize);
264             return this;
265         } catch (IOException e) {
266             throw new ChannelException(e);
267         }
268     }
269 
270     @Override
271     public int getReceiveBufferSize() {
272         try {
273             return ((KQueueDatagramChannel) channel).socket.getReceiveBufferSize();
274         } catch (IOException e) {
275             throw new ChannelException(e);
276         }
277     }
278 
279     @Override
280     public KQueueDatagramChannelConfig setReceiveBufferSize(int receiveBufferSize) {
281         try {
282             ((KQueueDatagramChannel) channel).socket.setReceiveBufferSize(receiveBufferSize);
283             return this;
284         } catch (IOException e) {
285             throw new ChannelException(e);
286         }
287     }
288 
289     @Override
290     public int getTrafficClass() {
291         try {
292             return ((KQueueDatagramChannel) channel).socket.getTrafficClass();
293         } catch (IOException e) {
294             throw new ChannelException(e);
295         }
296     }
297 
298     @Override
299     public KQueueDatagramChannelConfig setTrafficClass(int trafficClass) {
300         try {
301             ((KQueueDatagramChannel) channel).socket.setTrafficClass(trafficClass);
302             return this;
303         } catch (IOException e) {
304             throw new ChannelException(e);
305         }
306     }
307 
308     @Override
309     public boolean isReuseAddress() {
310         try {
311             return ((KQueueDatagramChannel) channel).socket.isReuseAddress();
312         } catch (IOException e) {
313             throw new ChannelException(e);
314         }
315     }
316 
317     @Override
318     public KQueueDatagramChannelConfig setReuseAddress(boolean reuseAddress) {
319         try {
320             ((KQueueDatagramChannel) channel).socket.setReuseAddress(reuseAddress);
321             return this;
322         } catch (IOException e) {
323             throw new ChannelException(e);
324         }
325     }
326 
327     @Override
328     public boolean isBroadcast() {
329         try {
330             return ((KQueueDatagramChannel) channel).socket.isBroadcast();
331         } catch (IOException e) {
332             throw new ChannelException(e);
333         }
334     }
335 
336     @Override
337     public KQueueDatagramChannelConfig setBroadcast(boolean broadcast) {
338         try {
339             ((KQueueDatagramChannel) channel).socket.setBroadcast(broadcast);
340             return this;
341         } catch (IOException e) {
342             throw new ChannelException(e);
343         }
344     }
345 
346     @Override
347     public boolean isLoopbackModeDisabled() {
348         return false;
349     }
350 
351     @Override
352     public DatagramChannelConfig setLoopbackModeDisabled(boolean loopbackModeDisabled) {
353         throw new UnsupportedOperationException("Multicast not supported");
354     }
355 
356     @Override
357     public int getTimeToLive() {
358         return -1;
359     }
360 
361     @Override
362     public KQueueDatagramChannelConfig setTimeToLive(int ttl) {
363         throw new UnsupportedOperationException("Multicast not supported");
364     }
365 
366     @Override
367     public InetAddress getInterface() {
368         return null;
369     }
370 
371     @Override
372     public KQueueDatagramChannelConfig setInterface(InetAddress interfaceAddress) {
373         throw new UnsupportedOperationException("Multicast not supported");
374     }
375 
376     @Override
377     public NetworkInterface getNetworkInterface() {
378         return null;
379     }
380 
381     @Override
382     public KQueueDatagramChannelConfig setNetworkInterface(NetworkInterface networkInterface) {
383         throw new UnsupportedOperationException("Multicast not supported");
384     }
385 
386     @Override
387     public KQueueDatagramChannelConfig setMaxMessagesPerWrite(int maxMessagesPerWrite) {
388         super.setMaxMessagesPerWrite(maxMessagesPerWrite);
389         return this;
390     }
391 }