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.InetSocketAddress;
23 import java.net.SocketAddress;
24 import java.nio.channels.DatagramChannel;
25 import java.nio.channels.SelectionKey;
26 import java.nio.channels.Selector;
27 import java.util.Collection;
28 import java.util.Iterator;
29 import java.util.concurrent.Executor;
30
31 import org.apache.mina.core.buffer.IoBuffer;
32 import org.apache.mina.core.polling.AbstractPollingConnectionlessIoAcceptor;
33 import org.apache.mina.core.service.IoAcceptor;
34 import org.apache.mina.core.service.IoProcessor;
35 import org.apache.mina.core.service.TransportMetadata;
36 import org.apache.mina.transport.socket.DatagramAcceptor;
37 import org.apache.mina.transport.socket.DatagramSessionConfig;
38 import org.apache.mina.transport.socket.DefaultDatagramSessionConfig;
39
40
41
42
43
44
45
46
47 public final class NioDatagramAcceptor
48 extends AbstractPollingConnectionlessIoAcceptor<NioSession, DatagramChannel>
49 implements DatagramAcceptor {
50
51 private volatile Selector selector;
52
53
54
55
56 public NioDatagramAcceptor() {
57 super(new DefaultDatagramSessionConfig());
58 }
59
60
61
62
63 public NioDatagramAcceptor(Executor executor) {
64 super(new DefaultDatagramSessionConfig(), executor);
65 }
66
67 @Override
68 protected void init() throws Exception {
69 this.selector = Selector.open();
70 }
71
72 @Override
73 protected void destroy() throws Exception {
74 if (selector != null) {
75 selector.close();
76 }
77 }
78
79 public TransportMetadata getTransportMetadata() {
80 return NioDatagramSession.METADATA;
81 }
82
83 @Override
84 public DatagramSessionConfig getSessionConfig() {
85 return (DatagramSessionConfig) super.getSessionConfig();
86 }
87
88 @Override
89 public InetSocketAddress getLocalAddress() {
90 return (InetSocketAddress) super.getLocalAddress();
91 }
92
93 @Override
94 public InetSocketAddress getDefaultLocalAddress() {
95 return (InetSocketAddress) super.getDefaultLocalAddress();
96 }
97
98 public void setDefaultLocalAddress(InetSocketAddress localAddress) {
99 setDefaultLocalAddress((SocketAddress) localAddress);
100 }
101
102 @Override
103 protected DatagramChannel open(SocketAddress localAddress) throws Exception {
104 final DatagramChannel c = DatagramChannel.open();
105 boolean success = false;
106 try {
107 new NioDatagramSessionConfig(c).setAll(getSessionConfig());
108 c.configureBlocking(false);
109 c.socket().bind(localAddress);
110 c.register(selector, SelectionKey.OP_READ);
111 success = true;
112 } finally {
113 if (!success) {
114 close(c);
115 }
116 }
117
118 return c;
119 }
120
121 @Override
122 protected boolean isReadable(DatagramChannel handle) {
123 SelectionKey key = handle.keyFor(selector);
124
125 if ((key == null) || (!key.isValid())) {
126 return false;
127 }
128
129 return key.isReadable();
130 }
131
132 @Override
133 protected boolean isWritable(DatagramChannel handle) {
134 SelectionKey key = handle.keyFor(selector);
135
136 if ((key == null) || (!key.isValid())) {
137 return false;
138 }
139
140 return key.isWritable();
141 }
142
143 @Override
144 protected SocketAddress localAddress(DatagramChannel handle)
145 throws Exception {
146 return handle.socket().getLocalSocketAddress();
147 }
148
149 @Override
150 protected NioSession newSession(
151 IoProcessor<NioSession> processor, DatagramChannel handle,
152 SocketAddress remoteAddress) {
153 SelectionKey key = handle.keyFor(selector);
154
155 if ((key == null) || (!key.isValid())) {
156 return null;
157 }
158
159 NioDatagramSession newSession = new NioDatagramSession(
160 this, handle, processor, remoteAddress);
161 newSession.setSelectionKey(key);
162
163 return newSession;
164 }
165
166 @Override
167 protected SocketAddress receive(DatagramChannel handle, IoBuffer buffer)
168 throws Exception {
169 return handle.receive(buffer.buf());
170 }
171
172 @Override
173 protected int select() throws Exception {
174 return selector.select();
175 }
176
177 @Override
178 protected int select(int timeout) throws Exception {
179 return selector.select(timeout);
180 }
181
182 @Override
183 protected Iterator<DatagramChannel> selectedHandles() {
184 return new DatagramChannelIterator(selector.selectedKeys());
185 }
186
187 @Override
188 protected int send(NioSession session, IoBuffer buffer,
189 SocketAddress remoteAddress) throws Exception {
190 return ((DatagramChannel) session.getChannel()).send(
191 buffer.buf(), remoteAddress);
192 }
193
194 @Override
195 protected void setInterestedInWrite(NioSession session, boolean interested)
196 throws Exception {
197 SelectionKey key = session.getSelectionKey();
198 if (key == null) {
199 return;
200 }
201
202 if (interested) {
203 key.interestOps(key.interestOps() | SelectionKey.OP_WRITE);
204 } else {
205 key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);
206 }
207 }
208
209 @Override
210 protected void close(DatagramChannel handle) throws Exception {
211 SelectionKey key = handle.keyFor(selector);
212
213 if (key != null) {
214 key.cancel();
215 }
216
217 handle.disconnect();
218 handle.close();
219 }
220
221 @Override
222 protected void wakeup() {
223 selector.wakeup();
224 }
225
226 private static class DatagramChannelIterator implements Iterator<DatagramChannel> {
227
228 private final Iterator<SelectionKey> i;
229
230 private DatagramChannelIterator(Collection<SelectionKey> keys) {
231 this.i = keys.iterator();
232 }
233
234 public boolean hasNext() {
235 return i.hasNext();
236 }
237
238 public DatagramChannel next() {
239 return (DatagramChannel) i.next().channel();
240 }
241
242 public void remove() {
243 i.remove();
244 }
245
246 }
247 }