Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java
41137 views
1
/*
2
* Copyright (c) 2008, 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
package sun.nio.ch;
27
28
import java.nio.channels.*;
29
import java.util.concurrent.*;
30
import java.io.IOException;
31
import java.io.FileDescriptor;
32
import java.net.InetSocketAddress;
33
import java.util.concurrent.atomic.AtomicBoolean;
34
import java.security.AccessControlContext;
35
import java.security.AccessController;
36
import java.security.PrivilegedAction;
37
38
/**
39
* Unix implementation of AsynchronousServerSocketChannel
40
*/
41
42
class UnixAsynchronousServerSocketChannelImpl
43
extends AsynchronousServerSocketChannelImpl
44
implements Port.PollableChannel
45
{
46
private static final NativeDispatcher nd = new SocketDispatcher();
47
48
private final Port port;
49
private final int fdVal;
50
51
// flag to indicate an accept is outstanding
52
private final AtomicBoolean accepting = new AtomicBoolean();
53
private void enableAccept() {
54
accepting.set(false);
55
}
56
57
// used to ensure that the context for an asynchronous accept is visible
58
// the pooled thread that handles the I/O event
59
private final Object updateLock = new Object();
60
61
// pending accept
62
private boolean acceptPending;
63
private CompletionHandler<AsynchronousSocketChannel,Object> acceptHandler;
64
private Object acceptAttachment;
65
private PendingFuture<AsynchronousSocketChannel,Object> acceptFuture;
66
67
// context for permission check when security manager set
68
@SuppressWarnings("removal")
69
private AccessControlContext acceptAcc;
70
71
72
UnixAsynchronousServerSocketChannelImpl(Port port)
73
throws IOException
74
{
75
super(port);
76
77
try {
78
IOUtil.configureBlocking(fd, false);
79
} catch (IOException x) {
80
nd.close(fd); // prevent leak
81
throw x;
82
}
83
this.port = port;
84
this.fdVal = IOUtil.fdVal(fd);
85
86
// add mapping from file descriptor to this channel
87
port.register(fdVal, this);
88
}
89
90
@Override
91
void implClose() throws IOException {
92
// remove the mapping
93
port.unregister(fdVal);
94
95
// close file descriptor
96
nd.close(fd);
97
98
// if there is a pending accept then complete it
99
CompletionHandler<AsynchronousSocketChannel,Object> handler;
100
Object att;
101
PendingFuture<AsynchronousSocketChannel,Object> future;
102
synchronized (updateLock) {
103
if (!acceptPending)
104
return; // no pending accept
105
acceptPending = false;
106
handler = acceptHandler;
107
att = acceptAttachment;
108
future = acceptFuture;
109
}
110
111
// discard the stack trace as otherwise it may appear that implClose
112
// has thrown the exception.
113
AsynchronousCloseException x = new AsynchronousCloseException();
114
x.setStackTrace(new StackTraceElement[0]);
115
if (handler == null) {
116
future.setFailure(x);
117
} else {
118
// invoke by submitting task rather than directly
119
Invoker.invokeIndirectly(this, handler, att, null, x);
120
}
121
}
122
123
@Override
124
public AsynchronousChannelGroupImpl group() {
125
return port;
126
}
127
128
/**
129
* Invoked by event handling thread when listener socket is polled
130
*/
131
@Override
132
public void onEvent(int events, boolean mayInvokeDirect) {
133
synchronized (updateLock) {
134
if (!acceptPending)
135
return; // may have been grabbed by asynchronous close
136
acceptPending = false;
137
}
138
139
// attempt to accept connection
140
FileDescriptor newfd = new FileDescriptor();
141
InetSocketAddress[] isaa = new InetSocketAddress[1];
142
Throwable exc = null;
143
try {
144
begin();
145
int n = Net.accept(this.fd, newfd, isaa);
146
147
// spurious wakeup, is this possible?
148
if (n == IOStatus.UNAVAILABLE) {
149
synchronized (updateLock) {
150
acceptPending = true;
151
}
152
port.startPoll(fdVal, Net.POLLIN);
153
return;
154
}
155
156
} catch (Throwable x) {
157
if (x instanceof ClosedChannelException)
158
x = new AsynchronousCloseException();
159
exc = x;
160
} finally {
161
end();
162
}
163
164
// Connection accepted so finish it when not holding locks.
165
AsynchronousSocketChannel child = null;
166
if (exc == null) {
167
try {
168
child = finishAccept(newfd, isaa[0], acceptAcc);
169
} catch (Throwable x) {
170
if (!(x instanceof IOException) && !(x instanceof SecurityException))
171
x = new IOException(x);
172
exc = x;
173
}
174
}
175
176
// copy field befores accept is re-renabled
177
CompletionHandler<AsynchronousSocketChannel,Object> handler = acceptHandler;
178
Object att = acceptAttachment;
179
PendingFuture<AsynchronousSocketChannel,Object> future = acceptFuture;
180
181
// re-enable accepting and invoke handler
182
enableAccept();
183
184
if (handler == null) {
185
future.setResult(child, exc);
186
// if an async cancel has already cancelled the operation then
187
// close the new channel so as to free resources
188
if (child != null && future.isCancelled()) {
189
try {
190
child.close();
191
} catch (IOException ignore) { }
192
}
193
} else {
194
Invoker.invoke(this, handler, att, child, exc);
195
}
196
}
197
198
/**
199
* Completes the accept by creating the AsynchronousSocketChannel for
200
* the given file descriptor and remote address. If this method completes
201
* with an IOException or SecurityException then the channel/file descriptor
202
* will be closed.
203
*/
204
@SuppressWarnings("removal")
205
private AsynchronousSocketChannel finishAccept(FileDescriptor newfd,
206
final InetSocketAddress remote,
207
AccessControlContext acc)
208
throws IOException, SecurityException
209
{
210
AsynchronousSocketChannel ch = null;
211
try {
212
ch = new UnixAsynchronousSocketChannelImpl(port, newfd, remote);
213
} catch (IOException x) {
214
nd.close(newfd);
215
throw x;
216
}
217
218
// permission check must always be in initiator's context
219
try {
220
if (acc != null) {
221
AccessController.doPrivileged(new PrivilegedAction<>() {
222
public Void run() {
223
SecurityManager sm = System.getSecurityManager();
224
if (sm != null) {
225
sm.checkAccept(remote.getAddress().getHostAddress(),
226
remote.getPort());
227
}
228
return null;
229
}
230
}, acc);
231
} else {
232
SecurityManager sm = System.getSecurityManager();
233
if (sm != null) {
234
sm.checkAccept(remote.getAddress().getHostAddress(),
235
remote.getPort());
236
}
237
}
238
} catch (SecurityException x) {
239
try {
240
ch.close();
241
} catch (Throwable suppressed) {
242
x.addSuppressed(suppressed);
243
}
244
throw x;
245
}
246
return ch;
247
}
248
249
@SuppressWarnings("removal")
250
@Override
251
Future<AsynchronousSocketChannel> implAccept(Object att,
252
CompletionHandler<AsynchronousSocketChannel,Object> handler)
253
{
254
// complete immediately if channel is closed
255
if (!isOpen()) {
256
Throwable e = new ClosedChannelException();
257
if (handler == null) {
258
return CompletedFuture.withFailure(e);
259
} else {
260
Invoker.invoke(this, handler, att, null, e);
261
return null;
262
}
263
}
264
if (localAddress == null)
265
throw new NotYetBoundException();
266
267
// cancel was invoked with pending accept so connection may have been
268
// dropped.
269
if (isAcceptKilled())
270
throw new RuntimeException("Accept not allowed due cancellation");
271
272
// check and set flag to prevent concurrent accepting
273
if (!accepting.compareAndSet(false, true))
274
throw new AcceptPendingException();
275
276
// attempt accept
277
FileDescriptor newfd = new FileDescriptor();
278
InetSocketAddress[] isaa = new InetSocketAddress[1];
279
Throwable exc = null;
280
try {
281
begin();
282
283
int n = Net.accept(this.fd, newfd, isaa);
284
if (n == IOStatus.UNAVAILABLE) {
285
286
// need calling context when there is security manager as
287
// permission check may be done in a different thread without
288
// any application call frames on the stack
289
PendingFuture<AsynchronousSocketChannel,Object> result = null;
290
synchronized (updateLock) {
291
if (handler == null) {
292
this.acceptHandler = null;
293
result = new PendingFuture<>(this);
294
this.acceptFuture = result;
295
} else {
296
this.acceptHandler = handler;
297
this.acceptAttachment = att;
298
}
299
this.acceptAcc = (System.getSecurityManager() == null) ?
300
null : AccessController.getContext();
301
this.acceptPending = true;
302
}
303
304
// register for connections
305
port.startPoll(fdVal, Net.POLLIN);
306
return result;
307
}
308
} catch (Throwable x) {
309
// accept failed
310
if (x instanceof ClosedChannelException)
311
x = new AsynchronousCloseException();
312
exc = x;
313
} finally {
314
end();
315
}
316
317
AsynchronousSocketChannel child = null;
318
if (exc == null) {
319
// connection accepted immediately
320
try {
321
child = finishAccept(newfd, isaa[0], null);
322
} catch (Throwable x) {
323
exc = x;
324
}
325
}
326
327
// re-enable accepting before invoking handler
328
enableAccept();
329
330
if (handler == null) {
331
return CompletedFuture.withResult(child, exc);
332
} else {
333
Invoker.invokeIndirectly(this, handler, att, child, exc);
334
return null;
335
}
336
}
337
}
338
339