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