1/* 2 * Copyright (c) 2015, 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 8071599 26 * @run main/othervm SendUrgentData 27 * @run main/othervm SendUrgentData -inline 28 * @summary Test sending of urgent data. 29 */ 30 31import java.io.IOException; 32import java.net.InetSocketAddress; 33import java.net.SocketAddress; 34import java.net.SocketException; 35import java.nio.ByteBuffer; 36import java.nio.channels.ServerSocketChannel; 37import java.nio.channels.SocketChannel; 38 39public class SendUrgentData { 40 41 /** 42 * The arguments may be one of the following: 43 * <ol> 44 * <li>-server</li> 45 * <li>-client host port [-inline]</li> 46 * <li>[-inline]</li> 47 * </ol> 48 * The first option creates a standalone server, the second a standalone 49 * client, and the third a self-contained server-client pair on the 50 * local host. 51 * 52 * @param args 53 * @throws Exception 54 */ 55 public static void main(String[] args) throws Exception { 56 57 ServerSocketChannelThread serverThread 58 = new ServerSocketChannelThread("SendUrgentDataServer"); 59 serverThread.start(); 60 boolean b = serverThread.isAlive(); 61 62 String host = null; 63 int port = 0; 64 boolean inline = false; 65 if (args.length > 0 && args[0].equals("-server")) { 66 System.out.println(serverThread.getAddress()); 67 Thread.currentThread().suspend(); 68 } else { 69 if (args.length > 0 && args[0].equals("-client")) { 70 host = args[1]; 71 port = Integer.parseInt(args[2]); 72 if (args.length > 3) { 73 inline = args[2].equals("-inline"); 74 } 75 } else { 76 host = "localhost"; 77 port = serverThread.getAddress().getPort(); 78 if (args.length > 0) { 79 inline = args[0].equals("-inline"); 80 } 81 } 82 } 83 84 System.out.println("OOB Inline : "+inline); 85 86 SocketAddress sa = new InetSocketAddress(host, port); 87 88 try (SocketChannel sc = SocketChannel.open(sa)) { 89 sc.configureBlocking(false); 90 sc.socket().setOOBInline(inline); 91 92 sc.socket().sendUrgentData(0); 93 System.out.println("wrote 1 OOB byte"); 94 95 ByteBuffer bb = ByteBuffer.wrap(new byte[100 * 1000]); 96 97 int blocked = 0; 98 long total = 0; 99 100 int n; 101 do { 102 n = sc.write(bb); 103 if (n == 0) { 104 System.out.println("blocked, wrote " + total + " so far"); 105 if (++blocked == 10) { 106 break; 107 } 108 Thread.sleep(100); 109 } else { 110 total += n; 111 bb.rewind(); 112 } 113 } while (n > 0); 114 115 long attempted = 0; 116 while (attempted < total) { 117 bb.rewind(); 118 n = sc.write(bb); 119 System.out.println("wrote " + n + " normal bytes"); 120 attempted += bb.capacity(); 121 122 String osName = System.getProperty("os.name").toLowerCase(); 123 124 try { 125 sc.socket().sendUrgentData(0); 126 } catch (IOException ex) { 127 if (osName.contains("linux")) { 128 if (!ex.getMessage().contains("Socket buffer full")) { 129 throw new RuntimeException("Unexpected message", ex); 130 } 131 } else if (osName.contains("os x") || osName.contains("mac")) { 132 if (!ex.getMessage().equals("No buffer space available")) { 133 throw new RuntimeException("Unexpected message", ex); 134 } 135 } else if (osName.contains("windows")) { 136 if (!(ex instanceof SocketException)) { 137 throw new RuntimeException("Unexpected exception", ex); 138 } else if (!ex.getMessage().contains("Resource temporarily unavailable")) { 139 throw new RuntimeException("Unexpected message", ex); 140 } 141 } else { 142 throw new RuntimeException("Unexpected IOException", ex); 143 } 144 } 145 146 try { 147 Thread.sleep(100); 148 } catch (InterruptedException ex) { 149 // don't want to fail on this so just print trace and break 150 ex.printStackTrace(); 151 break; 152 } 153 } 154 } finally { 155 serverThread.close(); 156 } 157 } 158 159 static class ServerSocketChannelThread extends Thread { 160 161 private ServerSocketChannel ssc; 162 163 private ServerSocketChannelThread(String name) { 164 super(name); 165 try { 166 ssc = ServerSocketChannel.open(); 167 ssc.bind(new InetSocketAddress((0))); 168 } catch (IOException ex) { 169 throw new RuntimeException(ex); 170 } 171 } 172 173 public void run() { 174 while (ssc.isOpen()) { 175 try { 176 Thread.sleep(100); 177 } catch (InterruptedException ex) { 178 throw new RuntimeException(ex); 179 } 180 } 181 try { 182 ssc.close(); 183 } catch (IOException ex) { 184 throw new RuntimeException(ex); 185 } 186 System.out.println("ServerSocketChannelThread exiting ..."); 187 } 188 189 public InetSocketAddress getAddress() throws IOException { 190 if (ssc == null) { 191 throw new IllegalStateException("ServerSocketChannel not created"); 192 } 193 194 return (InetSocketAddress) ssc.getLocalAddress(); 195 } 196 197 public void close() { 198 try { 199 ssc.close(); 200 } catch (IOException ex) { 201 throw new RuntimeException(ex); 202 } 203 } 204 } 205} 206