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/SocketChannelImpl.java
38918 views
1
/*
2
* Copyright (c) 2000, 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.io.FileDescriptor;
29
import java.io.IOException;
30
import java.net.*;
31
import java.nio.ByteBuffer;
32
import java.nio.channels.*;
33
import java.nio.channels.spi.*;
34
import java.util.*;
35
import sun.net.NetHooks;
36
import sun.net.ExtendedOptionsImpl;
37
import sun.net.ExtendedOptionsHelper;
38
39
40
/**
41
* An implementation of SocketChannels
42
*/
43
44
class SocketChannelImpl
45
extends SocketChannel
46
implements SelChImpl
47
{
48
49
// Used to make native read and write calls
50
private static NativeDispatcher nd;
51
52
// Our file descriptor object
53
private final FileDescriptor fd;
54
private final int fdVal;
55
56
// IDs of native threads doing reads and writes, for signalling
57
private volatile long readerThread = 0;
58
private volatile long writerThread = 0;
59
60
// Lock held by current reading or connecting thread
61
private final Object readLock = new Object();
62
63
// Lock held by current writing or connecting thread
64
private final Object writeLock = new Object();
65
66
// Lock held by any thread that modifies the state fields declared below
67
// DO NOT invoke a blocking I/O operation while holding this lock!
68
private final Object stateLock = new Object();
69
70
// -- The following fields are protected by stateLock
71
72
// set true when exclusive binding is on and SO_REUSEADDR is emulated
73
private boolean isReuseAddress;
74
75
// State, increases monotonically
76
private static final int ST_UNINITIALIZED = -1;
77
private static final int ST_UNCONNECTED = 0;
78
private static final int ST_PENDING = 1;
79
private static final int ST_CONNECTED = 2;
80
private static final int ST_KILLPENDING = 3;
81
private static final int ST_KILLED = 4;
82
private int state = ST_UNINITIALIZED;
83
84
// Binding
85
private InetSocketAddress localAddress;
86
private InetSocketAddress remoteAddress;
87
88
// Input/Output open
89
private boolean isInputOpen = true;
90
private boolean isOutputOpen = true;
91
private boolean readyToConnect = false;
92
93
// Socket adaptor, created on demand
94
private Socket socket;
95
96
// -- End of fields protected by stateLock
97
98
99
// Constructor for normal connecting sockets
100
//
101
SocketChannelImpl(SelectorProvider sp) throws IOException {
102
super(sp);
103
this.fd = Net.socket(true);
104
this.fdVal = IOUtil.fdVal(fd);
105
this.state = ST_UNCONNECTED;
106
}
107
108
SocketChannelImpl(SelectorProvider sp,
109
FileDescriptor fd,
110
boolean bound)
111
throws IOException
112
{
113
super(sp);
114
this.fd = fd;
115
this.fdVal = IOUtil.fdVal(fd);
116
this.state = ST_UNCONNECTED;
117
if (bound)
118
this.localAddress = Net.localAddress(fd);
119
}
120
121
// Constructor for sockets obtained from server sockets
122
//
123
SocketChannelImpl(SelectorProvider sp,
124
FileDescriptor fd, InetSocketAddress remote)
125
throws IOException
126
{
127
super(sp);
128
this.fd = fd;
129
this.fdVal = IOUtil.fdVal(fd);
130
this.state = ST_CONNECTED;
131
this.localAddress = Net.localAddress(fd);
132
this.remoteAddress = remote;
133
}
134
135
public Socket socket() {
136
synchronized (stateLock) {
137
if (socket == null)
138
socket = SocketAdaptor.create(this);
139
return socket;
140
}
141
}
142
143
@Override
144
public SocketAddress getLocalAddress() throws IOException {
145
synchronized (stateLock) {
146
if (!isOpen())
147
throw new ClosedChannelException();
148
return Net.getRevealedLocalAddress(localAddress);
149
}
150
}
151
152
@Override
153
public SocketAddress getRemoteAddress() throws IOException {
154
synchronized (stateLock) {
155
if (!isOpen())
156
throw new ClosedChannelException();
157
return remoteAddress;
158
}
159
}
160
161
@Override
162
public <T> SocketChannel setOption(SocketOption<T> name, T value)
163
throws IOException
164
{
165
if (name == null)
166
throw new NullPointerException();
167
if (!supportedOptions().contains(name))
168
throw new UnsupportedOperationException("'" + name + "' not supported");
169
170
synchronized (stateLock) {
171
if (!isOpen())
172
throw new ClosedChannelException();
173
174
if (name == StandardSocketOptions.IP_TOS) {
175
ProtocolFamily family = Net.isIPv6Available() ?
176
StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
177
Net.setSocketOption(fd, family, name, value);
178
return this;
179
}
180
181
if (name == StandardSocketOptions.SO_REUSEADDR && Net.useExclusiveBind()) {
182
// SO_REUSEADDR emulated when using exclusive bind
183
isReuseAddress = (Boolean)value;
184
return this;
185
}
186
187
// no options that require special handling
188
Net.setSocketOption(fd, Net.UNSPEC, name, value);
189
return this;
190
}
191
}
192
193
@Override
194
@SuppressWarnings("unchecked")
195
public <T> T getOption(SocketOption<T> name)
196
throws IOException
197
{
198
if (name == null)
199
throw new NullPointerException();
200
if (!supportedOptions().contains(name))
201
throw new UnsupportedOperationException("'" + name + "' not supported");
202
203
synchronized (stateLock) {
204
if (!isOpen())
205
throw new ClosedChannelException();
206
207
if (name == StandardSocketOptions.SO_REUSEADDR &&
208
Net.useExclusiveBind())
209
{
210
// SO_REUSEADDR emulated when using exclusive bind
211
return (T)Boolean.valueOf(isReuseAddress);
212
}
213
214
// special handling for IP_TOS: always return 0 when IPv6
215
if (name == StandardSocketOptions.IP_TOS) {
216
ProtocolFamily family = Net.isIPv6Available() ?
217
StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
218
return (T) Net.getSocketOption(fd, family, name);
219
}
220
221
// no options that require special handling
222
return (T) Net.getSocketOption(fd, Net.UNSPEC, name);
223
}
224
}
225
226
private static class DefaultOptionsHolder {
227
static final Set<SocketOption<?>> defaultOptions = defaultOptions();
228
229
private static Set<SocketOption<?>> defaultOptions() {
230
HashSet<SocketOption<?>> set = new HashSet<SocketOption<?>>(8);
231
set.add(StandardSocketOptions.SO_SNDBUF);
232
set.add(StandardSocketOptions.SO_RCVBUF);
233
set.add(StandardSocketOptions.SO_KEEPALIVE);
234
set.add(StandardSocketOptions.SO_REUSEADDR);
235
set.add(StandardSocketOptions.SO_LINGER);
236
set.add(StandardSocketOptions.TCP_NODELAY);
237
// additional options required by socket adaptor
238
set.add(StandardSocketOptions.IP_TOS);
239
set.add(ExtendedSocketOption.SO_OOBINLINE);
240
if (ExtendedOptionsImpl.flowSupported()) {
241
set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA);
242
}
243
set.addAll(ExtendedOptionsHelper.keepAliveOptions());
244
return Collections.unmodifiableSet(set);
245
}
246
}
247
248
@Override
249
public final Set<SocketOption<?>> supportedOptions() {
250
return DefaultOptionsHolder.defaultOptions;
251
}
252
253
private boolean ensureReadOpen() throws ClosedChannelException {
254
synchronized (stateLock) {
255
if (!isOpen())
256
throw new ClosedChannelException();
257
if (!isConnected())
258
throw new NotYetConnectedException();
259
if (!isInputOpen)
260
return false;
261
else
262
return true;
263
}
264
}
265
266
private void ensureWriteOpen() throws ClosedChannelException {
267
synchronized (stateLock) {
268
if (!isOpen())
269
throw new ClosedChannelException();
270
if (!isOutputOpen)
271
throw new ClosedChannelException();
272
if (!isConnected())
273
throw new NotYetConnectedException();
274
}
275
}
276
277
private void readerCleanup() throws IOException {
278
synchronized (stateLock) {
279
readerThread = 0;
280
if (state == ST_KILLPENDING)
281
kill();
282
}
283
}
284
285
private void writerCleanup() throws IOException {
286
synchronized (stateLock) {
287
writerThread = 0;
288
if (state == ST_KILLPENDING)
289
kill();
290
}
291
}
292
293
public int read(ByteBuffer buf) throws IOException {
294
295
if (buf == null)
296
throw new NullPointerException();
297
298
synchronized (readLock) {
299
if (!ensureReadOpen())
300
return -1;
301
int n = 0;
302
try {
303
304
// Set up the interruption machinery; see
305
// AbstractInterruptibleChannel for details
306
//
307
begin();
308
309
synchronized (stateLock) {
310
if (!isOpen()) {
311
// Either the current thread is already interrupted, so
312
// begin() closed the channel, or another thread closed the
313
// channel since we checked it a few bytecodes ago. In
314
// either case the value returned here is irrelevant since
315
// the invocation of end() in the finally block will throw
316
// an appropriate exception.
317
//
318
return 0;
319
320
}
321
322
// Save this thread so that it can be signalled on those
323
// platforms that require it
324
//
325
readerThread = NativeThread.current();
326
}
327
328
// Between the previous test of isOpen() and the return of the
329
// IOUtil.read invocation below, this channel might be closed
330
// or this thread might be interrupted. We rely upon the
331
// implicit synchronization point in the kernel read() call to
332
// make sure that the right thing happens. In either case the
333
// implCloseSelectableChannel method is ultimately invoked in
334
// some other thread, so there are three possibilities:
335
//
336
// - implCloseSelectableChannel() invokes nd.preClose()
337
// before this thread invokes read(), in which case the
338
// read returns immediately with either EOF or an error,
339
// the latter of which will cause an IOException to be
340
// thrown.
341
//
342
// - implCloseSelectableChannel() invokes nd.preClose() after
343
// this thread is blocked in read(). On some operating
344
// systems (e.g., Solaris and Windows) this causes the read
345
// to return immediately with either EOF or an error
346
// indication.
347
//
348
// - implCloseSelectableChannel() invokes nd.preClose() after
349
// this thread is blocked in read() but the operating
350
// system (e.g., Linux) doesn't support preemptive close,
351
// so implCloseSelectableChannel() proceeds to signal this
352
// thread, thereby causing the read to return immediately
353
// with IOStatus.INTERRUPTED.
354
//
355
// In all three cases the invocation of end() in the finally
356
// clause will notice that the channel has been closed and
357
// throw an appropriate exception (AsynchronousCloseException
358
// or ClosedByInterruptException) if necessary.
359
//
360
// *There is A fourth possibility. implCloseSelectableChannel()
361
// invokes nd.preClose(), signals reader/writer thred and quickly
362
// moves on to nd.close() in kill(), which does a real close.
363
// Then a third thread accepts a new connection, opens file or
364
// whatever that causes the released "fd" to be recycled. All
365
// above happens just between our last isOpen() check and the
366
// next kernel read reached, with the recycled "fd". The solution
367
// is to postpone the real kill() if there is a reader or/and
368
// writer thread(s) over there "waiting", leave the cleanup/kill
369
// to the reader or writer thread. (the preClose() still happens
370
// so the connection gets cut off as usual).
371
//
372
// For socket channels there is the additional wrinkle that
373
// asynchronous shutdown works much like asynchronous close,
374
// except that the channel is shutdown rather than completely
375
// closed. This is analogous to the first two cases above,
376
// except that the shutdown operation plays the role of
377
// nd.preClose().
378
for (;;) {
379
n = IOUtil.read(fd, buf, -1, nd);
380
if ((n == IOStatus.INTERRUPTED) && isOpen()) {
381
// The system call was interrupted but the channel
382
// is still open, so retry
383
continue;
384
}
385
return IOStatus.normalize(n);
386
}
387
388
} finally {
389
readerCleanup(); // Clear reader thread
390
// The end method, which is defined in our superclass
391
// AbstractInterruptibleChannel, resets the interruption
392
// machinery. If its argument is true then it returns
393
// normally; otherwise it checks the interrupt and open state
394
// of this channel and throws an appropriate exception if
395
// necessary.
396
//
397
// So, if we actually managed to do any I/O in the above try
398
// block then we pass true to the end method. We also pass
399
// true if the channel was in non-blocking mode when the I/O
400
// operation was initiated but no data could be transferred;
401
// this prevents spurious exceptions from being thrown in the
402
// rare event that a channel is closed or a thread is
403
// interrupted at the exact moment that a non-blocking I/O
404
// request is made.
405
//
406
end(n > 0 || (n == IOStatus.UNAVAILABLE));
407
408
// Extra case for socket channels: Asynchronous shutdown
409
//
410
synchronized (stateLock) {
411
if ((n <= 0) && (!isInputOpen))
412
return IOStatus.EOF;
413
}
414
415
assert IOStatus.check(n);
416
417
}
418
}
419
}
420
421
public long read(ByteBuffer[] dsts, int offset, int length)
422
throws IOException
423
{
424
if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
425
throw new IndexOutOfBoundsException();
426
synchronized (readLock) {
427
if (!ensureReadOpen())
428
return -1;
429
long n = 0;
430
try {
431
begin();
432
synchronized (stateLock) {
433
if (!isOpen())
434
return 0;
435
readerThread = NativeThread.current();
436
}
437
438
for (;;) {
439
n = IOUtil.read(fd, dsts, offset, length, nd);
440
if ((n == IOStatus.INTERRUPTED) && isOpen())
441
continue;
442
return IOStatus.normalize(n);
443
}
444
} finally {
445
readerCleanup();
446
end(n > 0 || (n == IOStatus.UNAVAILABLE));
447
synchronized (stateLock) {
448
if ((n <= 0) && (!isInputOpen))
449
return IOStatus.EOF;
450
}
451
assert IOStatus.check(n);
452
}
453
}
454
}
455
456
public int write(ByteBuffer buf) throws IOException {
457
if (buf == null)
458
throw new NullPointerException();
459
synchronized (writeLock) {
460
ensureWriteOpen();
461
int n = 0;
462
try {
463
begin();
464
synchronized (stateLock) {
465
if (!isOpen())
466
return 0;
467
writerThread = NativeThread.current();
468
}
469
for (;;) {
470
n = IOUtil.write(fd, buf, -1, nd);
471
if ((n == IOStatus.INTERRUPTED) && isOpen())
472
continue;
473
return IOStatus.normalize(n);
474
}
475
} finally {
476
writerCleanup();
477
end(n > 0 || (n == IOStatus.UNAVAILABLE));
478
synchronized (stateLock) {
479
if ((n <= 0) && (!isOutputOpen))
480
throw new AsynchronousCloseException();
481
}
482
assert IOStatus.check(n);
483
}
484
}
485
}
486
487
public long write(ByteBuffer[] srcs, int offset, int length)
488
throws IOException
489
{
490
if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
491
throw new IndexOutOfBoundsException();
492
synchronized (writeLock) {
493
ensureWriteOpen();
494
long n = 0;
495
try {
496
begin();
497
synchronized (stateLock) {
498
if (!isOpen())
499
return 0;
500
writerThread = NativeThread.current();
501
}
502
for (;;) {
503
n = IOUtil.write(fd, srcs, offset, length, nd);
504
if ((n == IOStatus.INTERRUPTED) && isOpen())
505
continue;
506
return IOStatus.normalize(n);
507
}
508
} finally {
509
writerCleanup();
510
end((n > 0) || (n == IOStatus.UNAVAILABLE));
511
synchronized (stateLock) {
512
if ((n <= 0) && (!isOutputOpen))
513
throw new AsynchronousCloseException();
514
}
515
assert IOStatus.check(n);
516
}
517
}
518
}
519
520
// package-private
521
int sendOutOfBandData(byte b) throws IOException {
522
synchronized (writeLock) {
523
ensureWriteOpen();
524
int n = 0;
525
try {
526
begin();
527
synchronized (stateLock) {
528
if (!isOpen())
529
return 0;
530
writerThread = NativeThread.current();
531
}
532
for (;;) {
533
n = sendOutOfBandData(fd, b);
534
if ((n == IOStatus.INTERRUPTED) && isOpen())
535
continue;
536
return IOStatus.normalize(n);
537
}
538
} finally {
539
writerCleanup();
540
end((n > 0) || (n == IOStatus.UNAVAILABLE));
541
synchronized (stateLock) {
542
if ((n <= 0) && (!isOutputOpen))
543
throw new AsynchronousCloseException();
544
}
545
assert IOStatus.check(n);
546
}
547
}
548
}
549
550
protected void implConfigureBlocking(boolean block) throws IOException {
551
IOUtil.configureBlocking(fd, block);
552
}
553
554
public InetSocketAddress localAddress() {
555
synchronized (stateLock) {
556
return localAddress;
557
}
558
}
559
560
public SocketAddress remoteAddress() {
561
synchronized (stateLock) {
562
return remoteAddress;
563
}
564
}
565
566
@Override
567
public SocketChannel bind(SocketAddress local) throws IOException {
568
synchronized (readLock) {
569
synchronized (writeLock) {
570
synchronized (stateLock) {
571
if (!isOpen())
572
throw new ClosedChannelException();
573
if (state == ST_PENDING)
574
throw new ConnectionPendingException();
575
if (localAddress != null)
576
throw new AlreadyBoundException();
577
InetSocketAddress isa = (local == null) ?
578
new InetSocketAddress(0) : Net.checkAddress(local);
579
SecurityManager sm = System.getSecurityManager();
580
if (sm != null) {
581
sm.checkListen(isa.getPort());
582
}
583
NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort());
584
Net.bind(fd, isa.getAddress(), isa.getPort());
585
localAddress = Net.localAddress(fd);
586
}
587
}
588
}
589
return this;
590
}
591
592
public boolean isConnected() {
593
synchronized (stateLock) {
594
return (state == ST_CONNECTED);
595
}
596
}
597
598
public boolean isConnectionPending() {
599
synchronized (stateLock) {
600
return (state == ST_PENDING);
601
}
602
}
603
604
void ensureOpenAndUnconnected() throws IOException { // package-private
605
synchronized (stateLock) {
606
if (!isOpen())
607
throw new ClosedChannelException();
608
if (state == ST_CONNECTED)
609
throw new AlreadyConnectedException();
610
if (state == ST_PENDING)
611
throw new ConnectionPendingException();
612
}
613
}
614
615
public boolean connect(SocketAddress sa) throws IOException {
616
int localPort = 0;
617
618
synchronized (readLock) {
619
synchronized (writeLock) {
620
ensureOpenAndUnconnected();
621
InetSocketAddress isa = Net.checkAddress(sa);
622
SecurityManager sm = System.getSecurityManager();
623
if (sm != null)
624
sm.checkConnect(isa.getAddress().getHostAddress(),
625
isa.getPort());
626
synchronized (blockingLock()) {
627
int n = 0;
628
try {
629
try {
630
begin();
631
synchronized (stateLock) {
632
if (!isOpen()) {
633
return false;
634
}
635
// notify hook only if unbound
636
if (localAddress == null) {
637
NetHooks.beforeTcpConnect(fd,
638
isa.getAddress(),
639
isa.getPort());
640
}
641
readerThread = NativeThread.current();
642
}
643
for (;;) {
644
InetAddress ia = isa.getAddress();
645
if (ia.isAnyLocalAddress())
646
ia = InetAddress.getLocalHost();
647
n = Net.connect(fd,
648
ia,
649
isa.getPort());
650
if ( (n == IOStatus.INTERRUPTED)
651
&& isOpen())
652
continue;
653
break;
654
}
655
656
} finally {
657
readerCleanup();
658
end((n > 0) || (n == IOStatus.UNAVAILABLE));
659
assert IOStatus.check(n);
660
}
661
} catch (IOException x) {
662
// If an exception was thrown, close the channel after
663
// invoking end() so as to avoid bogus
664
// AsynchronousCloseExceptions
665
close();
666
throw x;
667
}
668
synchronized (stateLock) {
669
remoteAddress = isa;
670
if (n > 0) {
671
672
// Connection succeeded; disallow further
673
// invocation
674
state = ST_CONNECTED;
675
if (isOpen())
676
localAddress = Net.localAddress(fd);
677
return true;
678
}
679
// If nonblocking and no exception then connection
680
// pending; disallow another invocation
681
if (!isBlocking())
682
state = ST_PENDING;
683
else
684
assert false;
685
}
686
}
687
return false;
688
}
689
}
690
}
691
692
public boolean finishConnect() throws IOException {
693
synchronized (readLock) {
694
synchronized (writeLock) {
695
synchronized (stateLock) {
696
if (!isOpen())
697
throw new ClosedChannelException();
698
if (state == ST_CONNECTED)
699
return true;
700
if (state != ST_PENDING)
701
throw new NoConnectionPendingException();
702
}
703
int n = 0;
704
try {
705
try {
706
begin();
707
synchronized (blockingLock()) {
708
synchronized (stateLock) {
709
if (!isOpen()) {
710
return false;
711
}
712
readerThread = NativeThread.current();
713
}
714
if (!isBlocking()) {
715
for (;;) {
716
n = checkConnect(fd, false,
717
readyToConnect);
718
if ( (n == IOStatus.INTERRUPTED)
719
&& isOpen())
720
continue;
721
break;
722
}
723
} else {
724
for (;;) {
725
n = checkConnect(fd, true,
726
readyToConnect);
727
if (n == 0) {
728
// Loop in case of
729
// spurious notifications
730
continue;
731
}
732
if ( (n == IOStatus.INTERRUPTED)
733
&& isOpen())
734
continue;
735
break;
736
}
737
}
738
}
739
} finally {
740
synchronized (stateLock) {
741
readerThread = 0;
742
if (state == ST_KILLPENDING) {
743
kill();
744
// poll()/getsockopt() does not report
745
// error (throws exception, with n = 0)
746
// on Linux platform after dup2 and
747
// signal-wakeup. Force n to 0 so the
748
// end() can throw appropriate exception
749
n = 0;
750
}
751
}
752
end((n > 0) || (n == IOStatus.UNAVAILABLE));
753
assert IOStatus.check(n);
754
}
755
} catch (IOException x) {
756
// If an exception was thrown, close the channel after
757
// invoking end() so as to avoid bogus
758
// AsynchronousCloseExceptions
759
close();
760
throw x;
761
}
762
if (n > 0) {
763
synchronized (stateLock) {
764
state = ST_CONNECTED;
765
if (isOpen())
766
localAddress = Net.localAddress(fd);
767
}
768
return true;
769
}
770
return false;
771
}
772
}
773
}
774
775
@Override
776
public SocketChannel shutdownInput() throws IOException {
777
synchronized (stateLock) {
778
if (!isOpen())
779
throw new ClosedChannelException();
780
if (!isConnected())
781
throw new NotYetConnectedException();
782
if (isInputOpen) {
783
Net.shutdown(fd, Net.SHUT_RD);
784
if (readerThread != 0)
785
NativeThread.signal(readerThread);
786
isInputOpen = false;
787
}
788
return this;
789
}
790
}
791
792
@Override
793
public SocketChannel shutdownOutput() throws IOException {
794
synchronized (stateLock) {
795
if (!isOpen())
796
throw new ClosedChannelException();
797
if (!isConnected())
798
throw new NotYetConnectedException();
799
if (isOutputOpen) {
800
Net.shutdown(fd, Net.SHUT_WR);
801
if (writerThread != 0)
802
NativeThread.signal(writerThread);
803
isOutputOpen = false;
804
}
805
return this;
806
}
807
}
808
809
public boolean isInputOpen() {
810
synchronized (stateLock) {
811
return isInputOpen;
812
}
813
}
814
815
public boolean isOutputOpen() {
816
synchronized (stateLock) {
817
return isOutputOpen;
818
}
819
}
820
821
// AbstractInterruptibleChannel synchronizes invocations of this method
822
// using AbstractInterruptibleChannel.closeLock, and also ensures that this
823
// method is only ever invoked once. Before we get to this method, isOpen
824
// (which is volatile) will have been set to false.
825
//
826
protected void implCloseSelectableChannel() throws IOException {
827
synchronized (stateLock) {
828
isInputOpen = false;
829
isOutputOpen = false;
830
831
// Close the underlying file descriptor and dup it to a known fd
832
// that's already closed. This prevents other operations on this
833
// channel from using the old fd, which might be recycled in the
834
// meantime and allocated to an entirely different channel.
835
//
836
if (state != ST_KILLED)
837
nd.preClose(fd);
838
839
// Signal native threads, if needed. If a target thread is not
840
// currently blocked in an I/O operation then no harm is done since
841
// the signal handler doesn't actually do anything.
842
//
843
if (readerThread != 0)
844
NativeThread.signal(readerThread);
845
846
if (writerThread != 0)
847
NativeThread.signal(writerThread);
848
849
// If this channel is not registered then it's safe to close the fd
850
// immediately since we know at this point that no thread is
851
// blocked in an I/O operation upon the channel and, since the
852
// channel is marked closed, no thread will start another such
853
// operation. If this channel is registered then we don't close
854
// the fd since it might be in use by a selector. In that case
855
// closing this channel caused its keys to be cancelled, so the
856
// last selector to deregister a key for this channel will invoke
857
// kill() to close the fd.
858
//
859
if (!isRegistered())
860
kill();
861
}
862
}
863
864
public void kill() throws IOException {
865
synchronized (stateLock) {
866
if (state == ST_KILLED)
867
return;
868
if (state == ST_UNINITIALIZED) {
869
state = ST_KILLED;
870
return;
871
}
872
assert !isOpen() && !isRegistered();
873
874
// Postpone the kill if there is a waiting reader
875
// or writer thread. See the comments in read() for
876
// more detailed explanation.
877
if (readerThread == 0 && writerThread == 0) {
878
nd.close(fd);
879
state = ST_KILLED;
880
} else {
881
state = ST_KILLPENDING;
882
}
883
}
884
}
885
886
/**
887
* Translates native poll revent ops into a ready operation ops
888
*/
889
public boolean translateReadyOps(int ops, int initialOps,
890
SelectionKeyImpl sk) {
891
int intOps = sk.nioInterestOps(); // Do this just once, it synchronizes
892
int oldOps = sk.nioReadyOps();
893
int newOps = initialOps;
894
895
if ((ops & Net.POLLNVAL) != 0) {
896
// This should only happen if this channel is pre-closed while a
897
// selection operation is in progress
898
// ## Throw an error if this channel has not been pre-closed
899
return false;
900
}
901
902
if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) {
903
newOps = intOps;
904
sk.nioReadyOps(newOps);
905
// No need to poll again in checkConnect,
906
// the error will be detected there
907
readyToConnect = true;
908
return (newOps & ~oldOps) != 0;
909
}
910
911
if (((ops & Net.POLLIN) != 0) &&
912
((intOps & SelectionKey.OP_READ) != 0) &&
913
(state == ST_CONNECTED))
914
newOps |= SelectionKey.OP_READ;
915
916
if (((ops & Net.POLLCONN) != 0) &&
917
((intOps & SelectionKey.OP_CONNECT) != 0) &&
918
((state == ST_UNCONNECTED) || (state == ST_PENDING))) {
919
newOps |= SelectionKey.OP_CONNECT;
920
readyToConnect = true;
921
}
922
923
if (((ops & Net.POLLOUT) != 0) &&
924
((intOps & SelectionKey.OP_WRITE) != 0) &&
925
(state == ST_CONNECTED))
926
newOps |= SelectionKey.OP_WRITE;
927
928
sk.nioReadyOps(newOps);
929
return (newOps & ~oldOps) != 0;
930
}
931
932
public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl sk) {
933
return translateReadyOps(ops, sk.nioReadyOps(), sk);
934
}
935
936
public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl sk) {
937
return translateReadyOps(ops, 0, sk);
938
}
939
940
// package-private
941
int poll(int events, long timeout) throws IOException {
942
assert Thread.holdsLock(blockingLock()) && !isBlocking();
943
944
synchronized (readLock) {
945
int n = 0;
946
try {
947
begin();
948
synchronized (stateLock) {
949
if (!isOpen())
950
return 0;
951
readerThread = NativeThread.current();
952
}
953
n = Net.poll(fd, events, timeout);
954
} finally {
955
readerCleanup();
956
end(n > 0);
957
}
958
return n;
959
}
960
}
961
962
/**
963
* Translates an interest operation set into a native poll event set
964
*/
965
public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) {
966
int newOps = 0;
967
if ((ops & SelectionKey.OP_READ) != 0)
968
newOps |= Net.POLLIN;
969
if ((ops & SelectionKey.OP_WRITE) != 0)
970
newOps |= Net.POLLOUT;
971
if ((ops & SelectionKey.OP_CONNECT) != 0)
972
newOps |= Net.POLLCONN;
973
sk.selector.putEventOps(sk, newOps);
974
}
975
976
public FileDescriptor getFD() {
977
return fd;
978
}
979
980
public int getFDVal() {
981
return fdVal;
982
}
983
984
@Override
985
public String toString() {
986
StringBuffer sb = new StringBuffer();
987
sb.append(this.getClass().getSuperclass().getName());
988
sb.append('[');
989
if (!isOpen())
990
sb.append("closed");
991
else {
992
synchronized (stateLock) {
993
switch (state) {
994
case ST_UNCONNECTED:
995
sb.append("unconnected");
996
break;
997
case ST_PENDING:
998
sb.append("connection-pending");
999
break;
1000
case ST_CONNECTED:
1001
sb.append("connected");
1002
if (!isInputOpen)
1003
sb.append(" ishut");
1004
if (!isOutputOpen)
1005
sb.append(" oshut");
1006
break;
1007
}
1008
InetSocketAddress addr = localAddress();
1009
if (addr != null) {
1010
sb.append(" local=");
1011
sb.append(Net.getRevealedLocalAddressAsString(addr));
1012
}
1013
if (remoteAddress() != null) {
1014
sb.append(" remote=");
1015
sb.append(remoteAddress().toString());
1016
}
1017
}
1018
}
1019
sb.append(']');
1020
return sb.toString();
1021
}
1022
1023
1024
// -- Native methods --
1025
1026
private static native int checkConnect(FileDescriptor fd,
1027
boolean block, boolean ready)
1028
throws IOException;
1029
1030
private static native int sendOutOfBandData(FileDescriptor fd, byte data)
1031
throws IOException;
1032
1033
static {
1034
IOUtil.load();
1035
nd = new SocketDispatcher();
1036
}
1037
1038
}
1039
1040