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 org.jboss.netty.channel.socket.nio;
17  
18  import java.io.IOException;
19  import java.net.InetAddress;
20  import java.net.NetworkInterface;
21  import java.net.SocketException;
22  import java.net.StandardSocketOptions;
23  import java.nio.channels.DatagramChannel;
24  import java.util.Enumeration;
25  import java.util.Map;
26  
27  import org.jboss.netty.channel.ChannelException;
28  import org.jboss.netty.channel.socket.DefaultDatagramChannelConfig;
29  import org.jboss.netty.logging.InternalLogger;
30  import org.jboss.netty.logging.InternalLoggerFactory;
31  import org.jboss.netty.util.internal.ConversionUtil;
32  import org.jboss.netty.util.internal.DetectionUtil;
33  
34  /**
35   * The default {@link NioSocketChannelConfig} implementation.
36   */
37  class DefaultNioDatagramChannelConfig extends DefaultDatagramChannelConfig
38          implements NioDatagramChannelConfig {
39  
40      private static final InternalLogger logger =
41              InternalLoggerFactory
42                      .getInstance(DefaultNioDatagramChannelConfig.class);
43  
44      private volatile int writeBufferHighWaterMark = 64 * 1024;
45      private volatile int writeBufferLowWaterMark = 32 * 1024;
46      private volatile int writeSpinCount = 16;
47      private final DatagramChannel channel;
48  
49      DefaultNioDatagramChannelConfig(DatagramChannel channel) {
50          super(channel.socket());
51          this.channel = channel;
52      }
53  
54      @Override
55      public void setOptions(Map<String, Object> options) {
56          super.setOptions(options);
57          if (getWriteBufferHighWaterMark() < getWriteBufferLowWaterMark()) {
58              // Recover the integrity of the configuration with a sensible value.
59              setWriteBufferLowWaterMark0(getWriteBufferHighWaterMark() >>> 1);
60              if (logger.isWarnEnabled()) {
61                  // Notify the user about misconfiguration.
62                  logger.warn("writeBufferLowWaterMark cannot be greater than "
63                          + "writeBufferHighWaterMark; setting to the half of the "
64                          + "writeBufferHighWaterMark.");
65              }
66          }
67      }
68  
69      @Override
70      public boolean setOption(String key, Object value) {
71          if (super.setOption(key, value)) {
72              return true;
73          }
74  
75          if ("writeBufferHighWaterMark".equals(key)) {
76              setWriteBufferHighWaterMark0(ConversionUtil.toInt(value));
77          } else if ("writeBufferLowWaterMark".equals(key)) {
78              setWriteBufferLowWaterMark0(ConversionUtil.toInt(value));
79          } else if ("writeSpinCount".equals(key)) {
80              setWriteSpinCount(ConversionUtil.toInt(value));
81          } else {
82              return false;
83          }
84          return true;
85      }
86  
87      public int getWriteBufferHighWaterMark() {
88          return writeBufferHighWaterMark;
89      }
90  
91      public void setWriteBufferHighWaterMark(int writeBufferHighWaterMark) {
92          if (writeBufferHighWaterMark < getWriteBufferLowWaterMark()) {
93              throw new IllegalArgumentException(
94                      "writeBufferHighWaterMark cannot be less than " +
95                              "writeBufferLowWaterMark (" +
96                              getWriteBufferLowWaterMark() + "): " +
97                              writeBufferHighWaterMark);
98          }
99          setWriteBufferHighWaterMark0(writeBufferHighWaterMark);
100     }
101 
102     private void setWriteBufferHighWaterMark0(int writeBufferHighWaterMark) {
103         if (writeBufferHighWaterMark < 0) {
104             throw new IllegalArgumentException("writeBufferHighWaterMark: " +
105                     writeBufferHighWaterMark);
106         }
107         this.writeBufferHighWaterMark = writeBufferHighWaterMark;
108     }
109 
110     public int getWriteBufferLowWaterMark() {
111         return writeBufferLowWaterMark;
112     }
113 
114     public void setWriteBufferLowWaterMark(int writeBufferLowWaterMark) {
115         if (writeBufferLowWaterMark > getWriteBufferHighWaterMark()) {
116             throw new IllegalArgumentException(
117                     "writeBufferLowWaterMark cannot be greater than " +
118                             "writeBufferHighWaterMark (" +
119                             getWriteBufferHighWaterMark() + "): " +
120                             writeBufferLowWaterMark);
121         }
122         setWriteBufferLowWaterMark0(writeBufferLowWaterMark);
123     }
124 
125     private void setWriteBufferLowWaterMark0(int writeBufferLowWaterMark) {
126         if (writeBufferLowWaterMark < 0) {
127             throw new IllegalArgumentException("writeBufferLowWaterMark: " +
128                     writeBufferLowWaterMark);
129         }
130         this.writeBufferLowWaterMark = writeBufferLowWaterMark;
131     }
132 
133     public int getWriteSpinCount() {
134         return writeSpinCount;
135     }
136 
137     public void setWriteSpinCount(int writeSpinCount) {
138         if (writeSpinCount <= 0) {
139             throw new IllegalArgumentException(
140                     "writeSpinCount must be a positive integer.");
141         }
142         this.writeSpinCount = writeSpinCount;
143     }
144 
145     @Override
146     public void setNetworkInterface(NetworkInterface networkInterface) {
147         if (DetectionUtil.javaVersion() < 7) {
148             throw new UnsupportedOperationException();
149         } else {
150             try {
151                 channel.setOption(StandardSocketOptions.IP_MULTICAST_IF, networkInterface);
152             } catch (IOException e) {
153                 throw new ChannelException(e);
154             }
155         }
156     }
157 
158     @Override
159     public NetworkInterface getNetworkInterface() {
160         if (DetectionUtil.javaVersion() < 7) {
161             throw new UnsupportedOperationException();
162         } else {
163             try {
164                 return channel.getOption(StandardSocketOptions.IP_MULTICAST_IF);
165             } catch (IOException e) {
166                 throw new ChannelException(e);
167             }
168         }
169     }
170 
171     @Override
172     public int getTimeToLive() {
173         if (DetectionUtil.javaVersion() < 7) {
174             throw new UnsupportedOperationException();
175         } else {
176             try {
177                 return channel.getOption(StandardSocketOptions.IP_MULTICAST_TTL);
178             } catch (IOException e) {
179                 throw new ChannelException(e);
180             }
181         }
182     }
183 
184     @Override
185     public void setTimeToLive(int ttl) {
186         if (DetectionUtil.javaVersion() < 7) {
187             throw new UnsupportedOperationException();
188         } else {
189             try {
190                 channel.setOption(StandardSocketOptions.IP_MULTICAST_TTL, ttl);
191             } catch (IOException e) {
192                 throw new ChannelException(e);
193             }
194         }
195     }
196 
197     @Override
198     public InetAddress getInterface() {
199         NetworkInterface inf = getNetworkInterface();
200         if (inf == null) {
201             return null;
202         } else {
203             Enumeration<InetAddress> addresses = inf.getInetAddresses();
204             if (addresses.hasMoreElements()) {
205                 return addresses.nextElement();
206             }
207             return null;
208         }
209     }
210 
211     @Override
212     public void setInterface(InetAddress interfaceAddress) {
213         try {
214             setNetworkInterface(NetworkInterface.getByInetAddress(interfaceAddress));
215         } catch (SocketException e) {
216             throw new ChannelException(e);
217         }
218     }
219 
220     @Override
221     public boolean isLoopbackModeDisabled() {
222         if (DetectionUtil.javaVersion() < 7) {
223             throw new UnsupportedOperationException();
224         } else {
225             try {
226                 return channel.getOption(StandardSocketOptions.IP_MULTICAST_LOOP);
227             } catch (IOException e) {
228                 throw new ChannelException(e);
229             }
230         }
231     }
232 
233     @Override
234     public void setLoopbackModeDisabled(boolean loopbackModeDisabled) {
235         if (DetectionUtil.javaVersion() < 7) {
236             throw new UnsupportedOperationException();
237         } else {
238             try {
239                 channel.setOption(StandardSocketOptions.IP_MULTICAST_LOOP, loopbackModeDisabled);
240             } catch (IOException e) {
241                 throw new ChannelException(e);
242             }
243         }
244     }
245 }