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