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