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.Inet4Address;
23 import java.net.Inet6Address;
24 import java.net.InetAddress;
25 import java.net.InetSocketAddress;
26 import java.net.SocketAddress;
27 import java.nio.channels.DatagramChannel;
28 import java.nio.channels.SelectionKey;
29 import java.nio.channels.Selector;
30 import java.util.Set;
31 import java.util.concurrent.Executor;
32
33 import org.apache.mina.core.buffer.IoBuffer;
34 import org.apache.mina.core.polling.AbstractPollingConnectionlessIoAcceptor;
35 import org.apache.mina.core.service.IoAcceptor;
36 import org.apache.mina.core.service.IoProcessor;
37 import org.apache.mina.core.service.TransportMetadata;
38 import org.apache.mina.transport.socket.DatagramAcceptor;
39 import org.apache.mina.transport.socket.DatagramSessionConfig;
40 import org.apache.mina.transport.socket.DefaultDatagramSessionConfig;
41
42
43
44
45
46
47
48 public final class NioDatagramAcceptor 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) throws Exception {
145 InetSocketAddress inetSocketAddress = (InetSocketAddress) handle.socket().getLocalSocketAddress();
146 InetAddress inetAddress = inetSocketAddress.getAddress();
147
148 if ((inetAddress instanceof Inet6Address) && (((Inet6Address) inetAddress).isIPv4CompatibleAddress())) {
149
150
151
152 byte[] ipV6Address = ((Inet6Address) inetAddress).getAddress();
153 byte[] ipV4Address = new byte[4];
154
155 for (int i = 0; i < 4; i++) {
156 ipV4Address[i] = ipV6Address[12 + i];
157 }
158
159 InetAddress inet4Adress = Inet4Address.getByAddress(ipV4Address);
160 return new InetSocketAddress(inet4Adress, inetSocketAddress.getPort());
161 } else {
162 return inetSocketAddress;
163 }
164 }
165
166 @Override
167 protected NioSession newSession(IoProcessor<NioSession> processor, DatagramChannel handle,
168 SocketAddress remoteAddress) {
169 SelectionKey key = handle.keyFor(selector);
170
171 if ((key == null) || (!key.isValid())) {
172 return null;
173 }
174
175 NioDatagramSession newSession = new NioDatagramSession(this, handle, processor, remoteAddress);
176 newSession.setSelectionKey(key);
177
178 return newSession;
179 }
180
181 @Override
182 protected SocketAddress receive(DatagramChannel handle, IoBuffer buffer) throws Exception {
183 return handle.receive(buffer.buf());
184 }
185
186 @Override
187 protected int select() throws Exception {
188 return selector.select();
189 }
190
191 @Override
192 protected int select(long timeout) throws Exception {
193 return selector.select(timeout);
194 }
195
196 @Override
197 protected Set<SelectionKey> selectedHandles() {
198 return selector.selectedKeys();
199 }
200
201 @Override
202 protected int send(NioSession session, IoBuffer buffer, SocketAddress remoteAddress) throws Exception {
203 return ((DatagramChannel) session.getChannel()).send(buffer.buf(), remoteAddress);
204 }
205
206 @Override
207 protected void setInterestedInWrite(NioSession session, boolean isInterested) throws Exception {
208 SelectionKey key = session.getSelectionKey();
209
210 if (key == null) {
211 return;
212 }
213
214 int newInterestOps = key.interestOps();
215
216 if (isInterested) {
217 newInterestOps |= SelectionKey.OP_WRITE;
218
219 } else {
220 newInterestOps &= ~SelectionKey.OP_WRITE;
221
222 }
223
224 key.interestOps(newInterestOps);
225 }
226
227 @Override
228 protected void close(DatagramChannel handle) throws Exception {
229 SelectionKey key = handle.keyFor(selector);
230
231 if (key != null) {
232 key.cancel();
233 }
234
235 handle.disconnect();
236 handle.close();
237 }
238
239 @Override
240 protected void wakeup() {
241 selector.wakeup();
242 }
243 }