556 if (si instanceof DelegatingSocketImpl) { |
556 if (si instanceof DelegatingSocketImpl) { |
557 si = ((DelegatingSocketImpl) si).delegate(); |
557 si = ((DelegatingSocketImpl) si).delegate(); |
558 assert si instanceof PlatformSocketImpl; |
558 assert si instanceof PlatformSocketImpl; |
559 } |
559 } |
560 |
560 |
561 // accept connection with a platform or custom SocketImpl |
561 // Accept connection with a platform or custom SocketImpl. |
|
562 // For the platform SocketImpl case: |
|
563 // - the connection is accepted with a new SocketImpl |
|
564 // - the SO_TIMEOUT socket option is copied to the new SocketImpl |
|
565 // - the Socket is connected to the new SocketImpl |
|
566 // - the existing/old SocketImpl is closed |
|
567 // For the custom SocketImpl case, the connection is accepted with the |
|
568 // existing custom SocketImpl. |
562 ensureCompatible(si); |
569 ensureCompatible(si); |
563 if (impl instanceof PlatformSocketImpl) { |
570 if (impl instanceof PlatformSocketImpl) { |
564 SocketImpl psi = platformImplAccept(); |
571 SocketImpl psi = platformImplAccept(); |
565 tryCopyOptions(si, psi); |
572 si.copyOptionsTo(psi); |
566 s.setImpl(psi); |
573 s.setImpl(psi); |
567 close(si); |
574 si.closeQuietly(); |
568 } else { |
575 } else { |
569 customImplAccept(s, si); |
576 s.impl = null; // temporarily break connection to impl |
570 assert s.impl == si; |
577 try { |
|
578 customImplAccept(si); |
|
579 } finally { |
|
580 s.impl = si; // restore connection to impl |
|
581 } |
571 } |
582 } |
572 s.postAccept(); |
583 s.postAccept(); |
573 } |
584 } |
574 |
585 |
575 /** |
586 /** |
578 */ |
589 */ |
579 private SocketImpl implAccept() throws IOException { |
590 private SocketImpl implAccept() throws IOException { |
580 if (impl instanceof PlatformSocketImpl) { |
591 if (impl instanceof PlatformSocketImpl) { |
581 return platformImplAccept(); |
592 return platformImplAccept(); |
582 } else { |
593 } else { |
583 // custom server SocketImpl, client socket SocketImpl must be set |
594 // custom server SocketImpl, client SocketImplFactory must be set |
584 SocketImplFactory factory = Socket.socketImplFactory(); |
595 SocketImplFactory factory = Socket.socketImplFactory(); |
585 if (factory == null) { |
596 if (factory == null) { |
586 throw new IOException("An instance of " + impl.getClass() + |
597 throw new IOException("An instance of " + impl.getClass() + |
587 " cannot accept connection with 'null' SocketImpl:" + |
598 " cannot accept connection with 'null' SocketImpl:" + |
588 " client socket implementation factory not set"); |
599 " client socket implementation factory not set"); |
589 } |
600 } |
590 SocketImpl si = factory.createSocketImpl(); |
601 SocketImpl si = factory.createSocketImpl(); |
591 implAccept(si); |
602 customImplAccept(si); |
592 return si; |
603 return si; |
593 } |
604 } |
594 } |
605 } |
595 |
606 |
596 /** |
607 /** |
605 implAccept(psi); |
616 implAccept(psi); |
606 return psi; |
617 return psi; |
607 } |
618 } |
608 |
619 |
609 /** |
620 /** |
610 * Accepts a new connection with a custom SocketImpl. |
621 * Accepts a new connection with the given custom SocketImpl. |
611 */ |
622 */ |
612 private void customImplAccept(Socket s, SocketImpl si) throws IOException { |
623 private void customImplAccept(SocketImpl si) throws IOException { |
613 assert !(impl instanceof PlatformSocketImpl) |
624 assert !(impl instanceof PlatformSocketImpl) |
614 && !(si instanceof PlatformSocketImpl); |
625 && !(si instanceof PlatformSocketImpl); |
615 |
626 |
616 s.impl = null; // break connection to impl |
|
617 si.reset(); |
627 si.reset(); |
618 try { |
628 try { |
|
629 // custom SocketImpl may expect fd/address objects to be created |
|
630 si.fd = new FileDescriptor(); |
|
631 si.address = new InetAddress(); |
619 implAccept(si); |
632 implAccept(si); |
620 } catch (Exception e) { |
633 } catch (Exception e) { |
621 si.reset(); |
634 si.reset(); |
622 throw e; |
635 throw e; |
623 } finally { |
|
624 s.impl = si; // restore connection to impl |
|
625 } |
636 } |
626 } |
637 } |
627 |
638 |
628 /** |
639 /** |
629 * Accepts a new connection so that the given SocketImpl is connected to |
640 * Accepts a new connection so that the given SocketImpl is connected to |
632 * @throws IOException if an I/O error occurs |
643 * @throws IOException if an I/O error occurs |
633 * @throws SecurityException if the security manager's checkAccept method fails |
644 * @throws SecurityException if the security manager's checkAccept method fails |
634 */ |
645 */ |
635 private void implAccept(SocketImpl si) throws IOException { |
646 private void implAccept(SocketImpl si) throws IOException { |
636 assert !(si instanceof DelegatingSocketImpl); |
647 assert !(si instanceof DelegatingSocketImpl); |
637 |
|
638 // custom SocketImpl may expect fd/address objects to be created |
|
639 if (!(si instanceof PlatformSocketImpl)) { |
|
640 si.fd = new FileDescriptor(); |
|
641 si.address = new InetAddress(); |
|
642 } |
|
643 |
648 |
644 // accept a connection |
649 // accept a connection |
645 impl.accept(si); |
650 impl.accept(si); |
646 |
651 |
647 // check permission, close SocketImpl/connection if denied |
652 // check permission, close SocketImpl/connection if denied |
652 } catch (SecurityException se) { |
657 } catch (SecurityException se) { |
653 si.close(); |
658 si.close(); |
654 throw se; |
659 throw se; |
655 } |
660 } |
656 } |
661 } |
657 } |
|
658 |
|
659 /** |
|
660 * Attempts to copy socket options from an old/existing SocketImpl to a new |
|
661 * SocketImpl. At this time, only the SO_TIMEOUT make sense to copy. |
|
662 */ |
|
663 private void tryCopyOptions(SocketImpl oldImpl, SocketImpl newImpl) { |
|
664 try { |
|
665 Object timeout = oldImpl.getOption(SocketOptions.SO_TIMEOUT); |
|
666 if (timeout instanceof Integer) { |
|
667 newImpl.setOption(SocketOptions.SO_TIMEOUT, timeout); |
|
668 } |
|
669 } catch (IOException ignore) { } |
|
670 } |
|
671 |
|
672 /** |
|
673 * Close the given SocketImpl. |
|
674 */ |
|
675 private void close(SocketImpl si) { |
|
676 try { |
|
677 si.close(); |
|
678 } catch (IOException ignore) { } |
|
679 } |
662 } |
680 |
663 |
681 /** |
664 /** |
682 * Throws IOException if the server SocketImpl and the given client |
665 * Throws IOException if the server SocketImpl and the given client |
683 * SocketImpl are not both platform or custom SocketImpls. |
666 * SocketImpl are not both platform or custom SocketImpls. |