Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java
38918 views
1
/*
2
* Copyright (c) 2000, 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.io.FileDescriptor;
29
import java.io.IOException;
30
import java.net.*;
31
import java.nio.channels.*;
32
import java.nio.channels.spi.*;
33
import java.util.*;
34
import sun.net.NetHooks;
35
import sun.net.ExtendedOptionsHelper;
36
37
38
/**
39
* An implementation of ServerSocketChannels
40
*/
41
42
class ServerSocketChannelImpl
43
extends ServerSocketChannel
44
implements SelChImpl
45
{
46
47
// Used to make native close and configure calls
48
private static NativeDispatcher nd;
49
50
// Our file descriptor
51
private final FileDescriptor fd;
52
private final int fdVal;
53
54
// ID of native thread currently blocked in this channel, for signalling
55
private volatile long thread = 0;
56
57
// Lock held by thread currently blocked in this channel
58
private final Object lock = new Object();
59
60
// Lock held by any thread that modifies the state fields declared below
61
// DO NOT invoke a blocking I/O operation while holding this lock!
62
private final Object stateLock = new Object();
63
64
// -- The following fields are protected by stateLock
65
66
// Channel state, increases monotonically
67
private static final int ST_UNINITIALIZED = -1;
68
private static final int ST_INUSE = 0;
69
private static final int ST_KILLED = 1;
70
private int state = ST_UNINITIALIZED;
71
72
// Binding
73
private InetSocketAddress localAddress; // null => unbound
74
75
// set true when exclusive binding is on and SO_REUSEADDR is emulated
76
private boolean isReuseAddress;
77
78
// Our socket adaptor, if any
79
ServerSocket socket;
80
81
// -- End of fields protected by stateLock
82
83
84
ServerSocketChannelImpl(SelectorProvider sp) throws IOException {
85
super(sp);
86
this.fd = Net.serverSocket(true);
87
this.fdVal = IOUtil.fdVal(fd);
88
this.state = ST_INUSE;
89
}
90
91
ServerSocketChannelImpl(SelectorProvider sp,
92
FileDescriptor fd,
93
boolean bound)
94
throws IOException
95
{
96
super(sp);
97
this.fd = fd;
98
this.fdVal = IOUtil.fdVal(fd);
99
this.state = ST_INUSE;
100
if (bound)
101
localAddress = Net.localAddress(fd);
102
}
103
104
public ServerSocket socket() {
105
synchronized (stateLock) {
106
if (socket == null)
107
socket = ServerSocketAdaptor.create(this);
108
return socket;
109
}
110
}
111
112
@Override
113
public SocketAddress getLocalAddress() throws IOException {
114
synchronized (stateLock) {
115
if (!isOpen())
116
throw new ClosedChannelException();
117
return localAddress == null ? localAddress
118
: Net.getRevealedLocalAddress(
119
Net.asInetSocketAddress(localAddress));
120
}
121
}
122
123
@Override
124
public <T> ServerSocketChannel setOption(SocketOption<T> name, T value)
125
throws IOException
126
{
127
if (name == null)
128
throw new NullPointerException();
129
if (!supportedOptions().contains(name))
130
throw new UnsupportedOperationException("'" + name + "' not supported");
131
synchronized (stateLock) {
132
if (!isOpen())
133
throw new ClosedChannelException();
134
135
if (name == StandardSocketOptions.IP_TOS) {
136
ProtocolFamily family = Net.isIPv6Available() ?
137
StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
138
Net.setSocketOption(fd, family, name, value);
139
return this;
140
}
141
142
if (name == StandardSocketOptions.SO_REUSEADDR &&
143
Net.useExclusiveBind())
144
{
145
// SO_REUSEADDR emulated when using exclusive bind
146
isReuseAddress = (Boolean)value;
147
} else {
148
// no options that require special handling
149
Net.setSocketOption(fd, Net.UNSPEC, name, value);
150
}
151
return this;
152
}
153
}
154
155
@Override
156
@SuppressWarnings("unchecked")
157
public <T> T getOption(SocketOption<T> name)
158
throws IOException
159
{
160
if (name == null)
161
throw new NullPointerException();
162
if (!supportedOptions().contains(name))
163
throw new UnsupportedOperationException("'" + name + "' not supported");
164
165
synchronized (stateLock) {
166
if (!isOpen())
167
throw new ClosedChannelException();
168
if (name == StandardSocketOptions.SO_REUSEADDR &&
169
Net.useExclusiveBind())
170
{
171
// SO_REUSEADDR emulated when using exclusive bind
172
return (T)Boolean.valueOf(isReuseAddress);
173
}
174
// no options that require special handling
175
return (T) Net.getSocketOption(fd, Net.UNSPEC, name);
176
}
177
}
178
179
private static class DefaultOptionsHolder {
180
static final Set<SocketOption<?>> defaultOptions = defaultOptions();
181
182
private static Set<SocketOption<?>> defaultOptions() {
183
HashSet<SocketOption<?>> set = new HashSet<SocketOption<?>>(2);
184
set.add(StandardSocketOptions.SO_RCVBUF);
185
set.add(StandardSocketOptions.SO_REUSEADDR);
186
set.add(StandardSocketOptions.IP_TOS);
187
set.addAll(ExtendedOptionsHelper.keepAliveOptions());
188
return Collections.unmodifiableSet(set);
189
}
190
}
191
192
@Override
193
public final Set<SocketOption<?>> supportedOptions() {
194
return DefaultOptionsHolder.defaultOptions;
195
}
196
197
public boolean isBound() {
198
synchronized (stateLock) {
199
return localAddress != null;
200
}
201
}
202
203
public InetSocketAddress localAddress() {
204
synchronized (stateLock) {
205
return localAddress;
206
}
207
}
208
209
@Override
210
public ServerSocketChannel bind(SocketAddress local, int backlog) throws IOException {
211
synchronized (lock) {
212
if (!isOpen())
213
throw new ClosedChannelException();
214
if (isBound())
215
throw new AlreadyBoundException();
216
InetSocketAddress isa = (local == null) ? new InetSocketAddress(0) :
217
Net.checkAddress(local);
218
SecurityManager sm = System.getSecurityManager();
219
if (sm != null)
220
sm.checkListen(isa.getPort());
221
NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort());
222
Net.bind(fd, isa.getAddress(), isa.getPort());
223
Net.listen(fd, backlog < 1 ? 50 : backlog);
224
synchronized (stateLock) {
225
localAddress = Net.localAddress(fd);
226
}
227
}
228
return this;
229
}
230
231
public SocketChannel accept() throws IOException {
232
synchronized (lock) {
233
if (!isOpen())
234
throw new ClosedChannelException();
235
if (!isBound())
236
throw new NotYetBoundException();
237
SocketChannel sc = null;
238
239
int n = 0;
240
FileDescriptor newfd = new FileDescriptor();
241
InetSocketAddress[] isaa = new InetSocketAddress[1];
242
243
try {
244
begin();
245
if (!isOpen())
246
return null;
247
thread = NativeThread.current();
248
for (;;) {
249
n = accept(this.fd, newfd, isaa);
250
if ((n == IOStatus.INTERRUPTED) && isOpen())
251
continue;
252
break;
253
}
254
} finally {
255
thread = 0;
256
end(n > 0);
257
assert IOStatus.check(n);
258
}
259
260
if (n < 1)
261
return null;
262
263
IOUtil.configureBlocking(newfd, true);
264
InetSocketAddress isa = isaa[0];
265
sc = new SocketChannelImpl(provider(), newfd, isa);
266
SecurityManager sm = System.getSecurityManager();
267
if (sm != null) {
268
try {
269
sm.checkAccept(isa.getAddress().getHostAddress(),
270
isa.getPort());
271
} catch (SecurityException x) {
272
sc.close();
273
throw x;
274
}
275
}
276
return sc;
277
278
}
279
}
280
281
protected void implConfigureBlocking(boolean block) throws IOException {
282
IOUtil.configureBlocking(fd, block);
283
}
284
285
protected void implCloseSelectableChannel() throws IOException {
286
synchronized (stateLock) {
287
if (state != ST_KILLED)
288
nd.preClose(fd);
289
long th = thread;
290
if (th != 0)
291
NativeThread.signal(th);
292
if (!isRegistered())
293
kill();
294
}
295
}
296
297
public void kill() throws IOException {
298
synchronized (stateLock) {
299
if (state == ST_KILLED)
300
return;
301
if (state == ST_UNINITIALIZED) {
302
state = ST_KILLED;
303
return;
304
}
305
assert !isOpen() && !isRegistered();
306
nd.close(fd);
307
state = ST_KILLED;
308
}
309
}
310
311
/**
312
* Translates native poll revent set into a ready operation set
313
*/
314
public boolean translateReadyOps(int ops, int initialOps,
315
SelectionKeyImpl sk) {
316
int intOps = sk.nioInterestOps(); // Do this just once, it synchronizes
317
int oldOps = sk.nioReadyOps();
318
int newOps = initialOps;
319
320
if ((ops & Net.POLLNVAL) != 0) {
321
// This should only happen if this channel is pre-closed while a
322
// selection operation is in progress
323
// ## Throw an error if this channel has not been pre-closed
324
return false;
325
}
326
327
if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) {
328
newOps = intOps;
329
sk.nioReadyOps(newOps);
330
return (newOps & ~oldOps) != 0;
331
}
332
333
if (((ops & Net.POLLIN) != 0) &&
334
((intOps & SelectionKey.OP_ACCEPT) != 0))
335
newOps |= SelectionKey.OP_ACCEPT;
336
337
sk.nioReadyOps(newOps);
338
return (newOps & ~oldOps) != 0;
339
}
340
341
public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl sk) {
342
return translateReadyOps(ops, sk.nioReadyOps(), sk);
343
}
344
345
public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl sk) {
346
return translateReadyOps(ops, 0, sk);
347
}
348
349
// package-private
350
int poll(int events, long timeout) throws IOException {
351
assert Thread.holdsLock(blockingLock()) && !isBlocking();
352
353
synchronized (lock) {
354
int n = 0;
355
try {
356
begin();
357
synchronized (stateLock) {
358
if (!isOpen())
359
return 0;
360
thread = NativeThread.current();
361
}
362
n = Net.poll(fd, events, timeout);
363
} finally {
364
thread = 0;
365
end(n > 0);
366
}
367
return n;
368
}
369
}
370
371
/**
372
* Translates an interest operation set into a native poll event set
373
*/
374
public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) {
375
int newOps = 0;
376
377
// Translate ops
378
if ((ops & SelectionKey.OP_ACCEPT) != 0)
379
newOps |= Net.POLLIN;
380
// Place ops into pollfd array
381
sk.selector.putEventOps(sk, newOps);
382
}
383
384
public FileDescriptor getFD() {
385
return fd;
386
}
387
388
public int getFDVal() {
389
return fdVal;
390
}
391
392
public String toString() {
393
StringBuffer sb = new StringBuffer();
394
sb.append(this.getClass().getName());
395
sb.append('[');
396
if (!isOpen()) {
397
sb.append("closed");
398
} else {
399
synchronized (stateLock) {
400
InetSocketAddress addr = localAddress();
401
if (addr == null) {
402
sb.append("unbound");
403
} else {
404
sb.append(Net.getRevealedLocalAddressAsString(addr));
405
}
406
}
407
}
408
sb.append(']');
409
return sb.toString();
410
}
411
412
/**
413
* Accept a connection on a socket.
414
*
415
* @implNote Wrap native call to allow instrumentation.
416
*/
417
private int accept(FileDescriptor ssfd, FileDescriptor newfd,
418
InetSocketAddress[] isaa)
419
throws IOException
420
{
421
return accept0(ssfd, newfd, isaa);
422
}
423
424
// -- Native methods --
425
426
// Accepts a new connection, setting the given file descriptor to refer to
427
// the new socket and setting isaa[0] to the socket's remote address.
428
// Returns 1 on success, or IOStatus.UNAVAILABLE (if non-blocking and no
429
// connections are pending) or IOStatus.INTERRUPTED.
430
//
431
private native int accept0(FileDescriptor ssfd, FileDescriptor newfd,
432
InetSocketAddress[] isaa)
433
throws IOException;
434
435
private static native void initIDs();
436
437
static {
438
IOUtil.load();
439
initIDs();
440
nd = new SocketDispatcher();
441
}
442
443
}
444
445