1/* 2 * Copyright (c) 2009, 2014, 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 30import java.io.IOException; 31import java.util.Set; 32import java.net.InetSocketAddress; 33import java.net.SocketAddress; 34import java.util.List; 35import java.util.Arrays; 36import java.util.Iterator; 37import java.nio.channels.ClosedChannelException; 38import com.sun.nio.sctp.SctpChannel; 39import com.sun.nio.sctp.SctpServerChannel; 40import com.sun.nio.sctp.SctpSocketOption; 41import java.security.AccessController; 42import java.security.PrivilegedAction; 43import static com.sun.nio.sctp.SctpStandardSocketOptions.*; 44import static java.lang.System.out; 45 46public class SocketOptionTests { 47 final String osName = AccessController.doPrivileged( 48 (PrivilegedAction<String>)() -> System.getProperty("os.name")); 49 50 <T> void checkOption(SctpChannel sc, SctpSocketOption<T> name, 51 T expectedValue) throws IOException { 52 T value = sc.getOption(name); 53 check(value.equals(expectedValue), name + ": value (" + value + 54 ") not as expected (" + expectedValue + ")"); 55 } 56 57 <T> void optionalSupport(SctpChannel sc, SctpSocketOption<T> name, 58 T value) { 59 try { 60 sc.setOption(name, value); 61 checkOption(sc, name, value); 62 } catch (IOException e) { 63 /* Informational only, not all options have native support */ 64 out.println(name + " not supported. " + e); 65 } 66 } 67 68 void test(String[] args) { 69 if (!Util.isSCTPSupported()) { 70 out.println("SCTP protocol is not supported"); 71 out.println("Test cannot be run"); 72 return; 73 } 74 75 try { 76 SctpChannel sc = SctpChannel.open(); 77 78 /* check supported options */ 79 Set<SctpSocketOption<?>> options = sc.supportedOptions(); 80 List<? extends SctpSocketOption<?>> expected = Arrays.<SctpSocketOption<?>>asList( 81 SCTP_DISABLE_FRAGMENTS, SCTP_EXPLICIT_COMPLETE, 82 SCTP_FRAGMENT_INTERLEAVE, SCTP_INIT_MAXSTREAMS, 83 SCTP_NODELAY, SCTP_PRIMARY_ADDR, SCTP_SET_PEER_PRIMARY_ADDR, 84 SO_SNDBUF, SO_RCVBUF, SO_LINGER); 85 86 for (SctpSocketOption opt: expected) { 87 if (!options.contains(opt)) 88 fail(opt.name() + " should be supported"); 89 } 90 91 InitMaxStreams streams = InitMaxStreams.create(1024, 1024); 92 sc.setOption(SCTP_INIT_MAXSTREAMS, streams); 93 checkOption(sc, SCTP_INIT_MAXSTREAMS, streams); 94 streams = sc.getOption(SCTP_INIT_MAXSTREAMS); 95 check(streams.maxInStreams() == 1024, "Max in streams: value: " 96 + streams.maxInStreams() + ", expected 1024 "); 97 check(streams.maxOutStreams() == 1024, "Max out streams: value: " 98 + streams.maxOutStreams() + ", expected 1024 "); 99 100 optionalSupport(sc, SCTP_DISABLE_FRAGMENTS, true); 101 optionalSupport(sc, SCTP_EXPLICIT_COMPLETE, true); 102 optionalSupport(sc, SCTP_FRAGMENT_INTERLEAVE, 1); 103 104 sc.setOption(SCTP_NODELAY, true); 105 checkOption(sc, SCTP_NODELAY, true); 106 sc.setOption(SO_SNDBUF, 16*1024); 107 checkOption(sc, SO_SNDBUF, 16*1024); 108 sc.setOption(SO_RCVBUF, 16*1024); 109 checkOption(sc, SO_RCVBUF, 16*1024); 110 checkOption(sc, SO_LINGER, -1); /* default should be negative */ 111 sc.setOption(SO_LINGER, 2000); 112 checkOption(sc, SO_LINGER, 2000); 113 114 /* SCTP_PRIMARY_ADDR */ 115 sctpPrimaryAddr(); 116 117 /* NullPointerException */ 118 try { 119 sc.setOption(null, "value"); 120 fail("NullPointerException not thrown for setOption"); 121 } catch (NullPointerException unused) { 122 pass(); 123 } 124 try { 125 sc.getOption(null); 126 fail("NullPointerException not thrown for getOption"); 127 } catch (NullPointerException unused) { 128 pass(); 129 } 130 131 /* ClosedChannelException */ 132 sc.close(); 133 try { 134 sc.setOption(SCTP_INIT_MAXSTREAMS, streams); 135 fail("ClosedChannelException not thrown"); 136 } catch (ClosedChannelException unused) { 137 pass(); 138 } 139 } catch (IOException ioe) { 140 unexpected(ioe); 141 } 142 } 143 144 /* SCTP_PRIMARY_ADDR */ 145 void sctpPrimaryAddr() throws IOException { 146 SocketAddress addrToSet = null;; 147 148 System.out.println("TESTING SCTP_PRIMARY_ADDR"); 149 SctpChannel sc = SctpChannel.open(); 150 SctpServerChannel ssc = SctpServerChannel.open().bind(null); 151 Set<SocketAddress> addrs = ssc.getAllLocalAddresses(); 152 if (addrs.isEmpty()) 153 debug("addrs should not be empty"); 154 debug("Listening on " + addrs); 155 156 InetSocketAddress serverAddr = (InetSocketAddress) addrs.iterator().next(); 157 debug("connecting to " + serverAddr); 158 sc.connect(serverAddr); 159 SctpChannel peerChannel = ssc.accept(); 160 ssc.close(); 161 Set<SocketAddress> peerAddrs = peerChannel.getAllLocalAddresses(); 162 debug("Peer local Addresses: "); 163 for (Iterator<SocketAddress> it = peerAddrs.iterator(); it.hasNext(); ) { 164 InetSocketAddress addr = (InetSocketAddress)it.next(); 165 debug("\t" + addr); 166 addrToSet = addr; // any of the peer addresses will do! 167 } 168 169 /* retrieval of SCTP_PRIMARY_ADDR is not supported on Solaris */ 170 if ("SunOS".equals(osName)) { 171 /* For now do not set this option. There is a bug on Solaris 10 pre Update 5 172 * where setting this option returns Invalid argument */ 173 //debug("Set SCTP_PRIMARY_ADDR with " + addrToSet); 174 //sc.setOption(SCTP_PRIMARY_ADDR, addrToSet); 175 return; 176 } else { /* Linux */ 177 SocketAddress primaryAddr = sc.getOption(SCTP_PRIMARY_ADDR); 178 System.out.println("SCTP_PRIMARY_ADDR returned: " + primaryAddr); 179 /* Verify that this is one of the peer addresses */ 180 boolean found = false; 181 addrToSet = primaryAddr; // may not have more than one addr 182 for (Iterator<SocketAddress> it = peerAddrs.iterator(); it.hasNext(); ) { 183 InetSocketAddress addr = (InetSocketAddress)it.next(); 184 if (addr.equals(primaryAddr)) { 185 found = true; 186 } 187 addrToSet = addr; 188 } 189 check(found, "SCTP_PRIMARY_ADDR returned bogus address!"); 190 191 System.out.println("SCTP_PRIMARY_ADDR try set to: " + addrToSet); 192 sc.setOption(SCTP_PRIMARY_ADDR, addrToSet); 193 System.out.println("SCTP_PRIMARY_ADDR set to: " + addrToSet); 194 primaryAddr = sc.getOption(SCTP_PRIMARY_ADDR); 195 System.out.println("SCTP_PRIMARY_ADDR returned: " + primaryAddr); 196 check(addrToSet.equals(primaryAddr),"SCTP_PRIMARY_ADDR not set correctly"); 197 } 198 } 199 //--------------------- Infrastructure --------------------------- 200 boolean debug = true; 201 volatile int passed = 0, failed = 0; 202 void pass() {passed++;} 203 void fail() {failed++; Thread.dumpStack();} 204 void fail(String msg) {System.err.println(msg); fail();} 205 void unexpected(Throwable t) {failed++; t.printStackTrace();} 206 void check(boolean cond) {if (cond) pass(); else fail();} 207 void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);} 208 void debug(String message) {if(debug) { System.out.println(message); } } 209 public static void main(String[] args) throws Throwable { 210 Class<?> k = new Object(){}.getClass().getEnclosingClass(); 211 try {k.getMethod("instanceMain",String[].class) 212 .invoke( k.newInstance(), (Object) args);} 213 catch (Throwable e) {throw e.getCause();}} 214 public void instanceMain(String[] args) throws Throwable { 215 try {test(args);} catch (Throwable t) {unexpected(t);} 216 System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); 217 if (failed > 0) throw new AssertionError("Some tests failed");} 218} 219