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;
21
22 import static org.junit.Assert.assertEquals;
23 import static org.junit.Assert.assertFalse;
24 import static org.junit.Assert.assertNotNull;
25 import static org.junit.Assert.assertNull;
26 import static org.junit.Assert.assertTrue;
27 import static org.junit.Assert.fail;
28
29 import java.io.IOException;
30 import java.net.SocketAddress;
31 import java.util.Collection;
32
33 import org.apache.mina.core.buffer.IoBuffer;
34 import org.apache.mina.core.future.ConnectFuture;
35 import org.apache.mina.core.service.IoAcceptor;
36 import org.apache.mina.core.service.IoConnector;
37 import org.apache.mina.core.service.IoHandlerAdapter;
38 import org.apache.mina.core.session.IdleStatus;
39 import org.apache.mina.core.session.IoSession;
40 import org.apache.mina.transport.socket.DatagramAcceptor;
41 import org.apache.mina.transport.socket.DatagramSessionConfig;
42 import org.apache.mina.transport.socket.SocketAcceptor;
43 import org.apache.mina.transport.socket.SocketSessionConfig;
44 import org.junit.After;
45 import org.junit.Ignore;
46 import org.junit.Test;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
49
50
51
52
53
54
55 public abstract class AbstractBindTest {
56 protected final IoAcceptor acceptor;
57
58 protected int port;
59
60 public AbstractBindTest(IoAcceptor acceptor) {
61 this.acceptor = acceptor;
62 }
63
64 protected abstract SocketAddress createSocketAddress(int port);
65
66 protected abstract int getPort(SocketAddress address);
67
68 protected abstract IoConnector newConnector();
69
70 protected void bind(boolean reuseAddress) throws IOException {
71 acceptor.setHandler(new EchoProtocolHandler());
72
73 setReuseAddress(reuseAddress);
74
75
76 boolean socketBound = false;
77
78
79
80
81 for (port = 1; port <= 65535; port++) {
82 socketBound = false;
83 try {
84 acceptor.setDefaultLocalAddress(createSocketAddress(port));
85 acceptor.bind();
86 socketBound = true;
87 break;
88 } catch (IOException e) {
89
90 }
91 }
92
93
94 if (!socketBound) {
95 throw new IOException("Cannot bind any test port.");
96 }
97
98
99 }
100
101 private void setReuseAddress(boolean reuseAddress) {
102 if (acceptor instanceof DatagramAcceptor) {
103 ((DatagramSessionConfig) acceptor.getSessionConfig())
104 .setReuseAddress(reuseAddress);
105 } else if (acceptor instanceof SocketAcceptor) {
106 ((SocketAcceptor) acceptor).setReuseAddress(reuseAddress);
107 }
108 }
109
110 @After
111 public void tearDown() {
112 try {
113 acceptor.dispose();
114 } catch (Exception e) {
115
116 }
117
118 acceptor.setDefaultLocalAddress(null);
119 }
120
121 @Test
122 public void testAnonymousBind() throws Exception {
123 acceptor.setHandler(new IoHandlerAdapter());
124 acceptor.setDefaultLocalAddress(null);
125 acceptor.bind();
126 assertNotNull(acceptor.getLocalAddress());
127 acceptor.unbind(acceptor.getLocalAddress());
128 assertNull(acceptor.getLocalAddress());
129 acceptor.setDefaultLocalAddress(createSocketAddress(0));
130 acceptor.bind();
131 assertNotNull(acceptor.getLocalAddress());
132 assertTrue(getPort(acceptor.getLocalAddress()) != 0);
133 acceptor.unbind(acceptor.getLocalAddress());
134 }
135
136 @Test
137 public void testDuplicateBind() throws IOException {
138 bind(false);
139
140 try {
141 acceptor.bind();
142 fail("Exception is not thrown");
143 } catch (Exception e) {
144
145 assertTrue(true);
146 }
147 }
148
149 @Test
150 public void testDuplicateUnbind() throws IOException {
151 bind(false);
152
153
154 acceptor.unbind();
155
156
157 acceptor.unbind();
158 }
159
160 @Test
161 public void testManyTimes() throws IOException {
162 bind(true);
163
164 for (int i = 0; i < 1024; i++) {
165 acceptor.unbind();
166 acceptor.bind();
167 }
168 }
169
170 @Test
171 public void testUnbindDisconnectsClients() throws Exception {
172 bind(true);
173 IoConnector connector = newConnector();
174 IoSession[] sessions = new IoSession[5];
175 connector.setHandler(new IoHandlerAdapter());
176 for (int i = 0; i < sessions.length; i++) {
177 ConnectFuture future = connector.connect(createSocketAddress(port));
178 future.awaitUninterruptibly();
179 sessions[i] = future.getSession();
180 assertTrue(sessions[i].isConnected());
181 assertTrue(sessions[i].write(IoBuffer.allocate(1)).awaitUninterruptibly().isWritten());
182 }
183
184
185 Thread.sleep(500);
186
187 Collection<IoSession> managedSessions = acceptor.getManagedSessions().values();
188 assertEquals(5, managedSessions.size());
189
190 acceptor.unbind();
191
192
193 Thread.sleep(500);
194
195 assertEquals(0, managedSessions.size());
196 for (IoSession element : managedSessions) {
197 assertFalse(element.isConnected());
198 }
199 }
200
201 @Test
202 public void testUnbindResume() throws Exception {
203 bind(true);
204 IoConnector connector = newConnector();
205 IoSession session = null;
206 connector.setHandler(new IoHandlerAdapter());
207
208 ConnectFuture future = connector.connect(createSocketAddress(port));
209 future.awaitUninterruptibly();
210 session = future.getSession();
211 assertTrue(session.isConnected());
212 assertTrue(session.write(IoBuffer.allocate(1)).awaitUninterruptibly().isWritten());
213
214
215 Thread.sleep(500);
216
217 Collection<IoSession> managedSession = acceptor.getManagedSessions().values();
218 assertEquals(1, managedSession.size());
219
220 acceptor.unbind();
221
222
223 Thread.sleep(500);
224
225 assertEquals(0, managedSession.size());
226 for (IoSession element : managedSession) {
227 assertFalse(element.isConnected());
228 }
229
230
231 bind(true);
232
233
234 future = connector.connect(createSocketAddress(port));
235 future.awaitUninterruptibly();
236 session = future.getSession();
237 assertTrue(session.isConnected());
238 assertTrue(session.write(IoBuffer.allocate(1)).awaitUninterruptibly().isWritten());
239
240
241 Thread.sleep(500);
242
243 managedSession = acceptor.getManagedSessions().values();
244 assertEquals(1, managedSession.size());
245 }
246
247 @Test
248 @Ignore
249 public void testRegressively() throws IOException {
250 setReuseAddress(true);
251
252 SocketAddress addr = createSocketAddress(port);
253 EchoProtocolHandler handler = new EchoProtocolHandler();
254 acceptor.setDefaultLocalAddress(addr);
255 acceptor.setHandler(handler);
256 for (int i = 0; i < 1048576; i++) {
257 acceptor.bind();
258 acceptor.unbind();
259 }
260 bind(false);
261 }
262
263 private static class EchoProtocolHandler extends IoHandlerAdapter {
264 private static final Logger LOG = LoggerFactory
265 .getLogger(EchoProtocolHandler.class);
266
267
268
269
270 public EchoProtocolHandler() {
271 super();
272 }
273
274 @Override
275 public void sessionCreated(IoSession session) {
276 if (session.getConfig() instanceof SocketSessionConfig) {
277 ((SocketSessionConfig) session.getConfig())
278 .setReceiveBufferSize(2048);
279 }
280
281 session.getConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
282 }
283
284 @Override
285 public void sessionIdle(IoSession session, IdleStatus status) {
286 LOG.info("*** IDLE #" + session.getIdleCount(IdleStatus.BOTH_IDLE)
287 + " ***");
288 }
289
290 @Override
291 public void exceptionCaught(IoSession session, Throwable cause) {
292
293 session.close(true);
294 }
295
296 @Override
297 public void messageReceived(IoSession session, Object message)
298 throws Exception {
299 if (!(message instanceof IoBuffer)) {
300 return;
301 }
302
303 IoBuffer rb = (IoBuffer) message;
304
305 IoBuffer wb = IoBuffer.allocate(rb.remaining());
306 wb.put(rb);
307 wb.flip();
308 session.write(wb);
309 }
310 }
311 }