1 /* |
1 /* |
2 * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved. |
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. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
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 |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
70 implements PrivilegedExceptionAction<Void> |
70 implements PrivilegedExceptionAction<Void> |
71 { |
71 { |
72 |
72 |
73 private final SelectorProvider sp; |
73 private final SelectorProvider sp; |
74 |
74 |
|
75 private IOException ioe = null; |
|
76 |
75 private Initializer(SelectorProvider sp) { |
77 private Initializer(SelectorProvider sp) { |
76 this.sp = sp; |
78 this.sp = sp; |
77 } |
79 } |
78 |
80 |
|
81 @Override |
79 public Void run() throws IOException { |
82 public Void run() throws IOException { |
80 ServerSocketChannel ssc = null; |
83 LoopbackConnector connector = new LoopbackConnector(); |
81 SocketChannel sc1 = null; |
84 connector.run(); |
82 SocketChannel sc2 = null; |
85 if (ioe instanceof ClosedByInterruptException) { |
|
86 ioe = null; |
|
87 Thread connThread = new Thread(connector) { |
|
88 @Override |
|
89 public void interrupt() {} |
|
90 }; |
|
91 connThread.start(); |
|
92 for (;;) { |
|
93 try { |
|
94 connThread.join(); |
|
95 break; |
|
96 } catch (InterruptedException ex) {} |
|
97 } |
|
98 Thread.currentThread().interrupt(); |
|
99 } |
83 |
100 |
84 try { |
101 if (ioe != null) |
85 // loopback address |
102 throw new IOException("Unable to establish loopback connection", ioe); |
86 InetAddress lb = InetAddress.getByName("127.0.0.1"); |
|
87 assert(lb.isLoopbackAddress()); |
|
88 |
103 |
89 // bind ServerSocketChannel to a port on the loopback address |
104 return null; |
90 ssc = ServerSocketChannel.open(); |
105 } |
91 ssc.socket().bind(new InetSocketAddress(lb, 0)); |
|
92 |
106 |
93 // Establish connection (assumes connections are eagerly |
107 private class LoopbackConnector implements Runnable { |
94 // accepted) |
|
95 InetSocketAddress sa |
|
96 = new InetSocketAddress(lb, ssc.socket().getLocalPort()); |
|
97 sc1 = SocketChannel.open(sa); |
|
98 |
108 |
99 ByteBuffer bb = ByteBuffer.allocate(8); |
109 @Override |
100 long secret = rnd.nextLong(); |
110 public void run() { |
101 bb.putLong(secret).flip(); |
111 ServerSocketChannel ssc = null; |
102 sc1.write(bb); |
112 SocketChannel sc1 = null; |
|
113 SocketChannel sc2 = null; |
103 |
114 |
104 // Get a connection and verify it is legitimate |
115 try { |
105 for (;;) { |
116 // Loopback address |
106 sc2 = ssc.accept(); |
117 InetAddress lb = InetAddress.getByName("127.0.0.1"); |
107 bb.clear(); |
118 assert(lb.isLoopbackAddress()); |
108 sc2.read(bb); |
119 InetSocketAddress sa = null; |
109 bb.rewind(); |
120 for(;;) { |
110 if (bb.getLong() == secret) |
121 // Bind ServerSocketChannel to a port on the loopback |
111 break; |
122 // address |
112 sc2.close(); |
123 if (ssc == null || !ssc.isOpen()) { |
|
124 ssc = ServerSocketChannel.open(); |
|
125 ssc.socket().bind(new InetSocketAddress(lb, 0)); |
|
126 sa = new InetSocketAddress(lb, ssc.socket().getLocalPort()); |
|
127 } |
|
128 |
|
129 // Establish connection (assume connections are eagerly |
|
130 // accepted) |
|
131 sc1 = SocketChannel.open(sa); |
|
132 ByteBuffer bb = ByteBuffer.allocate(8); |
|
133 long secret = rnd.nextLong(); |
|
134 bb.putLong(secret).flip(); |
|
135 sc1.write(bb); |
|
136 |
|
137 // Get a connection and verify it is legitimate |
|
138 sc2 = ssc.accept(); |
|
139 bb.clear(); |
|
140 sc2.read(bb); |
|
141 bb.rewind(); |
|
142 if (bb.getLong() == secret) |
|
143 break; |
|
144 sc2.close(); |
|
145 sc1.close(); |
|
146 } |
|
147 |
|
148 // Create source and sink channels |
|
149 source = new SourceChannelImpl(sp, sc1); |
|
150 sink = new SinkChannelImpl(sp, sc2); |
|
151 } catch (IOException e) { |
|
152 try { |
|
153 if (sc1 != null) |
|
154 sc1.close(); |
|
155 if (sc2 != null) |
|
156 sc2.close(); |
|
157 } catch (IOException e2) {} |
|
158 ioe = e; |
|
159 } finally { |
|
160 try { |
|
161 if (ssc != null) |
|
162 ssc.close(); |
|
163 } catch (IOException e2) {} |
113 } |
164 } |
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 } |
165 } |
135 return null; |
|
136 } |
166 } |
137 } |
167 } |
138 |
168 |
139 PipeImpl(final SelectorProvider sp) throws IOException { |
169 PipeImpl(final SelectorProvider sp) throws IOException { |
140 try { |
170 try { |