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