1 /*
2 * Copyright (c) 2010, 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 * @summary Test socket adapter sendUrgentData method
26 * @bug 6963907
27 * @key randomness
28 */
29
30 import java.net.*;
31 import java.nio.ByteBuffer;
32 import java.nio.channels.*;
33 import java.io.IOException;
34 import java.util.Random;
35
36 public class OutOfBand {
37
38 private static final Random rand = new Random();
39
40 public static void main(String[] args) throws Exception {
41 ServerSocketChannel ssc = null;
42 SocketChannel sc1 = null;
43 SocketChannel sc2 = null;
44
45 try {
46
47 // establish loopback connection
48 ssc = ServerSocketChannel.open().bind(new InetSocketAddress(0));
49 InetAddress lh = InetAddress.getLocalHost();
50 SocketAddress remote =
51 new InetSocketAddress(lh, ssc.socket().getLocalPort());
52 sc1 = SocketChannel.open(remote);
53 sc2 = ssc.accept();
54
55 // enable SO_OOBLINE on server side
56 sc2.socket().setOOBInline(true);
57
58 // run tests
59 test1(sc1, sc2);
60 test2(sc1, sc2);
61 test3(sc1, sc2);
62 } finally {
63 if (sc1 != null) sc1.close();
64 if (sc2 != null) sc2.close();
65 if (ssc != null) ssc.close();
66 }
67 }
68
69 /**
70 * Basic test to check that OOB/TCP urgent byte is received.
71 */
72 static void test1(SocketChannel client, SocketChannel server)
73 throws Exception
74 {
75 assert server.socket().getOOBInline();
76 ByteBuffer bb = ByteBuffer.allocate(100);
77 for (int i=0; i<1000; i++) {
78 int b1 = -127 + rand.nextInt(384);
79 client.socket().sendUrgentData(b1);
80
81 bb.clear();
82 if (server.read(bb) != 1)
83 throw new RuntimeException("One byte expected");
84 bb.flip();
85 byte b2 = bb.get();
86 if ((byte)b1 != b2)
87 throw new RuntimeException("Unexpected byte");
88 }
89 }
90
91 /**
92 * Basic test to check that OOB/TCP urgent byte is received, maybe with
93 * OOB mark changing.
94 */
95 static void test2(final SocketChannel client, SocketChannel server)
96 throws Exception
97 {
98 assert server.socket().getOOBInline();
99 Runnable sender = new Runnable() {
100 public void run() {
101 try {
102 for (int i=0; i<256; i++)
103 client.socket().sendUrgentData(i);
104 } catch (IOException ioe) {
105 ioe.printStackTrace();
106 }
107 }
108 };
109 Thread thr = new Thread(sender);
110 thr.start();
111
112 ByteBuffer bb = ByteBuffer.allocate(256);
113 while (bb.hasRemaining()) {
114 if (server.read(bb) < 0)
115 throw new RuntimeException("Unexpected EOF");
116 }
117 bb.flip();
118 byte expect = 0;
119 while (bb.hasRemaining()) {
120 if (bb.get() != expect)
121 throw new RuntimeException("Unexpected byte");
122 expect++;
123 }
124
125 thr.join();
126 }
127
128 /**
129 * Test that is close to some real world examples where an urgent byte is
130 * used to "cancel" a long running query or transaction on the server.
131 */
132 static void test3(SocketChannel client, final SocketChannel server)
133 throws Exception
134 {
135 final int STOP = rand.nextInt(256);
136
137 assert server.socket().getOOBInline();
138 Runnable reader = new Runnable() {
139 public void run() {
140 ByteBuffer bb = ByteBuffer.allocate(100);
141 try {
142 int n = server.read(bb);
143 if (n != 1) {
144 String msg = (n < 0) ? "Unexpected EOF" :
145 "One byte expected";
146 throw new RuntimeException(msg);
147 }
148 bb.flip();
149 if (bb.get() != (byte)STOP)
150 throw new RuntimeException("Unexpected byte");
151 bb.flip();
152 server.write(bb);
153 } catch (IOException ioe) {
154 ioe.printStackTrace();
155 }
156
157 }
158 };
159
160 Thread thr = new Thread(reader);
161 thr.start();
162
163 // "stop" server
164 client.socket().sendUrgentData(STOP);
165
166 // wait for server reply
167 ByteBuffer bb = ByteBuffer.allocate(100);
168 int n = client.read(bb);
169 if (n != 1)
170 throw new RuntimeException("Unexpected number of bytes");
171 bb.flip();
172 if (bb.get() != (byte)STOP)
173 throw new RuntimeException("Unexpected reply");
174
175 thr.join();
176 }
177 }
--- EOF ---