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;
21  
22  import java.net.SocketAddress;
23  import java.net.SocketException;
24  import java.nio.channels.SelectionKey;
25  import java.nio.channels.SocketChannel;
26  
27  import org.apache.mina.common.IoFilterChain;
28  import org.apache.mina.common.IoHandler;
29  import org.apache.mina.common.IoService;
30  import org.apache.mina.common.IoServiceConfig;
31  import org.apache.mina.common.IoSession;
32  import org.apache.mina.common.IoSessionConfig;
33  import org.apache.mina.common.RuntimeIOException;
34  import org.apache.mina.common.TransportType;
35  import org.apache.mina.common.IoFilter.WriteRequest;
36  import org.apache.mina.common.support.BaseIoSession;
37  import org.apache.mina.common.support.BaseIoSessionConfig;
38  import org.apache.mina.common.support.IoServiceListenerSupport;
39  import org.apache.mina.util.Queue;
40  
41  /**
42   * An {@link IoSession} for socket transport (TCP/IP).
43   *
44   * @author The Apache Directory Project (mina-dev@directory.apache.org)
45   * @version $Rev: 585050 $, $Date: 2007-10-16 14:57:53 +0900 (화, 16 10월 2007) $
46   */
47  class SocketSessionImpl extends BaseIoSession {
48      private final IoService manager;
49  
50      private final IoServiceConfig serviceConfig;
51  
52      private final SocketSessionConfig config = new SessionConfigImpl();
53  
54      private final SocketIoProcessor ioProcessor;
55  
56      private final SocketFilterChain filterChain;
57  
58      private final SocketChannel ch;
59  
60      private final Queue writeRequestQueue;
61  
62      private final IoHandler handler;
63  
64      private final SocketAddress remoteAddress;
65  
66      private final SocketAddress localAddress;
67  
68      private final SocketAddress serviceAddress;
69  
70      private final IoServiceListenerSupport serviceListeners;
71  
72      private SelectionKey key;
73  
74      private int readBufferSize = 1024;
75      private boolean deferDecreaseReadBufferSize = true;
76  
77      /**
78       * Creates a new instance.
79       */
80      SocketSessionImpl(IoService manager, SocketIoProcessor ioProcessor,
81              IoServiceListenerSupport listeners, IoServiceConfig serviceConfig,
82              SocketChannel ch, IoHandler defaultHandler,
83              SocketAddress serviceAddress) {
84          this.manager = manager;
85          this.serviceListeners = listeners;
86          this.ioProcessor = ioProcessor;
87          this.filterChain = new SocketFilterChain(this);
88          this.ch = ch;
89          this.writeRequestQueue = new Queue();
90          this.handler = defaultHandler;
91          this.remoteAddress = ch.socket().getRemoteSocketAddress();
92          this.localAddress = ch.socket().getLocalSocketAddress();
93          this.serviceAddress = serviceAddress;
94          this.serviceConfig = serviceConfig;
95  
96          // Apply the initial session settings
97          IoSessionConfig sessionConfig = serviceConfig.getSessionConfig();
98          if (sessionConfig instanceof SocketSessionConfig) {
99              SocketSessionConfig cfg = (SocketSessionConfig) sessionConfig;
100             this.config.setKeepAlive(cfg.isKeepAlive());
101             this.config.setOobInline(cfg.isOobInline());
102             this.config.setReceiveBufferSize(cfg.getReceiveBufferSize());
103             this.config.setReuseAddress(cfg.isReuseAddress());
104             this.config.setSendBufferSize(cfg.getSendBufferSize());
105             this.config.setSoLinger(cfg.getSoLinger());
106             this.config.setTcpNoDelay(cfg.isTcpNoDelay());
107 
108             if (this.config.getTrafficClass() != cfg.getTrafficClass()) {
109                 this.config.setTrafficClass(cfg.getTrafficClass());
110             }
111         }
112     }
113 
114     public IoService getService() {
115         return manager;
116     }
117 
118     public IoServiceConfig getServiceConfig() {
119         return serviceConfig;
120     }
121 
122     public IoSessionConfig getConfig() {
123         return config;
124     }
125 
126     SocketIoProcessor getIoProcessor() {
127         return ioProcessor;
128     }
129 
130     public IoFilterChain getFilterChain() {
131         return filterChain;
132     }
133 
134     SocketChannel getChannel() {
135         return ch;
136     }
137 
138     IoServiceListenerSupport getServiceListeners() {
139         return serviceListeners;
140     }
141 
142     SelectionKey getSelectionKey() {
143         return key;
144     }
145 
146     void setSelectionKey(SelectionKey key) {
147         this.key = key;
148     }
149 
150     public IoHandler getHandler() {
151         return handler;
152     }
153 
154     protected void close0() {
155         filterChain.fireFilterClose(this);
156     }
157 
158     Queue getWriteRequestQueue() {
159         return writeRequestQueue;
160     }
161 
162     protected void write0(WriteRequest writeRequest) {
163         filterChain.fireFilterWrite(this, writeRequest);
164     }
165 
166     public TransportType getTransportType() {
167         return TransportType.SOCKET;
168     }
169 
170     public SocketAddress getRemoteAddress() {
171         return remoteAddress;
172     }
173 
174     public SocketAddress getLocalAddress() {
175         return localAddress;
176     }
177 
178     public SocketAddress getServiceAddress() {
179         return serviceAddress;
180     }
181 
182     protected void updateTrafficMask() {
183         this.ioProcessor.updateTrafficMask(this);
184     }
185 
186     int getReadBufferSize() {
187         return readBufferSize;
188     }
189     
190     void increaseReadBufferSize() {
191         int newReadBufferSize = getReadBufferSize() << 1;
192         if (newReadBufferSize <= ((SocketSessionConfig) getConfig()).getReceiveBufferSize() << 1) {
193             // read buffer size shouldn't get bigger than
194             // twice of the receive buffer size because of
195             // read-write fairness.
196             setReadBufferSize(newReadBufferSize);
197         }
198     }
199     
200     void decreaseReadBufferSize() {
201         if (deferDecreaseReadBufferSize) {
202             deferDecreaseReadBufferSize = false;
203             return;
204         }
205         
206         if (getReadBufferSize() > 64) {
207             setReadBufferSize(getReadBufferSize() >>> 1);
208         }
209     }
210     
211     private void setReadBufferSize(int readBufferSize) {
212         this.readBufferSize = readBufferSize;
213         this.deferDecreaseReadBufferSize = true;
214     }
215 
216     private class SessionConfigImpl extends BaseIoSessionConfig implements
217             SocketSessionConfig {
218         public boolean isKeepAlive() {
219             try {
220                 return ch.socket().getKeepAlive();
221             } catch (SocketException e) {
222                 throw new RuntimeIOException(e);
223             }
224         }
225 
226         public void setKeepAlive(boolean on) {
227             try {
228                 ch.socket().setKeepAlive(on);
229             } catch (SocketException e) {
230                 throw new RuntimeIOException(e);
231             }
232         }
233 
234         public boolean isOobInline() {
235             try {
236                 return ch.socket().getOOBInline();
237             } catch (SocketException e) {
238                 throw new RuntimeIOException(e);
239             }
240         }
241 
242         public void setOobInline(boolean on) {
243             try {
244                 ch.socket().setOOBInline(on);
245             } catch (SocketException e) {
246                 throw new RuntimeIOException(e);
247             }
248         }
249 
250         public boolean isReuseAddress() {
251             try {
252                 return ch.socket().getReuseAddress();
253             } catch (SocketException e) {
254                 throw new RuntimeIOException(e);
255             }
256         }
257 
258         public void setReuseAddress(boolean on) {
259             try {
260                 ch.socket().setReuseAddress(on);
261             } catch (SocketException e) {
262                 throw new RuntimeIOException(e);
263             }
264         }
265 
266         public int getSoLinger() {
267             try {
268                 return ch.socket().getSoLinger();
269             } catch (SocketException e) {
270                 throw new RuntimeIOException(e);
271             }
272         }
273 
274         public void setSoLinger(int linger) {
275             try {
276                 if (linger < 0) {
277                     ch.socket().setSoLinger(false, 0);
278                 } else {
279                     ch.socket().setSoLinger(true, linger);
280                 }
281             } catch (SocketException e) {
282                 throw new RuntimeIOException(e);
283             }
284         }
285 
286         public boolean isTcpNoDelay() {
287             try {
288                 return ch.socket().getTcpNoDelay();
289             } catch (SocketException e) {
290                 throw new RuntimeIOException(e);
291             }
292         }
293 
294         public void setTcpNoDelay(boolean on) {
295             try {
296                 ch.socket().setTcpNoDelay(on);
297             } catch (SocketException e) {
298                 throw new RuntimeIOException(e);
299             }
300         }
301 
302         public int getTrafficClass() {
303             if (SocketSessionConfigImpl.isGetTrafficClassAvailable()) {
304                 try {
305                     return ch.socket().getTrafficClass();
306                 } catch (SocketException e) {
307                     // Throw an exception only when setTrafficClass is also available.
308                     if (SocketSessionConfigImpl.isSetTrafficClassAvailable()) {
309                         throw new RuntimeIOException(e);
310                     }
311                 }
312             }
313 
314             return 0;
315         }
316 
317         public void setTrafficClass(int tc) {
318             if (SocketSessionConfigImpl.isSetTrafficClassAvailable()) {
319                 try {
320                     ch.socket().setTrafficClass(tc);
321                 } catch (SocketException e) {
322                     throw new RuntimeIOException(e);
323                 }
324             }
325         }
326 
327         public int getSendBufferSize() {
328             try {
329                 return ch.socket().getSendBufferSize();
330             } catch (SocketException e) {
331                 throw new RuntimeIOException(e);
332             }
333         }
334 
335         public void setSendBufferSize(int size) {
336             if (SocketSessionConfigImpl.isSetSendBufferSizeAvailable()) {
337                 try {
338                     ch.socket().setSendBufferSize(size);
339                 } catch (SocketException e) {
340                     throw new RuntimeIOException(e);
341                 }
342             }
343         }
344 
345         public int getReceiveBufferSize() {
346             try {
347                 return ch.socket().getReceiveBufferSize();
348             } catch (SocketException e) {
349                 throw new RuntimeIOException(e);
350             }
351         }
352 
353         public void setReceiveBufferSize(int size) {
354             if (SocketSessionConfigImpl.isSetReceiveBufferSizeAvailable()) {
355                 try {
356                     ch.socket().setReceiveBufferSize(size);
357                 } catch (SocketException e) {
358                     throw new RuntimeIOException(e);
359                 }
360             }
361         }
362     }
363 }