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/AsynchronousSocketChannelImpl.java
38918 views
1
/*
2
* Copyright (c) 2008, 2018, 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.ByteBuffer;
29
import java.nio.channels.*;
30
import java.net.SocketOption;
31
import java.net.StandardSocketOptions;
32
import java.net.SocketAddress;
33
import java.net.InetSocketAddress;
34
import java.io.IOException;
35
import java.io.FileDescriptor;
36
import java.util.Set;
37
import java.util.HashSet;
38
import java.util.Collections;
39
import java.util.concurrent.*;
40
import java.util.concurrent.locks.*;
41
import sun.net.NetHooks;
42
import sun.net.ExtendedOptionsImpl;
43
import sun.net.ExtendedOptionsHelper;
44
45
/**
46
* Base implementation of AsynchronousSocketChannel
47
*/
48
49
abstract class AsynchronousSocketChannelImpl
50
extends AsynchronousSocketChannel
51
implements Cancellable, Groupable
52
{
53
protected final FileDescriptor fd;
54
55
// protects state, localAddress, and remoteAddress
56
protected final Object stateLock = new Object();
57
58
protected volatile InetSocketAddress localAddress = null;
59
protected volatile InetSocketAddress remoteAddress = null;
60
61
// State, increases monotonically
62
static final int ST_UNINITIALIZED = -1;
63
static final int ST_UNCONNECTED = 0;
64
static final int ST_PENDING = 1;
65
static final int ST_CONNECTED = 2;
66
protected volatile int state = ST_UNINITIALIZED;
67
68
// reading state
69
private final Object readLock = new Object();
70
private boolean reading;
71
private boolean readShutdown;
72
private boolean readKilled; // further reading disallowed due to timeout
73
74
// writing state
75
private final Object writeLock = new Object();
76
private boolean writing;
77
private boolean writeShutdown;
78
private boolean writeKilled; // further writing disallowed due to timeout
79
80
// close support
81
private final ReadWriteLock closeLock = new ReentrantReadWriteLock();
82
private volatile boolean open = true;
83
84
// set true when exclusive binding is on and SO_REUSEADDR is emulated
85
private boolean isReuseAddress;
86
87
AsynchronousSocketChannelImpl(AsynchronousChannelGroupImpl group)
88
throws IOException
89
{
90
super(group.provider());
91
this.fd = Net.socket(true);
92
this.state = ST_UNCONNECTED;
93
}
94
95
// Constructor for sockets obtained from AsynchronousServerSocketChannelImpl
96
AsynchronousSocketChannelImpl(AsynchronousChannelGroupImpl group,
97
FileDescriptor fd,
98
InetSocketAddress remote)
99
throws IOException
100
{
101
super(group.provider());
102
this.fd = fd;
103
this.state = ST_CONNECTED;
104
this.localAddress = Net.localAddress(fd);
105
this.remoteAddress = remote;
106
}
107
108
@Override
109
public final boolean isOpen() {
110
return open;
111
}
112
113
/**
114
* Marks beginning of access to file descriptor/handle
115
*/
116
final void begin() throws IOException {
117
closeLock.readLock().lock();
118
if (!isOpen())
119
throw new ClosedChannelException();
120
}
121
122
/**
123
* Marks end of access to file descriptor/handle
124
*/
125
final void end() {
126
closeLock.readLock().unlock();
127
}
128
129
/**
130
* Invoked to close socket and release other resources.
131
*/
132
abstract void implClose() throws IOException;
133
134
@Override
135
public final void close() throws IOException {
136
// synchronize with any threads initiating asynchronous operations
137
closeLock.writeLock().lock();
138
try {
139
if (!open)
140
return; // already closed
141
open = false;
142
} finally {
143
closeLock.writeLock().unlock();
144
}
145
implClose();
146
}
147
148
final void enableReading(boolean killed) {
149
synchronized (readLock) {
150
reading = false;
151
if (killed)
152
readKilled = true;
153
}
154
}
155
156
final void enableReading() {
157
enableReading(false);
158
}
159
160
final void enableWriting(boolean killed) {
161
synchronized (writeLock) {
162
writing = false;
163
if (killed)
164
writeKilled = true;
165
}
166
}
167
168
final void enableWriting() {
169
enableWriting(false);
170
}
171
172
final void killReading() {
173
synchronized (readLock) {
174
readKilled = true;
175
}
176
}
177
178
final void killWriting() {
179
synchronized (writeLock) {
180
writeKilled = true;
181
}
182
}
183
184
final void killConnect() {
185
// when a connect is cancelled then the connection may have been
186
// established so prevent reading or writing.
187
killReading();
188
killWriting();
189
}
190
191
/**
192
* Invoked by connect to initiate the connect operation.
193
*/
194
abstract <A> Future<Void> implConnect(SocketAddress remote,
195
A attachment,
196
CompletionHandler<Void,? super A> handler);
197
198
@Override
199
public final Future<Void> connect(SocketAddress remote) {
200
return implConnect(remote, null, null);
201
}
202
203
@Override
204
public final <A> void connect(SocketAddress remote,
205
A attachment,
206
CompletionHandler<Void,? super A> handler)
207
{
208
if (handler == null)
209
throw new NullPointerException("'handler' is null");
210
implConnect(remote, attachment, handler);
211
}
212
213
/**
214
* Invoked by read to initiate the I/O operation.
215
*/
216
abstract <V extends Number,A> Future<V> implRead(boolean isScatteringRead,
217
ByteBuffer dst,
218
ByteBuffer[] dsts,
219
long timeout,
220
TimeUnit unit,
221
A attachment,
222
CompletionHandler<V,? super A> handler);
223
224
@SuppressWarnings("unchecked")
225
private <V extends Number,A> Future<V> read(boolean isScatteringRead,
226
ByteBuffer dst,
227
ByteBuffer[] dsts,
228
long timeout,
229
TimeUnit unit,
230
A att,
231
CompletionHandler<V,? super A> handler)
232
{
233
if (!isOpen()) {
234
Throwable e = new ClosedChannelException();
235
if (handler == null)
236
return CompletedFuture.withFailure(e);
237
Invoker.invoke(this, handler, att, null, e);
238
return null;
239
}
240
241
if (remoteAddress == null)
242
throw new NotYetConnectedException();
243
244
boolean hasSpaceToRead = isScatteringRead || dst.hasRemaining();
245
boolean shutdown = false;
246
247
// check and update state
248
synchronized (readLock) {
249
if (readKilled)
250
throw new IllegalStateException("Reading not allowed due to timeout or cancellation");
251
if (reading)
252
throw new ReadPendingException();
253
if (readShutdown) {
254
shutdown = true;
255
} else {
256
if (hasSpaceToRead) {
257
reading = true;
258
}
259
}
260
}
261
262
// immediately complete with -1 if shutdown for read
263
// immediately complete with 0 if no space remaining
264
if (shutdown || !hasSpaceToRead) {
265
Number result;
266
if (isScatteringRead) {
267
result = (shutdown) ? Long.valueOf(-1L) : Long.valueOf(0L);
268
} else {
269
result = (shutdown) ? -1 : 0;
270
}
271
if (handler == null)
272
return CompletedFuture.withResult((V)result);
273
Invoker.invoke(this, handler, att, (V)result, null);
274
return null;
275
}
276
277
return implRead(isScatteringRead, dst, dsts, timeout, unit, att, handler);
278
}
279
280
@Override
281
public final Future<Integer> read(ByteBuffer dst) {
282
if (dst.isReadOnly())
283
throw new IllegalArgumentException("Read-only buffer");
284
return read(false, dst, null, 0L, TimeUnit.MILLISECONDS, null, null);
285
}
286
287
@Override
288
public final <A> void read(ByteBuffer dst,
289
long timeout,
290
TimeUnit unit,
291
A attachment,
292
CompletionHandler<Integer,? super A> handler)
293
{
294
if (handler == null)
295
throw new NullPointerException("'handler' is null");
296
if (dst.isReadOnly())
297
throw new IllegalArgumentException("Read-only buffer");
298
read(false, dst, null, timeout, unit, attachment, handler);
299
}
300
301
@Override
302
public final <A> void read(ByteBuffer[] dsts,
303
int offset,
304
int length,
305
long timeout,
306
TimeUnit unit,
307
A attachment,
308
CompletionHandler<Long,? super A> handler)
309
{
310
if (handler == null)
311
throw new NullPointerException("'handler' is null");
312
if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
313
throw new IndexOutOfBoundsException();
314
ByteBuffer[] bufs = Util.subsequence(dsts, offset, length);
315
for (int i=0; i<bufs.length; i++) {
316
if (bufs[i].isReadOnly())
317
throw new IllegalArgumentException("Read-only buffer");
318
}
319
read(true, null, bufs, timeout, unit, attachment, handler);
320
}
321
322
/**
323
* Invoked by write to initiate the I/O operation.
324
*/
325
abstract <V extends Number,A> Future<V> implWrite(boolean isGatheringWrite,
326
ByteBuffer src,
327
ByteBuffer[] srcs,
328
long timeout,
329
TimeUnit unit,
330
A attachment,
331
CompletionHandler<V,? super A> handler);
332
333
@SuppressWarnings("unchecked")
334
private <V extends Number,A> Future<V> write(boolean isGatheringWrite,
335
ByteBuffer src,
336
ByteBuffer[] srcs,
337
long timeout,
338
TimeUnit unit,
339
A att,
340
CompletionHandler<V,? super A> handler)
341
{
342
boolean hasDataToWrite = isGatheringWrite || src.hasRemaining();
343
344
boolean closed = false;
345
if (isOpen()) {
346
if (remoteAddress == null)
347
throw new NotYetConnectedException();
348
// check and update state
349
synchronized (writeLock) {
350
if (writeKilled)
351
throw new IllegalStateException("Writing not allowed due to timeout or cancellation");
352
if (writing)
353
throw new WritePendingException();
354
if (writeShutdown) {
355
closed = true;
356
} else {
357
if (hasDataToWrite)
358
writing = true;
359
}
360
}
361
} else {
362
closed = true;
363
}
364
365
// channel is closed or shutdown for write
366
if (closed) {
367
Throwable e = new ClosedChannelException();
368
if (handler == null)
369
return CompletedFuture.withFailure(e);
370
Invoker.invoke(this, handler, att, null, e);
371
return null;
372
}
373
374
// nothing to write so complete immediately
375
if (!hasDataToWrite) {
376
Number result = (isGatheringWrite) ? (Number)0L : (Number)0;
377
if (handler == null)
378
return CompletedFuture.withResult((V)result);
379
Invoker.invoke(this, handler, att, (V)result, null);
380
return null;
381
}
382
383
return implWrite(isGatheringWrite, src, srcs, timeout, unit, att, handler);
384
}
385
386
@Override
387
public final Future<Integer> write(ByteBuffer src) {
388
return write(false, src, null, 0L, TimeUnit.MILLISECONDS, null, null);
389
}
390
391
@Override
392
public final <A> void write(ByteBuffer src,
393
long timeout,
394
TimeUnit unit,
395
A attachment,
396
CompletionHandler<Integer,? super A> handler)
397
{
398
if (handler == null)
399
throw new NullPointerException("'handler' is null");
400
write(false, src, null, timeout, unit, attachment, handler);
401
}
402
403
@Override
404
public final <A> void write(ByteBuffer[] srcs,
405
int offset,
406
int length,
407
long timeout,
408
TimeUnit unit,
409
A attachment,
410
CompletionHandler<Long,? super A> handler)
411
{
412
if (handler == null)
413
throw new NullPointerException("'handler' is null");
414
if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
415
throw new IndexOutOfBoundsException();
416
srcs = Util.subsequence(srcs, offset, length);
417
write(true, null, srcs, timeout, unit, attachment, handler);
418
}
419
420
@Override
421
public final AsynchronousSocketChannel bind(SocketAddress local)
422
throws IOException
423
{
424
try {
425
begin();
426
synchronized (stateLock) {
427
if (state == ST_PENDING)
428
throw new ConnectionPendingException();
429
if (localAddress != null)
430
throw new AlreadyBoundException();
431
InetSocketAddress isa = (local == null) ?
432
new InetSocketAddress(0) : Net.checkAddress(local);
433
SecurityManager sm = System.getSecurityManager();
434
if (sm != null) {
435
sm.checkListen(isa.getPort());
436
}
437
NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort());
438
Net.bind(fd, isa.getAddress(), isa.getPort());
439
localAddress = Net.localAddress(fd);
440
}
441
} finally {
442
end();
443
}
444
return this;
445
}
446
447
@Override
448
public final SocketAddress getLocalAddress() throws IOException {
449
if (!isOpen())
450
throw new ClosedChannelException();
451
return Net.getRevealedLocalAddress(localAddress);
452
}
453
454
@Override
455
public final <T> AsynchronousSocketChannel setOption(SocketOption<T> name, T value)
456
throws IOException
457
{
458
if (name == null)
459
throw new NullPointerException();
460
if (!supportedOptions().contains(name))
461
throw new UnsupportedOperationException("'" + name + "' not supported");
462
463
try {
464
begin();
465
if (writeShutdown)
466
throw new IOException("Connection has been shutdown for writing");
467
if (name == StandardSocketOptions.SO_REUSEADDR &&
468
Net.useExclusiveBind())
469
{
470
// SO_REUSEADDR emulated when using exclusive bind
471
isReuseAddress = (Boolean)value;
472
} else {
473
Net.setSocketOption(fd, Net.UNSPEC, name, value);
474
}
475
return this;
476
} finally {
477
end();
478
}
479
}
480
481
@Override
482
@SuppressWarnings("unchecked")
483
public final <T> T getOption(SocketOption<T> name) throws IOException {
484
if (name == null)
485
throw new NullPointerException();
486
if (!supportedOptions().contains(name))
487
throw new UnsupportedOperationException("'" + name + "' not supported");
488
489
try {
490
begin();
491
if (name == StandardSocketOptions.SO_REUSEADDR &&
492
Net.useExclusiveBind())
493
{
494
// SO_REUSEADDR emulated when using exclusive bind
495
return (T)Boolean.valueOf(isReuseAddress);
496
}
497
return (T) Net.getSocketOption(fd, Net.UNSPEC, name);
498
} finally {
499
end();
500
}
501
}
502
503
private static class DefaultOptionsHolder {
504
static final Set<SocketOption<?>> defaultOptions = defaultOptions();
505
506
private static Set<SocketOption<?>> defaultOptions() {
507
HashSet<SocketOption<?>> set = new HashSet<SocketOption<?>>(5);
508
set.add(StandardSocketOptions.SO_SNDBUF);
509
set.add(StandardSocketOptions.SO_RCVBUF);
510
set.add(StandardSocketOptions.SO_KEEPALIVE);
511
set.add(StandardSocketOptions.SO_REUSEADDR);
512
set.add(StandardSocketOptions.TCP_NODELAY);
513
if (ExtendedOptionsImpl.flowSupported()) {
514
set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA);
515
}
516
set.addAll(ExtendedOptionsHelper.keepAliveOptions());
517
return Collections.unmodifiableSet(set);
518
}
519
}
520
521
@Override
522
public final Set<SocketOption<?>> supportedOptions() {
523
return DefaultOptionsHolder.defaultOptions;
524
}
525
526
@Override
527
public final SocketAddress getRemoteAddress() throws IOException {
528
if (!isOpen())
529
throw new ClosedChannelException();
530
return remoteAddress;
531
}
532
533
@Override
534
public final AsynchronousSocketChannel shutdownInput() throws IOException {
535
try {
536
begin();
537
if (remoteAddress == null)
538
throw new NotYetConnectedException();
539
synchronized (readLock) {
540
if (!readShutdown) {
541
Net.shutdown(fd, Net.SHUT_RD);
542
readShutdown = true;
543
}
544
}
545
} finally {
546
end();
547
}
548
return this;
549
}
550
551
@Override
552
public final AsynchronousSocketChannel shutdownOutput() throws IOException {
553
try {
554
begin();
555
if (remoteAddress == null)
556
throw new NotYetConnectedException();
557
synchronized (writeLock) {
558
if (!writeShutdown) {
559
Net.shutdown(fd, Net.SHUT_WR);
560
writeShutdown = true;
561
}
562
}
563
} finally {
564
end();
565
}
566
return this;
567
}
568
569
@Override
570
public final String toString() {
571
StringBuilder sb = new StringBuilder();
572
sb.append(this.getClass().getName());
573
sb.append('[');
574
synchronized (stateLock) {
575
if (!isOpen()) {
576
sb.append("closed");
577
} else {
578
switch (state) {
579
case ST_UNCONNECTED:
580
sb.append("unconnected");
581
break;
582
case ST_PENDING:
583
sb.append("connection-pending");
584
break;
585
case ST_CONNECTED:
586
sb.append("connected");
587
if (readShutdown)
588
sb.append(" ishut");
589
if (writeShutdown)
590
sb.append(" oshut");
591
break;
592
}
593
if (localAddress != null) {
594
sb.append(" local=");
595
sb.append(
596
Net.getRevealedLocalAddressAsString(localAddress));
597
}
598
if (remoteAddress != null) {
599
sb.append(" remote=");
600
sb.append(remoteAddress.toString());
601
}
602
}
603
}
604
sb.append(']');
605
return sb.toString();
606
}
607
}
608
609