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.WriteFuture;
39  import org.apache.mina.common.IoFilter.WriteRequest;
40  import org.apache.mina.common.support.BaseIoSession;
41  import org.apache.mina.transport.socket.nio.DatagramServiceConfig;
42  import org.apache.mina.transport.socket.nio.DatagramSessionConfig;
43  
44  /**
45   * An {@link IoSession} for datagram transport (UDP/IP).
46   *
47   * @author The Apache Directory Project (mina-dev@directory.apache.org)
48   * @version $Rev: 580333 $, $Date: 2007-09-28 21:45:13 +0900 (Fri, 28 Sep 2007) $
49   */
50  class DatagramSessionImpl extends BaseIoSession implements BroadcastIoSession {
51      private final IoService wrapperManager;
52  
53      private final IoServiceConfig serviceConfig;
54  
55      private final DatagramSessionConfig config = new SessionConfigImpl();
56  
57      private final DatagramService managerDelegate;
58  
59      private final DatagramFilterChain filterChain;
60  
61      private final DatagramChannel ch;
62  
63      private final Queue<WriteRequest> writeRequestQueue;
64  
65      private final IoHandler handler;
66  
67      private final SocketAddress localAddress;
68  
69      private final SocketAddress serviceAddress;
70  
71      private SocketAddress remoteAddress;
72  
73      private SelectionKey key;
74  
75      private int readBufferSize;
76  
77      /**
78       * Creates a new instance.
79       */
80      DatagramSessionImpl(IoService wrapperManager,
81              DatagramService managerDelegate, IoServiceConfig serviceConfig,
82              DatagramChannel ch, IoHandler defaultHandler,
83              SocketAddress serviceAddress, SocketAddress localAddress) {
84          this.wrapperManager = wrapperManager;
85          this.managerDelegate = managerDelegate;
86          this.filterChain = new DatagramFilterChain(this);
87          this.ch = ch;
88          this.writeRequestQueue = new ConcurrentLinkedQueue<WriteRequest>();
89          this.handler = defaultHandler;
90          this.remoteAddress = ch.socket().getRemoteSocketAddress();
91  
92          this.serviceAddress = serviceAddress;
93          this.localAddress = localAddress;
94          this.serviceConfig = serviceConfig;
95  
96          // Apply the initial session settings
97          IoSessionConfig sessionConfig = serviceConfig.getSessionConfig();
98          if (sessionConfig instanceof DatagramSessionConfig) {
99              DatagramSessionConfig cfg = (DatagramSessionConfig) sessionConfig;
100             this.config.setBroadcast(cfg.isBroadcast());
101             this.config.setReceiveBufferSize(cfg.getReceiveBufferSize());
102             this.config.setReuseAddress(cfg.isReuseAddress());
103             this.config.setSendBufferSize(cfg.getSendBufferSize());
104 
105             if (this.config.getTrafficClass() != cfg.getTrafficClass()) {
106                 this.config.setTrafficClass(cfg.getTrafficClass());
107             }
108         }
109     }
110 
111     public IoService getService() {
112         return wrapperManager;
113     }
114 
115     public IoServiceConfig getServiceConfig() {
116         return serviceConfig;
117     }
118 
119     public IoSessionConfig getConfig() {
120         return config;
121     }
122 
123     DatagramService getManagerDelegate() {
124         return managerDelegate;
125     }
126 
127     public IoFilterChain getFilterChain() {
128         return filterChain;
129     }
130 
131     DatagramChannel getChannel() {
132         return ch;
133     }
134 
135     SelectionKey getSelectionKey() {
136         return key;
137     }
138 
139     void setSelectionKey(SelectionKey key) {
140         this.key = key;
141     }
142 
143     public IoHandler getHandler() {
144         return handler;
145     }
146 
147     @Override
148     protected void close0() {
149         IoServiceConfig config = getServiceConfig();
150         if (config instanceof DatagramServiceConfig) {
151             ((DatagramServiceConfig) config).getSessionRecycler().remove(this);
152         }
153         filterChain.fireFilterClose(this);
154     }
155 
156     Queue<WriteRequest> getWriteRequestQueue() {
157         return writeRequestQueue;
158     }
159 
160     @Override
161     protected void write0(WriteRequest writeRequest) {
162         filterChain.fireFilterWrite(this, writeRequest);
163     }
164 
165     public TransportType getTransportType() {
166         return TransportType.DATAGRAM;
167     }
168 
169     public SocketAddress getRemoteAddress() {
170         return remoteAddress;
171     }
172 
173     void setRemoteAddress(SocketAddress remoteAddress) {
174         this.remoteAddress = remoteAddress;
175     }
176 
177     public SocketAddress getLocalAddress() {
178         return localAddress;
179     }
180 
181     public SocketAddress getServiceAddress() {
182         return serviceAddress;
183     }
184 
185     @Override
186     protected void updateTrafficMask() {
187         managerDelegate.updateTrafficMask(this);
188     }
189 
190     int getReadBufferSize() {
191         return readBufferSize;
192     }
193 
194     private class SessionConfigImpl extends DatagramSessionConfigImpl implements
195             DatagramSessionConfig {
196         @Override
197         public int getReceiveBufferSize() {
198             try {
199                 return ch.socket().getReceiveBufferSize();
200             } catch (SocketException e) {
201                 throw new RuntimeIOException(e);
202             }
203         }
204 
205         @Override
206         public void setReceiveBufferSize(int receiveBufferSize) {
207             if (DatagramSessionConfigImpl.isSetReceiveBufferSizeAvailable()) {
208                 try {
209                     ch.socket().setReceiveBufferSize(receiveBufferSize);
210                     // Re-retrieve the effective receive buffer size.
211                     receiveBufferSize = ch.socket().getReceiveBufferSize();
212                     DatagramSessionImpl.this.readBufferSize = receiveBufferSize;
213                 } catch (SocketException e) {
214                     throw new RuntimeIOException(e);
215                 }
216             }
217         }
218 
219         @Override
220         public boolean isBroadcast() {
221             try {
222                 return ch.socket().getBroadcast();
223             } catch (SocketException e) {
224                 throw new RuntimeIOException(e);
225             }
226         }
227 
228         @Override
229         public void setBroadcast(boolean broadcast) {
230             try {
231                 ch.socket().setBroadcast(broadcast);
232             } catch (SocketException e) {
233                 throw new RuntimeIOException(e);
234             }
235         }
236 
237         @Override
238         public int getSendBufferSize() {
239             try {
240                 return ch.socket().getSendBufferSize();
241             } catch (SocketException e) {
242                 throw new RuntimeIOException(e);
243             }
244         }
245 
246         @Override
247         public void setSendBufferSize(int sendBufferSize) {
248             if (DatagramSessionConfigImpl.isSetSendBufferSizeAvailable()) {
249                 try {
250                     ch.socket().setSendBufferSize(sendBufferSize);
251                 } catch (SocketException e) {
252                     throw new RuntimeIOException(e);
253                 }
254             }
255         }
256 
257         @Override
258         public boolean isReuseAddress() {
259             try {
260                 return ch.socket().getReuseAddress();
261             } catch (SocketException e) {
262                 throw new RuntimeIOException(e);
263             }
264         }
265 
266         @Override
267         public void setReuseAddress(boolean reuseAddress) {
268             try {
269                 ch.socket().setReuseAddress(reuseAddress);
270             } catch (SocketException e) {
271                 throw new RuntimeIOException(e);
272             }
273         }
274 
275         @Override
276         public int getTrafficClass() {
277             if (DatagramSessionConfigImpl.isGetTrafficClassAvailable()) {
278                 try {
279                     return ch.socket().getTrafficClass();
280                 } catch (SocketException e) {
281                     throw new RuntimeIOException(e);
282                 }
283             } else {
284                 return 0;
285             }
286         }
287 
288         @Override
289         public void setTrafficClass(int trafficClass) {
290             if (DatagramSessionConfigImpl.isSetTrafficClassAvailable()) {
291                 try {
292                     ch.socket().setTrafficClass(trafficClass);
293                 } catch (SocketException e) {
294                     throw new RuntimeIOException(e);
295                 }
296             }
297         }
298     }
299 }