View Javadoc

    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  import static org.junit.Assert.assertEquals;
    22
    23  import java.io.IOException;
    24  import java.net.InetSocketAddress;
    25  import java.net.SocketAddress;
    26  import java.security.GeneralSecurityException;
    27
    28  import org.apache.mina.core.buffer.IoBuffer;
    29  import org.apache.mina.core.service.IoAcceptor;
    30  import org.apache.mina.core.session.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.apache.mina.util.AvailablePortFinder;
    37  import org.junit.After;
    38  import org.junit.Before;
    39  import org.slf4j.Logger;
    40  import org.slf4j.LoggerFactory;
    41
    42  /**
    43   * Tests echo server example.
    44   *
    45   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
    46   */
    47  public abstract class AbstractTest {
    48      private final static Logger LOGGER = LoggerFactory.getLogger(AbstractTest.class);
    49
    50      protected boolean useSSL;
    51
    52      protected int port;
    53
    54      protected SocketAddress boundAddress;
    55
    56      protected IoAcceptor datagramAcceptor;
    57
    58      protected IoAcceptor socketAcceptor;
    59
    60      protected AbstractTest() {
    61          // Do nothing
    62      }
    63
    64      protected static void isEquals(byte[] expected, byte[] actual) {
    65          assertEquals(toString(expected), toString(actual));
    66      }
    67
    68      protected static void isEquals(IoBuffer expected, IoBuffer actual) {
    69          assertEquals(toString(expected), toString(actual));
    70      }
    71
    72      protected static String toString(byte[] buf) {
    73          StringBuilder str = new StringBuilder(buf.length * 4);
    74          for (byte element : buf) {
    75              str.append(element);
    76              str.append(' ');
    77          }
    78          return str.toString();
    79      }
    80
    81      protected static String toString(IoBuffer buf) {
    82          return buf.getHexDump();
    83      }
    84
    85      @Before
    86      public void setUp() throws Exception {
    87          // Disable SSL by default
    88          useSSL = false;
    89
    90          boundAddress = null;
    91          datagramAcceptor = new NioDatagramAcceptor();
    92          socketAcceptor = new NioSocketAcceptor();
    93
    94          ((DatagramSessionConfig) datagramAcceptor.getSessionConfig())
    95                  .setReuseAddress(true);
    96          ((NioSocketAcceptor) socketAcceptor).setReuseAddress(true);
    97
    98          // Find an available test port and bind to it.
    99          boolean socketBound = false;
    100         boolean datagramBound = false;
    101
    102         // Let's start from port #1 to detect possible resource leak
    103         // because test will fail in port 1-1023 if user run this test
    104         // as a normal user.
    105
    106         SocketAddress address = null;
    107
    108         // Find the first available port above 1024
    109         port = AvailablePortFinder.getNextAvailable(1024);
    110
    111         socketBound = false;
    112         datagramBound = false;
    113
    114         address = new InetSocketAddress(port);
    115
    116         try {
    117             socketAcceptor.setHandler(new EchoProtocolHandler() {
    118                 @Override
    119                 public void sessionCreated(IoSession session) {
    120                     if (useSSL) {
    121                         try {
    122                             session.getFilterChain().addFirst(
    123                                     "SSL",
    124                                     new SslFilter(BogusSslContextFactory
    125                                             .getInstance(true)));
    126                         } catch (GeneralSecurityException e) {
    127                             LOGGER.error("", e);
    128                             throw new RuntimeException(e);
    129                         }
    130                     }
    131                 }
    132
    133                 // This is for TLS re-entrance test
    134                 @Override
    135                 public void messageReceived(IoSession session, Object message)
    136                         throws Exception {
    137                     if (!(message instanceof IoBuffer)) {
    138                         return;
    139                     }
    140
    141                     IoBuffer buf = (IoBuffer) message;
    142
    143                     buf.mark();
    144
    145                     if (session.getFilterChain().contains("SSL")
    146                             && buf.remaining() == 1 && buf.get() == (byte) '.') {
    147                         LOGGER.info("TLS Reentrance");
    148                         ((SslFilter) session.getFilterChain().get("SSL"))
    149                                 .startSsl(session);
    150
    151                         // Send a response
    152                         buf.capacity(1);
    153                         buf.flip();
    154                         session.setAttribute(SslFilter.DISABLE_ENCRYPTION_ONCE);
    155                         session.write(buf);
    156                     } else {
    157                         buf.reset();
    158                         super.messageReceived(session, buf);
    159                     }
    160                 }
    161             });
    162
    163             socketAcceptor.bind(address);
    164             socketBound = true;
    165
    166             datagramAcceptor.setHandler(new EchoProtocolHandler());
    167             datagramAcceptor.bind(address);
    168             datagramBound = true;
    169         } catch (IOException e) {
    170             // Do nothing
    171         } finally {
    172             if (socketBound && !datagramBound) {
    173                 socketAcceptor.unbind();
    174             }
    175             if (datagramBound && !socketBound) {
    176                 datagramAcceptor.unbind();
    177             }
    178         }
    179
    180         // If there is no port available, test fails.
    181         if (!socketBound || !datagramBound) {
    182             throw new IOException("Cannot bind any test port.");
    183         }
    184
    185         boundAddress = address;
    186         LOGGER.info("Using port " + port + " for testing.");
    187     }
    188
    189     @After
    190     public void tearDown() throws Exception {
    191         if (boundAddress != null) {
    192             socketAcceptor.dispose();
    193             datagramAcceptor.dispose();
    194         }
    195     }
    196 }