Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java
32288 views
1
/*
2
* Copyright (c) 2008, 2013, 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.net.InetSocketAddress;
30
import java.util.concurrent.Future;
31
import java.util.concurrent.atomic.AtomicBoolean;
32
import java.io.IOException;
33
import java.security.AccessControlContext;
34
import java.security.AccessController;
35
import java.security.PrivilegedAction;
36
import sun.misc.Unsafe;
37
38
/**
39
* Windows implementation of AsynchronousServerSocketChannel using overlapped I/O.
40
*/
41
42
class WindowsAsynchronousServerSocketChannelImpl
43
extends AsynchronousServerSocketChannelImpl implements Iocp.OverlappedChannel
44
{
45
private static final Unsafe unsafe = Unsafe.getUnsafe();
46
47
// 2 * (sizeof(SOCKET_ADDRESS) + 16)
48
private static final int DATA_BUFFER_SIZE = 88;
49
50
private final long handle;
51
private final int completionKey;
52
private final Iocp iocp;
53
54
// typically there will be zero, or one I/O operations pending. In rare
55
// cases there may be more. These rare cases arise when a sequence of accept
56
// operations complete immediately and handled by the initiating thread.
57
// The corresponding OVERLAPPED cannot be reused/released until the completion
58
// event has been posted.
59
private final PendingIoCache ioCache;
60
61
// the data buffer to receive the local/remote socket address
62
private final long dataBuffer;
63
64
// flag to indicate that an accept operation is outstanding
65
private AtomicBoolean accepting = new AtomicBoolean();
66
67
68
WindowsAsynchronousServerSocketChannelImpl(Iocp iocp) throws IOException {
69
super(iocp);
70
71
// associate socket with given completion port
72
long h = IOUtil.fdVal(fd);
73
int key;
74
try {
75
key = iocp.associate(this, h);
76
} catch (IOException x) {
77
closesocket0(h); // prevent leak
78
throw x;
79
}
80
81
this.handle = h;
82
this.completionKey = key;
83
this.iocp = iocp;
84
this.ioCache = new PendingIoCache();
85
this.dataBuffer = unsafe.allocateMemory(DATA_BUFFER_SIZE);
86
}
87
88
@Override
89
public <V,A> PendingFuture<V,A> getByOverlapped(long overlapped) {
90
return ioCache.remove(overlapped);
91
}
92
93
@Override
94
void implClose() throws IOException {
95
// close socket (which may cause outstanding accept to be aborted).
96
closesocket0(handle);
97
98
// waits until the accept operations have completed
99
ioCache.close();
100
101
// finally disassociate from the completion port
102
iocp.disassociate(completionKey);
103
104
// release other resources
105
unsafe.freeMemory(dataBuffer);
106
}
107
108
@Override
109
public AsynchronousChannelGroupImpl group() {
110
return iocp;
111
}
112
113
/**
114
* Task to initiate accept operation and to handle result.
115
*/
116
private class AcceptTask implements Runnable, Iocp.ResultHandler {
117
private final WindowsAsynchronousSocketChannelImpl channel;
118
private final AccessControlContext acc;
119
private final PendingFuture<AsynchronousSocketChannel,Object> result;
120
121
AcceptTask(WindowsAsynchronousSocketChannelImpl channel,
122
AccessControlContext acc,
123
PendingFuture<AsynchronousSocketChannel,Object> result)
124
{
125
this.channel = channel;
126
this.acc = acc;
127
this.result = result;
128
}
129
130
void enableAccept() {
131
accepting.set(false);
132
}
133
134
void closeChildChannel() {
135
try {
136
channel.close();
137
} catch (IOException ignore) { }
138
}
139
140
// caller must have acquired read lock for the listener and child channel.
141
void finishAccept() throws IOException {
142
/**
143
* Set local/remote addresses. This is currently very inefficient
144
* in that it requires 2 calls to getsockname and 2 calls to getpeername.
145
* (should change this to use GetAcceptExSockaddrs)
146
*/
147
updateAcceptContext(handle, channel.handle());
148
149
InetSocketAddress local = Net.localAddress(channel.fd);
150
final InetSocketAddress remote = Net.remoteAddress(channel.fd);
151
channel.setConnected(local, remote);
152
153
// permission check (in context of initiating thread)
154
if (acc != null) {
155
AccessController.doPrivileged(new PrivilegedAction<Void>() {
156
public Void run() {
157
SecurityManager sm = System.getSecurityManager();
158
sm.checkAccept(remote.getAddress().getHostAddress(),
159
remote.getPort());
160
return null;
161
}
162
}, acc);
163
}
164
}
165
166
/**
167
* Initiates the accept operation.
168
*/
169
@Override
170
public void run() {
171
long overlapped = 0L;
172
173
try {
174
// begin usage of listener socket
175
begin();
176
try {
177
// begin usage of child socket (as it is registered with
178
// completion port and so may be closed in the event that
179
// the group is forcefully closed).
180
channel.begin();
181
182
synchronized (result) {
183
overlapped = ioCache.add(result);
184
185
int n = accept0(handle, channel.handle(), overlapped, dataBuffer);
186
if (n == IOStatus.UNAVAILABLE) {
187
return;
188
}
189
190
// connection accepted immediately
191
finishAccept();
192
193
// allow another accept before the result is set
194
enableAccept();
195
result.setResult(channel);
196
}
197
} finally {
198
// end usage on child socket
199
channel.end();
200
}
201
} catch (Throwable x) {
202
// failed to initiate accept so release resources
203
if (overlapped != 0L)
204
ioCache.remove(overlapped);
205
closeChildChannel();
206
if (x instanceof ClosedChannelException)
207
x = new AsynchronousCloseException();
208
if (!(x instanceof IOException) && !(x instanceof SecurityException))
209
x = new IOException(x);
210
enableAccept();
211
result.setFailure(x);
212
} finally {
213
// end of usage of listener socket
214
end();
215
}
216
217
// accept completed immediately but may not have executed on
218
// initiating thread in which case the operation may have been
219
// cancelled.
220
if (result.isCancelled()) {
221
closeChildChannel();
222
}
223
224
// invoke completion handler
225
Invoker.invokeIndirectly(result);
226
}
227
228
/**
229
* Executed when the I/O has completed
230
*/
231
@Override
232
public void completed(int bytesTransferred, boolean canInvokeDirect) {
233
try {
234
// connection accept after group has shutdown
235
if (iocp.isShutdown()) {
236
throw new IOException(new ShutdownChannelGroupException());
237
}
238
239
// finish the accept
240
try {
241
begin();
242
try {
243
channel.begin();
244
finishAccept();
245
} finally {
246
channel.end();
247
}
248
} finally {
249
end();
250
}
251
252
// allow another accept before the result is set
253
enableAccept();
254
result.setResult(channel);
255
} catch (Throwable x) {
256
enableAccept();
257
closeChildChannel();
258
if (x instanceof ClosedChannelException)
259
x = new AsynchronousCloseException();
260
if (!(x instanceof IOException) && !(x instanceof SecurityException))
261
x = new IOException(x);
262
result.setFailure(x);
263
}
264
265
// if an async cancel has already cancelled the operation then
266
// close the new channel so as to free resources
267
if (result.isCancelled()) {
268
closeChildChannel();
269
}
270
271
// invoke handler (but not directly)
272
Invoker.invokeIndirectly(result);
273
}
274
275
@Override
276
public void failed(int error, IOException x) {
277
enableAccept();
278
closeChildChannel();
279
280
// release waiters
281
if (isOpen()) {
282
result.setFailure(x);
283
} else {
284
result.setFailure(new AsynchronousCloseException());
285
}
286
Invoker.invokeIndirectly(result);
287
}
288
}
289
290
@Override
291
Future<AsynchronousSocketChannel> implAccept(Object attachment,
292
final CompletionHandler<AsynchronousSocketChannel,Object> handler)
293
{
294
if (!isOpen()) {
295
Throwable exc = new ClosedChannelException();
296
if (handler == null)
297
return CompletedFuture.withFailure(exc);
298
Invoker.invokeIndirectly(this, handler, attachment, null, exc);
299
return null;
300
}
301
if (isAcceptKilled())
302
throw new RuntimeException("Accept not allowed due to cancellation");
303
304
// ensure channel is bound to local address
305
if (localAddress == null)
306
throw new NotYetBoundException();
307
308
// create the socket that will be accepted. The creation of the socket
309
// is enclosed by a begin/end for the listener socket to ensure that
310
// we check that the listener is open and also to prevent the I/O
311
// port from being closed as the new socket is registered.
312
WindowsAsynchronousSocketChannelImpl ch = null;
313
IOException ioe = null;
314
try {
315
begin();
316
ch = new WindowsAsynchronousSocketChannelImpl(iocp, false);
317
} catch (IOException x) {
318
ioe = x;
319
} finally {
320
end();
321
}
322
if (ioe != null) {
323
if (handler == null)
324
return CompletedFuture.withFailure(ioe);
325
Invoker.invokeIndirectly(this, handler, attachment, null, ioe);
326
return null;
327
}
328
329
// need calling context when there is security manager as
330
// permission check may be done in a different thread without
331
// any application call frames on the stack
332
AccessControlContext acc = (System.getSecurityManager() == null) ?
333
null : AccessController.getContext();
334
335
PendingFuture<AsynchronousSocketChannel,Object> result =
336
new PendingFuture<AsynchronousSocketChannel,Object>(this, handler, attachment);
337
AcceptTask task = new AcceptTask(ch, acc, result);
338
result.setContext(task);
339
340
// check and set flag to prevent concurrent accepting
341
if (!accepting.compareAndSet(false, true))
342
throw new AcceptPendingException();
343
344
// initiate I/O
345
if (Iocp.supportsThreadAgnosticIo()) {
346
task.run();
347
} else {
348
Invoker.invokeOnThreadInThreadPool(this, task);
349
}
350
return result;
351
}
352
353
// -- Native methods --
354
355
private static native void initIDs();
356
357
private static native int accept0(long listenSocket, long acceptSocket,
358
long overlapped, long dataBuffer) throws IOException;
359
360
private static native void updateAcceptContext(long listenSocket,
361
long acceptSocket) throws IOException;
362
363
private static native void closesocket0(long socket) throws IOException;
364
365
static {
366
IOUtil.load();
367
initIDs();
368
}
369
}
370
371