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.nio;
21
22 import java.io.IOException;
23 import java.net.SocketAddress;
24 import java.nio.ByteBuffer;
25 import java.nio.channels.DatagramChannel;
26
27 import org.apache.mina.api.IoService;
28 import org.apache.mina.service.idlechecker.IdleChecker;
29 import org.apache.mina.session.WriteRequest;
30 import org.apache.mina.transport.udp.UdpSessionConfig;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33
34
35
36
37
38
39 public class NioUdpSession extends AbstractNioSession implements SelectorListener {
40
41 private static final Logger LOG = LoggerFactory.getLogger(NioUdpSession.class);
42
43 private static final boolean IS_DEBUG = LOG.isDebugEnabled();
44
45 private final SocketAddress localAddress;
46
47 private final SocketAddress remoteAddress;
48
49
50
51
52 private SelectorLoop selectorLoop = null;
53
54
55 private final UdpSessionConfig configuration;
56
57
58
59
60
61 SocketAddress localAddress, SocketAddress remoteAddress) {
62 super(service, datagramChannel, idleChecker);
63 this.localAddress = localAddress;
64 this.remoteAddress = remoteAddress;
65 this.config = service.getSessionConfig();
66 this.configuration = (UdpSessionConfig) this.config;
67 }
68
69
70
71
72
73 SocketAddress localAddress, SocketAddress remoteAddress, NioSelectorLoop selectorLoop) {
74 super(service, datagramChannel, idleChecker);
75 this.selectorLoop = selectorLoop;
76 this.localAddress = localAddress;
77 this.remoteAddress = remoteAddress;
78 this.config = service.getSessionConfig();
79 this.configuration = (UdpSessionConfig) this.config;
80 }
81
82
83
84
85 @Override
86 protected void channelClose() {
87 LOG.debug("channelClose");
88
89 if (channel != null) {
90 try {
91 selectorLoop.unregister(this, channel);
92 channel.close();
93 } catch (final IOException e) {
94 LOG.error("Exception while closing the channel : ", e);
95 processException(e);
96 }
97 }
98 processSessionClosed();
99 }
100
101
102
103
104 @Override
105 public void flushWriteQueue() {
106
107 if (selectorLoop != null) {
108 selectorLoop.modifyRegistration(false, !isReadSuspended(), true, this, channel, true);
109 }
110 }
111
112
113
114
115 @Override
116 public SocketAddress getRemoteAddress() {
117 return remoteAddress;
118 }
119
120
121
122
123 @Override
124 public SocketAddress getLocalAddress() {
125 return localAddress;
126 }
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143 @Override
144 public void suspendRead() {
145
146 throw new IllegalStateException("not implemented");
147 }
148
149
150
151
152 @Override
153 public void suspendWrite() {
154
155 throw new IllegalStateException("not implemented");
156 }
157
158
159
160
161 @Override
162 public void resumeRead() {
163
164 throw new IllegalStateException("not implemented");
165 }
166
167
168
169
170 @Override
171 public void resumeWrite() {
172
173 throw new IllegalStateException("not implemented");
174 }
175
176
177
178
179 @Override
180 public boolean isReadSuspended() {
181
182 return false;
183 }
184
185
186
187
188 @Override
189 public boolean isWriteSuspended() {
190
191 return false;
192 }
193
194
195
196
197 @Override
198 public UdpSessionConfig getConfig() {
199 return configuration;
200 }
201
202
203
204
205
206
207 void receivedDatagram(ByteBuffer readBuffer) {
208 processMessageReceived(readBuffer);
209 idleChecker.sessionRead(this, System.currentTimeMillis());
210 }
211
212
213
214
215 @Override
216 protected int writeDirect(Object message) {
217 try {
218
219 if (!isRegisteredForWrite()) {
220
221
222 if (!((DatagramChannel) channel).isConnected()) {
223 ((DatagramChannel) channel).connect(remoteAddress);
224 }
225
226
227
228 return ((DatagramChannel) channel).write((ByteBuffer) message);
229 } else {
230 LOG.debug("Cannot write");
231 return -1;
232 }
233 } catch (final IOException e) {
234 LOG.error("Exception while reading : ", e);
235 processException(e);
236
237 return -1;
238 }
239 }
240
241
242
243
244 @Override
245 protected ByteBuffer convertToDirectBuffer(WriteRequest writeRequest, boolean createNew) {
246
247 return (ByteBuffer) writeRequest.getMessage();
248 }
249
250
251
252
253 void setConnected() {
254 if (!isCreated()) {
255 throw new IllegalStateException("Trying to open a non created session");
256 }
257
258 state = SessionState.CONNECTED;
259 processSessionOpen();
260 }
261
262 @Override
263 public void ready(boolean accept, boolean connect, boolean read, ByteBuffer readBuffer, boolean write) {
264 if (IS_DEBUG) {
265 LOG.debug("session {} ready for accept={}, connect={}, read={}, write={}", new Object[] { this, accept,
266 connect, read, write });
267 }
268
269 if (read) {
270 if (IS_DEBUG) {
271 LOG.debug("readable datagram for UDP service : {}", this);
272 }
273
274
275 try {
276 readBuffer.clear();
277 ((DatagramChannel) channel).receive(readBuffer);
278 readBuffer.flip();
279
280 int readbytes = readBuffer.remaining();
281
282 if (IS_DEBUG) {
283 LOG.debug("read {} bytes", readbytes);
284 }
285
286 if (readbytes <= 0) {
287
288 if (IS_DEBUG) {
289 LOG.debug("session closed by the remote peer");
290 }
291
292 close(true);
293 } else {
294 receivedDatagram(readBuffer);
295 }
296 } catch (IOException e) {
297 processException(e);
298 }
299
300 }
301
302 if (write) {
303 processWrite(selectorLoop);
304 }
305 if (accept) {
306 throw new IllegalStateException("accept event should never occur on NioUdpSession");
307 }
308
309 }
310
311 }