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