131 this.localAddress = Net.localAddress(fd);
132 }
133 }
134 }
135
136 // Constructor for sockets obtained from server sockets
137 //
138 SocketChannelImpl(SelectorProvider sp, FileDescriptor fd, InetSocketAddress isa)
139 throws IOException
140 {
141 super(sp);
142 this.fd = fd;
143 this.fdVal = IOUtil.fdVal(fd);
144 synchronized (stateLock) {
145 this.localAddress = Net.localAddress(fd);
146 this.remoteAddress = isa;
147 this.state = ST_CONNECTED;
148 }
149 }
150
151 // @throws ClosedChannelException if channel is closed
152 private void ensureOpen() throws ClosedChannelException {
153 if (!isOpen())
154 throw new ClosedChannelException();
155 }
156
157 @Override
158 public Socket socket() {
159 synchronized (stateLock) {
160 if (socket == null)
161 socket = SocketAdaptor.create(this);
162 return socket;
163 }
164 }
165
166 @Override
167 public SocketAddress getLocalAddress() throws IOException {
168 synchronized (stateLock) {
169 ensureOpen();
170 return Net.getRevealedLocalAddress(localAddress);
171 }
172 }
173
174 @Override
175 public SocketAddress getRemoteAddress() throws IOException {
176 synchronized (stateLock) {
258 set.addAll(ExtendedSocketOptions.getInstance().options());
259 return Collections.unmodifiableSet(set);
260 }
261 }
262
263 @Override
264 public final Set<SocketOption<?>> supportedOptions() {
265 return DefaultOptionsHolder.defaultOptions;
266 }
267
268 /**
269 * Marks the beginning of a read operation that might block.
270 *
271 * @throws ClosedChannelException if the channel is closed
272 * @throws NotYetConnectedException if the channel is not yet connected
273 */
274 private void beginRead(boolean blocking) throws ClosedChannelException {
275 if (blocking) {
276 // set hook for Thread.interrupt
277 begin();
278 }
279 synchronized (stateLock) {
280 ensureOpen();
281 if (state != ST_CONNECTED)
282 throw new NotYetConnectedException();
283 if (blocking)
284 readerThread = NativeThread.current();
285 }
286 }
287
288 /**
289 * Marks the end of a read operation that may have blocked.
290 *
291 * @throws AsynchronousCloseException if the channel was closed due to this
292 * thread being interrupted on a blocking read operation.
293 */
294 private void endRead(boolean blocking, boolean completed)
295 throws AsynchronousCloseException
296 {
297 if (blocking) {
298 synchronized (stateLock) {
299 readerThread = 0;
300 // notify any thread waiting in implCloseSelectableChannel
301 if (state == ST_CLOSING) {
302 stateLock.notifyAll();
303 }
304 }
305 // remove hook for Thread.interrupt
368 endRead(blocking, n > 0);
369 if (n <= 0 && isInputClosed)
370 return IOStatus.EOF;
371 }
372 return IOStatus.normalize(n);
373 } finally {
374 readLock.unlock();
375 }
376 }
377
378 /**
379 * Marks the beginning of a write operation that might block.
380 *
381 * @throws ClosedChannelException if the channel is closed or output shutdown
382 * @throws NotYetConnectedException if the channel is not yet connected
383 */
384 private void beginWrite(boolean blocking) throws ClosedChannelException {
385 if (blocking) {
386 // set hook for Thread.interrupt
387 begin();
388 }
389 synchronized (stateLock) {
390 ensureOpen();
391 if (isOutputClosed)
392 throw new ClosedChannelException();
393 if (state != ST_CONNECTED)
394 throw new NotYetConnectedException();
395 if (blocking)
396 writerThread = NativeThread.current();
397 }
398 }
399
400 /**
401 * Marks the end of a write operation that may have blocked.
402 *
403 * @throws AsynchronousCloseException if the channel was closed due to this
404 * thread being interrupted on a blocking write operation.
405 */
406 private void endWrite(boolean blocking, boolean completed)
407 throws AsynchronousCloseException
408 {
409 if (blocking) {
410 synchronized (stateLock) {
411 writerThread = 0;
412 // notify any thread waiting in implCloseSelectableChannel
413 if (state == ST_CLOSING) {
414 stateLock.notifyAll();
415 }
416 }
417 // remove hook for Thread.interrupt
595 throws IOException
596 {
597 if (blocking) {
598 // set hook for Thread.interrupt
599 begin();
600 }
601 synchronized (stateLock) {
602 ensureOpen();
603 int state = this.state;
604 if (state == ST_CONNECTED)
605 throw new AlreadyConnectedException();
606 if (state == ST_CONNECTIONPENDING)
607 throw new ConnectionPendingException();
608 assert state == ST_UNCONNECTED;
609 this.state = ST_CONNECTIONPENDING;
610
611 if (localAddress == null)
612 NetHooks.beforeTcpConnect(fd, isa.getAddress(), isa.getPort());
613 remoteAddress = isa;
614
615 if (blocking)
616 readerThread = NativeThread.current();
617 }
618 }
619
620 /**
621 * Marks the end of a connect operation that may have blocked.
622 *
623 * @throws AsynchronousCloseException if the channel was closed due to this
624 * thread being interrupted on a blocking connect operation.
625 * @throws IOException if completed and unable to obtain the local address
626 */
627 private void endConnect(boolean blocking, boolean completed)
628 throws IOException
629 {
630 endRead(blocking, completed);
631
632 if (completed) {
633 synchronized (stateLock) {
634 if (state == ST_CONNECTIONPENDING) {
635 localAddress = Net.localAddress(fd);
636 state = ST_CONNECTED;
637 }
638 }
678 close();
679 throw ioe;
680 }
681 }
682
683 /**
684 * Marks the beginning of a finishConnect operation that might block.
685 *
686 * @throws ClosedChannelException if the channel is closed
687 * @throws NoConnectionPendingException if no connection is pending
688 */
689 private void beginFinishConnect(boolean blocking) throws ClosedChannelException {
690 if (blocking) {
691 // set hook for Thread.interrupt
692 begin();
693 }
694 synchronized (stateLock) {
695 ensureOpen();
696 if (state != ST_CONNECTIONPENDING)
697 throw new NoConnectionPendingException();
698 if (blocking)
699 readerThread = NativeThread.current();
700 }
701 }
702
703 /**
704 * Marks the end of a finishConnect operation that may have blocked.
705 *
706 * @throws AsynchronousCloseException if the channel was closed due to this
707 * thread being interrupted on a blocking connect operation.
708 * @throws IOException if completed and unable to obtain the local address
709 */
710 private void endFinishConnect(boolean blocking, boolean completed)
711 throws IOException
712 {
713 endRead(blocking, completed);
714
715 if (completed) {
716 synchronized (stateLock) {
717 if (state == ST_CONNECTIONPENDING) {
718 localAddress = Net.localAddress(fd);
719 state = ST_CONNECTED;
720 }
721 }
|
131 this.localAddress = Net.localAddress(fd);
132 }
133 }
134 }
135
136 // Constructor for sockets obtained from server sockets
137 //
138 SocketChannelImpl(SelectorProvider sp, FileDescriptor fd, InetSocketAddress isa)
139 throws IOException
140 {
141 super(sp);
142 this.fd = fd;
143 this.fdVal = IOUtil.fdVal(fd);
144 synchronized (stateLock) {
145 this.localAddress = Net.localAddress(fd);
146 this.remoteAddress = isa;
147 this.state = ST_CONNECTED;
148 }
149 }
150
151 /**
152 * Checks that the channel is open.
153 *
154 * @throws ClosedChannelException if channel is closed (or closing)
155 */
156 private void ensureOpen() throws ClosedChannelException {
157 if (!isOpen())
158 throw new ClosedChannelException();
159 }
160
161 /**
162 * Checks that the channel is open and connected.
163 *
164 * @apiNote This method uses the "state" field to check if the channel is
165 * open. It should never be used in conjuncion with isOpen or ensureOpen
166 * as these methods check AbstractInterruptibleChannel's closed field - that
167 * field is set before implCloseSelectableChannel is called and so before
168 * the state is changed.
169 *
170 * @throws ClosedChannelException if channel is closed (or closing)
171 * @throws NotYetConnectedException if open and not connected
172 */
173 private void ensureOpenAndConnected() throws ClosedChannelException {
174 int state = this.state;
175 if (state < ST_CONNECTED) {
176 throw new NotYetConnectedException();
177 } else if (state > ST_CONNECTED) {
178 throw new ClosedChannelException();
179 }
180 }
181
182 @Override
183 public Socket socket() {
184 synchronized (stateLock) {
185 if (socket == null)
186 socket = SocketAdaptor.create(this);
187 return socket;
188 }
189 }
190
191 @Override
192 public SocketAddress getLocalAddress() throws IOException {
193 synchronized (stateLock) {
194 ensureOpen();
195 return Net.getRevealedLocalAddress(localAddress);
196 }
197 }
198
199 @Override
200 public SocketAddress getRemoteAddress() throws IOException {
201 synchronized (stateLock) {
283 set.addAll(ExtendedSocketOptions.getInstance().options());
284 return Collections.unmodifiableSet(set);
285 }
286 }
287
288 @Override
289 public final Set<SocketOption<?>> supportedOptions() {
290 return DefaultOptionsHolder.defaultOptions;
291 }
292
293 /**
294 * Marks the beginning of a read operation that might block.
295 *
296 * @throws ClosedChannelException if the channel is closed
297 * @throws NotYetConnectedException if the channel is not yet connected
298 */
299 private void beginRead(boolean blocking) throws ClosedChannelException {
300 if (blocking) {
301 // set hook for Thread.interrupt
302 begin();
303
304 synchronized (stateLock) {
305 ensureOpenAndConnected();
306 // record thread so it can be signalled if needed
307 readerThread = NativeThread.current();
308 }
309 } else {
310 ensureOpenAndConnected();
311 }
312 }
313
314 /**
315 * Marks the end of a read operation that may have blocked.
316 *
317 * @throws AsynchronousCloseException if the channel was closed due to this
318 * thread being interrupted on a blocking read operation.
319 */
320 private void endRead(boolean blocking, boolean completed)
321 throws AsynchronousCloseException
322 {
323 if (blocking) {
324 synchronized (stateLock) {
325 readerThread = 0;
326 // notify any thread waiting in implCloseSelectableChannel
327 if (state == ST_CLOSING) {
328 stateLock.notifyAll();
329 }
330 }
331 // remove hook for Thread.interrupt
394 endRead(blocking, n > 0);
395 if (n <= 0 && isInputClosed)
396 return IOStatus.EOF;
397 }
398 return IOStatus.normalize(n);
399 } finally {
400 readLock.unlock();
401 }
402 }
403
404 /**
405 * Marks the beginning of a write operation that might block.
406 *
407 * @throws ClosedChannelException if the channel is closed or output shutdown
408 * @throws NotYetConnectedException if the channel is not yet connected
409 */
410 private void beginWrite(boolean blocking) throws ClosedChannelException {
411 if (blocking) {
412 // set hook for Thread.interrupt
413 begin();
414
415 synchronized (stateLock) {
416 ensureOpenAndConnected();
417 if (isOutputClosed)
418 throw new ClosedChannelException();
419 // record thread so it can be signalled if needed
420 writerThread = NativeThread.current();
421 }
422 } else {
423 ensureOpenAndConnected();
424 }
425 }
426
427 /**
428 * Marks the end of a write operation that may have blocked.
429 *
430 * @throws AsynchronousCloseException if the channel was closed due to this
431 * thread being interrupted on a blocking write operation.
432 */
433 private void endWrite(boolean blocking, boolean completed)
434 throws AsynchronousCloseException
435 {
436 if (blocking) {
437 synchronized (stateLock) {
438 writerThread = 0;
439 // notify any thread waiting in implCloseSelectableChannel
440 if (state == ST_CLOSING) {
441 stateLock.notifyAll();
442 }
443 }
444 // remove hook for Thread.interrupt
622 throws IOException
623 {
624 if (blocking) {
625 // set hook for Thread.interrupt
626 begin();
627 }
628 synchronized (stateLock) {
629 ensureOpen();
630 int state = this.state;
631 if (state == ST_CONNECTED)
632 throw new AlreadyConnectedException();
633 if (state == ST_CONNECTIONPENDING)
634 throw new ConnectionPendingException();
635 assert state == ST_UNCONNECTED;
636 this.state = ST_CONNECTIONPENDING;
637
638 if (localAddress == null)
639 NetHooks.beforeTcpConnect(fd, isa.getAddress(), isa.getPort());
640 remoteAddress = isa;
641
642 if (blocking) {
643 // record thread so it can be signalled if needed
644 readerThread = NativeThread.current();
645 }
646 }
647 }
648
649 /**
650 * Marks the end of a connect operation that may have blocked.
651 *
652 * @throws AsynchronousCloseException if the channel was closed due to this
653 * thread being interrupted on a blocking connect operation.
654 * @throws IOException if completed and unable to obtain the local address
655 */
656 private void endConnect(boolean blocking, boolean completed)
657 throws IOException
658 {
659 endRead(blocking, completed);
660
661 if (completed) {
662 synchronized (stateLock) {
663 if (state == ST_CONNECTIONPENDING) {
664 localAddress = Net.localAddress(fd);
665 state = ST_CONNECTED;
666 }
667 }
707 close();
708 throw ioe;
709 }
710 }
711
712 /**
713 * Marks the beginning of a finishConnect operation that might block.
714 *
715 * @throws ClosedChannelException if the channel is closed
716 * @throws NoConnectionPendingException if no connection is pending
717 */
718 private void beginFinishConnect(boolean blocking) throws ClosedChannelException {
719 if (blocking) {
720 // set hook for Thread.interrupt
721 begin();
722 }
723 synchronized (stateLock) {
724 ensureOpen();
725 if (state != ST_CONNECTIONPENDING)
726 throw new NoConnectionPendingException();
727 if (blocking) {
728 // record thread so it can be signalled if needed
729 readerThread = NativeThread.current();
730 }
731 }
732 }
733
734 /**
735 * Marks the end of a finishConnect operation that may have blocked.
736 *
737 * @throws AsynchronousCloseException if the channel was closed due to this
738 * thread being interrupted on a blocking connect operation.
739 * @throws IOException if completed and unable to obtain the local address
740 */
741 private void endFinishConnect(boolean blocking, boolean completed)
742 throws IOException
743 {
744 endRead(blocking, completed);
745
746 if (completed) {
747 synchronized (stateLock) {
748 if (state == ST_CONNECTIONPENDING) {
749 localAddress = Net.localAddress(fd);
750 state = ST_CONNECTED;
751 }
752 }
|