1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
43
44
45
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
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
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
194
195
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
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 }