From 22a37e548e63b9f1996093971ffcded631942cbe Mon Sep 17 00:00:00 2001 From: Jestan Nirojan Date: Sun, 12 Feb 2012 11:42:14 +0530 Subject: [PATCH] 1)implemented defragmenting sctp frame decoder 2)implemented sctp netty testsuite --- transport-sctp/pom.xml | 9 +- .../java/com/sun/nio/sctp/MessageInfo.java | 2 + .../sctp/DefaultSctpChannelConfig.java | 20 - .../netty/channel/sctp/SctpChannelConfig.java | 12 - .../channel/sctp/SctpClientPipelineSink.java | 2 +- .../java/io/netty/channel/sctp/SctpFrame.java | 15 + .../channel/sctp/SctpSendBufferPool.java | 2 +- .../channel/sctp/SctpServerPipelineSink.java | 2 +- .../io/netty/channel/sctp/SctpWorker.java | 8 +- .../codec/DefaultInboundStreamFilter.java | 26 + ...ava => DefaultOutboundStreamSelector.java} | 2 +- .../sctp/codec/InboundStreamFilter.java | 24 + ...ector.java => OutboundStreamSelector.java} | 2 +- .../channel/sctp/codec/SctpFrameDecoder.java | 43 +- .../channel/sctp/codec/SctpFrameEncoder.java | 6 +- .../channel/sctp/codec/package-info.java | 3 +- .../io/netty/channel/sctp/package-info.java | 3 +- .../AbstractSocketClientBootstrapTest.java | 192 ++++++ ...tSocketCompatibleObjectStreamEchoTest.java | 190 ++++++ .../transport/AbstractSocketEchoTest.java | 186 +++++ .../AbstractSocketFixedLengthEchoTest.java | 190 ++++++ .../AbstractSocketObjectStreamEchoTest.java | 189 ++++++ .../AbstractSocketServerBootstrapTest.java | 217 ++++++ .../transport/AbstractSocketSslEchoTest.java | 640 ++++++++++++++++++ .../AbstractSocketStringEchoTest.java | 196 ++++++ .../sctp/SctpClientBootstrapTest.java | 29 + .../SctpCompatibleObjectStreamEchoTest.java | 35 + .../transport/sctp/SctpEchoTest.java | 35 + .../sctp/SctpFixedLengthEchoTest.java | 35 + .../sctp/SctpObjectStreamEchoTest.java | 35 + .../sctp/SctpServerBootstrapTest.java | 30 + .../transport/sctp/SctpSslEchoTest.java | 35 + .../transport/sctp/SctpStringEchoTest.java | 35 + .../io/netty/testsuite/util/DummyHandler.java | 34 + .../testsuite/util/SctpSocketAddresses.java | 22 + 35 files changed, 2453 insertions(+), 53 deletions(-) create mode 100644 transport-sctp/src/main/java/io/netty/channel/sctp/codec/DefaultInboundStreamFilter.java rename transport-sctp/src/main/java/io/netty/channel/sctp/codec/{DefaultSctpWriteStreamSelector.java => DefaultOutboundStreamSelector.java} (91%) create mode 100644 transport-sctp/src/main/java/io/netty/channel/sctp/codec/InboundStreamFilter.java rename transport-sctp/src/main/java/io/netty/channel/sctp/codec/{SctpWriteStreamSelector.java => OutboundStreamSelector.java} (94%) create mode 100644 transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketClientBootstrapTest.java create mode 100644 transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketCompatibleObjectStreamEchoTest.java create mode 100644 transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketEchoTest.java create mode 100644 transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketFixedLengthEchoTest.java create mode 100644 transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketObjectStreamEchoTest.java create mode 100644 transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketServerBootstrapTest.java create mode 100644 transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketSslEchoTest.java create mode 100644 transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketStringEchoTest.java create mode 100644 transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpClientBootstrapTest.java create mode 100644 transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpCompatibleObjectStreamEchoTest.java create mode 100644 transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpEchoTest.java create mode 100644 transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpFixedLengthEchoTest.java create mode 100644 transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpObjectStreamEchoTest.java create mode 100644 transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpServerBootstrapTest.java create mode 100644 transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpSslEchoTest.java create mode 100644 transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpStringEchoTest.java create mode 100644 transport-sctp/src/test/java/io/netty/testsuite/util/DummyHandler.java create mode 100644 transport-sctp/src/test/java/io/netty/testsuite/util/SctpSocketAddresses.java diff --git a/transport-sctp/pom.xml b/transport-sctp/pom.xml index 95aab04293..ebf608425f 100644 --- a/transport-sctp/pom.xml +++ b/transport-sctp/pom.xml @@ -38,7 +38,12 @@ ${project.groupId} netty-codec - ${project.version} - + ${project.version} + + + ${project.groupId} + netty-handler + ${project.version} + diff --git a/transport-sctp/src/main/java/com/sun/nio/sctp/MessageInfo.java b/transport-sctp/src/main/java/com/sun/nio/sctp/MessageInfo.java index bab8487f3f..1f7eaccbd0 100644 --- a/transport-sctp/src/main/java/com/sun/nio/sctp/MessageInfo.java +++ b/transport-sctp/src/main/java/com/sun/nio/sctp/MessageInfo.java @@ -32,5 +32,7 @@ public abstract class MessageInfo { public abstract int payloadProtocolID(); public abstract MessageInfo payloadProtocolID(int ppid); public abstract boolean isComplete(); + public abstract boolean isUnordered(); + public abstract MessageInfo unordered(boolean b); } diff --git a/transport-sctp/src/main/java/io/netty/channel/sctp/DefaultSctpChannelConfig.java b/transport-sctp/src/main/java/io/netty/channel/sctp/DefaultSctpChannelConfig.java index 25d667951d..d2fafb6ad4 100644 --- a/transport-sctp/src/main/java/io/netty/channel/sctp/DefaultSctpChannelConfig.java +++ b/transport-sctp/src/main/java/io/netty/channel/sctp/DefaultSctpChannelConfig.java @@ -50,8 +50,6 @@ class DefaultSctpChannelConfig extends DefaultChannelConfig implements SctpChann setSendBufferSize(ConversionUtil.toInt(value)); } else if (key.equals("sctpNoDelay")) { setSctpNoDelay(ConversionUtil.toBoolean(value)); - } else if (key.equals("soLinger")) { - setSoLinger(ConversionUtil.toInt(value)); } else if (key.equals("sctpInitMaxStreams")) { setInitMaxStreams((InitMaxStreams) value); } else { @@ -78,24 +76,6 @@ class DefaultSctpChannelConfig extends DefaultChannelConfig implements SctpChann } } - @Override - public int getSoLinger() { - try { - return channel.getOption(SO_LINGER); - } catch (IOException e) { - throw new ChannelException(e); - } - } - - @Override - public void setSoLinger(int soLinger) { - try { - channel.setOption(SO_LINGER, soLinger); - } catch (IOException e) { - throw new ChannelException(e); - } - } - @Override public int getSendBufferSize() { try { diff --git a/transport-sctp/src/main/java/io/netty/channel/sctp/SctpChannelConfig.java b/transport-sctp/src/main/java/io/netty/channel/sctp/SctpChannelConfig.java index bf67ec3ac2..798285abcc 100644 --- a/transport-sctp/src/main/java/io/netty/channel/sctp/SctpChannelConfig.java +++ b/transport-sctp/src/main/java/io/netty/channel/sctp/SctpChannelConfig.java @@ -32,8 +32,6 @@ import io.netty.channel.ChannelConfig; * * {@code "sctpNoDelay"}{@link #setSctpNoDelay(boolean)}} * - * {@code "soLinger"}{@link #setSoLinger(int)} - * * {@code "receiveBufferSize"}{@link #setReceiveBufferSize(int)} * * {@code "sendBufferSize"}{@link #setSendBufferSize(int)} @@ -54,16 +52,6 @@ public interface SctpChannelConfig extends ChannelConfig { */ void setSctpNoDelay(boolean sctpNoDelay); - /** - * Gets the {@code SO_LINGER} option. - */ - int getSoLinger(); - - /** - * Sets the {@code SO_LINGER} option. - */ - void setSoLinger(int soLinger); - /** * Gets the {@code SO_SNDBUF} option. */ diff --git a/transport-sctp/src/main/java/io/netty/channel/sctp/SctpClientPipelineSink.java b/transport-sctp/src/main/java/io/netty/channel/sctp/SctpClientPipelineSink.java index cdd483beb2..20f5961160 100644 --- a/transport-sctp/src/main/java/io/netty/channel/sctp/SctpClientPipelineSink.java +++ b/transport-sctp/src/main/java/io/netty/channel/sctp/SctpClientPipelineSink.java @@ -227,7 +227,7 @@ class SctpClientPipelineSink extends AbstractChannelSink { wakenUp.set(false); try { - int selectedKeyCount = selector.select(500); + int selectedKeyCount = selector.select(100); // 'wakenUp.compareAndSet(false, true)' is always evaluated // before calling 'selector.wakeup()' to reduce the wake-up diff --git a/transport-sctp/src/main/java/io/netty/channel/sctp/SctpFrame.java b/transport-sctp/src/main/java/io/netty/channel/sctp/SctpFrame.java index ddea344751..30a2919ef9 100644 --- a/transport-sctp/src/main/java/io/netty/channel/sctp/SctpFrame.java +++ b/transport-sctp/src/main/java/io/netty/channel/sctp/SctpFrame.java @@ -15,6 +15,7 @@ */ package io.netty.channel.sctp; +import com.sun.nio.sctp.MessageInfo; import io.netty.buffer.ChannelBuffer; import io.netty.buffer.ChannelBuffers; @@ -23,8 +24,11 @@ import io.netty.buffer.ChannelBuffers; public final class SctpFrame { private final int streamIdentifier; private final int protocolIdentifier; + private final ChannelBuffer payloadBuffer; + private MessageInfo msgInfo; + /** * Essential data that is being carried within SCTP Data Chunk * @param protocolIdentifier of payload @@ -37,6 +41,13 @@ public final class SctpFrame { this.payloadBuffer = payloadBuffer; } + public SctpFrame(MessageInfo msgInfo, ChannelBuffer payloadBuffer) { + this.msgInfo = msgInfo; + this.streamIdentifier = msgInfo.streamNumber(); + this.protocolIdentifier = msgInfo.payloadProtocolID(); + this.payloadBuffer = payloadBuffer; + } + public int getStreamIdentifier() { return streamIdentifier; } @@ -53,6 +64,10 @@ public final class SctpFrame { } } + public MessageInfo getMessageInfo() { + return msgInfo; + } + @Override public String toString() { return new StringBuilder(). diff --git a/transport-sctp/src/main/java/io/netty/channel/sctp/SctpSendBufferPool.java b/transport-sctp/src/main/java/io/netty/channel/sctp/SctpSendBufferPool.java index c920195414..382e5b4fc4 100644 --- a/transport-sctp/src/main/java/io/netty/channel/sctp/SctpSendBufferPool.java +++ b/transport-sctp/src/main/java/io/netty/channel/sctp/SctpSendBufferPool.java @@ -43,7 +43,7 @@ final class SctpSendBufferPool { return acquire((SctpFrame) message); } else { throw new IllegalArgumentException( - "unsupported message type: " + message.getClass() + " required io.netty.channel.sctp.SctpFrame instance"); + "unsupported message type: " + message.getClass() + " required: io.netty.channel.sctp.SctpFrame"); } } diff --git a/transport-sctp/src/main/java/io/netty/channel/sctp/SctpServerPipelineSink.java b/transport-sctp/src/main/java/io/netty/channel/sctp/SctpServerPipelineSink.java index d39ca7b688..31719676fb 100644 --- a/transport-sctp/src/main/java/io/netty/channel/sctp/SctpServerPipelineSink.java +++ b/transport-sctp/src/main/java/io/netty/channel/sctp/SctpServerPipelineSink.java @@ -227,7 +227,7 @@ class SctpServerPipelineSink extends AbstractChannelSink { try { for (;;) { try { - if (selector.select(500) > 0) { + if (selector.select(100) > 0) { selector.selectedKeys().clear(); } diff --git a/transport-sctp/src/main/java/io/netty/channel/sctp/SctpWorker.java b/transport-sctp/src/main/java/io/netty/channel/sctp/SctpWorker.java index 3f01e3a9f5..20b876fa57 100644 --- a/transport-sctp/src/main/java/io/netty/channel/sctp/SctpWorker.java +++ b/transport-sctp/src/main/java/io/netty/channel/sctp/SctpWorker.java @@ -310,10 +310,10 @@ class SctpWorker implements Runnable { messageInfo = channel.channel.receive(bb, null, notificationHandler); if (messageInfo != null) { messageReceived = true; - if (messageInfo.isComplete()) { + if (!messageInfo.isUnordered()) { failure = false; } else { - logger.error("Received incomplete sctp packet, can not continue! Expected SCTP_EXPLICIT_COMPLETE message"); + logger.error("Received unordered SCTP Packet"); failure = true; } } else { @@ -343,9 +343,7 @@ class SctpWorker implements Runnable { // Fire the event. fireMessageReceived(channel, - new SctpFrame(messageInfo.streamNumber(), - messageInfo.payloadProtocolID(), - buffer), + new SctpFrame(messageInfo, buffer), messageInfo.address()); } else { recvBufferPool.release(bb); diff --git a/transport-sctp/src/main/java/io/netty/channel/sctp/codec/DefaultInboundStreamFilter.java b/transport-sctp/src/main/java/io/netty/channel/sctp/codec/DefaultInboundStreamFilter.java new file mode 100644 index 0000000000..ae8ae6e35a --- /dev/null +++ b/transport-sctp/src/main/java/io/netty/channel/sctp/codec/DefaultInboundStreamFilter.java @@ -0,0 +1,26 @@ +/* + * Copyright 2011 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.channel.sctp.codec; + +import io.netty.channel.sctp.SctpChannel; +import io.netty.channel.sctp.SctpFrame; + +public class DefaultInboundStreamFilter implements InboundStreamFilter { + @Override + public boolean filter(SctpChannel sctpChannel, SctpFrame sctpFrame) { + return true; + } +} diff --git a/transport-sctp/src/main/java/io/netty/channel/sctp/codec/DefaultSctpWriteStreamSelector.java b/transport-sctp/src/main/java/io/netty/channel/sctp/codec/DefaultOutboundStreamSelector.java similarity index 91% rename from transport-sctp/src/main/java/io/netty/channel/sctp/codec/DefaultSctpWriteStreamSelector.java rename to transport-sctp/src/main/java/io/netty/channel/sctp/codec/DefaultOutboundStreamSelector.java index f089bf5164..c712d2052f 100644 --- a/transport-sctp/src/main/java/io/netty/channel/sctp/codec/DefaultSctpWriteStreamSelector.java +++ b/transport-sctp/src/main/java/io/netty/channel/sctp/codec/DefaultOutboundStreamSelector.java @@ -17,7 +17,7 @@ package io.netty.channel.sctp.codec; import io.netty.channel.sctp.SctpChannel; -public class DefaultSctpWriteStreamSelector implements SctpWriteStreamSelector { +public class DefaultOutboundStreamSelector implements OutboundStreamSelector { @Override public int streamIdentifier(SctpChannel sctpChannel, Object msg) { return 1; diff --git a/transport-sctp/src/main/java/io/netty/channel/sctp/codec/InboundStreamFilter.java b/transport-sctp/src/main/java/io/netty/channel/sctp/codec/InboundStreamFilter.java new file mode 100644 index 0000000000..a28beb8111 --- /dev/null +++ b/transport-sctp/src/main/java/io/netty/channel/sctp/codec/InboundStreamFilter.java @@ -0,0 +1,24 @@ +/* + * Copyright 2011 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.channel.sctp.codec; + +import io.netty.channel.sctp.SctpChannel; +import io.netty.channel.sctp.SctpFrame; + +public interface InboundStreamFilter { + + boolean filter(SctpChannel sctpChannel, SctpFrame sctpFrame); +} diff --git a/transport-sctp/src/main/java/io/netty/channel/sctp/codec/SctpWriteStreamSelector.java b/transport-sctp/src/main/java/io/netty/channel/sctp/codec/OutboundStreamSelector.java similarity index 94% rename from transport-sctp/src/main/java/io/netty/channel/sctp/codec/SctpWriteStreamSelector.java rename to transport-sctp/src/main/java/io/netty/channel/sctp/codec/OutboundStreamSelector.java index 54574889f6..188e1eb214 100644 --- a/transport-sctp/src/main/java/io/netty/channel/sctp/codec/SctpWriteStreamSelector.java +++ b/transport-sctp/src/main/java/io/netty/channel/sctp/codec/OutboundStreamSelector.java @@ -17,6 +17,6 @@ package io.netty.channel.sctp.codec; import io.netty.channel.sctp.SctpChannel; -public interface SctpWriteStreamSelector { +public interface OutboundStreamSelector { int streamIdentifier(SctpChannel sctpChannel, Object msg); } diff --git a/transport-sctp/src/main/java/io/netty/channel/sctp/codec/SctpFrameDecoder.java b/transport-sctp/src/main/java/io/netty/channel/sctp/codec/SctpFrameDecoder.java index 4722e91b77..b3e6a9ca02 100644 --- a/transport-sctp/src/main/java/io/netty/channel/sctp/codec/SctpFrameDecoder.java +++ b/transport-sctp/src/main/java/io/netty/channel/sctp/codec/SctpFrameDecoder.java @@ -15,23 +15,62 @@ */ package io.netty.channel.sctp.codec; +import io.netty.buffer.ChannelBuffer; +import io.netty.buffer.ChannelBuffers; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.sctp.SctpChannel; import io.netty.channel.sctp.SctpFrame; import io.netty.handler.codec.oneone.OneToOneDecoder; /** - * SCTP Frame Decoder which just extract payload channel buffer + * SCTP Frame Decoder which extract payload channel buffer + * Note: Supported SCTP Frame Interleave Level - 0 */ public class SctpFrameDecoder extends OneToOneDecoder { + private final InboundStreamFilter inboundStreamFilter; + + private volatile ChannelBuffer cumulation; + + public SctpFrameDecoder() { + this.inboundStreamFilter = new DefaultInboundStreamFilter(); + } + + public SctpFrameDecoder(InboundStreamFilter inboundStreamFilter) { + this.inboundStreamFilter = inboundStreamFilter; + } + @Override protected Object decode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception { if (!(msg instanceof SctpFrame)) { return msg; } + final SctpChannel sctpChannel = (SctpChannel) channel; + final SctpFrame sctpFrame = (SctpFrame) msg; - return ((SctpFrame) msg).getPayloadBuffer(); + if (inboundStreamFilter.filter(sctpChannel, sctpFrame)) { + + final boolean complete = sctpFrame.getMessageInfo().isComplete(); + if (complete) { + if (cumulation == null) { + return sctpFrame.getPayloadBuffer(); + } else { + final ChannelBuffer extractedFrame = ChannelBuffers.wrappedBuffer(cumulation, sctpFrame.getPayloadBuffer()); + cumulation = null; + return extractedFrame; + } + } else { + if (cumulation == null) { + cumulation = sctpFrame.getPayloadBuffer(); + } else { + cumulation = ChannelBuffers.wrappedBuffer(cumulation, sctpFrame.getPayloadBuffer()); + } + return null; + } + } else { + return msg; + } } } diff --git a/transport-sctp/src/main/java/io/netty/channel/sctp/codec/SctpFrameEncoder.java b/transport-sctp/src/main/java/io/netty/channel/sctp/codec/SctpFrameEncoder.java index 7864cbbd71..96dd2b242a 100644 --- a/transport-sctp/src/main/java/io/netty/channel/sctp/codec/SctpFrameEncoder.java +++ b/transport-sctp/src/main/java/io/netty/channel/sctp/codec/SctpFrameEncoder.java @@ -28,17 +28,17 @@ import io.netty.handler.codec.oneone.OneToOneEncoder; public class SctpFrameEncoder extends OneToOneEncoder { private final int protocolIdentifier; - private final SctpWriteStreamSelector sctpWriteStreamSelector; + private final OutboundStreamSelector sctpWriteStreamSelector; public SctpFrameEncoder() { this(0); } public SctpFrameEncoder(int protocolIdentifier) { - this(protocolIdentifier, new DefaultSctpWriteStreamSelector()); + this(protocolIdentifier, new DefaultOutboundStreamSelector()); } - public SctpFrameEncoder(final int protocolIdentifier, final SctpWriteStreamSelector sctpWriteStreamSelector) { + public SctpFrameEncoder(final int protocolIdentifier, final OutboundStreamSelector sctpWriteStreamSelector) { if (sctpWriteStreamSelector == null) { throw new NullPointerException("sctpWriteStreamSelector"); } diff --git a/transport-sctp/src/main/java/io/netty/channel/sctp/codec/package-info.java b/transport-sctp/src/main/java/io/netty/channel/sctp/codec/package-info.java index 25918fec9e..d9fd0907d2 100644 --- a/transport-sctp/src/main/java/io/netty/channel/sctp/codec/package-info.java +++ b/transport-sctp/src/main/java/io/netty/channel/sctp/codec/package-info.java @@ -15,7 +15,6 @@ */ /** - * NIO-based socket channel - * API implementation - recommended for a large number of connections (>= 1000). + * */ package io.netty.channel.sctp.codec; diff --git a/transport-sctp/src/main/java/io/netty/channel/sctp/package-info.java b/transport-sctp/src/main/java/io/netty/channel/sctp/package-info.java index d99e070321..8da61a048b 100644 --- a/transport-sctp/src/main/java/io/netty/channel/sctp/package-info.java +++ b/transport-sctp/src/main/java/io/netty/channel/sctp/package-info.java @@ -15,7 +15,6 @@ */ /** - * NIO-based socket channel - * API implementation - recommended for a large number of connections (>= 1000). + * NIO -based SCTP channel API implementation. */ package io.netty.channel.sctp; diff --git a/transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketClientBootstrapTest.java b/transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketClientBootstrapTest.java new file mode 100644 index 0000000000..e8ca6d7fd7 --- /dev/null +++ b/transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketClientBootstrapTest.java @@ -0,0 +1,192 @@ +/* + * Copyright 2011 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.testsuite.transport; + +import com.sun.nio.sctp.SctpChannel; +import com.sun.nio.sctp.SctpServerChannel; +import io.netty.bootstrap.ClientBootstrap; +import io.netty.channel.ChannelFactory; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelPipelineException; +import io.netty.channel.ChannelPipelineFactory; +import io.netty.channel.sctp.codec.SctpFrameDecoder; +import io.netty.channel.sctp.codec.SctpFrameEncoder; +import io.netty.testsuite.util.DummyHandler; +import io.netty.testsuite.util.SctpSocketAddresses; +import io.netty.util.internal.ExecutorUtil; +import org.easymock.EasyMock; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.Iterator; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + + +/** + * An abstract test class to test socket client bootstraps + */ +public abstract class AbstractSocketClientBootstrapTest { + + private static ExecutorService executor; + + @BeforeClass + public static void init() { + executor = Executors.newCachedThreadPool(); + } + + @AfterClass + public static void destroy() { + ExecutorUtil.terminate(executor); + } + + protected abstract ChannelFactory newClientSocketChannelFactory(Executor executor); + + @Test(timeout = 10000) + public void testFailedConnectionAttempt() throws Exception { + ClientBootstrap bootstrap = new ClientBootstrap(); + bootstrap.setFactory(newClientSocketChannelFactory(executor)); + bootstrap.getPipeline().addLast("sctp-decoder", new SctpFrameDecoder()); + bootstrap.getPipeline().addLast("sctp-encoder", new SctpFrameEncoder()); + bootstrap.getPipeline().addLast("dummy", new DummyHandler()); + bootstrap.setOption("remoteAddress", new InetSocketAddress("255.255.255.255", 1)); + ChannelFuture future = bootstrap.connect(); + future.awaitUninterruptibly(); + assertFalse(future.isSuccess()); + assertTrue(future.getCause() instanceof IOException); + } + + @Test(timeout = 10000) + public void testSuccessfulConnectionAttempt() throws Throwable { + SctpServerChannel serverChannel = SctpServerChannel.open(); + serverChannel.bind(new InetSocketAddress(SctpSocketAddresses.LOOP_BACK, 0)); + + try { + serverChannel.configureBlocking(false); + + final Iterator serverAddresses = serverChannel.getAllLocalAddresses().iterator(); + InetSocketAddress serverAddress = (InetSocketAddress) serverAddresses.next(); + int serverPort = serverAddress.getPort(); + + ClientBootstrap bootstrap = + new ClientBootstrap(newClientSocketChannelFactory(executor)); + + bootstrap.getPipeline().addLast("sctp-decoder", new SctpFrameDecoder()); + bootstrap.getPipeline().addLast("sctp-encoder", new SctpFrameEncoder()); + bootstrap.getPipeline().addLast("dummy", new DummyHandler()); + bootstrap.setOption( + "remoteAddress", + new InetSocketAddress( + SctpSocketAddresses.LOOP_BACK, + serverPort)); + + ChannelFuture future = bootstrap.connect(); + serverChannel.accept(); + future.awaitUninterruptibly(); + + if (future.getCause() != null) { + throw future.getCause(); + } + assertTrue(future.isSuccess()); + + future.getChannel().close().awaitUninterruptibly(); + } finally { + try { + serverChannel.close(); + } catch (IOException e) { + // Ignore. + } + } + } + + @Test(timeout = 10000) + public void testSuccessfulConnectionAttemptWithLocalAddress() throws Throwable { + SctpServerChannel serverChannel = SctpServerChannel.open(); + + try { + serverChannel.configureBlocking(false); + serverChannel = serverChannel.bind(new InetSocketAddress(SctpSocketAddresses.LOOP_BACK, 0)); + + final Iterator serverAddresses = serverChannel.getAllLocalAddresses().iterator(); + InetSocketAddress serverAddress = (InetSocketAddress) serverAddresses.next(); + int serverPort = serverAddress.getPort(); + ClientBootstrap bootstrap = + new ClientBootstrap(newClientSocketChannelFactory(executor)); + + bootstrap.getPipeline().addLast("dummy", new DummyHandler()); + bootstrap.setOption( + "remoteAddress", + new InetSocketAddress( + SctpSocketAddresses.LOOP_BACK, + serverPort)); + bootstrap.setOption("localAddress", new InetSocketAddress(SctpSocketAddresses.LOOP_BACK, 0)); + + ChannelFuture future = bootstrap.connect(); + serverChannel.accept(); + future.awaitUninterruptibly(); + + if (future.getCause() != null) { + throw future.getCause(); + } + assertTrue(future.isSuccess()); + + future.getChannel().close().awaitUninterruptibly(); + } finally { + try { + serverChannel.close(); + } catch (IOException e) { + // Ignore. + } + } + } + + @Test(expected = ChannelPipelineException.class) + public void testFailedPipelineInitialization() throws Exception { + ClientBootstrap bootstrap = new ClientBootstrap(EasyMock.createMock(ChannelFactory.class)); + ChannelPipelineFactory pipelineFactory = EasyMock.createMock(ChannelPipelineFactory.class); + bootstrap.setPipelineFactory(pipelineFactory); + + EasyMock.expect(pipelineFactory.getPipeline()).andThrow(new ChannelPipelineException()); + EasyMock.replay(pipelineFactory); + + bootstrap.connect(new InetSocketAddress(SctpSocketAddresses.LOOP_BACK, 1)); + } + + @Test(expected = IllegalStateException.class) + public void shouldHaveRemoteAddressOption() { + new ClientBootstrap(EasyMock.createMock(ChannelFactory.class)).connect(); + } + + + @Test(expected = NullPointerException.class) + public void shouldDisallowNullRemoteAddressParameter1() { + new ClientBootstrap(EasyMock.createMock(ChannelFactory.class)).connect(null); + } + + @Test(expected = NullPointerException.class) + public void shouldDisallowNullRemoteAddressParameter2() { + new ClientBootstrap(EasyMock.createMock(ChannelFactory.class)).connect(null, null); + } +} diff --git a/transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketCompatibleObjectStreamEchoTest.java b/transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketCompatibleObjectStreamEchoTest.java new file mode 100644 index 0000000000..eb2f2d424d --- /dev/null +++ b/transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketCompatibleObjectStreamEchoTest.java @@ -0,0 +1,190 @@ +/* + * Copyright 2011 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.testsuite.transport; + +import io.netty.bootstrap.ClientBootstrap; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.*; +import io.netty.channel.sctp.codec.SctpFrameDecoder; +import io.netty.channel.sctp.codec.SctpFrameEncoder; +import io.netty.handler.codec.serialization.CompatibleObjectDecoder; +import io.netty.handler.codec.serialization.CompatibleObjectEncoder; +import io.netty.testsuite.util.SctpSocketAddresses; +import io.netty.util.internal.ExecutorUtil; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.util.Random; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicReference; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public abstract class AbstractSocketCompatibleObjectStreamEchoTest { + + static final Random random = new Random(); + static final String[] data = new String[512];//could not test with jumbo sctp frame + + private static ExecutorService executor; + + static { + for (int i = 0; i < data.length; i ++) { + int eLen = random.nextInt(512); + char[] e = new char[eLen]; + for (int j = 0; j < eLen; j ++) { + e[j] = (char) ('a' + random.nextInt(26)); + } + + data[i] = new String(e); + } + } + + @BeforeClass + public static void init() { + executor = Executors.newCachedThreadPool(); + } + + @AfterClass + public static void destroy() { + ExecutorUtil.terminate(executor); + } + + protected abstract ChannelFactory newServerSocketChannelFactory(Executor executor); + protected abstract ChannelFactory newClientSocketChannelFactory(Executor executor); + + @Test + @SuppressWarnings("deprecation") + public void testCompatibleObjectEcho() throws Throwable { + ServerBootstrap sb = new ServerBootstrap(newServerSocketChannelFactory(executor)); + ClientBootstrap cb = new ClientBootstrap(newClientSocketChannelFactory(executor)); + + EchoHandler sh = new EchoHandler(); + EchoHandler ch = new EchoHandler(); + + sb.getPipeline().addLast("sctp-decoder", new SctpFrameDecoder()); + sb.getPipeline().addLast("sctp-encoder", new SctpFrameEncoder()); + sb.getPipeline().addLast("decoder", new CompatibleObjectDecoder()); + sb.getPipeline().addLast("encoder", new CompatibleObjectEncoder()); + sb.getPipeline().addLast("handler", sh); + + cb.getPipeline().addLast("sctp-decoder", new SctpFrameDecoder()); + cb.getPipeline().addLast("sctp-encoder", new SctpFrameEncoder()); + cb.getPipeline().addLast("decoder", new CompatibleObjectDecoder()); + cb.getPipeline().addLast("encoder", new CompatibleObjectEncoder()); + cb.getPipeline().addLast("handler", ch); + + Channel sc = sb.bind(new InetSocketAddress(SctpSocketAddresses.LOOP_BACK, 0)); + int port = ((InetSocketAddress) sc.getLocalAddress()).getPort(); + + ChannelFuture ccf = cb.connect(new InetSocketAddress(SctpSocketAddresses.LOOP_BACK, port)); + assertTrue(ccf.awaitUninterruptibly().isSuccess()); + + Channel cc = ccf.getChannel(); + for (String element : data) { + cc.write(element); + } + + while (ch.counter < data.length) { + if (sh.exception.get() != null) { + break; + } + if (ch.exception.get() != null) { + break; + } + + try { + Thread.sleep(1); + } catch (InterruptedException e) { + // Ignore. + } + } + + while (sh.counter < data.length) { + if (sh.exception.get() != null) { + break; + } + if (ch.exception.get() != null) { + break; + } + + try { + Thread.sleep(1); + } catch (InterruptedException e) { + // Ignore. + } + } + + sh.channel.close().awaitUninterruptibly(); + ch.channel.close().awaitUninterruptibly(); + sc.close().awaitUninterruptibly(); + + if (sh.exception.get() != null && !(sh.exception.get() instanceof IOException)) { + throw sh.exception.get(); + } + if (ch.exception.get() != null && !(ch.exception.get() instanceof IOException)) { + throw ch.exception.get(); + } + if (sh.exception.get() != null) { + throw sh.exception.get(); + } + if (ch.exception.get() != null) { + throw ch.exception.get(); + } + } + + private static class EchoHandler extends SimpleChannelUpstreamHandler { + volatile Channel channel; + final AtomicReference exception = new AtomicReference(); + volatile int counter; + + EchoHandler() { + } + + @Override + public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) + throws Exception { + channel = e.getChannel(); + } + + @Override + public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) + throws Exception { + + String m = (String) e.getMessage(); + assertEquals(data[counter], m); + + if (channel.getParent() != null) { + channel.write(m); + } + + counter ++; + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) + throws Exception { + if (exception.compareAndSet(null, e.getCause())) { + e.getChannel().close(); + } + } + } +} diff --git a/transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketEchoTest.java b/transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketEchoTest.java new file mode 100644 index 0000000000..90821601e1 --- /dev/null +++ b/transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketEchoTest.java @@ -0,0 +1,186 @@ +/* + * Copyright 2011 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.testsuite.transport; + +import io.netty.bootstrap.ClientBootstrap; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.buffer.ChannelBuffer; +import io.netty.buffer.ChannelBuffers; +import io.netty.channel.*; +import io.netty.channel.sctp.codec.SctpFrameDecoder; +import io.netty.channel.sctp.codec.SctpFrameEncoder; +import io.netty.testsuite.util.SctpSocketAddresses; +import io.netty.util.internal.ExecutorUtil; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.util.Random; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicReference; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public abstract class AbstractSocketEchoTest { + + private static final Random random = new Random(); + static final byte[] data = new byte[4096];//could not test ultra jumbo frames + + private static ExecutorService executor; + + static { + random.nextBytes(data); + } + + @BeforeClass + public static void init() { + executor = Executors.newCachedThreadPool(); + } + + @AfterClass + public static void destroy() { + ExecutorUtil.terminate(executor); + } + + protected abstract ChannelFactory newServerSocketChannelFactory(Executor executor); + protected abstract ChannelFactory newClientSocketChannelFactory(Executor executor); + + @Test + public void testSimpleEcho() throws Throwable { + ServerBootstrap sb = new ServerBootstrap(newServerSocketChannelFactory(executor)); + + ClientBootstrap cb = new ClientBootstrap(newClientSocketChannelFactory(executor)); + + + EchoHandler sh = new EchoHandler(); + EchoHandler ch = new EchoHandler(); + + sb.getPipeline().addLast("sctp-decoder", new SctpFrameDecoder()); + sb.getPipeline().addLast("sctp-encoder", new SctpFrameEncoder()); + sb.getPipeline().addLast("handler", sh); + + cb.getPipeline().addLast("sctp-decoder", new SctpFrameDecoder()); + cb.getPipeline().addLast("sctp-encoder", new SctpFrameEncoder()); + cb.getPipeline().addLast("handler", ch); + + Channel sc = sb.bind(new InetSocketAddress(SctpSocketAddresses.LOOP_BACK, 0)); + int port = ((InetSocketAddress) sc.getLocalAddress()).getPort(); + + ChannelFuture ccf = cb.connect(new InetSocketAddress(SctpSocketAddresses.LOOP_BACK, port)); + assertTrue(ccf.awaitUninterruptibly().isSuccess()); + + Channel cc = ccf.getChannel(); + for (int i = 0; i < data.length;) { + int length = Math.min(random.nextInt(1024 * 64), data.length - i); + cc.write(ChannelBuffers.wrappedBuffer(data, i, length)); + i += length; + } + + while (ch.counter < data.length) { + if (sh.exception.get() != null) { + break; + } + if (ch.exception.get() != null) { + break; + } + + try { + Thread.sleep(5); + } catch (InterruptedException e) { + // Ignore. + } + } + + while (sh.counter < data.length) { + if (sh.exception.get() != null) { + break; + } + if (ch.exception.get() != null) { + break; + } + + try { + Thread.sleep(5); + } catch (InterruptedException e) { + // Ignore. + } + } + + sh.channel.close().awaitUninterruptibly(); + ch.channel.close().awaitUninterruptibly(); + sc.close().awaitUninterruptibly(); + + if (sh.exception.get() != null && !(sh.exception.get() instanceof IOException)) { + throw sh.exception.get(); + } + if (ch.exception.get() != null && !(ch.exception.get() instanceof IOException)) { + throw ch.exception.get(); + } + if (sh.exception.get() != null) { + throw sh.exception.get(); + } + if (ch.exception.get() != null) { + throw ch.exception.get(); + } + } + + private static class EchoHandler extends SimpleChannelUpstreamHandler { + volatile Channel channel; + final AtomicReference exception = new AtomicReference(); + volatile int counter; + + EchoHandler() { + } + + @Override + public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) + throws Exception { + channel = e.getChannel(); + } + + @Override + public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) + throws Exception { + ChannelBuffer m = (ChannelBuffer) e.getMessage(); + byte[] actual = new byte[m.readableBytes()]; + m.getBytes(0, actual); + + int lastIdx = counter; + for (int i = 0; i < actual.length; i ++) { + assertEquals(data[i + lastIdx], actual[i]); + } + + if (channel.getParent() != null) { + channel.write(m); + } + + counter += actual.length; + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) + throws Exception { + if (exception.compareAndSet(null, e.getCause())) { + e.getChannel().close(); + } + } + } +} diff --git a/transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketFixedLengthEchoTest.java b/transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketFixedLengthEchoTest.java new file mode 100644 index 0000000000..697d694bb1 --- /dev/null +++ b/transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketFixedLengthEchoTest.java @@ -0,0 +1,190 @@ +/* + * Copyright 2011 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.testsuite.transport; + +import io.netty.bootstrap.ClientBootstrap; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.buffer.ChannelBuffer; +import io.netty.buffer.ChannelBuffers; +import io.netty.channel.*; +import io.netty.channel.sctp.codec.SctpFrameDecoder; +import io.netty.channel.sctp.codec.SctpFrameEncoder; +import io.netty.handler.codec.frame.FixedLengthFrameDecoder; +import io.netty.testsuite.util.SctpSocketAddresses; +import io.netty.util.internal.ExecutorUtil; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.util.Random; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicReference; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public abstract class AbstractSocketFixedLengthEchoTest { + + private static final Random random = new Random(); + static final byte[] data = new byte[1024];//could not test with jumbo frames + + private static ExecutorService executor; + + static { + random.nextBytes(data); + } + + @BeforeClass + public static void init() { + executor = Executors.newCachedThreadPool(); + } + + @AfterClass + public static void destroy() { + ExecutorUtil.terminate(executor); + } + + protected abstract ChannelFactory newServerSocketChannelFactory(Executor executor); + protected abstract ChannelFactory newClientSocketChannelFactory(Executor executor); + + @Test + public void testFixedLengthEcho() throws Throwable { + ServerBootstrap sb = new ServerBootstrap(newServerSocketChannelFactory(executor)); + ClientBootstrap cb = new ClientBootstrap(newClientSocketChannelFactory(executor)); + + EchoHandler sh = new EchoHandler(); + EchoHandler ch = new EchoHandler(); + + sb.getPipeline().addLast("sctp-decoder", new SctpFrameDecoder()); + sb.getPipeline().addLast("sctp-encoder", new SctpFrameEncoder()); + sb.getPipeline().addLast("decoder", new FixedLengthFrameDecoder(1024)); + sb.getPipeline().addAfter("decoder", "handler", sh); + + + cb.getPipeline().addLast("sctp-decoder", new SctpFrameDecoder()); + cb.getPipeline().addLast("sctp-encoder", new SctpFrameEncoder()); + cb.getPipeline().addLast("decoder", new FixedLengthFrameDecoder(1024)); + cb.getPipeline().addAfter("decoder", "handler", ch); + + Channel sc = sb.bind(new InetSocketAddress(0)); + int port = ((InetSocketAddress) sc.getLocalAddress()).getPort(); + + ChannelFuture ccf = cb.connect(new InetSocketAddress(SctpSocketAddresses.LOOP_BACK, port)); + assertTrue(ccf.awaitUninterruptibly().isSuccess()); + + Channel cc = ccf.getChannel(); + for (int i = 0; i < data.length;) { + int length = Math.min(random.nextInt(1024 * 3), data.length - i); + cc.write(ChannelBuffers.wrappedBuffer(data, i, length)); + i += length; + } + + while (ch.counter < data.length) { + if (sh.exception.get() != null) { + break; + } + if (ch.exception.get() != null) { + break; + } + + try { + Thread.sleep(1); + } catch (InterruptedException e) { + // Ignore. + } + } + + while (sh.counter < data.length) { + if (sh.exception.get() != null) { + break; + } + if (ch.exception.get() != null) { + break; + } + + try { + Thread.sleep(1); + } catch (InterruptedException e) { + // Ignore. + } + } + + sh.channel.close().awaitUninterruptibly(); + ch.channel.close().awaitUninterruptibly(); + sc.close().awaitUninterruptibly(); + + if (sh.exception.get() != null && !(sh.exception.get() instanceof IOException)) { + throw sh.exception.get(); + } + if (ch.exception.get() != null && !(ch.exception.get() instanceof IOException)) { + throw ch.exception.get(); + } + if (sh.exception.get() != null) { + throw sh.exception.get(); + } + if (ch.exception.get() != null) { + throw ch.exception.get(); + } + } + + private static class EchoHandler extends SimpleChannelUpstreamHandler { + volatile Channel channel; + final AtomicReference exception = new AtomicReference(); + volatile int counter; + + EchoHandler() { + } + + @Override + public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) + throws Exception { + channel = e.getChannel(); + } + + @Override + public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) + throws Exception { + ChannelBuffer m = (ChannelBuffer) e.getMessage(); + assertEquals(1024, m.readableBytes()); + + byte[] actual = new byte[m.readableBytes()]; + m.getBytes(0, actual); + + int lastIdx = counter; + for (int i = 0; i < actual.length; i ++) { + assertEquals(data[i + lastIdx], actual[i]); + } + + if (channel.getParent() != null) { + channel.write(m); + } + + counter += actual.length; + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) + throws Exception { + if (exception.compareAndSet(null, e.getCause())) { + e.getChannel().close(); + } + } + } +} diff --git a/transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketObjectStreamEchoTest.java b/transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketObjectStreamEchoTest.java new file mode 100644 index 0000000000..59102e3ce8 --- /dev/null +++ b/transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketObjectStreamEchoTest.java @@ -0,0 +1,189 @@ +/* + * Copyright 2011 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.testsuite.transport; + +import io.netty.bootstrap.ClientBootstrap; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.*; +import io.netty.channel.sctp.codec.SctpFrameDecoder; +import io.netty.channel.sctp.codec.SctpFrameEncoder; +import io.netty.handler.codec.serialization.ObjectDecoder; +import io.netty.handler.codec.serialization.ObjectEncoder; +import io.netty.testsuite.util.SctpSocketAddresses; +import io.netty.util.internal.ExecutorUtil; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.util.Random; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicReference; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public abstract class AbstractSocketObjectStreamEchoTest { + + static final Random random = new Random(); + static final String[] data = new String[512];//could not test jumbo frames + + private static ExecutorService executor; + + static { + for (int i = 0; i < data.length; i ++) { + int eLen = random.nextInt(512); + char[] e = new char[eLen]; + for (int j = 0; j < eLen; j ++) { + e[j] = (char) ('a' + random.nextInt(26)); + } + + data[i] = new String(e); + } + } + + @BeforeClass + public static void init() { + executor = Executors.newCachedThreadPool(); + } + + @AfterClass + public static void destroy() { + ExecutorUtil.terminate(executor); + } + + protected abstract ChannelFactory newServerSocketChannelFactory(Executor executor); + protected abstract ChannelFactory newClientSocketChannelFactory(Executor executor); + + @Test + public void testObjectEcho() throws Throwable { + ServerBootstrap sb = new ServerBootstrap(newServerSocketChannelFactory(executor)); + ClientBootstrap cb = new ClientBootstrap(newClientSocketChannelFactory(executor)); + + EchoHandler sh = new EchoHandler(); + EchoHandler ch = new EchoHandler(); + + sb.getPipeline().addLast("sctp-decoder", new SctpFrameDecoder()); + sb.getPipeline().addLast("sctp-encoder", new SctpFrameEncoder()); + sb.getPipeline().addLast("decoder", new ObjectDecoder()); + sb.getPipeline().addLast("encoder", new ObjectEncoder()); + sb.getPipeline().addLast("handler", sh); + + cb.getPipeline().addLast("sctp-decoder", new SctpFrameDecoder()); + cb.getPipeline().addLast("sctp-encoder", new SctpFrameEncoder()); + cb.getPipeline().addLast("decoder", new ObjectDecoder()); + cb.getPipeline().addLast("encoder", new ObjectEncoder()); + cb.getPipeline().addLast("handler", ch); + + Channel sc = sb.bind(new InetSocketAddress(SctpSocketAddresses.LOOP_BACK, 0)); + int port = ((InetSocketAddress) sc.getLocalAddress()).getPort(); + + ChannelFuture ccf = cb.connect(new InetSocketAddress(SctpSocketAddresses.LOOP_BACK, port)); + assertTrue(ccf.awaitUninterruptibly().isSuccess()); + + Channel cc = ccf.getChannel(); + for (String element : data) { + cc.write(element); + } + + while (ch.counter < data.length) { + if (sh.exception.get() != null) { + break; + } + if (ch.exception.get() != null) { + break; + } + + try { + Thread.sleep(5); + } catch (InterruptedException e) { + // Ignore. + } + } + + while (sh.counter < data.length) { + if (sh.exception.get() != null) { + break; + } + if (ch.exception.get() != null) { + break; + } + + try { + Thread.sleep(5); + } catch (InterruptedException e) { + // Ignore. + } + } + + sh.channel.close().awaitUninterruptibly(); + ch.channel.close().awaitUninterruptibly(); + sc.close().awaitUninterruptibly(); + + if (sh.exception.get() != null && !(sh.exception.get() instanceof IOException)) { + throw sh.exception.get(); + } + if (ch.exception.get() != null && !(ch.exception.get() instanceof IOException)) { + throw ch.exception.get(); + } + if (sh.exception.get() != null) { + throw sh.exception.get(); + } + if (ch.exception.get() != null) { + throw ch.exception.get(); + } + } + + private static class EchoHandler extends SimpleChannelUpstreamHandler { + volatile Channel channel; + final AtomicReference exception = new AtomicReference(); + volatile int counter; + + EchoHandler() { + } + + @Override + public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) + throws Exception { + channel = e.getChannel(); + } + + @Override + public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) + throws Exception { + + String m = (String) e.getMessage(); + assertEquals(data[counter], m); + + if (channel.getParent() != null) { + channel.write(m); + } + + counter ++; + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) + throws Exception { + if (exception.compareAndSet(null, e.getCause())) { + e.getChannel().close(); + } + } + } +} diff --git a/transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketServerBootstrapTest.java b/transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketServerBootstrapTest.java new file mode 100644 index 0000000000..28709c363d --- /dev/null +++ b/transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketServerBootstrapTest.java @@ -0,0 +1,217 @@ +/* + * Copyright 2011 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.testsuite.transport; + +import com.sun.nio.sctp.SctpChannel; +import com.sun.nio.sctp.SctpServerChannel; +import com.sun.nio.sctp.SctpStandardSocketOptions; +import io.netty.bootstrap.ClientBootstrap; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.*; +import io.netty.channel.sctp.SctpChannelConfig; +import io.netty.testsuite.util.DummyHandler; +import io.netty.testsuite.util.SctpSocketAddresses; +import io.netty.util.internal.ExecutorUtil; +import org.easymock.EasyMock; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.Iterator; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import static org.junit.Assert.assertEquals; + + +/** + * An abstract test class to test server socket bootstraps + */ +public abstract class AbstractSocketServerBootstrapTest { + + private static final boolean BUFSIZE_MODIFIABLE; + + static { + boolean bufSizeModifiable = true; + + SctpChannel s = null; + try { + s = SctpChannel.open(); + bufSizeModifiable = s.supportedOptions().contains(SctpStandardSocketOptions.SO_RCVBUF); + } catch (Exception e) { + bufSizeModifiable = false; + System.err.println( + "SCTP SO_RCVBUF does not work: " + e); + } finally { + BUFSIZE_MODIFIABLE = bufSizeModifiable; + try { + if (s != null) { + s.close(); + } + } catch (IOException e) { + // Ignore. + } + } + } + + private static ExecutorService executor; + + @BeforeClass + public static void init() { + executor = Executors.newCachedThreadPool(); + } + + @AfterClass + public static void destroy() { + ExecutorUtil.terminate(executor); + } + + protected abstract ChannelFactory newServerSocketChannelFactory(Executor executor); + + @Test(timeout = 30000, expected = ChannelException.class) + public void testFailedBindAttempt() throws Exception { + SctpServerChannel serverChannel = SctpServerChannel.open(); + serverChannel.bind(new InetSocketAddress(SctpSocketAddresses.LOOP_BACK, 0)); + + try { + final Iterator serverAddresses = serverChannel.getAllLocalAddresses().iterator(); + InetSocketAddress serverAddress = (InetSocketAddress) serverAddresses.next(); + final int boundPort = serverAddress.getPort(); + ServerBootstrap bootstrap = new ServerBootstrap(); + bootstrap.setFactory(newServerSocketChannelFactory(executor)); + bootstrap.setOption("localAddress", new InetSocketAddress(SctpSocketAddresses.LOOP_BACK, boundPort)); + bootstrap.bind().close().awaitUninterruptibly(); + } finally { + serverChannel.close(); + } + } + + @Test(timeout = 30000) + public void testSuccessfulBindAttempt() throws Exception { + ServerBootstrap bootstrap = new ServerBootstrap( + newServerSocketChannelFactory(executor)); + + bootstrap.setParentHandler(new ParentChannelHandler()); + bootstrap.setOption("localAddress", new InetSocketAddress(SctpSocketAddresses.LOOP_BACK, 0)); + bootstrap.setOption("child.receiveBufferSize", 9753); + bootstrap.setOption("child.sendBufferSize", 8642); + + bootstrap.getPipeline().addLast("dummy", new DummyHandler()); + + Channel channel = bootstrap.bind(); + ParentChannelHandler pch = + channel.getPipeline().get(ParentChannelHandler.class); + + SctpChannel sctpChannel = SctpChannel.open(); + try { + sctpChannel.connect( + new InetSocketAddress( + SctpSocketAddresses.LOOP_BACK, + ((InetSocketAddress) channel.getLocalAddress()).getPort())); + + // Wait until the connection is open in the server side. + while (pch.child == null) { + Thread.yield(); + } + + SctpChannelConfig cfg = (SctpChannelConfig) pch.child.getConfig(); + if (BUFSIZE_MODIFIABLE) { + assertEquals(9753, cfg.getReceiveBufferSize()); + assertEquals(8642, cfg.getSendBufferSize()); + } + } finally { + if (sctpChannel != null) { + try { + sctpChannel.close(); + } catch (IOException e) { + // Ignore. + } + } + channel.close().awaitUninterruptibly(); + } + + // Wait until the child connection is closed in the client side. + // We do not use Channel.close() to make sure it is closed automatically. + while (pch.child.isOpen()) { + try { + Thread.sleep(1); + } catch (InterruptedException e) { + // Ignore + } + } + + // Wait until all child events are fired. + while (pch.result.length() < 2) { + try { + Thread.sleep(1); + } catch (InterruptedException e) { + // Ignore + } + } + + // Confirm the received child events. + assertEquals("12", pch.result.toString()); + } + + @Test(expected = ChannelPipelineException.class) + public void testFailedPipelineInitialization() throws Exception { + ClientBootstrap bootstrap = new ClientBootstrap(EasyMock.createMock(ChannelFactory.class)); + ChannelPipelineFactory pipelineFactory = EasyMock.createMock(ChannelPipelineFactory.class); + bootstrap.setPipelineFactory(pipelineFactory); + + EasyMock.expect(pipelineFactory.getPipeline()).andThrow(new ChannelPipelineException()); + EasyMock.replay(pipelineFactory); + + bootstrap.connect(new InetSocketAddress(SctpSocketAddresses.LOOP_BACK, 1)); + } + + @Test(expected = IllegalStateException.class) + public void shouldHaveLocalAddressOption() { + new ServerBootstrap(EasyMock.createMock(ServerChannelFactory.class)).bind(); + } + + + @Test(expected = NullPointerException.class) + public void shouldDisallowNullLocalAddressParameter() { + new ServerBootstrap(EasyMock.createMock(ServerChannelFactory.class)).bind(null); + } + + private static class ParentChannelHandler extends SimpleChannelUpstreamHandler { + + volatile Channel child; + final StringBuffer result = new StringBuffer(); + + ParentChannelHandler() { + } + + @Override + public void childChannelClosed(ChannelHandlerContext ctx, + ChildChannelStateEvent e) throws Exception { + result.append('2'); + } + + @Override + public void childChannelOpen(ChannelHandlerContext ctx, + ChildChannelStateEvent e) throws Exception { + child = e.getChildChannel(); + result.append('1'); + } + } +} diff --git a/transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketSslEchoTest.java b/transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketSslEchoTest.java new file mode 100644 index 0000000000..b169ef6d43 --- /dev/null +++ b/transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketSslEchoTest.java @@ -0,0 +1,640 @@ +/* + * Copyright 2011 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.testsuite.transport; + +import io.netty.bootstrap.ClientBootstrap; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.buffer.ChannelBuffer; +import io.netty.buffer.ChannelBuffers; +import io.netty.channel.*; +import io.netty.channel.sctp.codec.SctpFrameDecoder; +import io.netty.channel.sctp.codec.SctpFrameEncoder; +import io.netty.handler.execution.ExecutionHandler; +import io.netty.handler.execution.OrderedMemoryAwareThreadPoolExecutor; +import io.netty.handler.ssl.SslHandler; +import io.netty.logging.InternalLogger; +import io.netty.logging.InternalLoggerFactory; +import io.netty.testsuite.util.SctpSocketAddresses; +import io.netty.util.internal.ExecutorUtil; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import javax.net.ssl.*; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.InetSocketAddress; +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.Security; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Random; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicReference; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public abstract class AbstractSocketSslEchoTest { + static final InternalLogger logger = + InternalLoggerFactory.getInstance(AbstractSocketSslEchoTest.class); + + private static final Random random = new Random(); + static final byte[] data = new byte[4096];//could not test jumbo frames + + private static ExecutorService executor; + private static ExecutorService eventExecutor; + + static { + random.nextBytes(data); + } + + @BeforeClass + public static void init() { + executor = Executors.newCachedThreadPool(); + eventExecutor = new OrderedMemoryAwareThreadPoolExecutor(16, 0, 0); + } + + @AfterClass + public static void destroy() { + ExecutorUtil.terminate(executor, eventExecutor); + } + + protected abstract ChannelFactory newServerSocketChannelFactory(Executor executor); + protected abstract ChannelFactory newClientSocketChannelFactory(Executor executor); + + protected boolean isExecutorRequired() { + return false; + } + + @Test + public void testSslEcho() throws Throwable { + ServerBootstrap sb = new ServerBootstrap(newServerSocketChannelFactory(executor)); + ClientBootstrap cb = new ClientBootstrap(newClientSocketChannelFactory(executor)); + + EchoHandler sh = new EchoHandler(true); + EchoHandler ch = new EchoHandler(false); + + SSLEngine sse = BogusSslContextFactory.getServerContext().createSSLEngine(); + SSLEngine cse = BogusSslContextFactory.getClientContext().createSSLEngine(); + sse.setUseClientMode(false); + cse.setUseClientMode(true); + + + sb.getPipeline().addLast("sctp-decoder", new SctpFrameDecoder()); + sb.getPipeline().addLast("sctp-encoder", new SctpFrameEncoder()); + sb.getPipeline().addLast("ssl", new SslHandler(sse)); + sb.getPipeline().addLast("handler", sh); + + cb.getPipeline().addLast("sctp-decoder", new SctpFrameDecoder()); + cb.getPipeline().addLast("sctp-encoder", new SctpFrameEncoder()); + cb.getPipeline().addLast("ssl", new SslHandler(cse)); + cb.getPipeline().addLast("handler", ch); + + if (isExecutorRequired()) { + sb.getPipeline().addFirst("executor", new ExecutionHandler(eventExecutor)); + cb.getPipeline().addFirst("executor", new ExecutionHandler(eventExecutor)); + } + + Channel sc = sb.bind(new InetSocketAddress(SctpSocketAddresses.LOOP_BACK, 0)); + int port = ((InetSocketAddress) sc.getLocalAddress()).getPort(); + + ChannelFuture ccf = cb.connect(new InetSocketAddress(SctpSocketAddresses.LOOP_BACK, port)); + ccf.awaitUninterruptibly(); + if (!ccf.isSuccess()) { + logger.error("Connection attempt failed", ccf.getCause()); + sc.close().awaitUninterruptibly(); + } + assertTrue(ccf.isSuccess()); + + Channel cc = ccf.getChannel(); + ChannelFuture hf = cc.getPipeline().get(SslHandler.class).handshake(); + hf.awaitUninterruptibly(); + if (!hf.isSuccess()) { + logger.error("Handshake failed", hf.getCause()); + sh.channel.close().awaitUninterruptibly(); + ch.channel.close().awaitUninterruptibly(); + sc.close().awaitUninterruptibly(); + } + + assertTrue(hf.isSuccess()); + + for (int i = 0; i < data.length;) { + int length = Math.min(random.nextInt(1024 * 64), data.length - i); + cc.write(ChannelBuffers.wrappedBuffer(data, i, length)); + i += length; + } + + while (ch.counter < data.length) { + if (sh.exception.get() != null) { + break; + } + if (ch.exception.get() != null) { + break; + } + + try { + Thread.sleep(1); + } catch (InterruptedException e) { + // Ignore. + } + } + + while (sh.counter < data.length) { + if (sh.exception.get() != null) { + break; + } + if (ch.exception.get() != null) { + break; + } + + try { + Thread.sleep(1); + } catch (InterruptedException e) { + // Ignore. + } + } + + sh.channel.close().awaitUninterruptibly(); + ch.channel.close().awaitUninterruptibly(); + sc.close().awaitUninterruptibly(); + + if (sh.exception.get() != null && !(sh.exception.get() instanceof IOException)) { + throw sh.exception.get(); + } + if (ch.exception.get() != null && !(ch.exception.get() instanceof IOException)) { + throw ch.exception.get(); + } + if (sh.exception.get() != null) { + throw sh.exception.get(); + } + if (ch.exception.get() != null) { + throw ch.exception.get(); + } + } + + private static class EchoHandler extends SimpleChannelUpstreamHandler { + volatile Channel channel; + final AtomicReference exception = new AtomicReference(); + volatile int counter; + private final boolean server; + + EchoHandler(boolean server) { + this.server = server; + } + + @Override + public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) + throws Exception { + channel = e.getChannel(); + } + + @Override + public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) + throws Exception { + ChannelBuffer m = (ChannelBuffer) e.getMessage(); + byte[] actual = new byte[m.readableBytes()]; + m.getBytes(0, actual); + + int lastIdx = counter; + for (int i = 0; i < actual.length; i ++) { + assertEquals(data[i + lastIdx], actual[i]); + } + + if (channel.getParent() != null) { + channel.write(m); + } + + counter += actual.length; + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) + throws Exception { + logger.warn( + "Unexpected exception from the " + + (server? "server" : "client") + " side", e.getCause()); + + exception.compareAndSet(null, e.getCause()); + e.getChannel().close(); + } + } + + private static class BogusSslContextFactory { + + private static final String PROTOCOL = "TLS"; + private static final SSLContext SERVER_CONTEXT; + private static final SSLContext CLIENT_CONTEXT; + + static { + String algorithm = Security.getProperty("ssl.KeyManagerFactory.algorithm"); + if (algorithm == null) { + algorithm = "SunX509"; + } + + SSLContext serverContext = null; + SSLContext clientContext = null; + try { + KeyStore ks = KeyStore.getInstance("JKS"); + ks.load(BogusKeyStore.asInputStream(), + BogusKeyStore.getKeyStorePassword()); + + // Set up key manager factory to use our key store + KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm); + kmf.init(ks, BogusKeyStore.getCertificatePassword()); + + // Initialize the SSLContext to work with our key managers. + serverContext = SSLContext.getInstance(PROTOCOL); + serverContext.init(kmf.getKeyManagers(), null, null); + } catch (Exception e) { + throw new Error( + "Failed to initialize the server-side SSLContext", e); + } + + try { + clientContext = SSLContext.getInstance(PROTOCOL); + clientContext.init(null, BogusTrustManagerFactory.getTrustManagers(), null); + } catch (Exception e) { + throw new Error( + "Failed to initialize the client-side SSLContext", e); + } + + SERVER_CONTEXT = serverContext; + CLIENT_CONTEXT = clientContext; + } + + public static SSLContext getServerContext() { + return SERVER_CONTEXT; + } + + public static SSLContext getClientContext() { + return CLIENT_CONTEXT; + } + } + + /** + * Bogus {@link javax.net.ssl.TrustManagerFactorySpi} which accepts any certificate + * even if it is invalid. + */ + private static class BogusTrustManagerFactory extends TrustManagerFactorySpi { + + private static final TrustManager DUMMY_TRUST_MANAGER = new X509TrustManager() { + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + + @Override + public void checkClientTrusted( + X509Certificate[] chain, String authType) throws CertificateException { + // Always trust - it is an example. + // You should do something in the real world. + // You will reach here only if you enabled client certificate auth, + // as described in SecureChatSslContextFactory. + System.err.println( + "UNKNOWN CLIENT CERTIFICATE: " + chain[0].getSubjectDN()); + } + + @Override + public void checkServerTrusted( + X509Certificate[] chain, String authType) throws CertificateException { + // Always trust - it is an example. + // You should do something in the real world. + System.err.println( + "UNKNOWN SERVER CERTIFICATE: " + chain[0].getSubjectDN()); + } + }; + + public static TrustManager[] getTrustManagers() { + return new TrustManager[] { DUMMY_TRUST_MANAGER }; + } + + @Override + protected TrustManager[] engineGetTrustManagers() { + return getTrustManagers(); + } + + @Override + protected void engineInit(KeyStore keystore) throws KeyStoreException { + // Unused + } + + @Override + protected void engineInit(ManagerFactoryParameters managerFactoryParameters) + throws InvalidAlgorithmParameterException { + // Unused + } + } + + /** + * A bogus key store which provides all the required information to + * create an example SSL connection. + * + * To generate a bogus key store: + *
+     * keytool  -genkey -alias bogus -keysize 2048 -validity 36500
+     *          -keyalg RSA -dname "CN=bogus"
+     *          -keypass secret -storepass secret
+     *          -keystore cert.jks
+     * 
+ */ + private static final class BogusKeyStore { + private static final short[] DATA = { + 0xfe, 0xed, 0xfe, 0xed, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, + 0x65, 0x00, 0x00, 0x01, 0x1a, 0x9f, 0x57, 0xa5, + 0x27, 0x00, 0x00, 0x01, 0x9a, 0x30, 0x82, 0x01, + 0x96, 0x30, 0x0e, 0x06, 0x0a, 0x2b, 0x06, 0x01, + 0x04, 0x01, 0x2a, 0x02, 0x11, 0x01, 0x01, 0x05, + 0x00, 0x04, 0x82, 0x01, 0x82, 0x48, 0x6d, 0xcf, + 0x16, 0xb5, 0x50, 0x95, 0x36, 0xbf, 0x47, 0x27, + 0x50, 0x58, 0x0d, 0xa2, 0x52, 0x7e, 0x25, 0xab, + 0x14, 0x1a, 0x26, 0x5e, 0x2d, 0x8a, 0x23, 0x90, + 0x60, 0x7f, 0x12, 0x20, 0x56, 0xd1, 0x43, 0xa2, + 0x6b, 0x47, 0x5d, 0xed, 0x9d, 0xd4, 0xe5, 0x83, + 0x28, 0x89, 0xc2, 0x16, 0x4c, 0x76, 0x06, 0xad, + 0x8e, 0x8c, 0x29, 0x1a, 0x9b, 0x0f, 0xdd, 0x60, + 0x4b, 0xb4, 0x62, 0x82, 0x9e, 0x4a, 0x63, 0x83, + 0x2e, 0xd2, 0x43, 0x78, 0xc2, 0x32, 0x1f, 0x60, + 0xa9, 0x8a, 0x7f, 0x0f, 0x7c, 0xa6, 0x1d, 0xe6, + 0x92, 0x9e, 0x52, 0xc7, 0x7d, 0xbb, 0x35, 0x3b, + 0xaa, 0x89, 0x73, 0x4c, 0xfb, 0x99, 0x54, 0x97, + 0x99, 0x28, 0x6e, 0x66, 0x5b, 0xf7, 0x9b, 0x7e, + 0x6d, 0x8a, 0x2f, 0xfa, 0xc3, 0x1e, 0x71, 0xb9, + 0xbd, 0x8f, 0xc5, 0x63, 0x25, 0x31, 0x20, 0x02, + 0xff, 0x02, 0xf0, 0xc9, 0x2c, 0xdd, 0x3a, 0x10, + 0x30, 0xab, 0xe5, 0xad, 0x3d, 0x1a, 0x82, 0x77, + 0x46, 0xed, 0x03, 0x38, 0xa4, 0x73, 0x6d, 0x36, + 0x36, 0x33, 0x70, 0xb2, 0x63, 0x20, 0xca, 0x03, + 0xbf, 0x5a, 0xf4, 0x7c, 0x35, 0xf0, 0x63, 0x1a, + 0x12, 0x33, 0x12, 0x58, 0xd9, 0xa2, 0x63, 0x6b, + 0x63, 0x82, 0x41, 0x65, 0x70, 0x37, 0x4b, 0x99, + 0x04, 0x9f, 0xdd, 0x5e, 0x07, 0x01, 0x95, 0x9f, + 0x36, 0xe8, 0xc3, 0x66, 0x2a, 0x21, 0x69, 0x68, + 0x40, 0xe6, 0xbc, 0xbb, 0x85, 0x81, 0x21, 0x13, + 0xe6, 0xa4, 0xcf, 0xd3, 0x67, 0xe3, 0xfd, 0x75, + 0xf0, 0xdf, 0x83, 0xe0, 0xc5, 0x36, 0x09, 0xac, + 0x1b, 0xd4, 0xf7, 0x2a, 0x23, 0x57, 0x1c, 0x5c, + 0x0f, 0xf4, 0xcf, 0xa2, 0xcf, 0xf5, 0xbd, 0x9c, + 0x69, 0x98, 0x78, 0x3a, 0x25, 0xe4, 0xfd, 0x85, + 0x11, 0xcc, 0x7d, 0xef, 0xeb, 0x74, 0x60, 0xb1, + 0xb7, 0xfb, 0x1f, 0x0e, 0x62, 0xff, 0xfe, 0x09, + 0x0a, 0xc3, 0x80, 0x2f, 0x10, 0x49, 0x89, 0x78, + 0xd2, 0x08, 0xfa, 0x89, 0x22, 0x45, 0x91, 0x21, + 0xbc, 0x90, 0x3e, 0xad, 0xb3, 0x0a, 0xb4, 0x0e, + 0x1c, 0xa1, 0x93, 0x92, 0xd8, 0x72, 0x07, 0x54, + 0x60, 0xe7, 0x91, 0xfc, 0xd9, 0x3c, 0xe1, 0x6f, + 0x08, 0xe4, 0x56, 0xf6, 0x0b, 0xb0, 0x3c, 0x39, + 0x8a, 0x2d, 0x48, 0x44, 0x28, 0x13, 0xca, 0xe9, + 0xf7, 0xa3, 0xb6, 0x8a, 0x5f, 0x31, 0xa9, 0x72, + 0xf2, 0xde, 0x96, 0xf2, 0xb1, 0x53, 0xb1, 0x3e, + 0x24, 0x57, 0xfd, 0x18, 0x45, 0x1f, 0xc5, 0x33, + 0x1b, 0xa4, 0xe8, 0x21, 0xfa, 0x0e, 0xb2, 0xb9, + 0xcb, 0xc7, 0x07, 0x41, 0xdd, 0x2f, 0xb6, 0x6a, + 0x23, 0x18, 0xed, 0xc1, 0xef, 0xe2, 0x4b, 0xec, + 0xc9, 0xba, 0xfb, 0x46, 0x43, 0x90, 0xd7, 0xb5, + 0x68, 0x28, 0x31, 0x2b, 0x8d, 0xa8, 0x51, 0x63, + 0xf7, 0x53, 0x99, 0x19, 0x68, 0x85, 0x66, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x05, 0x58, 0x2e, 0x35, + 0x30, 0x39, 0x00, 0x00, 0x02, 0x3a, 0x30, 0x82, + 0x02, 0x36, 0x30, 0x82, 0x01, 0xe0, 0xa0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x04, 0x48, 0x59, 0xf1, + 0x92, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, + 0x30, 0x81, 0xa0, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4b, 0x52, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x0a, 0x4b, 0x79, 0x75, 0x6e, 0x67, + 0x67, 0x69, 0x2d, 0x64, 0x6f, 0x31, 0x14, 0x30, + 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0b, + 0x53, 0x65, 0x6f, 0x6e, 0x67, 0x6e, 0x61, 0x6d, + 0x2d, 0x73, 0x69, 0x31, 0x1a, 0x30, 0x18, 0x06, + 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x54, 0x68, + 0x65, 0x20, 0x4e, 0x65, 0x74, 0x74, 0x79, 0x20, + 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x31, + 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0b, + 0x13, 0x0f, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, + 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x73, 0x31, 0x30, 0x30, 0x2e, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x27, 0x73, 0x65, 0x63, 0x75, + 0x72, 0x65, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x65, + 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x6e, + 0x65, 0x74, 0x74, 0x79, 0x2e, 0x67, 0x6c, 0x65, + 0x61, 0x6d, 0x79, 0x6e, 0x6f, 0x64, 0x65, 0x2e, + 0x6e, 0x65, 0x74, 0x30, 0x20, 0x17, 0x0d, 0x30, + 0x38, 0x30, 0x36, 0x31, 0x39, 0x30, 0x35, 0x34, + 0x31, 0x33, 0x38, 0x5a, 0x18, 0x0f, 0x32, 0x31, + 0x38, 0x37, 0x31, 0x31, 0x32, 0x34, 0x30, 0x35, + 0x34, 0x31, 0x33, 0x38, 0x5a, 0x30, 0x81, 0xa0, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x4b, 0x52, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, + 0x4b, 0x79, 0x75, 0x6e, 0x67, 0x67, 0x69, 0x2d, + 0x64, 0x6f, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, + 0x55, 0x04, 0x07, 0x13, 0x0b, 0x53, 0x65, 0x6f, + 0x6e, 0x67, 0x6e, 0x61, 0x6d, 0x2d, 0x73, 0x69, + 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x13, 0x11, 0x54, 0x68, 0x65, 0x20, 0x4e, + 0x65, 0x74, 0x74, 0x79, 0x20, 0x50, 0x72, 0x6f, + 0x6a, 0x65, 0x63, 0x74, 0x31, 0x18, 0x30, 0x16, + 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0f, 0x45, + 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x73, 0x31, 0x30, + 0x30, 0x2e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x27, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x63, + 0x68, 0x61, 0x74, 0x2e, 0x65, 0x78, 0x61, 0x6d, + 0x70, 0x6c, 0x65, 0x2e, 0x6e, 0x65, 0x74, 0x74, + 0x79, 0x2e, 0x67, 0x6c, 0x65, 0x61, 0x6d, 0x79, + 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x65, 0x74, + 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, + 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41, + 0x00, 0xc3, 0xe3, 0x5e, 0x41, 0xa7, 0x87, 0x11, + 0x00, 0x42, 0x2a, 0xb0, 0x4b, 0xed, 0xb2, 0xe0, + 0x23, 0xdb, 0xb1, 0x3d, 0x58, 0x97, 0x35, 0x60, + 0x0b, 0x82, 0x59, 0xd3, 0x00, 0xea, 0xd4, 0x61, + 0xb8, 0x79, 0x3f, 0xb6, 0x3c, 0x12, 0x05, 0x93, + 0x2e, 0x9a, 0x59, 0x68, 0x14, 0x77, 0x3a, 0xc8, + 0x50, 0x25, 0x57, 0xa4, 0x49, 0x18, 0x63, 0x41, + 0xf0, 0x2d, 0x28, 0xec, 0x06, 0xfb, 0xb4, 0x9f, + 0xbf, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, + 0x65, 0x6c, 0x30, 0x01, 0xc2, 0x8e, 0x3e, 0xcb, + 0xb3, 0x77, 0x48, 0xe9, 0x66, 0x61, 0x9a, 0x40, + 0x86, 0xaf, 0xf6, 0x03, 0xeb, 0xba, 0x6a, 0xf2, + 0xfd, 0xe2, 0xaf, 0x36, 0x5e, 0x7b, 0xaa, 0x22, + 0x04, 0xdd, 0x2c, 0x20, 0xc4, 0xfc, 0xdd, 0xd0, + 0x82, 0x20, 0x1c, 0x3d, 0xd7, 0x9e, 0x5e, 0x5c, + 0x92, 0x5a, 0x76, 0x71, 0x28, 0xf5, 0x07, 0x7d, + 0xa2, 0x81, 0xba, 0x77, 0x9f, 0x2a, 0xd9, 0x44, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x6d, 0x79, + 0x6b, 0x65, 0x79, 0x00, 0x00, 0x01, 0x1a, 0x9f, + 0x5b, 0x56, 0xa0, 0x00, 0x00, 0x01, 0x99, 0x30, + 0x82, 0x01, 0x95, 0x30, 0x0e, 0x06, 0x0a, 0x2b, + 0x06, 0x01, 0x04, 0x01, 0x2a, 0x02, 0x11, 0x01, + 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x81, 0x29, + 0xa8, 0xb6, 0x08, 0x0c, 0x85, 0x75, 0x3e, 0xdd, + 0xb5, 0xe5, 0x1a, 0x87, 0x68, 0xd1, 0x90, 0x4b, + 0x29, 0x31, 0xee, 0x90, 0xbc, 0x9d, 0x73, 0xa0, + 0x3f, 0xe9, 0x0b, 0xa4, 0xef, 0x30, 0x9b, 0x36, + 0x9a, 0xb2, 0x54, 0x77, 0x81, 0x07, 0x4b, 0xaa, + 0xa5, 0x77, 0x98, 0xe1, 0xeb, 0xb5, 0x7c, 0x4e, + 0x48, 0xd5, 0x08, 0xfc, 0x2c, 0x36, 0xe2, 0x65, + 0x03, 0xac, 0xe5, 0xf3, 0x96, 0xb7, 0xd0, 0xb5, + 0x3b, 0x92, 0xe4, 0x14, 0x05, 0x7a, 0x6a, 0x92, + 0x56, 0xfe, 0x4e, 0xab, 0xd3, 0x0e, 0x32, 0x04, + 0x22, 0x22, 0x74, 0x47, 0x7d, 0xec, 0x21, 0x99, + 0x30, 0x31, 0x64, 0x46, 0x64, 0x9b, 0xc7, 0x13, + 0xbf, 0xbe, 0xd0, 0x31, 0x49, 0xe7, 0x3c, 0xbf, + 0xba, 0xb1, 0x20, 0xf9, 0x42, 0xf4, 0xa9, 0xa9, + 0xe5, 0x13, 0x65, 0x32, 0xbf, 0x7c, 0xcc, 0x91, + 0xd3, 0xfd, 0x24, 0x47, 0x0b, 0xe5, 0x53, 0xad, + 0x50, 0x30, 0x56, 0xd1, 0xfa, 0x9c, 0x37, 0xa8, + 0xc1, 0xce, 0xf6, 0x0b, 0x18, 0xaa, 0x7c, 0xab, + 0xbd, 0x1f, 0xdf, 0xe4, 0x80, 0xb8, 0xa7, 0xe0, + 0xad, 0x7d, 0x50, 0x74, 0xf1, 0x98, 0x78, 0xbc, + 0x58, 0xb9, 0xc2, 0x52, 0xbe, 0xd2, 0x5b, 0x81, + 0x94, 0x83, 0x8f, 0xb9, 0x4c, 0xee, 0x01, 0x2b, + 0x5e, 0xc9, 0x6e, 0x9b, 0xf5, 0x63, 0x69, 0xe4, + 0xd8, 0x0b, 0x47, 0xd8, 0xfd, 0xd8, 0xe0, 0xed, + 0xa8, 0x27, 0x03, 0x74, 0x1e, 0x5d, 0x32, 0xe6, + 0x5c, 0x63, 0xc2, 0xfb, 0x3f, 0xee, 0xb4, 0x13, + 0xc6, 0x0e, 0x6e, 0x74, 0xe0, 0x22, 0xac, 0xce, + 0x79, 0xf9, 0x43, 0x68, 0xc1, 0x03, 0x74, 0x2b, + 0xe1, 0x18, 0xf8, 0x7f, 0x76, 0x9a, 0xea, 0x82, + 0x3f, 0xc2, 0xa6, 0xa7, 0x4c, 0xfe, 0xae, 0x29, + 0x3b, 0xc1, 0x10, 0x7c, 0xd5, 0x77, 0x17, 0x79, + 0x5f, 0xcb, 0xad, 0x1f, 0xd8, 0xa1, 0xfd, 0x90, + 0xe1, 0x6b, 0xb2, 0xef, 0xb9, 0x41, 0x26, 0xa4, + 0x0b, 0x4f, 0xc6, 0x83, 0x05, 0x6f, 0xf0, 0x64, + 0x40, 0xe1, 0x44, 0xc4, 0xf9, 0x40, 0x2b, 0x3b, + 0x40, 0xdb, 0xaf, 0x35, 0xa4, 0x9b, 0x9f, 0xc4, + 0x74, 0x07, 0xe5, 0x18, 0x60, 0xc5, 0xfe, 0x15, + 0x0e, 0x3a, 0x25, 0x2a, 0x11, 0xee, 0x78, 0x2f, + 0xb8, 0xd1, 0x6e, 0x4e, 0x3c, 0x0a, 0xb5, 0xb9, + 0x40, 0x86, 0x27, 0x6d, 0x8f, 0x53, 0xb7, 0x77, + 0x36, 0xec, 0x5d, 0xed, 0x32, 0x40, 0x43, 0x82, + 0xc3, 0x52, 0x58, 0xc4, 0x26, 0x39, 0xf3, 0xb3, + 0xad, 0x58, 0xab, 0xb7, 0xf7, 0x8e, 0x0e, 0xba, + 0x8e, 0x78, 0x9d, 0xbf, 0x58, 0x34, 0xbd, 0x77, + 0x73, 0xa6, 0x50, 0x55, 0x00, 0x60, 0x26, 0xbf, + 0x6d, 0xb4, 0x98, 0x8a, 0x18, 0x83, 0x89, 0xf8, + 0xcd, 0x0d, 0x49, 0x06, 0xae, 0x51, 0x6e, 0xaf, + 0xbd, 0xe2, 0x07, 0x13, 0xd8, 0x64, 0xcc, 0xbf, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x58, 0x2e, + 0x35, 0x30, 0x39, 0x00, 0x00, 0x02, 0x34, 0x30, + 0x82, 0x02, 0x30, 0x30, 0x82, 0x01, 0xda, 0xa0, + 0x03, 0x02, 0x01, 0x02, 0x02, 0x04, 0x48, 0x59, + 0xf2, 0x84, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, + 0x00, 0x30, 0x81, 0x9d, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4b, + 0x52, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, + 0x04, 0x08, 0x13, 0x0a, 0x4b, 0x79, 0x75, 0x6e, + 0x67, 0x67, 0x69, 0x2d, 0x64, 0x6f, 0x31, 0x14, + 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, + 0x0b, 0x53, 0x65, 0x6f, 0x6e, 0x67, 0x6e, 0x61, + 0x6d, 0x2d, 0x73, 0x69, 0x31, 0x1a, 0x30, 0x18, + 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x54, + 0x68, 0x65, 0x20, 0x4e, 0x65, 0x74, 0x74, 0x79, + 0x20, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, + 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, + 0x0b, 0x13, 0x0c, 0x43, 0x6f, 0x6e, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x73, 0x31, + 0x30, 0x30, 0x2e, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x27, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, + 0x63, 0x68, 0x61, 0x74, 0x2e, 0x65, 0x78, 0x61, + 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x6e, 0x65, 0x74, + 0x74, 0x79, 0x2e, 0x67, 0x6c, 0x65, 0x61, 0x6d, + 0x79, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x65, + 0x74, 0x30, 0x20, 0x17, 0x0d, 0x30, 0x38, 0x30, + 0x36, 0x31, 0x39, 0x30, 0x35, 0x34, 0x35, 0x34, + 0x30, 0x5a, 0x18, 0x0f, 0x32, 0x31, 0x38, 0x37, + 0x31, 0x31, 0x32, 0x33, 0x30, 0x35, 0x34, 0x35, + 0x34, 0x30, 0x5a, 0x30, 0x81, 0x9d, 0x31, 0x0b, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4b, 0x52, 0x31, 0x13, 0x30, 0x11, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x4b, 0x79, + 0x75, 0x6e, 0x67, 0x67, 0x69, 0x2d, 0x64, 0x6f, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x0b, 0x53, 0x65, 0x6f, 0x6e, 0x67, + 0x6e, 0x61, 0x6d, 0x2d, 0x73, 0x69, 0x31, 0x1a, + 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, + 0x11, 0x54, 0x68, 0x65, 0x20, 0x4e, 0x65, 0x74, + 0x74, 0x79, 0x20, 0x50, 0x72, 0x6f, 0x6a, 0x65, + 0x63, 0x74, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, + 0x55, 0x04, 0x0b, 0x13, 0x0c, 0x43, 0x6f, 0x6e, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, + 0x73, 0x31, 0x30, 0x30, 0x2e, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x27, 0x73, 0x65, 0x63, 0x75, + 0x72, 0x65, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x65, + 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x6e, + 0x65, 0x74, 0x74, 0x79, 0x2e, 0x67, 0x6c, 0x65, + 0x61, 0x6d, 0x79, 0x6e, 0x6f, 0x64, 0x65, 0x2e, + 0x6e, 0x65, 0x74, 0x30, 0x5c, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, + 0x48, 0x02, 0x41, 0x00, 0x95, 0xb3, 0x47, 0x17, + 0x95, 0x0f, 0x57, 0xcf, 0x66, 0x72, 0x0a, 0x7e, + 0x5b, 0x54, 0xea, 0x8c, 0x6f, 0x79, 0xde, 0x94, + 0xac, 0x0b, 0x5a, 0xd4, 0xd6, 0x1b, 0x58, 0x12, + 0x1a, 0x16, 0x3d, 0xfe, 0xdf, 0xa5, 0x2b, 0x86, + 0xbc, 0x64, 0xd4, 0x80, 0x1e, 0x3f, 0xf9, 0xe2, + 0x04, 0x03, 0x79, 0x9b, 0xc1, 0x5c, 0xf0, 0xf1, + 0xf3, 0xf1, 0xe3, 0xbf, 0x3f, 0xc0, 0x1f, 0xdd, + 0xdb, 0xc0, 0x5b, 0x21, 0x02, 0x03, 0x01, 0x00, + 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, + 0x03, 0x41, 0x00, 0x02, 0xd7, 0xdd, 0xbd, 0x0c, + 0x8e, 0x21, 0x20, 0xef, 0x9e, 0x4f, 0x1f, 0xf5, + 0x49, 0xf1, 0xae, 0x58, 0x9b, 0x94, 0x3a, 0x1f, + 0x70, 0x33, 0xf0, 0x9b, 0xbb, 0xe9, 0xc0, 0xf3, + 0x72, 0xcb, 0xde, 0xb6, 0x56, 0x72, 0xcc, 0x1c, + 0xf0, 0xd6, 0x5a, 0x2a, 0xbc, 0xa1, 0x7e, 0x23, + 0x83, 0xe9, 0xe7, 0xcf, 0x9e, 0xa5, 0xf9, 0xcc, + 0xc2, 0x61, 0xf4, 0xdb, 0x40, 0x93, 0x1d, 0x63, + 0x8a, 0x50, 0x4c, 0x11, 0x39, 0xb1, 0x91, 0xc1, + 0xe6, 0x9d, 0xd9, 0x1a, 0x62, 0x1b, 0xb8, 0xd3, + 0xd6, 0x9a, 0x6d, 0xb9, 0x8e, 0x15, 0x51 }; + + public static InputStream asInputStream() { + byte[] data = new byte[DATA.length]; + for (int i = 0; i < data.length; i ++) { + data[i] = (byte) DATA[i]; + } + return new ByteArrayInputStream(data); + } + + public static char[] getCertificatePassword() { + return "secret".toCharArray(); + } + + public static char[] getKeyStorePassword() { + return "secret".toCharArray(); + } + + private BogusKeyStore() { + // Unused + } + } +} diff --git a/transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketStringEchoTest.java b/transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketStringEchoTest.java new file mode 100644 index 0000000000..9163d99e32 --- /dev/null +++ b/transport-sctp/src/test/java/io/netty/testsuite/transport/AbstractSocketStringEchoTest.java @@ -0,0 +1,196 @@ +/* + * Copyright 2011 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.testsuite.transport; + +import io.netty.bootstrap.ClientBootstrap; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.*; +import io.netty.channel.sctp.codec.SctpFrameDecoder; +import io.netty.channel.sctp.codec.SctpFrameEncoder; +import io.netty.handler.codec.frame.DelimiterBasedFrameDecoder; +import io.netty.handler.codec.frame.Delimiters; +import io.netty.handler.codec.string.StringDecoder; +import io.netty.handler.codec.string.StringEncoder; +import io.netty.testsuite.util.SctpSocketAddresses; +import io.netty.util.CharsetUtil; +import io.netty.util.internal.ExecutorUtil; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.util.Random; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicReference; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public abstract class AbstractSocketStringEchoTest { + + static final Random random = new Random(); + static final String[] data = new String[1024]; + + private static ExecutorService executor; + + static { + for (int i = 0; i < data.length; i ++) { + int eLen = random.nextInt(512); + char[] e = new char[eLen]; + for (int j = 0; j < eLen; j ++) { + e[j] = (char) ('a' + random.nextInt(26)); + } + + data[i] = new String(e); + } + } + + @BeforeClass + public static void init() { + executor = Executors.newCachedThreadPool(); + } + + @AfterClass + public static void destroy() { + ExecutorUtil.terminate(executor); + } + + protected abstract ChannelFactory newServerSocketChannelFactory(Executor executor); + protected abstract ChannelFactory newClientSocketChannelFactory(Executor executor); + + @Test + public void testStringEcho() throws Throwable { + ServerBootstrap sb = new ServerBootstrap(newServerSocketChannelFactory(executor)); + ClientBootstrap cb = new ClientBootstrap(newClientSocketChannelFactory(executor)); + + EchoHandler sh = new EchoHandler(); + EchoHandler ch = new EchoHandler(); + + sb.getPipeline().addFirst("sctp-decoder", new SctpFrameDecoder()); + sb.getPipeline().addFirst("sctp-encoder", new SctpFrameEncoder()); + sb.getPipeline().addLast("framer", new DelimiterBasedFrameDecoder(512, Delimiters.lineDelimiter())); + sb.getPipeline().addLast("decoder", new StringDecoder(CharsetUtil.ISO_8859_1)); + sb.getPipeline().addLast("encoder", new StringEncoder(CharsetUtil.ISO_8859_1)); + sb.getPipeline().addLast("handler", sh); + + cb.getPipeline().addFirst("sctp-decoder", new SctpFrameDecoder()); + cb.getPipeline().addFirst("sctp-encoder", new SctpFrameEncoder()); + cb.getPipeline().addLast("framer", new DelimiterBasedFrameDecoder(512, Delimiters.lineDelimiter())); + cb.getPipeline().addLast("decoder", new StringDecoder(CharsetUtil.ISO_8859_1)); + cb.getPipeline().addLast("encoder", new StringEncoder(CharsetUtil.ISO_8859_1)); + cb.getPipeline().addLast("handler", ch); + + Channel sc = sb.bind(new InetSocketAddress(SctpSocketAddresses.LOOP_BACK, 0)); + int port = ((InetSocketAddress) sc.getLocalAddress()).getPort(); + + ChannelFuture ccf = cb.connect(new InetSocketAddress(SctpSocketAddresses.LOOP_BACK, port)); + assertTrue(ccf.awaitUninterruptibly().isSuccess()); + + Channel cc = ccf.getChannel(); + for (String element : data) { + String delimiter = random.nextBoolean() ? "\r\n" : "\n"; + cc.write(element + delimiter); + } + + while (ch.counter < data.length) { + if (sh.exception.get() != null) { + break; + } + if (ch.exception.get() != null) { + break; + } + + try { + Thread.sleep(1); + } catch (InterruptedException e) { + // Ignore. + } + } + + while (sh.counter < data.length) { + if (sh.exception.get() != null) { + break; + } + if (ch.exception.get() != null) { + break; + } + + try { + Thread.sleep(1); + } catch (InterruptedException e) { + // Ignore. + } + } + + sh.channel.close().awaitUninterruptibly(); + ch.channel.close().awaitUninterruptibly(); + sc.close().awaitUninterruptibly(); + + if (sh.exception.get() != null && !(sh.exception.get() instanceof IOException)) { + throw sh.exception.get(); + } + if (ch.exception.get() != null && !(ch.exception.get() instanceof IOException)) { + throw ch.exception.get(); + } + if (sh.exception.get() != null) { + throw sh.exception.get(); + } + if (ch.exception.get() != null) { + throw ch.exception.get(); + } + } + + private static class EchoHandler extends SimpleChannelUpstreamHandler { + volatile Channel channel; + final AtomicReference exception = new AtomicReference(); + volatile int counter; + + EchoHandler() { + } + + @Override + public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) + throws Exception { + channel = e.getChannel(); + } + + @Override + public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) + throws Exception { + + String m = (String) e.getMessage(); + assertEquals(data[counter], m); + + if (channel.getParent() != null) { + String delimiter = random.nextBoolean() ? "\r\n" : "\n"; + channel.write(m + delimiter); + } + + counter ++; + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) + throws Exception { + if (exception.compareAndSet(null, e.getCause())) { + e.getChannel().close(); + } + } + } +} diff --git a/transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpClientBootstrapTest.java b/transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpClientBootstrapTest.java new file mode 100644 index 0000000000..33845d13b8 --- /dev/null +++ b/transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpClientBootstrapTest.java @@ -0,0 +1,29 @@ +/* + * Copyright 2011 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.testsuite.transport.sctp; + +import io.netty.channel.ChannelFactory; +import io.netty.channel.sctp.SctpClientSocketChannelFactory; +import io.netty.testsuite.transport.AbstractSocketClientBootstrapTest; + +import java.util.concurrent.Executor; + +public class SctpClientBootstrapTest extends AbstractSocketClientBootstrapTest { + @Override + protected ChannelFactory newClientSocketChannelFactory(Executor executor) { + return new SctpClientSocketChannelFactory(executor, executor); + } +} diff --git a/transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpCompatibleObjectStreamEchoTest.java b/transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpCompatibleObjectStreamEchoTest.java new file mode 100644 index 0000000000..dc38655dce --- /dev/null +++ b/transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpCompatibleObjectStreamEchoTest.java @@ -0,0 +1,35 @@ +/* + * Copyright 2011 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.testsuite.transport.sctp; + +import io.netty.channel.ChannelFactory; +import io.netty.channel.sctp.SctpClientSocketChannelFactory; +import io.netty.channel.sctp.SctpServerSocketChannelFactory; +import io.netty.testsuite.transport.AbstractSocketCompatibleObjectStreamEchoTest; + +import java.util.concurrent.Executor; + +public class SctpCompatibleObjectStreamEchoTest extends AbstractSocketCompatibleObjectStreamEchoTest { + @Override + protected ChannelFactory newServerSocketChannelFactory(Executor executor) { + return new SctpServerSocketChannelFactory(executor, executor); + } + + @Override + protected ChannelFactory newClientSocketChannelFactory(Executor executor) { + return new SctpClientSocketChannelFactory(executor, executor); + } +} diff --git a/transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpEchoTest.java b/transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpEchoTest.java new file mode 100644 index 0000000000..bbe24bde2a --- /dev/null +++ b/transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpEchoTest.java @@ -0,0 +1,35 @@ +/* + * Copyright 2011 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.testsuite.transport.sctp; + +import io.netty.channel.ChannelFactory; +import io.netty.channel.sctp.SctpClientSocketChannelFactory; +import io.netty.channel.sctp.SctpServerSocketChannelFactory; +import io.netty.testsuite.transport.AbstractSocketEchoTest; + +import java.util.concurrent.Executor; + +public class SctpEchoTest extends AbstractSocketEchoTest { + @Override + protected ChannelFactory newServerSocketChannelFactory(Executor executor) { + return new SctpServerSocketChannelFactory(executor, executor); + } + + @Override + protected ChannelFactory newClientSocketChannelFactory(Executor executor) { + return new SctpClientSocketChannelFactory(executor, executor); + } +} diff --git a/transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpFixedLengthEchoTest.java b/transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpFixedLengthEchoTest.java new file mode 100644 index 0000000000..a1e590438d --- /dev/null +++ b/transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpFixedLengthEchoTest.java @@ -0,0 +1,35 @@ +/* + * Copyright 2011 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.testsuite.transport.sctp; + +import io.netty.channel.ChannelFactory; +import io.netty.channel.sctp.SctpClientSocketChannelFactory; +import io.netty.channel.sctp.SctpServerSocketChannelFactory; +import io.netty.testsuite.transport.AbstractSocketFixedLengthEchoTest; + +import java.util.concurrent.Executor; + +public class SctpFixedLengthEchoTest extends AbstractSocketFixedLengthEchoTest { + @Override + protected ChannelFactory newServerSocketChannelFactory(Executor executor) { + return new SctpServerSocketChannelFactory(executor, executor); + } + + @Override + protected ChannelFactory newClientSocketChannelFactory(Executor executor) { + return new SctpClientSocketChannelFactory(executor, executor); + } +} diff --git a/transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpObjectStreamEchoTest.java b/transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpObjectStreamEchoTest.java new file mode 100644 index 0000000000..55c84e0684 --- /dev/null +++ b/transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpObjectStreamEchoTest.java @@ -0,0 +1,35 @@ +/* + * Copyright 2011 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.testsuite.transport.sctp; + +import io.netty.channel.ChannelFactory; +import io.netty.channel.sctp.SctpClientSocketChannelFactory; +import io.netty.channel.sctp.SctpServerSocketChannelFactory; +import io.netty.testsuite.transport.AbstractSocketObjectStreamEchoTest; + +import java.util.concurrent.Executor; + +public class SctpObjectStreamEchoTest extends AbstractSocketObjectStreamEchoTest { + @Override + protected ChannelFactory newServerSocketChannelFactory(Executor executor) { + return new SctpServerSocketChannelFactory(executor, executor); + } + + @Override + protected ChannelFactory newClientSocketChannelFactory(Executor executor) { + return new SctpClientSocketChannelFactory(executor, executor); + } +} diff --git a/transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpServerBootstrapTest.java b/transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpServerBootstrapTest.java new file mode 100644 index 0000000000..bcb680c1f7 --- /dev/null +++ b/transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpServerBootstrapTest.java @@ -0,0 +1,30 @@ +/* + * Copyright 2011 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.testsuite.transport.sctp; + +import io.netty.channel.ChannelFactory; +import io.netty.channel.sctp.SctpClientSocketChannelFactory; +import io.netty.channel.sctp.SctpServerSocketChannelFactory; +import io.netty.testsuite.transport.AbstractSocketServerBootstrapTest; + +import java.util.concurrent.Executor; + +public class SctpServerBootstrapTest extends AbstractSocketServerBootstrapTest { + @Override + protected ChannelFactory newServerSocketChannelFactory(Executor executor) { + return new SctpServerSocketChannelFactory(executor, executor); + } +} diff --git a/transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpSslEchoTest.java b/transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpSslEchoTest.java new file mode 100644 index 0000000000..e840cce264 --- /dev/null +++ b/transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpSslEchoTest.java @@ -0,0 +1,35 @@ +/* + * Copyright 2011 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.testsuite.transport.sctp; + +import io.netty.channel.ChannelFactory; +import io.netty.channel.sctp.SctpClientSocketChannelFactory; +import io.netty.channel.sctp.SctpServerSocketChannelFactory; +import io.netty.testsuite.transport.AbstractSocketSslEchoTest; + +import java.util.concurrent.Executor; + +public class SctpSslEchoTest extends AbstractSocketSslEchoTest { + @Override + protected ChannelFactory newServerSocketChannelFactory(Executor executor) { + return new SctpServerSocketChannelFactory(executor, executor); + } + + @Override + protected ChannelFactory newClientSocketChannelFactory(Executor executor) { + return new SctpClientSocketChannelFactory(executor, executor); + } +} diff --git a/transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpStringEchoTest.java b/transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpStringEchoTest.java new file mode 100644 index 0000000000..31440bec6a --- /dev/null +++ b/transport-sctp/src/test/java/io/netty/testsuite/transport/sctp/SctpStringEchoTest.java @@ -0,0 +1,35 @@ +/* + * Copyright 2011 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.testsuite.transport.sctp; + +import io.netty.channel.ChannelFactory; +import io.netty.channel.sctp.SctpClientSocketChannelFactory; +import io.netty.channel.sctp.SctpServerSocketChannelFactory; +import io.netty.testsuite.transport.AbstractSocketStringEchoTest; + +import java.util.concurrent.Executor; + +public class SctpStringEchoTest extends AbstractSocketStringEchoTest { + @Override + protected ChannelFactory newServerSocketChannelFactory(Executor executor) { + return new SctpServerSocketChannelFactory(executor, executor); + } + + @Override + protected ChannelFactory newClientSocketChannelFactory(Executor executor) { + return new SctpClientSocketChannelFactory(executor, executor); + } +} diff --git a/transport-sctp/src/test/java/io/netty/testsuite/util/DummyHandler.java b/transport-sctp/src/test/java/io/netty/testsuite/util/DummyHandler.java new file mode 100644 index 0000000000..5ec679a904 --- /dev/null +++ b/transport-sctp/src/test/java/io/netty/testsuite/util/DummyHandler.java @@ -0,0 +1,34 @@ +/* + * Copyright 2011 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.testsuite.util; + +import io.netty.channel.ChannelDownstreamHandler; +import io.netty.channel.ChannelEvent; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelUpstreamHandler; + +public class DummyHandler implements ChannelUpstreamHandler, ChannelDownstreamHandler { + + public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) + throws Exception { + ctx.sendUpstream(e); + } + + public void handleDownstream(ChannelHandlerContext ctx, ChannelEvent e) + throws Exception { + ctx.sendDownstream(e); + } +} diff --git a/transport-sctp/src/test/java/io/netty/testsuite/util/SctpSocketAddresses.java b/transport-sctp/src/test/java/io/netty/testsuite/util/SctpSocketAddresses.java new file mode 100644 index 0000000000..34467995a5 --- /dev/null +++ b/transport-sctp/src/test/java/io/netty/testsuite/util/SctpSocketAddresses.java @@ -0,0 +1,22 @@ +/* + * Copyright 2011 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +package io.netty.testsuite.util; + +public class SctpSocketAddresses { + //io.netty.util.SocketAddresses.LOCALHOST interface has MTU SIZE issues with SCTP, we have to use local loop back interface for testing + public final static String LOOP_BACK = "127.0.0.1"; +}