Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/windows/classes/sun/nio/ch/PipeImpl.java
41139 views
1
/*
2
* Copyright (c) 2002, 2021, 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.UnixDomainSocketAddress;
36
import java.net.StandardProtocolFamily;
37
import java.net.StandardSocketOptions;
38
import java.nio.*;
39
import java.nio.channels.*;
40
import java.nio.file.Files;
41
import java.nio.file.Path;
42
import java.nio.channels.spi.*;
43
import java.security.AccessController;
44
import java.security.PrivilegedExceptionAction;
45
import java.security.PrivilegedActionException;
46
import java.security.SecureRandom;
47
import java.util.Random;
48
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 IOException ioe;
73
SourceChannelImpl source;
74
SinkChannelImpl sink;
75
76
private Initializer(SelectorProvider sp) {
77
this.sp = sp;
78
}
79
80
@Override
81
public Void run() throws IOException {
82
LoopbackConnector connector = new LoopbackConnector();
83
connector.run();
84
if (ioe instanceof ClosedByInterruptException) {
85
ioe = null;
86
Thread connThread = new Thread(connector) {
87
@Override
88
public void interrupt() {}
89
};
90
connThread.start();
91
for (;;) {
92
try {
93
connThread.join();
94
break;
95
} catch (InterruptedException ex) {}
96
}
97
Thread.currentThread().interrupt();
98
}
99
100
if (ioe != null)
101
throw new IOException("Unable to establish loopback connection", ioe);
102
103
return null;
104
}
105
106
private class LoopbackConnector implements Runnable {
107
108
@Override
109
public void run() {
110
ServerSocketChannel ssc = null;
111
SocketChannel sc1 = null;
112
SocketChannel sc2 = null;
113
// Loopback address
114
SocketAddress sa = null;
115
116
try {
117
// Create secret with a backing array.
118
ByteBuffer secret = ByteBuffer.allocate(NUM_SECRET_BYTES);
119
ByteBuffer bb = ByteBuffer.allocate(NUM_SECRET_BYTES);
120
121
for(;;) {
122
// Bind ServerSocketChannel to a port on the loopback
123
// address
124
if (ssc == null || !ssc.isOpen()) {
125
ssc = createListener();
126
sa = ssc.getLocalAddress();
127
}
128
129
// Establish connection (assume connections are eagerly
130
// accepted)
131
sc1 = SocketChannel.open(sa);
132
RANDOM_NUMBER_GENERATOR.nextBytes(secret.array());
133
do {
134
sc1.write(secret);
135
} while (secret.hasRemaining());
136
secret.rewind();
137
138
// Get a connection and verify it is legitimate
139
sc2 = ssc.accept();
140
do {
141
sc2.read(bb);
142
} while (bb.hasRemaining());
143
bb.rewind();
144
145
if (bb.equals(secret))
146
break;
147
148
sc2.close();
149
sc1.close();
150
}
151
152
// Create source and sink channels
153
source = new SourceChannelImpl(sp, sc1);
154
sink = new SinkChannelImpl(sp, sc2);
155
} catch (IOException e) {
156
try {
157
if (sc1 != null)
158
sc1.close();
159
if (sc2 != null)
160
sc2.close();
161
} catch (IOException e2) {}
162
ioe = e;
163
} finally {
164
try {
165
if (ssc != null)
166
ssc.close();
167
if (sa instanceof UnixDomainSocketAddress) {
168
Path path = ((UnixDomainSocketAddress) sa).getPath();
169
Files.deleteIfExists(path);
170
}
171
} catch (IOException e2) {}
172
}
173
}
174
}
175
}
176
177
/**
178
* Creates a Pipe implementation that supports buffering.
179
*/
180
PipeImpl(SelectorProvider sp) throws IOException {
181
this(sp, true);
182
}
183
184
/**
185
* Creates Pipe implementation that supports optionally buffering.
186
*
187
* @implNote The pipe uses Unix domain sockets where possible. It uses a
188
* loopback connection on older editions of Windows. When buffering is
189
* disabled then it sets TCP_NODELAY on the sink channel.
190
*/
191
@SuppressWarnings("removal")
192
PipeImpl(SelectorProvider sp, boolean buffering) throws IOException {
193
Initializer initializer = new Initializer(sp);
194
try {
195
AccessController.doPrivileged(initializer);
196
SinkChannelImpl sink = initializer.sink;
197
if (sink.isNetSocket() && !buffering) {
198
sink.setOption(StandardSocketOptions.TCP_NODELAY, true);
199
}
200
} catch (PrivilegedActionException pae) {
201
throw (IOException) pae.getCause();
202
}
203
this.source = initializer.source;
204
this.sink = initializer.sink;
205
}
206
207
public SourceChannelImpl source() {
208
return source;
209
}
210
211
public SinkChannelImpl sink() {
212
return sink;
213
}
214
215
private static volatile boolean noUnixDomainSockets;
216
217
private static ServerSocketChannel createListener() throws IOException {
218
ServerSocketChannel listener = null;
219
if (!noUnixDomainSockets) {
220
try {
221
listener = ServerSocketChannel.open(StandardProtocolFamily.UNIX);
222
return listener.bind(null);
223
} catch (UnsupportedOperationException | IOException e) {
224
// IOException is most likely to be caused by the temporary directory
225
// name being too long. Possibly should log this.
226
noUnixDomainSockets = true;
227
if (listener != null)
228
listener.close();
229
}
230
}
231
listener = ServerSocketChannel.open();
232
InetAddress lb = InetAddress.getLoopbackAddress();
233
listener.bind(new InetSocketAddress(lb, 0));
234
return listener;
235
}
236
}
237
238