Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java
32300 views
1
/*
2
* Copyright (c) 2009, 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
package sun.nio.ch.sctp;
26
27
import java.net.SocketAddress;
28
import java.net.InetSocketAddress;
29
import java.net.InetAddress;
30
import java.io.FileDescriptor;
31
import java.io.IOException;
32
import java.util.Collections;
33
import java.util.Set;
34
import java.util.HashSet;
35
import java.nio.channels.SelectionKey;
36
import java.nio.channels.ClosedChannelException;
37
import java.nio.channels.NotYetBoundException;
38
import java.nio.channels.spi.SelectorProvider;
39
import com.sun.nio.sctp.IllegalUnbindException;
40
import com.sun.nio.sctp.SctpChannel;
41
import com.sun.nio.sctp.SctpServerChannel;
42
import com.sun.nio.sctp.SctpSocketOption;
43
import com.sun.nio.sctp.SctpStandardSocketOptions;
44
import sun.nio.ch.DirectBuffer;
45
import sun.nio.ch.NativeThread;
46
import sun.nio.ch.IOStatus;
47
import sun.nio.ch.IOUtil;
48
import sun.nio.ch.Net;
49
import sun.nio.ch.PollArrayWrapper;
50
import sun.nio.ch.SelChImpl;
51
import sun.nio.ch.SelectionKeyImpl;
52
import sun.nio.ch.Util;
53
54
/**
55
* An implementation of SctpServerChannel
56
*/
57
public class SctpServerChannelImpl extends SctpServerChannel
58
implements SelChImpl
59
{
60
private final FileDescriptor fd;
61
62
private final int fdVal;
63
64
/* IDs of native thread doing accept, for signalling */
65
private volatile long thread = 0;
66
67
/* Lock held by thread currently blocked in this channel */
68
private final Object lock = new Object();
69
70
/* Lock held by any thread that modifies the state fields declared below
71
* DO NOT invoke a blocking I/O operation while holding this lock! */
72
private final Object stateLock = new Object();
73
74
private enum ChannelState {
75
UNINITIALIZED,
76
INUSE,
77
KILLPENDING,
78
KILLED,
79
}
80
/* -- The following fields are protected by stateLock -- */
81
private ChannelState state = ChannelState.UNINITIALIZED;
82
83
/* Binding: Once bound the port will remain constant. */
84
int port = -1;
85
private HashSet<InetSocketAddress> localAddresses = new HashSet<InetSocketAddress>();
86
/* Has the channel been bound to the wildcard address */
87
private boolean wildcard; /* false */
88
89
/* -- End of fields protected by stateLock -- */
90
91
/**
92
* Initializes a new instance of this class.
93
*/
94
public SctpServerChannelImpl(SelectorProvider provider)
95
throws IOException {
96
//TODO: update provider remove public modifier
97
super(provider);
98
this.fd = SctpNet.socket(true);
99
this.fdVal = IOUtil.fdVal(fd);
100
this.state = ChannelState.INUSE;
101
}
102
103
@Override
104
public SctpServerChannel bind(SocketAddress local, int backlog)
105
throws IOException {
106
synchronized (lock) {
107
synchronized (stateLock) {
108
if (!isOpen())
109
throw new ClosedChannelException();
110
if (isBound())
111
SctpNet.throwAlreadyBoundException();
112
113
InetSocketAddress isa = (local == null) ?
114
new InetSocketAddress(0) : Net.checkAddress(local);
115
SecurityManager sm = System.getSecurityManager();
116
if (sm != null)
117
sm.checkListen(isa.getPort());
118
Net.bind(fd, isa.getAddress(), isa.getPort());
119
120
InetSocketAddress boundIsa = Net.localAddress(fd);
121
port = boundIsa.getPort();
122
localAddresses.add(isa);
123
if (isa.getAddress().isAnyLocalAddress())
124
wildcard = true;
125
126
SctpNet.listen(fdVal, backlog < 1 ? 50 : backlog);
127
}
128
}
129
return this;
130
}
131
132
@Override
133
public SctpServerChannel bindAddress(InetAddress address)
134
throws IOException {
135
return bindUnbindAddress(address, true);
136
}
137
138
@Override
139
public SctpServerChannel unbindAddress(InetAddress address)
140
throws IOException {
141
return bindUnbindAddress(address, false);
142
}
143
144
private SctpServerChannel bindUnbindAddress(InetAddress address, boolean add)
145
throws IOException {
146
if (address == null)
147
throw new IllegalArgumentException();
148
149
synchronized (lock) {
150
synchronized (stateLock) {
151
if (!isOpen())
152
throw new ClosedChannelException();
153
if (!isBound())
154
throw new NotYetBoundException();
155
if (wildcard)
156
throw new IllegalStateException(
157
"Cannot add or remove addresses from a channel that is bound to the wildcard address");
158
if (address.isAnyLocalAddress())
159
throw new IllegalArgumentException(
160
"Cannot add or remove the wildcard address");
161
if (add) {
162
for (InetSocketAddress addr : localAddresses) {
163
if (addr.getAddress().equals(address)) {
164
SctpNet.throwAlreadyBoundException();
165
}
166
}
167
} else { /*removing */
168
/* Verify that there is more than one address
169
* and that address is already bound */
170
if (localAddresses.size() <= 1)
171
throw new IllegalUnbindException("Cannot remove address from a channel with only one address bound");
172
boolean foundAddress = false;
173
for (InetSocketAddress addr : localAddresses) {
174
if (addr.getAddress().equals(address)) {
175
foundAddress = true;
176
break;
177
}
178
}
179
if (!foundAddress )
180
throw new IllegalUnbindException("Cannot remove address from a channel that is not bound to that address");
181
}
182
183
SctpNet.bindx(fdVal, new InetAddress[]{address}, port, add);
184
185
/* Update our internal Set to reflect the addition/removal */
186
if (add)
187
localAddresses.add(new InetSocketAddress(address, port));
188
else {
189
for (InetSocketAddress addr : localAddresses) {
190
if (addr.getAddress().equals(address)) {
191
localAddresses.remove(addr);
192
break;
193
}
194
}
195
}
196
}
197
}
198
return this;
199
}
200
201
private boolean isBound() {
202
synchronized (stateLock) {
203
return port == -1 ? false : true;
204
}
205
}
206
207
private void acceptCleanup() throws IOException {
208
synchronized (stateLock) {
209
thread = 0;
210
if (state == ChannelState.KILLPENDING)
211
kill();
212
}
213
}
214
215
@Override
216
public SctpChannel accept() throws IOException {
217
synchronized (lock) {
218
if (!isOpen())
219
throw new ClosedChannelException();
220
if (!isBound())
221
throw new NotYetBoundException();
222
SctpChannel sc = null;
223
224
int n = 0;
225
FileDescriptor newfd = new FileDescriptor();
226
InetSocketAddress[] isaa = new InetSocketAddress[1];
227
228
try {
229
begin();
230
if (!isOpen())
231
return null;
232
thread = NativeThread.current();
233
for (;;) {
234
n = accept0(fd, newfd, isaa);
235
if ((n == IOStatus.INTERRUPTED) && isOpen())
236
continue;
237
break;
238
}
239
} finally {
240
acceptCleanup();
241
end(n > 0);
242
assert IOStatus.check(n);
243
}
244
245
if (n < 1)
246
return null;
247
248
IOUtil.configureBlocking(newfd, true);
249
InetSocketAddress isa = isaa[0];
250
sc = new SctpChannelImpl(provider(), newfd);
251
252
SecurityManager sm = System.getSecurityManager();
253
if (sm != null)
254
sm.checkAccept(isa.getAddress().getHostAddress(),
255
isa.getPort());
256
257
return sc;
258
}
259
}
260
261
@Override
262
protected void implConfigureBlocking(boolean block) throws IOException {
263
IOUtil.configureBlocking(fd, block);
264
}
265
266
@Override
267
public void implCloseSelectableChannel() throws IOException {
268
synchronized (stateLock) {
269
SctpNet.preClose(fdVal);
270
if (thread != 0)
271
NativeThread.signal(thread);
272
if (!isRegistered())
273
kill();
274
}
275
}
276
277
@Override
278
public void kill() throws IOException {
279
synchronized (stateLock) {
280
if (state == ChannelState.KILLED)
281
return;
282
if (state == ChannelState.UNINITIALIZED) {
283
state = ChannelState.KILLED;
284
return;
285
}
286
assert !isOpen() && !isRegistered();
287
288
// Postpone the kill if there is a thread in accept
289
if (thread == 0) {
290
SctpNet.close(fdVal);
291
state = ChannelState.KILLED;
292
} else {
293
state = ChannelState.KILLPENDING;
294
}
295
}
296
}
297
298
@Override
299
public FileDescriptor getFD() {
300
return fd;
301
}
302
303
@Override
304
public int getFDVal() {
305
return fdVal;
306
}
307
308
/**
309
* Translates native poll revent ops into a ready operation ops
310
*/
311
private boolean translateReadyOps(int ops, int initialOps,
312
SelectionKeyImpl sk) {
313
int intOps = sk.nioInterestOps();
314
int oldOps = sk.nioReadyOps();
315
int newOps = initialOps;
316
317
if ((ops & Net.POLLNVAL) != 0) {
318
/* This should only happen if this channel is pre-closed while a
319
* selection operation is in progress
320
* ## Throw an error if this channel has not been pre-closed */
321
return false;
322
}
323
324
if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) {
325
newOps = intOps;
326
sk.nioReadyOps(newOps);
327
return (newOps & ~oldOps) != 0;
328
}
329
330
if (((ops & Net.POLLIN) != 0) &&
331
((intOps & SelectionKey.OP_ACCEPT) != 0))
332
newOps |= SelectionKey.OP_ACCEPT;
333
334
sk.nioReadyOps(newOps);
335
return (newOps & ~oldOps) != 0;
336
}
337
338
@Override
339
public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl sk) {
340
return translateReadyOps(ops, sk.nioReadyOps(), sk);
341
}
342
343
@Override
344
public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl sk) {
345
return translateReadyOps(ops, 0, sk);
346
}
347
348
@Override
349
public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) {
350
int newOps = 0;
351
352
/* Translate ops */
353
if ((ops & SelectionKey.OP_ACCEPT) != 0)
354
newOps |= Net.POLLIN;
355
/* Place ops into pollfd array */
356
sk.selector.putEventOps(sk, newOps);
357
358
}
359
360
@Override
361
public <T> SctpServerChannel setOption(SctpSocketOption<T> name, T value)
362
throws IOException {
363
if (name == null)
364
throw new NullPointerException();
365
if (!supportedOptions().contains(name))
366
throw new UnsupportedOperationException("'" + name + "' not supported");
367
368
synchronized (stateLock) {
369
if (!isOpen())
370
throw new ClosedChannelException();
371
372
SctpNet.setSocketOption(fdVal, name, value, 0 /*oneToOne*/);
373
return this;
374
}
375
}
376
377
@Override
378
@SuppressWarnings("unchecked")
379
public <T> T getOption(SctpSocketOption<T> name) throws IOException {
380
if (name == null)
381
throw new NullPointerException();
382
if (!supportedOptions().contains(name))
383
throw new UnsupportedOperationException("'" + name + "' not supported");
384
385
synchronized (stateLock) {
386
if (!isOpen())
387
throw new ClosedChannelException();
388
389
return (T) SctpNet.getSocketOption(fdVal, name, 0 /*oneToOne*/);
390
}
391
}
392
393
private static class DefaultOptionsHolder {
394
static final Set<SctpSocketOption<?>> defaultOptions = defaultOptions();
395
396
private static Set<SctpSocketOption<?>> defaultOptions() {
397
HashSet<SctpSocketOption<?>> set = new HashSet<SctpSocketOption<?>>(1);
398
set.add(SctpStandardSocketOptions.SCTP_INIT_MAXSTREAMS);
399
return Collections.unmodifiableSet(set);
400
}
401
}
402
403
@Override
404
public final Set<SctpSocketOption<?>> supportedOptions() {
405
return DefaultOptionsHolder.defaultOptions;
406
}
407
408
@Override
409
public Set<SocketAddress> getAllLocalAddresses()
410
throws IOException {
411
synchronized (stateLock) {
412
if (!isOpen())
413
throw new ClosedChannelException();
414
if (!isBound())
415
return Collections.emptySet();
416
417
return SctpNet.getLocalAddresses(fdVal);
418
}
419
}
420
421
/* Native */
422
private static native void initIDs();
423
424
private static native int accept0(FileDescriptor ssfd,
425
FileDescriptor newfd, InetSocketAddress[] isaa) throws IOException;
426
427
static {
428
IOUtil.load(); // loads nio & net native libraries
429
java.security.AccessController.doPrivileged(
430
new java.security.PrivilegedAction<Void>() {
431
public Void run() {
432
System.loadLibrary("sctp");
433
return null;
434
}
435
});
436
initIDs();
437
}
438
}
439
440