Path: blob/master/test/jdk/com/sun/nio/sctp/SctpMultiChannel/Branch.java
41155 views
/*1* Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/* @test24* @bug 492764025* @summary Tests the SCTP protocol implementation26* @author chegar27*/2829import java.net.InetSocketAddress;30import java.net.SocketAddress;31import java.io.IOException;32import java.util.Set;33import java.util.Iterator;34import java.util.concurrent.CountDownLatch;35import java.util.concurrent.TimeUnit;36import java.nio.ByteBuffer;37import com.sun.nio.sctp.AbstractNotificationHandler;38import com.sun.nio.sctp.Association;39import com.sun.nio.sctp.AssociationChangeNotification;40import com.sun.nio.sctp.AssociationChangeNotification.AssocChangeEvent;41import com.sun.nio.sctp.HandlerResult;42import com.sun.nio.sctp.InvalidStreamException;43import com.sun.nio.sctp.MessageInfo;44import com.sun.nio.sctp.SctpChannel;45import com.sun.nio.sctp.SctpMultiChannel;46import com.sun.nio.sctp.ShutdownNotification;47import static java.lang.System.out;48import static java.lang.System.err;4950public class Branch {51/* Latches used to synchronize between the client and server so that52* connections without any IO may not be closed without being accepted */53final CountDownLatch clientFinishedLatch = new CountDownLatch(1);54final CountDownLatch serverFinishedLatch = new CountDownLatch(1);5556void test(String[] args) {57SocketAddress address = null;58Server server = null;5960if (!Util.isSCTPSupported()) {61out.println("SCTP protocol is not supported");62out.println("Test cannot be run");63return;64}6566if (args.length == 2) {67/* requested to connecct to a specific address */68try {69int port = Integer.valueOf(args[1]);70address = new InetSocketAddress(args[0], port);71} catch (NumberFormatException nfe) {72err.println(nfe);73}74} else {75/* start server on local machine, default */76try {77server = new Server();78server.start();79address = server.address();80debug("Server started and listening on " + address);81} catch (IOException ioe) {82ioe.printStackTrace();83return;84}85}8687doTest(address);88}8990void doTest(SocketAddress peerAddress) {91SctpMultiChannel channel = null;92ByteBuffer buffer = ByteBuffer.allocate(Util.LARGE_BUFFER);93MessageInfo info = MessageInfo.createOutgoing(null, 0);9495try {96channel = SctpMultiChannel.open();9798/* setup an association implicitly by sending a small message */99int streamNumber = 0;100debug("sending to " + peerAddress + " on stream number: " + streamNumber);101info = MessageInfo.createOutgoing(peerAddress, streamNumber);102buffer.put(Util.SMALL_MESSAGE.getBytes("ISO-8859-1"));103buffer.flip();104int position = buffer.position();105int remaining = buffer.remaining();106107debug("sending small message: " + buffer);108int sent = channel.send(buffer, info);109110check(sent == remaining, "sent should be equal to remaining");111check(buffer.position() == (position + sent),112"buffers position should have been incremented by sent");113114/* Receive the COMM_UP */115buffer.clear();116BranchNotificationHandler handler = new BranchNotificationHandler();117info = channel.receive(buffer, null, handler);118check(handler.receivedCommUp(), "COMM_UP no received");119Set<Association> associations = channel.associations();120check(!associations.isEmpty(),"There should be some associations");121Association bassoc = associations.iterator().next();122123/* TEST 1: branch */124SctpChannel bchannel = channel.branch(bassoc);125126check(!bchannel.getAllLocalAddresses().isEmpty(),127"branched channel should be bound");128check(!bchannel.getRemoteAddresses().isEmpty(),129"branched channel should be connected");130check(channel.associations().isEmpty(),131"there should be no associations since the only one was branched off");132133buffer.clear();134info = bchannel.receive(buffer, null, null);135buffer.flip();136check(info != null, "info is null");137check(info.streamNumber() == streamNumber,138"message not sent on the correct stream");139check(info.bytes() == Util.SMALL_MESSAGE.getBytes("ISO-8859-1").140length, "bytes received not equal to message length");141check(info.bytes() == buffer.remaining(), "bytes != remaining");142check(Util.compare(buffer, Util.SMALL_MESSAGE),143"received message not the same as sent message");144145} catch (IOException ioe) {146unexpected(ioe);147} finally {148clientFinishedLatch.countDown();149try { serverFinishedLatch.await(10L, TimeUnit.SECONDS); }150catch (InterruptedException ie) { unexpected(ie); }151if (channel != null) {152try { channel.close(); }153catch (IOException e) { unexpected (e);}154}155}156}157158class Server implements Runnable159{160final InetSocketAddress serverAddr;161private SctpMultiChannel serverChannel;162163public Server() throws IOException {164serverChannel = SctpMultiChannel.open().bind(null);165java.util.Set<SocketAddress> addrs = serverChannel.getAllLocalAddresses();166if (addrs.isEmpty())167debug("addrs should not be empty");168169serverAddr = (InetSocketAddress) addrs.iterator().next();170}171172public void start() {173(new Thread(this, "Server-" + serverAddr.getPort())).start();174}175176public InetSocketAddress address() {177return serverAddr;178}179180@Override181public void run() {182ByteBuffer buffer = ByteBuffer.allocateDirect(Util.LARGE_BUFFER);183try {184MessageInfo info;185186/* receive a small message */187do {188info = serverChannel.receive(buffer, null, null);189if (info == null) {190fail("Server: unexpected null from receive");191return;192}193} while (!info.isComplete());194195buffer.flip();196check(info != null, "info is null");197check(info.streamNumber() == 0,198"message not sent on the correct stream");199check(info.bytes() == Util.SMALL_MESSAGE.getBytes("ISO-8859-1").200length, "bytes received not equal to message length");201check(info.bytes() == buffer.remaining(), "bytes != remaining");202check(Util.compare(buffer, Util.SMALL_MESSAGE),203"received message not the same as sent message");204205check(info != null, "info is null");206Set<Association> assocs = serverChannel.associations();207check(assocs.size() == 1, "there should be only one association");208209/* echo the message */210debug("Server: echoing first message");211buffer.flip();212MessageInfo sendInfo = MessageInfo.createOutgoing(info.association(), null, 0);213int bytes = serverChannel.send(buffer, sendInfo);214debug("Server: sent " + bytes + "bytes");215216clientFinishedLatch.await(10L, TimeUnit.SECONDS);217serverFinishedLatch.countDown();218} catch (IOException ioe) {219unexpected(ioe);220} catch (InterruptedException ie) {221unexpected(ie);222} finally {223try { if (serverChannel != null) serverChannel.close(); }224catch (IOException unused) {}225}226}227}228229class BranchNotificationHandler extends AbstractNotificationHandler<Object>230{231boolean receivedCommUp; // false232233boolean receivedCommUp() {234return receivedCommUp;235}236237@Override238public HandlerResult handleNotification(239AssociationChangeNotification notification, Object attachment) {240AssocChangeEvent event = notification.event();241debug("AssociationChangeNotification");242debug(" Association: " + notification.association());243debug(" Event: " + event);244245if (event.equals(AssocChangeEvent.COMM_UP))246receivedCommUp = true;247248return HandlerResult.RETURN;249}250251/* A ShutdownNotification handler is provided to ensure that no252* shutdown notification are being handled since we don't expect253* to receive them. This is not part of branch testing, it just254* fits here to test another bug. */255@Override256public HandlerResult handleNotification(257ShutdownNotification notification, Object attachment) {258debug("ShutdownNotification");259debug(" Association: " + notification.association());260261fail("Shutdown should not be received");262263return HandlerResult.RETURN;264}265266}267268//--------------------- Infrastructure ---------------------------269boolean debug = true;270volatile int passed = 0, failed = 0;271void pass() {passed++;}272void fail() {failed++; Thread.dumpStack();}273void fail(String msg) {System.err.println(msg); fail();}274void unexpected(Throwable t) {failed++; t.printStackTrace();}275void check(boolean cond) {if (cond) pass(); else fail();}276void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);}277void debug(String message) {if(debug) { System.out.println(message); } }278public static void main(String[] args) throws Throwable {279Class<?> k = new Object(){}.getClass().getEnclosingClass();280try {k.getMethod("instanceMain",String[].class)281.invoke( k.newInstance(), (Object) args);}282catch (Throwable e) {throw e.getCause();}}283public void instanceMain(String[] args) throws Throwable {284try {test(args);} catch (Throwable t) {unexpected(t);}285System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);286if (failed > 0) throw new AssertionError("Some tests failed");}287288}289290291