1 /* 2 * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* @test 25 * @bug 4927640 26 * @summary Tests the SCTP protocol implementation 27 * @author chegar 28 */ 29 30 import java.net.InetSocketAddress; 31 import java.net.SocketAddress; 32 import java.io.IOException; 33 import java.util.HashSet; 34 import java.util.Iterator; 35 import java.util.Set; 36 import java.util.concurrent.CountDownLatch; 37 import java.nio.channels.AlreadyConnectedException; 38 import java.nio.channels.Selector; 39 import java.nio.channels.SelectionKey; 40 import com.sun.nio.sctp.SctpChannel; 41 import com.sun.nio.sctp.SctpServerChannel; 42 import static java.lang.System.out; 43 import static java.lang.System.err; 44 45 public class NonBlockingAccept { 46 static CountDownLatch acceptLatch = new CountDownLatch(1); 47 static final int SEL_TIMEOUT = 10000; 48 static final int NUM_TEST_CONNECTIONS = 10; 49 test(String[] args)50 void test(String[] args) { 51 SocketAddress address = null; 52 NonblockingServer server; 53 54 if (!Util.isSCTPSupported()) { 55 out.println("SCTP protocol is not supported"); 56 out.println("Test cannot be run"); 57 return; 58 } 59 60 if (args.length == 2) { 61 /* requested to connecct to a specific address */ 62 try { 63 int port = Integer.valueOf(args[1]); 64 address = new InetSocketAddress(args[0], port); 65 } catch (NumberFormatException nfe) { 66 err.println(nfe); 67 } 68 } else { 69 /* start server on local machine, default */ 70 try { 71 server = new NonblockingServer(); 72 server.start(); 73 address = server.address(); 74 debug("Server started and listening on " + address); 75 } catch (IOException ioe) { 76 ioe.printStackTrace(); 77 return; 78 } 79 } 80 81 doClient(address); 82 } 83 doClient(SocketAddress peerAddress)84 void doClient(SocketAddress peerAddress) { 85 Set<SctpChannel> channels = new HashSet<SctpChannel>(NUM_TEST_CONNECTIONS); 86 87 try { 88 for (int i=0; i<NUM_TEST_CONNECTIONS;) { 89 debug("connecting " + ++i); 90 channels.add(SctpChannel.open(peerAddress, 0, 0)); 91 sleep(100); 92 } 93 94 /* don't close the channels until they have been accepted */ 95 acceptLatch.await(); 96 97 for(SctpChannel sc: channels) 98 sc.close(); 99 } catch (IOException ioe) { 100 unexpected(ioe); 101 } catch (InterruptedException ie) { 102 unexpected(ie); 103 } 104 } 105 106 class NonblockingServer implements Runnable 107 { 108 final InetSocketAddress serverAddr; 109 private SctpServerChannel ssc; 110 private Thread serverThread; 111 NonblockingServer()112 public NonblockingServer() throws IOException { 113 ssc = SctpServerChannel.open().bind(null); 114 java.util.Set<SocketAddress> addrs = ssc.getAllLocalAddresses(); 115 if (addrs.isEmpty()) 116 debug("addrs should not be empty"); 117 118 serverAddr = (InetSocketAddress) addrs.iterator().next(); 119 } 120 start()121 void start() { 122 serverThread = new Thread(this, "NonblockingServer-" + 123 serverAddr.getPort()); 124 serverThread.start(); 125 } 126 address()127 InetSocketAddress address () { 128 return serverAddr; 129 } 130 131 @Override run()132 public void run() { 133 Selector acceptSelector = null; 134 SelectionKey acceptKey = null; 135 136 try { 137 acceptSelector = Selector.open(); 138 ssc.configureBlocking(false); 139 check(ssc.isBlocking() == false, "Should be in non-blocking mode"); 140 acceptKey = ssc.register(acceptSelector, SelectionKey.OP_ACCEPT); 141 142 int connectionsAccepted = 0; 143 while (connectionsAccepted < NUM_TEST_CONNECTIONS) { 144 int keysAdded = acceptSelector.select(SEL_TIMEOUT); 145 if (keysAdded > 0) { 146 Set<SelectionKey> keys = acceptSelector.selectedKeys(); 147 Iterator<SelectionKey> i = keys.iterator(); 148 while(i.hasNext()) { 149 SelectionKey sk = i.next(); 150 i.remove(); 151 SctpServerChannel nextReady = 152 (SctpServerChannel)sk.channel(); 153 check(nextReady.equals(ssc), 154 "channels should be equal"); 155 check(sk.isAcceptable(), 156 "key should be acceptable"); 157 check(!sk.isReadable(), 158 "key should not be readable"); 159 check(!sk.isWritable(), 160 "key should not be writable"); 161 check(!sk.isConnectable(), 162 "key should not be connectable"); 163 SctpChannel acceptsc = nextReady.accept(); 164 connectionsAccepted++; 165 debug("Accepted " + connectionsAccepted + " connections"); 166 check(acceptsc != null, 167 "Accepted channel should not be null"); 168 if (acceptsc != null) { 169 checkAcceptedChannel(acceptsc); 170 acceptsc.close(); 171 } 172 } /* while */ 173 } /* if */ 174 } /* while */ 175 } catch (IOException ioe) { 176 ioe.printStackTrace(); 177 } finally { 178 acceptLatch.countDown(); 179 if (acceptKey != null) acceptKey.cancel(); 180 try { if (acceptSelector != null) acceptSelector.close(); } 181 catch (IOException ioe) { unexpected(ioe); } 182 try { if (ssc != null) ssc.close(); } 183 catch (IOException ioe) { unexpected(ioe); } 184 } 185 } 186 } 187 checkAcceptedChannel(SctpChannel sc)188 void checkAcceptedChannel(SctpChannel sc) { 189 try { 190 debug("Checking accepted SctpChannel"); 191 check(sc.association() != null, 192 "accepted channel should have an association"); 193 check(!(sc.getRemoteAddresses().isEmpty()), 194 "accepted channel should be connected"); 195 check(!(sc.isConnectionPending()), 196 "accepted channel should not have a connection pending"); 197 check(sc.isBlocking(), 198 "accepted channel should be blocking"); 199 try { sc.connect(new TestSocketAddress()); fail(); } 200 catch (AlreadyConnectedException unused) { pass(); } 201 try { sc.bind(new TestSocketAddress()); fail(); } 202 catch (AlreadyConnectedException unused) { pass(); } 203 } catch (IOException unused) { fail(); } 204 } 205 206 static class TestSocketAddress extends SocketAddress {} 207 208 //--------------------- Infrastructure --------------------------- 209 boolean debug = true; 210 volatile int passed = 0, failed = 0; pass()211 void pass() {passed++;} fail()212 void fail() {failed++; Thread.dumpStack();} fail(String msg)213 void fail(String msg) {err.println(msg); fail();} unexpected(Throwable t)214 void unexpected(Throwable t) {failed++; t.printStackTrace();} check(boolean cond)215 void check(boolean cond) {if (cond) pass(); else fail();} check(boolean cond, String failMessage)216 void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);} debug(String message)217 void debug(String message) {if(debug) { out.println(message); } } sleep(long millis)218 void sleep(long millis) { try { Thread.currentThread().sleep(millis); } 219 catch(InterruptedException ie) { unexpected(ie); }} main(String[] args)220 public static void main(String[] args) throws Throwable { 221 Class<?> k = new Object(){}.getClass().getEnclosingClass(); 222 try {k.getMethod("instanceMain",String[].class) 223 .invoke( k.newInstance(), (Object) args);} 224 catch (Throwable e) {throw e.getCause();}} instanceMain(String[] args)225 public void instanceMain(String[] args) throws Throwable { 226 try {test(args);} catch (Throwable t) {unexpected(t);} 227 out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); 228 if (failed > 0) throw new AssertionError("Some tests failed");} 229 230 } 231