View Javadoc

    1   /*
    2    *  Licensed to the Apache Software Foundation (ASF) under one
    3    *  or more contributor license agreements.  See the NOTICE file
    4    *  distributed with this work for additional information
    5    *  regarding copyright ownership.  The ASF licenses this file
    6    *  to you under the Apache License, Version 2.0 (the
    7    *  "License"); you may not use this file except in compliance
    8    *  with the License.  You may obtain a copy of the License at
    9    *
    10   *    http://www.apache.org/licenses/LICENSE-2.0
    11   *
    12   *  Unless required by applicable law or agreed to in writing,
    13   *  software distributed under the License is distributed on an
    14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    15   *  KIND, either express or implied.  See the License for the
    16   *  specific language governing permissions and limitations
    17   *  under the License.
    18   *
    19   */
    20  package org.apache.mina.transport.socket.nio.support;
    21
    22  import java.net.SocketAddress;
    23  import java.net.SocketException;
    24  import java.nio.channels.DatagramChannel;
    25  import java.nio.channels.SelectionKey;
    26  import java.util.Queue;
    27  import java.util.concurrent.ConcurrentLinkedQueue;
    28
    29  import org.apache.mina.common.BroadcastIoSession;
    30  import org.apache.mina.common.IoFilterChain;
    31  import org.apache.mina.common.IoHandler;
    32  import org.apache.mina.common.IoService;
    33  import org.apache.mina.common.IoServiceConfig;
    34  import org.apache.mina.common.IoSession;
    35  import org.apache.mina.common.IoSessionConfig;
    36  import org.apache.mina.common.RuntimeIOException;
    37  import org.apache.mina.common.TransportType;
    38  import org.apache.mina.common.IoFilter.WriteRequest;
    39  import org.apache.mina.common.support.BaseIoSession;
    40  import org.apache.mina.transport.socket.nio.DatagramServiceConfig;
    41  import org.apache.mina.transport.socket.nio.DatagramSessionConfig;
    42
    43  /**
    44   * An {@link IoSession} for datagram transport (UDP/IP).
    45   *
    46   * @author The Apache Directory Project (mina-dev@directory.apache.org)
    47   * @version $Rev: 585050 $, $Date: 2007-10-16 14:57:53 +0900 (Tue, 16 Oct 2007) $
    48   */
    49  class DatagramSessionImpl extends BaseIoSession implements BroadcastIoSession {
    50      private final IoService wrapperManager;
    51
    52      private final IoServiceConfig serviceConfig;
    53
    54      private final DatagramSessionConfig config = new SessionConfigImpl();
    55
    56      private final DatagramService managerDelegate;
    57
    58      private final DatagramFilterChain filterChain;
    59
    60      private final DatagramChannel ch;
    61
    62      private final Queue<WriteRequest> writeRequestQueue;
    63
    64      private final IoHandler handler;
    65
    66      private final SocketAddress localAddress;
    67
    68      private final SocketAddress serviceAddress;
    69
    70      private SocketAddress remoteAddress;
    71
    72      private SelectionKey key;
    73
    74      private int readBufferSize;
    75
    76      /**
    77       * Creates a new instance.
    78       */
    79      DatagramSessionImpl(IoService wrapperManager,
    80              DatagramService managerDelegate, IoServiceConfig serviceConfig,
    81              DatagramChannel ch, IoHandler defaultHandler,
    82              SocketAddress serviceAddress, SocketAddress localAddress) {
    83          this.wrapperManager = wrapperManager;
    84          this.managerDelegate = managerDelegate;
    85          this.filterChain = new DatagramFilterChain(this);
    86          this.ch = ch;
    87          this.writeRequestQueue = new ConcurrentLinkedQueue<WriteRequest>();
    88          this.handler = defaultHandler;
    89          this.remoteAddress = ch.socket().getRemoteSocketAddress();
    90
    91          this.serviceAddress = serviceAddress;
    92          this.localAddress = localAddress;
    93          this.serviceConfig = serviceConfig;
    94
    95          // Apply the initial session settings
    96          IoSessionConfig sessionConfig = serviceConfig.getSessionConfig();
    97          if (sessionConfig instanceof DatagramSessionConfig) {
    98              DatagramSessionConfig cfg = (DatagramSessionConfig) sessionConfig;
    99              this.config.setBroadcast(cfg.isBroadcast());
    100             this.config.setReceiveBufferSize(cfg.getReceiveBufferSize());
    101             this.config.setReuseAddress(cfg.isReuseAddress());
    102             this.config.setSendBufferSize(cfg.getSendBufferSize());
    103
    104             if (this.config.getTrafficClass() != cfg.getTrafficClass()) {
    105                 this.config.setTrafficClass(cfg.getTrafficClass());
    106             }
    107         }
    108     }
    109
    110     public IoService getService() {
    111         return wrapperManager;
    112     }
    113
    114     public IoServiceConfig getServiceConfig() {
    115         return serviceConfig;
    116     }
    117
    118     public IoSessionConfig getConfig() {
    119         return config;
    120     }
    121
    122     DatagramService getManagerDelegate() {
    123         return managerDelegate;
    124     }
    125
    126     public IoFilterChain getFilterChain() {
    127         return filterChain;
    128     }
    129
    130     DatagramChannel getChannel() {
    131         return ch;
    132     }
    133
    134     SelectionKey getSelectionKey() {
    135         return key;
    136     }
    137
    138     void setSelectionKey(SelectionKey key) {
    139         this.key = key;
    140     }
    141
    142     public IoHandler getHandler() {
    143         return handler;
    144     }
    145
    146     @Override
    147     protected void close0() {
    148         IoServiceConfig config = getServiceConfig();
    149         if (config instanceof DatagramServiceConfig) {
    150             ((DatagramServiceConfig) config).getSessionRecycler().remove(this);
    151         }
    152         filterChain.fireFilterClose(this);
    153     }
    154
    155     Queue<WriteRequest> getWriteRequestQueue() {
    156         return writeRequestQueue;
    157     }
    158
    159     @Override
    160     protected void write0(WriteRequest writeRequest) {
    161         filterChain.fireFilterWrite(this, writeRequest);
    162     }
    163
    164     public TransportType getTransportType() {
    165         return TransportType.DATAGRAM;
    166     }
    167
    168     public SocketAddress getRemoteAddress() {
    169         return remoteAddress;
    170     }
    171
    172     void setRemoteAddress(SocketAddress remoteAddress) {
    173         this.remoteAddress = remoteAddress;
    174     }
    175
    176     public SocketAddress getLocalAddress() {
    177         return localAddress;
    178     }
    179
    180     public SocketAddress getServiceAddress() {
    181         return serviceAddress;
    182     }
    183
    184     @Override
    185     protected void updateTrafficMask() {
    186         managerDelegate.updateTrafficMask(this);
    187     }
    188
    189     int getReadBufferSize() {
    190         return readBufferSize;
    191     }
    192
    193     private class SessionConfigImpl extends DatagramSessionConfigImpl implements
    194             DatagramSessionConfig {
    195         @Override
    196         public int getReceiveBufferSize() {
    197             try {
    198                 return ch.socket().getReceiveBufferSize();
    199             } catch (SocketException e) {
    200                 throw new RuntimeIOException(e);
    201             }
    202         }
    203
    204         @Override
    205         public void setReceiveBufferSize(int receiveBufferSize) {
    206             if (DatagramSessionConfigImpl.isSetReceiveBufferSizeAvailable()) {
    207                 try {
    208                     ch.socket().setReceiveBufferSize(receiveBufferSize);
    209                     // Re-retrieve the effective receive buffer size.
    210                     receiveBufferSize = ch.socket().getReceiveBufferSize();
    211                     DatagramSessionImpl.this.readBufferSize = receiveBufferSize;
    212                 } catch (SocketException e) {
    213                     throw new RuntimeIOException(e);
    214                 }
    215             }
    216         }
    217
    218         @Override
    219         public boolean isBroadcast() {
    220             try {
    221                 return ch.socket().getBroadcast();
    222             } catch (SocketException e) {
    223                 throw new RuntimeIOException(e);
    224             }
    225         }
    226
    227         @Override
    228         public void setBroadcast(boolean broadcast) {
    229             try {
    230                 ch.socket().setBroadcast(broadcast);
    231             } catch (SocketException e) {
    232                 throw new RuntimeIOException(e);
    233             }
    234         }
    235
    236         @Override
    237         public int getSendBufferSize() {
    238             try {
    239                 return ch.socket().getSendBufferSize();
    240             } catch (SocketException e) {
    241                 throw new RuntimeIOException(e);
    242             }
    243         }
    244
    245         @Override
    246         public void setSendBufferSize(int sendBufferSize) {
    247             if (DatagramSessionConfigImpl.isSetSendBufferSizeAvailable()) {
    248                 try {
    249                     ch.socket().setSendBufferSize(sendBufferSize);
    250                 } catch (SocketException e) {
    251                     throw new RuntimeIOException(e);
    252                 }
    253             }
    254         }
    255
    256         @Override
    257         public boolean isReuseAddress() {
    258             try {
    259                 return ch.socket().getReuseAddress();
    260             } catch (SocketException e) {
    261                 throw new RuntimeIOException(e);
    262             }
    263         }
    264
    265         @Override
    266         public void setReuseAddress(boolean reuseAddress) {
    267             try {
    268                 ch.socket().setReuseAddress(reuseAddress);
    269             } catch (SocketException e) {
    270                 throw new RuntimeIOException(e);
    271             }
    272         }
    273
    274         @Override
    275         public int getTrafficClass() {
    276             if (DatagramSessionConfigImpl.isGetTrafficClassAvailable()) {
    277                 try {
    278                     return ch.socket().getTrafficClass();
    279                 } catch (SocketException e) {
    280                     throw new RuntimeIOException(e);
    281                 }
    282             } else {
    283                 return 0;
    284             }
    285         }
    286
    287         @Override
    288         public void setTrafficClass(int trafficClass) {
    289             if (DatagramSessionConfigImpl.isSetTrafficClassAvailable()) {
    290                 try {
    291                     ch.socket().setTrafficClass(trafficClass);
    292                 } catch (SocketException e) {
    293                     throw new RuntimeIOException(e);
    294                 }
    295             }
    296         }
    297     }
    298 }