1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.mina.example.echoserver;
21  
22  import java.io.IOException;
23  import java.net.InetSocketAddress;
24  import java.net.SocketAddress;
25  
26  import junit.framework.TestCase;
27  
28  import org.apache.mina.common.IoAcceptor;
29  import org.apache.mina.common.IoBuffer;
30  import org.apache.mina.common.IoSession;
31  import org.apache.mina.example.echoserver.ssl.BogusSslContextFactory;
32  import org.apache.mina.filter.ssl.SslFilter;
33  import org.apache.mina.transport.socket.DatagramSessionConfig;
34  import org.apache.mina.transport.socket.nio.NioDatagramAcceptor;
35  import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
36  import org.slf4j.Logger;
37  import org.slf4j.LoggerFactory;
38  
39  /**
40   * Tests echo server example.
41   *
42   * @author The Apache MINA Project (dev@mina.apache.org)
43   * @version $Rev:448075 $, $Date:2006-09-20 05:26:53Z $
44   */
45  public abstract class AbstractTest extends TestCase {
46      private final Logger logger = LoggerFactory.getLogger(getClass());
47  
48      protected boolean useSSL;
49  
50      protected int port;
51  
52      protected SocketAddress boundAddress;
53  
54      protected IoAcceptor datagramAcceptor;
55  
56      protected IoAcceptor socketAcceptor;
57  
58      protected AbstractTest() {
59      }
60  
61      protected static void assertEquals(byte[] expected, byte[] actual) {
62          assertEquals(toString(expected), toString(actual));
63      }
64  
65      protected static void assertEquals(IoBuffer expected, IoBuffer actual) {
66          assertEquals(toString(expected), toString(actual));
67      }
68  
69      protected static String toString(byte[] buf) {
70          StringBuffer str = new StringBuffer(buf.length * 4);
71          for (byte element : buf) {
72              str.append(element);
73              str.append(' ');
74          }
75          return str.toString();
76      }
77  
78      protected static String toString(IoBuffer buf) {
79          return buf.getHexDump();
80      }
81  
82      @Override
83      protected void setUp() throws Exception {
84          // Disable SSL by default
85          useSSL = false;
86          final SslFilter sslFilter = new SslFilter(BogusSslContextFactory
87                  .getInstance(true));
88  
89          boundAddress = null;
90          datagramAcceptor = new NioDatagramAcceptor();
91          socketAcceptor = new NioSocketAcceptor();
92  
93          ((DatagramSessionConfig) datagramAcceptor.getSessionConfig())
94                  .setReuseAddress(true);
95          ((NioSocketAcceptor) socketAcceptor).setReuseAddress(true);
96  
97          // Find an availble test port and bind to it.
98          boolean socketBound = false;
99          boolean datagramBound = false;
100 
101         // Let's start from port #1 to detect possible resource leak
102         // because test will fail in port 1-1023 if user run this test
103         // as a normal user.
104 
105         SocketAddress address = null;
106 
107         for (port = 1; port <= 65535; port++) {
108             socketBound = false;
109             datagramBound = false;
110 
111             address = new InetSocketAddress(port);
112 
113             try {
114                 socketAcceptor.setHandler(new EchoProtocolHandler() {
115                     @Override
116                     public void sessionCreated(IoSession session) {
117                         if (useSSL) {
118                             session.getFilterChain().addFirst("SSL", sslFilter);
119                         }
120                     }
121 
122                     // This is for TLS reentrance test
123                     @Override
124                     public void messageReceived(IoSession session,
125                             Object message) throws Exception {
126                         if (!(message instanceof IoBuffer)) {
127                             return;
128                         }
129 
130                         IoBuffer buf = (IoBuffer) message;
131                         if (session.getFilterChain().contains("SSL")
132                                 && buf.remaining() == 1
133                                 && buf.get() == (byte) '.') {
134                             logger.info("TLS Reentrance");
135                             ((SslFilter) session.getFilterChain().get("SSL"))
136                                     .startSsl(session);
137 
138                             // Send a response
139                             buf = IoBuffer.allocate(1);
140                             buf.put((byte) '.');
141                             buf.flip();
142                             session
143                                     .setAttribute(SslFilter.DISABLE_ENCRYPTION_ONCE);
144                             session.write(buf);
145                         } else {
146                             super.messageReceived(session, message);
147                         }
148                     }
149                 });
150                 socketAcceptor.bind(address);
151                 socketBound = true;
152 
153                 datagramAcceptor.setHandler(new EchoProtocolHandler());
154                 datagramAcceptor.bind(address);
155                 datagramBound = true;
156 
157                 break;
158             } catch (IOException e) {
159             } finally {
160                 if (socketBound && !datagramBound) {
161                     socketAcceptor.unbind();
162                 }
163                 if (datagramBound && !socketBound) {
164                     datagramAcceptor.unbind();
165                 }
166             }
167         }
168 
169         // If there is no port available, test fails.
170         if (!socketBound || !datagramBound) {
171             throw new IOException("Cannot bind any test port.");
172         }
173 
174         boundAddress = address;
175         System.out.println("Using port " + port + " for testing.");
176     }
177 
178     @Override
179     protected void tearDown() throws Exception {
180         if (boundAddress != null) {
181             socketAcceptor.dispose();
182             datagramAcceptor.dispose();
183         }
184     }
185 }