1 /*
2 * Copyright (c) 2002, 2008, 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
55 // Random object for handshake values
56 private static final Random rnd;
57
58 static {
59 Util.load();
60 byte[] someBytes = new byte[8];
61 boolean resultOK = IOUtil.randomBytes(someBytes);
62 if (resultOK) {
63 rnd = new Random(ByteBuffer.wrap(someBytes).getLong());
64 } else {
65 rnd = new Random();
66 }
67 }
68
69 private class Initializer
70 implements PrivilegedExceptionAction<Void>
71 {
72
73 private final SelectorProvider sp;
74
75 private Initializer(SelectorProvider sp) {
76 this.sp = sp;
77 }
78
79 public Void run() throws IOException {
80 ServerSocketChannel ssc = null;
81 SocketChannel sc1 = null;
82 SocketChannel sc2 = null;
83
84 try {
85 // loopback address
86 InetAddress lb = InetAddress.getByName("127.0.0.1");
87 assert(lb.isLoopbackAddress());
88
89 // bind ServerSocketChannel to a port on the loopback address
90 ssc = ServerSocketChannel.open();
91 ssc.socket().bind(new InetSocketAddress(lb, 0));
92
93 // Establish connection (assumes connections are eagerly
94 // accepted)
95 InetSocketAddress sa
96 = new InetSocketAddress(lb, ssc.socket().getLocalPort());
97 sc1 = SocketChannel.open(sa);
98
99 ByteBuffer bb = ByteBuffer.allocate(8);
100 long secret = rnd.nextLong();
101 bb.putLong(secret).flip();
102 sc1.write(bb);
103
104 // Get a connection and verify it is legitimate
105 for (;;) {
106 sc2 = ssc.accept();
107 bb.clear();
108 sc2.read(bb);
109 bb.rewind();
110 if (bb.getLong() == secret)
111 break;
112 sc2.close();
113 }
114
115 // Create source and sink channels
116 source = new SourceChannelImpl(sp, sc1);
117 sink = new SinkChannelImpl(sp, sc2);
118 } catch (IOException e) {
119 try {
120 if (sc1 != null)
121 sc1.close();
122 if (sc2 != null)
123 sc2.close();
124 } catch (IOException e2) { }
125 IOException x = new IOException("Unable to establish"
126 + " loopback connection");
127 x.initCause(e);
128 throw x;
129 } finally {
130 try {
131 if (ssc != null)
132 ssc.close();
133 } catch (IOException e2) { }
134 }
135 return null;
136 }
137 }
138
139 PipeImpl(final SelectorProvider sp) throws IOException {
140 try {
141 AccessController.doPrivileged(new Initializer(sp));
142 } catch (PrivilegedActionException x) {
143 throw (IOException)x.getCause();
144 }
145 }
146
147
148 public SourceChannel source() {
149 return source;
150 }
151
152 public SinkChannel sink() {
153 return sink;
154 }
155
|
1 /*
2 * Copyright (c) 2002, 2012, 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
55 // Random object for handshake values
56 private static final Random rnd;
57
58 static {
59 Util.load();
60 byte[] someBytes = new byte[8];
61 boolean resultOK = IOUtil.randomBytes(someBytes);
62 if (resultOK) {
63 rnd = new Random(ByteBuffer.wrap(someBytes).getLong());
64 } else {
65 rnd = new Random();
66 }
67 }
68
69 private class Initializer
70 implements PrivilegedExceptionAction<Void>
71 {
72
73 private final SelectorProvider sp;
74
75 private IOException ioe = null;
76
77 private Initializer(SelectorProvider sp) {
78 this.sp = sp;
79 }
80
81 @Override
82 public Void run() throws IOException {
83 boolean interrupted = false;
84
85 ServerSocketChannel ssc = null;
86 SocketChannel sc1 = null;
87 SocketChannel sc2 = null;
88
89 try {
90 // loopback address
91 InetAddress lb = InetAddress.getByName("127.0.0.1");
92 assert(lb.isLoopbackAddress());
93 InetSocketAddress sa = null;
94 for(;;) {
95 // bind ServerSocketChannel to a port on the loopback
96 // address
97 if (ssc == null || !ssc.isOpen()) {
98 ssc = ServerSocketChannel.open();
99 ssc.socket().bind(new InetSocketAddress(lb, 0));
100 sa = new InetSocketAddress(lb,
101 ssc.socket().getLocalPort());
102 }
103
104 // Establish connection (assume connections are eagerly
105 // accepted)
106 sc1 = SocketChannel.open(sa);
107 ByteBuffer bb = ByteBuffer.allocate(8);
108 long secret = rnd.nextLong();
109 bb.putLong(secret).flip();
110 sc1.write(bb);
111
112 // Get a connection and verify it is legitimate
113 sc2 = ssc.accept();
114 bb.clear();
115 sc2.read(bb);
116 bb.rewind();
117 if (bb.getLong() == secret)
118 break;
119 sc2.close();
120 sc1.close();
121 }
122
123 // Create source and sink channels
124 source = new SourceChannelImpl(sp, sc1);
125 sink = new SinkChannelImpl(sp, sc2);
126 } catch (IOException e) {
127 try {
128 if (sc1 != null)
129 sc1.close();
130 if (sc2 != null)
131 sc2.close();
132 } catch (IOException e2) {}
133
134 if (!(e instanceof ClosedByInterruptException))
135 throw new IOException("Unable to establish loopback"
136 + " connection", e);
137 interrupted = true;
138 Thread.interrupted();
139 } finally {
140 try {
141 if (ssc != null)
142 ssc.close();
143 } catch (IOException e2) {}
144 }
145
146 if (interrupted)
147 UninterruptibleConnect();
148
149 return null;
150 }
151
152 // Use short-lived uninterruptible thread to establish
153 // loopback connections
154 private void UninterruptibleConnect() throws IOException {
155 Thread connector = new Thread("UninterruptibleConnector") {
156 ServerSocketChannel ssc = null;
157 SocketChannel sc1 = null;
158 SocketChannel sc2 = null;
159
160 @Override
161 public void run() {
162 try {
163 // loopback address
164 InetAddress lb = InetAddress.getByName("127.0.0.1");
165 assert(lb.isLoopbackAddress());
166 InetSocketAddress sa = null;
167
168 for (;;) {
169 // bind ServerSocketChannel to a port on the
170 // loopback address
171 if (ssc == null || !ssc.isOpen()) {
172 ssc = ServerSocketChannel.open();
173 ssc.socket().bind(new InetSocketAddress(lb, 0));
174 sa = new InetSocketAddress(lb,
175 ssc.socket().getLocalPort());
176 }
177 assert(sa != null);
178
179 // Establish connection (assumes connections are
180 // eagerly accepted)
181 sc1 = SocketChannel.open(sa);
182 ByteBuffer bb = ByteBuffer.allocate(8);
183 long secret = rnd.nextLong();
184 bb.putLong(secret).flip();
185 sc1.write(bb);
186
187 // Get a connection and verify it is legitimate
188 sc2 = ssc.accept();
189 bb.clear();
190 sc2.read(bb);
191 bb.rewind();
192 if (bb.getLong() == secret)
193 break;
194 sc2.close();
195 sc1.close();
196 }
197
198 // Create source and sink channels
199 source = new SourceChannelImpl(sp, sc1);
200 sink = new SinkChannelImpl(sp, sc2);
201 } catch (IOException e) {
202 try {
203 if (sc1 != null)
204 sc1.close();
205 if (sc2 != null)
206 sc2.close();
207 } catch (IOException e2) {}
208 ioe = e;
209 } finally {
210 try {
211 if (ssc != null)
212 ssc.close();
213 } catch (IOException e2) {}
214 }
215 }
216
217 @Override
218 public void interrupt() {}
219 };
220 connector.start();
221 for(;;) {
222 try {
223 connector.join();
224 break;
225 } catch (InterruptedException ex) {}
226 }
227
228 Thread.currentThread().interrupt();
229
230 if (ioe != null || source == null || sink == null)
231 throw new IOException("Unable to establish loopback connection",
232 ioe);
233 }
234 }
235
236 PipeImpl(final SelectorProvider sp) throws IOException {
237 try {
238 AccessController.doPrivileged(new Initializer(sp));
239 } catch (PrivilegedActionException x) {
240 throw (IOException)x.getCause();
241 }
242 }
243
244
245 public SourceChannel source() {
246 return source;
247 }
248
249 public SinkChannel sink() {
250 return sink;
251 }
252
|