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 }