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  
70      @Override
71      public boolean setOption(String key, Object value) {
72          if (super.setOption(key, value)) {
73              return true;
74          }
75  
76          if (key.equals("writeBufferHighWaterMark")) {
77              setWriteBufferHighWaterMark0(ConversionUtil.toInt(value));
78          } else if (key.equals("writeBufferLowWaterMark")) {
79              setWriteBufferLowWaterMark0(ConversionUtil.toInt(value));
80          } else if (key.equals("writeSpinCount")) {
81              setWriteSpinCount(ConversionUtil.toInt(value));
82          } else {
83              return false;
84          }
85          return true;
86      }
87  
88      public int getWriteBufferHighWaterMark() {
89          return writeBufferHighWaterMark;
90      }
91  
92      public void setWriteBufferHighWaterMark(int writeBufferHighWaterMark) {
93          if (writeBufferHighWaterMark < getWriteBufferLowWaterMark()) {
94              throw new IllegalArgumentException(
95                      "writeBufferHighWaterMark cannot be less than " +
96                              "writeBufferLowWaterMark (" +
97                              getWriteBufferLowWaterMark() + "): " +
98                              writeBufferHighWaterMark);
99          }
100         setWriteBufferHighWaterMark0(writeBufferHighWaterMark);
101     }
102 
103     private void setWriteBufferHighWaterMark0(int writeBufferHighWaterMark) {
104         if (writeBufferHighWaterMark < 0) {
105             throw new IllegalArgumentException("writeBufferHighWaterMark: " +
106                     writeBufferHighWaterMark);
107         }
108         this.writeBufferHighWaterMark = writeBufferHighWaterMark;
109     }
110 
111     public int getWriteBufferLowWaterMark() {
112         return writeBufferLowWaterMark;
113     }
114 
115     public void setWriteBufferLowWaterMark(int writeBufferLowWaterMark) {
116         if (writeBufferLowWaterMark > getWriteBufferHighWaterMark()) {
117             throw new IllegalArgumentException(
118                     "writeBufferLowWaterMark cannot be greater than " +
119                             "writeBufferHighWaterMark (" +
120                             getWriteBufferHighWaterMark() + "): " +
121                             writeBufferLowWaterMark);
122         }
123         setWriteBufferLowWaterMark0(writeBufferLowWaterMark);
124     }
125 
126     private void setWriteBufferLowWaterMark0(int writeBufferLowWaterMark) {
127         if (writeBufferLowWaterMark < 0) {
128             throw new IllegalArgumentException("writeBufferLowWaterMark: " +
129                     writeBufferLowWaterMark);
130         }
131         this.writeBufferLowWaterMark = writeBufferLowWaterMark;
132     }
133 
134     public int getWriteSpinCount() {
135         return writeSpinCount;
136     }
137 
138     public void setWriteSpinCount(int writeSpinCount) {
139         if (writeSpinCount <= 0) {
140             throw new IllegalArgumentException(
141                     "writeSpinCount must be a positive integer.");
142         }
143         this.writeSpinCount = writeSpinCount;
144     }
145 
146     @Override
147     public void setNetworkInterface(NetworkInterface networkInterface) {
148         if (DetectionUtil.javaVersion() < 7) {
149             throw new UnsupportedOperationException();
150         } else {
151             try {
152                 channel.setOption(StandardSocketOptions.IP_MULTICAST_IF, networkInterface);
153             } catch (IOException e) {
154                 throw new ChannelException(e);
155             }
156         }
157     }
158 
159     @Override
160     public NetworkInterface getNetworkInterface() {
161         if (DetectionUtil.javaVersion() < 7) {
162             throw new UnsupportedOperationException();
163         } else {
164             try {
165                 return channel.getOption(StandardSocketOptions.IP_MULTICAST_IF);
166             } catch (IOException e) {
167                 throw new ChannelException(e);
168             }
169         }
170     }
171 
172     @Override
173     public int getTimeToLive() {
174         if (DetectionUtil.javaVersion() < 7) {
175             throw new UnsupportedOperationException();
176         } else {
177             try {
178                 return channel.getOption(StandardSocketOptions.IP_MULTICAST_TTL);
179             } catch (IOException e) {
180                 throw new ChannelException(e);
181             }
182         }
183     }
184 
185     @Override
186     public void setTimeToLive(int ttl) {
187         if (DetectionUtil.javaVersion() < 7) {
188             throw new UnsupportedOperationException();
189         } else {
190             try {
191                 channel.setOption(StandardSocketOptions.IP_MULTICAST_TTL, ttl);
192             } catch (IOException e) {
193                 throw new ChannelException(e);
194             }
195         }
196 
197     }
198 
199     @Override
200     public InetAddress getInterface() {
201         NetworkInterface inf = getNetworkInterface();
202         if (inf == null) {
203             return null;
204         } else {
205             Enumeration<InetAddress> addresses = inf.getInetAddresses();
206             if (addresses.hasMoreElements()) {
207                 return addresses.nextElement();
208             }
209             return null;
210         }
211     }
212 
213     @Override
214     public void setInterface(InetAddress interfaceAddress) {
215         try {
216             setNetworkInterface(NetworkInterface.getByInetAddress(interfaceAddress));
217         } catch (SocketException e) {
218             throw new ChannelException(e);
219         }
220     }
221 
222     @Override
223     public boolean isLoopbackModeDisabled() {
224         if (DetectionUtil.javaVersion() < 7) {
225             throw new UnsupportedOperationException();
226         } else {
227             try {
228                 return channel.getOption(StandardSocketOptions.IP_MULTICAST_LOOP);
229             } catch (IOException e) {
230                 throw new ChannelException(e);
231             }
232         }
233     }
234 
235     @Override
236     public void setLoopbackModeDisabled(boolean loopbackModeDisabled) {
237         if (DetectionUtil.javaVersion() < 7) {
238             throw new UnsupportedOperationException();
239         } else {
240             try {
241                 channel.setOption(StandardSocketOptions.IP_MULTICAST_LOOP, loopbackModeDisabled);
242             } catch (IOException e) {
243                 throw new ChannelException(e);
244             }
245         }
246     }
247 
248 
249 }