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  
27  import org.apache.mina.common.BroadcastIoSession;
28  import org.apache.mina.common.IoFilterChain;
29  import org.apache.mina.common.IoHandler;
30  import org.apache.mina.common.IoService;
31  import org.apache.mina.common.IoServiceConfig;
32  import org.apache.mina.common.IoSession;
33  import org.apache.mina.common.IoSessionConfig;
34  import org.apache.mina.common.RuntimeIOException;
35  import org.apache.mina.common.TransportType;
36  import org.apache.mina.common.WriteFuture;
37  import org.apache.mina.common.IoFilter.WriteRequest;
38  import org.apache.mina.common.support.BaseIoSession;
39  import org.apache.mina.transport.socket.nio.DatagramServiceConfig;
40  import org.apache.mina.transport.socket.nio.DatagramSessionConfig;
41  import org.apache.mina.util.Queue;
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: 561242 $, $Date: 2007-07-31 15:43:29 +0900 (화, 31  7월 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 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 Queue();
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     protected void close0() {
147         IoServiceConfig config = getServiceConfig();
148         if (config instanceof DatagramServiceConfig) {
149             ((DatagramServiceConfig) config).getSessionRecycler().remove(this);
150         }
151         filterChain.fireFilterClose(this);
152     }
153 
154     Queue getWriteRequestQueue() {
155         return writeRequestQueue;
156     }
157 
158     public WriteFuture write(Object message, SocketAddress destination) {
159         if (!this.config.isBroadcast()) {
160             throw new IllegalStateException("Non-broadcast session");
161         }
162 
163         return super.write(message, destination);
164     }
165 
166     protected void write0(WriteRequest writeRequest) {
167         filterChain.fireFilterWrite(this, writeRequest);
168     }
169 
170     public int getScheduledWriteRequests() {
171         synchronized (writeRequestQueue) {
172             return writeRequestQueue.messageSize();
173         }
174     }
175 
176     public int getScheduledWriteBytes() {
177         synchronized (writeRequestQueue) {
178             return writeRequestQueue.byteSize();
179         }
180     }
181 
182     public TransportType getTransportType() {
183         return TransportType.DATAGRAM;
184     }
185 
186     public SocketAddress getRemoteAddress() {
187         return remoteAddress;
188     }
189 
190     void setRemoteAddress(SocketAddress remoteAddress) {
191         this.remoteAddress = remoteAddress;
192     }
193 
194     public SocketAddress getLocalAddress() {
195         return localAddress;
196     }
197 
198     public SocketAddress getServiceAddress() {
199         return serviceAddress;
200     }
201 
202     protected void updateTrafficMask() {
203         managerDelegate.updateTrafficMask(this);
204     }
205 
206     int getReadBufferSize() {
207         return readBufferSize;
208     }
209 
210     private class SessionConfigImpl extends DatagramSessionConfigImpl implements
211             DatagramSessionConfig {
212         public int getReceiveBufferSize() {
213             try {
214                 return ch.socket().getReceiveBufferSize();
215             } catch (SocketException e) {
216                 throw new RuntimeIOException(e);
217             }
218         }
219 
220         public void setReceiveBufferSize(int receiveBufferSize) {
221             if (DatagramSessionConfigImpl.isSetReceiveBufferSizeAvailable()) {
222                 try {
223                     ch.socket().setReceiveBufferSize(receiveBufferSize);
224                     // Re-retrieve the effective receive buffer size.
225                     receiveBufferSize = ch.socket().getReceiveBufferSize();
226                     DatagramSessionImpl.this.readBufferSize = receiveBufferSize;
227                 } catch (SocketException e) {
228                     throw new RuntimeIOException(e);
229                 }
230             }
231         }
232 
233         public boolean isBroadcast() {
234             try {
235                 return ch.socket().getBroadcast();
236             } catch (SocketException e) {
237                 throw new RuntimeIOException(e);
238             }
239         }
240 
241         public void setBroadcast(boolean broadcast) {
242             try {
243                 ch.socket().setBroadcast(broadcast);
244             } catch (SocketException e) {
245                 throw new RuntimeIOException(e);
246             }
247         }
248 
249         public int getSendBufferSize() {
250             try {
251                 return ch.socket().getSendBufferSize();
252             } catch (SocketException e) {
253                 throw new RuntimeIOException(e);
254             }
255         }
256 
257         public void setSendBufferSize(int sendBufferSize) {
258             if (DatagramSessionConfigImpl.isSetSendBufferSizeAvailable()) {
259                 try {
260                     ch.socket().setSendBufferSize(sendBufferSize);
261                 } catch (SocketException e) {
262                     throw new RuntimeIOException(e);
263                 }
264             }
265         }
266 
267         public boolean isReuseAddress() {
268             try {
269                 return ch.socket().getReuseAddress();
270             } catch (SocketException e) {
271                 throw new RuntimeIOException(e);
272             }
273         }
274 
275         public void setReuseAddress(boolean reuseAddress) {
276             try {
277                 ch.socket().setReuseAddress(reuseAddress);
278             } catch (SocketException e) {
279                 throw new RuntimeIOException(e);
280             }
281         }
282 
283         public int getTrafficClass() {
284             if (DatagramSessionConfigImpl.isGetTrafficClassAvailable()) {
285                 try {
286                     return ch.socket().getTrafficClass();
287                 } catch (SocketException e) {
288                     throw new RuntimeIOException(e);
289                 }
290             } else {
291                 return 0;
292             }
293         }
294 
295         public void setTrafficClass(int trafficClass) {
296             if (DatagramSessionConfigImpl.isSetTrafficClassAvailable()) {
297                 try {
298                     ch.socket().setTrafficClass(trafficClass);
299                 } catch (SocketException e) {
300                     throw new RuntimeIOException(e);
301                 }
302             }
303         }
304     }
305 }