Path: blob/master/test/jdk/com/sun/nio/sctp/SctpChannel/CommUp.java
41155 views
/*1* Copyright (c) 2009, 2019, 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 686311025* @summary Newly connected/accepted SctpChannel should fire OP_READ if registered with a Selector26* @author chegar27*/2829import java.net.InetSocketAddress;30import java.net.SocketAddress;31import java.io.IOException;32import java.util.Iterator;33import java.util.Set;34import java.util.concurrent.CountDownLatch;35import java.nio.ByteBuffer;36import java.nio.channels.Selector;37import java.nio.channels.SelectionKey;38import com.sun.nio.sctp.AbstractNotificationHandler;39import com.sun.nio.sctp.AssociationChangeNotification;40import com.sun.nio.sctp.AssociationChangeNotification.AssocChangeEvent;41import com.sun.nio.sctp.HandlerResult;42import com.sun.nio.sctp.Notification;43import com.sun.nio.sctp.SctpChannel;44import com.sun.nio.sctp.SctpServerChannel;45import com.sun.nio.sctp.ShutdownNotification;46import static java.lang.System.out;47import static java.lang.System.err;48import static java.nio.channels.SelectionKey.OP_CONNECT;49import static java.nio.channels.SelectionKey.OP_READ;5051public class CommUp {52static CountDownLatch acceptLatch = new CountDownLatch(1);53static final int TIMEOUT = 10000;5455CommUpNotificationHandler clientHandler = new CommUpNotificationHandler();56CommUpNotificationHandler serverHandler = new CommUpNotificationHandler();57CommUpServer server;58Thread clientThread;5960void test(String[] args) {61SocketAddress address = null;6263if (!Util.isSCTPSupported()) {64out.println("SCTP protocol is not supported");65out.println("Test cannot be run");66return;67}6869if (args.length == 2) {70/* requested to connecct to a specific address */71try {72int port = Integer.valueOf(args[1]);73address = new InetSocketAddress(args[0], port);74} catch (NumberFormatException nfe) {75err.println(nfe);76}77} else {78/* start server on local machine, default */79try {80server = new CommUpServer();81server.start();82address = server.address();83debug("Server started and listening on " + address);84} catch (IOException ioe) {85ioe.printStackTrace();86return;87}88}8990/* store the main thread so that the server can interrupt it, if necessary */91clientThread = Thread.currentThread();9293doClient(address);94}9596void doClient(SocketAddress peerAddress) {97SctpChannel sc = null;98try {99debug("connecting to " + peerAddress);100sc = SctpChannel.open();101sc.configureBlocking(false);102check(sc.isBlocking() == false, "Should be in non-blocking mode");103sc.connect(peerAddress);104105Selector selector = Selector.open();106SelectionKey selectiontKey = sc.register(selector, OP_CONNECT);107108/* Expect two interest Ops */109boolean opConnectReceived = false;110boolean opReadReceived = false;111for (int z=0; z<2; z++) {112debug("select " + z);113int keysAdded = selector.select(TIMEOUT);114debug("returned " + keysAdded + " keys");115if (keysAdded > 0) {116Set<SelectionKey> keys = selector.selectedKeys();117Iterator<SelectionKey> i = keys.iterator();118while(i.hasNext()) {119SelectionKey sk = i.next();120i.remove();121SctpChannel readyChannel =122(SctpChannel)sk.channel();123124/* OP_CONNECT */125if (sk.isConnectable()) {126/* some trivial checks */127check(opConnectReceived == false,128"should only received one OP_CONNECT");129check(opReadReceived == false,130"should not receive OP_READ before OP_CONNECT");131check(readyChannel.equals(sc),132"channels should be equal");133check(!sk.isAcceptable(),134"key should not be acceptable");135check(!sk.isReadable(),136"key should not be readable");137check(!sk.isWritable(),138"key should not be writable");139140/* now process the OP_CONNECT */141opConnectReceived = true;142check((sk.interestOps() & OP_CONNECT) == OP_CONNECT,143"selection key interest ops should contain OP_CONNECT");144sk.interestOps(OP_READ);145check((sk.interestOps() & OP_CONNECT) != OP_CONNECT,146"selection key interest ops should not contain OP_CONNECT");147check(sc.finishConnect(),148"finishConnect should return true");149} /* OP_READ */150else if (sk.isReadable()) {151/* some trivial checks */152check(opConnectReceived == true,153"should receive one OP_CONNECT before OP_READ");154check(opReadReceived == false,155"should not receive OP_READ before OP_CONNECT");156check(readyChannel.equals(sc),157"channels should be equal");158check(!sk.isAcceptable(),159"key should not be acceptable");160check(sk.isReadable(),161"key should be readable");162check(!sk.isWritable(),163"key should not be writable");164check(!sk.isConnectable(),165"key should not be connectable");166167/* now process the OP_READ */168opReadReceived = true;169selectiontKey.cancel();170171/* try with small buffer to see if native172* implementation can handle this */173ByteBuffer buffer = ByteBuffer.allocateDirect(1);174readyChannel.receive(buffer, null, clientHandler);175check(clientHandler.receivedCommUp(),176"Client should have received COMM_UP");177178/* dont close (or put anything on) the channel until179* we check that the server's accepted channel also180* received COMM_UP */181serverHandler.waitForCommUp();182} else {183fail("Unexpected selection key");184}185}186} else {187fail("Client selector returned 0 ready keys");188/* stop the server */189server.thread().interrupt();190}191} //for192193try { sc.close(); }194catch (IOException ioe) { unexpected(ioe); }195196} catch (IOException ioe) {197unexpected(ioe);198} catch (InterruptedException ie) {199unexpected(ie);200}201}202203class CommUpServer implements Runnable204{205final InetSocketAddress serverAddr;206private SctpServerChannel ssc;207private Thread serverThread;208209public CommUpServer() throws IOException {210ssc = SctpServerChannel.open().bind(null);211java.util.Set<SocketAddress> addrs = ssc.getAllLocalAddresses();212if (addrs.isEmpty())213debug("addrs should not be empty");214215serverAddr = (InetSocketAddress) addrs.iterator().next();216}217218void start() {219serverThread = new Thread(this, "CommUpServer-" +220serverAddr.getPort());221serverThread.start();222}223224InetSocketAddress address () {225return serverAddr;226}227228Thread thread() {229return serverThread;230}231232@Override233public void run() {234Selector selector = null;235SctpChannel sc = null;236SelectionKey readKey = null;237try {238sc = ssc.accept();239debug("accepted " + sc);240241selector = Selector.open();242sc.configureBlocking(false);243check(sc.isBlocking() == false, "Should be in non-blocking mode");244readKey = sc.register(selector, SelectionKey.OP_READ);245246debug("select");247int keysAdded = selector.select(TIMEOUT);248debug("returned " + keysAdded + " keys");249if (keysAdded > 0) {250Set<SelectionKey> keys = selector.selectedKeys();251Iterator<SelectionKey> i = keys.iterator();252while(i.hasNext()) {253SelectionKey sk = i.next();254i.remove();255SctpChannel readyChannel =256(SctpChannel)sk.channel();257check(readyChannel.equals(sc),258"channels should be equal");259check(!sk.isAcceptable(),260"key should not be acceptable");261check(sk.isReadable(),262"key should be readable");263check(!sk.isWritable(),264"key should not be writable");265check(!sk.isConnectable(),266"key should not be connectable");267268/* block until we check if the client has received its COMM_UP*/269clientHandler.waitForCommUp();270271ByteBuffer buffer = ByteBuffer.allocateDirect(1);272sc.receive(buffer, null, serverHandler);273check(serverHandler.receivedCommUp(),274"Accepted channel should have received COMM_UP");275}276} else {277fail("Server selector returned 0 ready keys");278/* stop the client */279clientThread.interrupt();280}281} catch (IOException ioe) {282ioe.printStackTrace();283} catch (InterruptedException unused) {284} finally {285if (readKey != null) readKey.cancel();286try { if (selector != null) selector.close(); }287catch (IOException ioe) { unexpected(ioe); }288try { if (ssc != null) ssc.close(); }289catch (IOException ioe) { unexpected(ioe); }290try { if (sc != null) sc.close(); }291catch (IOException ioe) { unexpected(ioe); }292}293}294}295296class CommUpNotificationHandler extends AbstractNotificationHandler<Object>297{298private boolean receivedCommUp; // false299300public synchronized boolean receivedCommUp() {301return receivedCommUp;302}303304public synchronized boolean waitForCommUp() throws InterruptedException {305while (receivedCommUp == false) {306wait();307}308309return false;310}311312@Override313public HandlerResult handleNotification(314Notification notification, Object attachment) {315fail("Unknown notification type");316return HandlerResult.CONTINUE;317}318319@Override320public synchronized HandlerResult handleNotification(321AssociationChangeNotification notification, Object attachment) {322AssocChangeEvent event = notification.event();323debug("AssociationChangeNotification");324debug(" Association: " + notification.association());325debug(" Event: " + event);326327if (event.equals(AssocChangeEvent.COMM_UP)) {328receivedCommUp = true;329notifyAll();330}331332return HandlerResult.RETURN;333}334335@Override336public HandlerResult handleNotification(337ShutdownNotification notification, Object attachment) {338debug("ShutdownNotification");339debug(" Association: " + notification.association());340return HandlerResult.RETURN;341}342}343344//--------------------- Infrastructure ---------------------------345boolean debug = true;346volatile int passed = 0, failed = 0;347void pass() {passed++;}348void fail() {failed++; Thread.dumpStack();}349void fail(String msg) {err.println(msg); fail();}350void unexpected(Throwable t) {failed++; t.printStackTrace();}351void check(boolean cond) {if (cond) pass(); else fail();}352void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);}353void debug(String message) {if(debug) { out.println(Thread.currentThread().getName() + ": " + message); } }354void sleep(long millis) { try { Thread.currentThread().sleep(millis); }355catch(InterruptedException ie) { unexpected(ie); }}356public static void main(String[] args) throws Throwable {357Class<?> k = new Object(){}.getClass().getEnclosingClass();358try {k.getMethod("instanceMain",String[].class)359.invoke( k.newInstance(), (Object) args);}360catch (Throwable e) {throw e.getCause();}}361public void instanceMain(String[] args) throws Throwable {362try {test(args);} catch (Throwable t) {unexpected(t);}363out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);364if (failed > 0) throw new AssertionError("Some tests failed");}365366}367368369