Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/src/java.base/windows/classes/sun/nio/ch/PipeImpl.java
67773 views
1
/*
2
* Copyright (c) 2002, 2022, 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
23
* questions.
24
*/
25
26
/*
27
*/
28
29
package sun.nio.ch;
30
31
import java.io.IOException;
32
import java.net.InetAddress;
33
import java.net.InetSocketAddress;
34
import java.net.SocketAddress;
35
import java.net.StandardSocketOptions;
36
import java.net.UnixDomainSocketAddress;
37
import java.nio.*;
38
import java.nio.channels.*;
39
import java.nio.file.Files;
40
import java.nio.file.Path;
41
import java.nio.channels.spi.*;
42
import java.security.AccessController;
43
import java.security.PrivilegedExceptionAction;
44
import java.security.PrivilegedActionException;
45
import java.security.SecureRandom;
46
import java.util.Random;
47
48
import static java.net.StandardProtocolFamily.UNIX;
49
50
/**
51
* A simple Pipe implementation based on a socket connection.
52
*/
53
54
class PipeImpl
55
extends Pipe
56
{
57
// Number of bytes in the secret handshake.
58
private static final int NUM_SECRET_BYTES = 16;
59
60
// Random object for handshake values
61
private static final Random RANDOM_NUMBER_GENERATOR = new SecureRandom();
62
63
// Source and sink channels
64
private final SourceChannelImpl source;
65
private final SinkChannelImpl sink;
66
67
private static class Initializer
68
implements PrivilegedExceptionAction<Void>
69
{
70
71
private final SelectorProvider sp;
72
private final boolean preferUnixDomain;
73
private IOException ioe;
74
SourceChannelImpl source;
75
SinkChannelImpl sink;
76
77
private Initializer(SelectorProvider sp, boolean preferUnixDomain) {
78
this.sp = sp;
79
this.preferUnixDomain = preferUnixDomain;
80
}
81
82
@Override
83
public Void run() throws IOException {
84
LoopbackConnector connector = new LoopbackConnector();
85
connector.run();
86
if (ioe instanceof ClosedByInterruptException) {
87
ioe = null;
88
Thread connThread = new Thread(connector) {
89
@Override
90
public void interrupt() {}
91
};
92
connThread.start();
93
for (;;) {
94
try {
95
connThread.join();
96
break;
97
} catch (InterruptedException ex) {}
98
}
99
Thread.currentThread().interrupt();
100
}
101
102
if (ioe != null)
103
throw new IOException("Unable to establish loopback connection", ioe);
104
105
return null;
106
}
107
108
private class LoopbackConnector implements Runnable {
109
110
@Override
111
public void run() {
112
ServerSocketChannel ssc = null;
113
SocketChannel sc1 = null;
114
SocketChannel sc2 = null;
115
// Loopback address
116
SocketAddress sa = null;
117
118
try {
119
// Create secret with a backing array.
120
ByteBuffer secret = ByteBuffer.allocate(NUM_SECRET_BYTES);
121
ByteBuffer bb = ByteBuffer.allocate(NUM_SECRET_BYTES);
122
123
for(;;) {
124
// Bind ServerSocketChannel to a port on the loopback
125
// address
126
if (ssc == null || !ssc.isOpen()) {
127
ssc = createListener(preferUnixDomain);
128
sa = ssc.getLocalAddress();
129
}
130
131
// Establish connection (assume connections are eagerly
132
// accepted)
133
sc1 = SocketChannel.open(sa);
134
RANDOM_NUMBER_GENERATOR.nextBytes(secret.array());
135
do {
136
sc1.write(secret);
137
} while (secret.hasRemaining());
138
secret.rewind();
139
140
// Get a connection and verify it is legitimate
141
sc2 = ssc.accept();
142
do {
143
sc2.read(bb);
144
} while (bb.hasRemaining());
145
bb.rewind();
146
147
if (bb.equals(secret))
148
break;
149
150
sc2.close();
151
sc1.close();
152
}
153
154
// Create source and sink channels
155
source = new SourceChannelImpl(sp, sc1);
156
sink = new SinkChannelImpl(sp, sc2);
157
} catch (IOException e) {
158
try {
159
if (sc1 != null)
160
sc1.close();
161
if (sc2 != null)
162
sc2.close();
163
} catch (IOException e2) {}
164
ioe = e;
165
} finally {
166
try {
167
if (ssc != null)
168
ssc.close();
169
if (sa instanceof UnixDomainSocketAddress uaddr) {
170
Files.deleteIfExists(uaddr.getPath());
171
}
172
} catch (IOException e2) {}
173
}
174
}
175
}
176
}
177
178
/**
179
* Creates a (TCP) Pipe implementation that supports buffering.
180
*/
181
PipeImpl(SelectorProvider sp) throws IOException {
182
this(sp, true, false);
183
}
184
185
/**
186
* Creates Pipe implementation that supports optionally buffering
187
* and is TCP by default, but if Unix domain is supported and
188
* preferAfUnix is true, then Unix domain sockets are used.
189
*
190
* @param preferAfUnix use Unix domain sockets if supported
191
*
192
* @param buffering if false set TCP_NODELAY on TCP sockets
193
*/
194
@SuppressWarnings("removal")
195
PipeImpl(SelectorProvider sp, boolean preferAfUnix, boolean buffering) throws IOException {
196
Initializer initializer = new Initializer(sp, preferAfUnix);
197
try {
198
AccessController.doPrivileged(initializer);
199
SinkChannelImpl sink = initializer.sink;
200
if (sink.isNetSocket() && !buffering) {
201
sink.setOption(StandardSocketOptions.TCP_NODELAY, true);
202
}
203
} catch (PrivilegedActionException pae) {
204
throw (IOException) pae.getCause();
205
}
206
this.source = initializer.source;
207
this.sink = initializer.sink;
208
}
209
210
public SourceChannelImpl source() {
211
return source;
212
}
213
214
public SinkChannelImpl sink() {
215
return sink;
216
}
217
218
private static ServerSocketChannel createListener(boolean preferUnixDomain) throws IOException {
219
ServerSocketChannel listener = null;
220
if (preferUnixDomain && UnixDomainSockets.isSupported()) {
221
try {
222
listener = ServerSocketChannel.open(UNIX);
223
listener.bind(null);
224
return listener;
225
} catch (IOException | UnsupportedOperationException e) {
226
if (listener != null)
227
listener.close();
228
}
229
}
230
listener = ServerSocketChannel.open();
231
InetAddress lb = InetAddress.getLoopbackAddress();
232
listener.bind(new InetSocketAddress(lb, 0));
233
return listener;
234
}
235
}
236
237