2
* Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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.
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
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.FileDescriptor;
33
import java.io.IOException;
34
import java.security.AccessControlContext;
35
import java.security.AccessController;
36
import java.security.PrivilegedAction;
39
* Windows implementation of AsynchronousServerSocketChannel using overlapped I/O.
42
class WindowsAsynchronousServerSocketChannelImpl
43
extends AsynchronousServerSocketChannelImpl
45
private final Iocp iocp;
47
// flag to indicate that an accept operation is outstanding
48
private AtomicBoolean accepting = new AtomicBoolean();
51
WindowsAsynchronousServerSocketChannelImpl(Iocp iocp) throws IOException {
58
void implClose() throws IOException {
59
// close socket (which may cause outstanding accept to be aborted).
60
SocketDispatcher.closeImpl(fd);
64
public AsynchronousChannelGroupImpl group() {
69
* Task to initiate accept operation and to handle result.
71
private class AcceptTask implements Runnable, Iocp.ResultHandler {
72
private final WindowsAsynchronousSocketChannelImpl channel;
73
private final AccessControlContext acc;
74
private final PendingFuture<AsynchronousSocketChannel,Object> result;
76
AcceptTask(WindowsAsynchronousSocketChannelImpl channel,
77
AccessControlContext acc,
78
PendingFuture<AsynchronousSocketChannel,Object> result)
80
this.channel = channel;
89
void closeChildChannel() {
92
} catch (IOException ignore) { }
95
// caller must have acquired read lock for the listener and child channel.
96
void finishAccept() throws IOException {
98
* Set local/remote addresses. This is currently very inefficient
99
* in that it requires 2 calls to getsockname and 2 calls to getpeername.
100
* (should change this to use GetAcceptExSockaddrs)
102
updateAcceptContext(fd, channel.fd);
104
InetSocketAddress local = Net.localAddress(channel.fd);
105
final InetSocketAddress remote = Net.remoteAddress(channel.fd);
106
channel.setConnected(local, remote);
108
// permission check (in context of initiating thread)
110
AccessController.doPrivileged(new PrivilegedAction<Void>() {
112
SecurityManager sm = System.getSecurityManager();
113
sm.checkAccept(remote.getAddress().getHostAddress(),
122
* Initiates the accept operation.
128
// begin usage of listener socket
131
// begin usage of child socket (as it is registered with
132
// completion port and so may be closed in the event that
133
// the group is forcefully closed).
136
synchronized (result) {
138
int n = accept0(fd, channel.fd, this);
139
if (n == IOStatus.UNAVAILABLE) {
143
// connection accepted immediately
146
// allow another accept before the result is set
148
result.setResult(channel);
151
// end usage on child socket
154
} catch (Throwable x) {
155
// failed to initiate accept so release resources
157
if (x instanceof ClosedChannelException)
158
x = new AsynchronousCloseException();
159
if (!(x instanceof IOException) && !(x instanceof SecurityException))
160
x = new IOException(x);
162
result.setFailure(x);
164
// end of usage of listener socket
168
// accept completed immediately but may not have executed on
169
// initiating thread in which case the operation may have been
171
if (result.isCancelled()) {
175
// invoke completion handler
176
Invoker.invokeIndirectly(result);
180
* Executed when the I/O has completed
183
public void completed(int bytesTransferred, boolean canInvokeDirect) {
185
// connection accept after group has shutdown
186
if (iocp.isShutdown()) {
187
throw new IOException(new ShutdownChannelGroupException());
203
// allow another accept before the result is set
205
result.setResult(channel);
206
} catch (Throwable x) {
209
if (x instanceof ClosedChannelException)
210
x = new AsynchronousCloseException();
211
if (!(x instanceof IOException) && !(x instanceof SecurityException))
212
x = new IOException(x);
213
result.setFailure(x);
216
// if an async cancel has already cancelled the operation then
217
// close the new channel so as to free resources
218
if (result.isCancelled()) {
222
// invoke handler (but not directly)
223
Invoker.invokeIndirectly(result);
227
public void failed(int error, IOException x) {
233
result.setFailure(x);
235
result.setFailure(new AsynchronousCloseException());
237
Invoker.invokeIndirectly(result);
242
Future<AsynchronousSocketChannel> implAccept(Object attachment,
243
final CompletionHandler<AsynchronousSocketChannel,Object> handler)
246
Throwable exc = new ClosedChannelException();
248
return CompletedFuture.withFailure(exc);
249
Invoker.invokeIndirectly(this, handler, attachment, null, exc);
252
if (isAcceptKilled())
253
throw new RuntimeException("Accept not allowed due to cancellation");
255
// ensure channel is bound to local address
256
if (localAddress == null)
257
throw new NotYetBoundException();
259
// create the socket that will be accepted. The creation of the socket
260
// is enclosed by a begin/end for the listener socket to ensure that
261
// we check that the listener is open and also to prevent the I/O
262
// port from being closed as the new socket is registered.
263
WindowsAsynchronousSocketChannelImpl ch = null;
264
IOException ioe = null;
267
ch = new WindowsAsynchronousSocketChannelImpl(iocp, false);
268
} catch (IOException x) {
275
return CompletedFuture.withFailure(ioe);
276
Invoker.invokeIndirectly(this, handler, attachment, null, ioe);
280
// need calling context when there is security manager as
281
// permission check may be done in a different thread without
282
// any application call frames on the stack
283
AccessControlContext acc = (System.getSecurityManager() == null) ?
284
null : AccessController.getContext();
286
PendingFuture<AsynchronousSocketChannel,Object> result =
287
new PendingFuture<AsynchronousSocketChannel,Object>(this, handler, attachment);
288
AcceptTask task = new AcceptTask(ch, acc, result);
289
result.setContext(task);
291
// check and set flag to prevent concurrent accepting
292
if (!accepting.compareAndSet(false, true))
293
throw new AcceptPendingException();
296
if (Iocp.supportsThreadAgnosticIo()) {
299
Invoker.invokeOnThreadInThreadPool(this, task);
304
// -- Native methods --
306
private static native void initIDs();
308
private static native int accept0(FileDescriptor listenSocket, FileDescriptor acceptSocket,
309
Iocp.ResultHandler handler) throws IOException;
311
private static native void updateAcceptContext(FileDescriptor listenSocket,
312
FileDescriptor acceptSocket) throws IOException;
314
private static native void closesocket0(long socket) throws IOException;