src/java.base/share/classes/java/net/Socket.java
branchniosocketimpl-branch
changeset 57347 16c087c9103e
parent 57344 8b621b0d921c
parent 54689 b28b7f631301
child 57382 14e01d39c01a
equal deleted inserted replaced
57344:8b621b0d921c 57347:16c087c9103e
    70      * The implementation of this Socket.
    70      * The implementation of this Socket.
    71      */
    71      */
    72     SocketImpl impl;
    72     SocketImpl impl;
    73 
    73 
    74     /**
    74     /**
    75      * Are we using an older SocketImpl?
       
    76      */
       
    77     private boolean oldImpl = false;
       
    78 
       
    79     /**
       
    80      * Socket input/output streams
    75      * Socket input/output streams
    81      */
    76      */
    82     private volatile InputStream in;
    77     private volatile InputStream in;
    83     private volatile OutputStream out;
    78     private volatile OutputStream out;
    84     private static final VarHandle IN, OUT;
    79     private static final VarHandle IN, OUT;
   156             }
   151             }
   157 
   152 
   158             // create a SOCKS or HTTP SocketImpl that delegates to a platform SocketImpl
   153             // create a SOCKS or HTTP SocketImpl that delegates to a platform SocketImpl
   159             SocketImpl delegate = SocketImpl.createPlatformSocketImpl(false);
   154             SocketImpl delegate = SocketImpl.createPlatformSocketImpl(false);
   160             impl = (type == Proxy.Type.SOCKS) ? new SocksSocketImpl(p, delegate)
   155             impl = (type == Proxy.Type.SOCKS) ? new SocksSocketImpl(p, delegate)
   161                                               : new HttpConnectSocketImpl(p, delegate);
   156                                               : new HttpConnectSocketImpl(p, delegate, this);
   162             impl.setSocket(this);
       
   163         } else {
   157         } else {
   164             if (p == Proxy.NO_PROXY) {
   158             if (p == Proxy.NO_PROXY) {
   165                 // create a platform or custom SocketImpl for the DIRECT case
   159                 // create a platform or custom SocketImpl for the DIRECT case
   166                 SocketImplFactory factory = Socket.factory;
   160                 SocketImplFactory factory = Socket.factory;
   167                 if (factory == null) {
   161                 if (factory == null) {
   168                     impl = SocketImpl.createPlatformSocketImpl(false);
   162                     impl = SocketImpl.createPlatformSocketImpl(false);
   169                 } else {
   163                 } else {
   170                     impl = factory.createSocketImpl();
   164                     impl = factory.createSocketImpl();
   171                 }
   165                 }
   172                 impl.setSocket(this);
       
   173             } else
   166             } else
   174                 throw new IllegalArgumentException("Invalid Proxy");
   167                 throw new IllegalArgumentException("Invalid Proxy");
   175         }
   168         }
   176     }
   169     }
   177 
   170 
   186      * such as a TCP error.
   179      * such as a TCP error.
   187      * @since   1.1
   180      * @since   1.1
   188      */
   181      */
   189     protected Socket(SocketImpl impl) throws SocketException {
   182     protected Socket(SocketImpl impl) throws SocketException {
   190         this.impl = impl;
   183         this.impl = impl;
   191         if (impl != null) {
       
   192             checkOldImpl();
       
   193             this.impl.setSocket(this);
       
   194         }
       
   195     }
   184     }
   196 
   185 
   197     /**
   186     /**
   198      * Creates a stream socket and connects it to the specified port
   187      * Creates a stream socket and connects it to the specified port
   199      * number on the named host.
   188      * number on the named host.
   484         } catch (IOException e) {
   473         } catch (IOException e) {
   485             throw new SocketException(e.getMessage());
   474             throw new SocketException(e.getMessage());
   486         }
   475         }
   487     }
   476     }
   488 
   477 
   489     private void checkOldImpl() {
       
   490         if (impl == null)
       
   491             return;
       
   492         // SocketImpl.connect() is a protected method, therefore we need to use
       
   493         // getDeclaredMethod, therefore we need permission to access the member
       
   494 
       
   495         oldImpl = AccessController.doPrivileged
       
   496                                 (new PrivilegedAction<>() {
       
   497             public Boolean run() {
       
   498                 Class<?> clazz = impl.getClass();
       
   499                 while (true) {
       
   500                     try {
       
   501                         clazz.getDeclaredMethod("connect", SocketAddress.class, int.class);
       
   502                         return Boolean.FALSE;
       
   503                     } catch (NoSuchMethodException e) {
       
   504                         clazz = clazz.getSuperclass();
       
   505                         // java.net.SocketImpl class will always have this abstract method.
       
   506                         // If we have not found it by now in the hierarchy then it does not
       
   507                         // exist, we are an old style impl.
       
   508                         if (clazz.equals(java.net.SocketImpl.class)) {
       
   509                             return Boolean.TRUE;
       
   510                         }
       
   511                     }
       
   512                 }
       
   513             }
       
   514         });
       
   515     }
       
   516 
       
   517     void setImpl(SocketImpl si) {
   478     void setImpl(SocketImpl si) {
   518          impl = si;
   479          impl = si;
   519          impl.setSocket(this);
       
   520     }
   480     }
   521 
   481 
   522     /**
   482     /**
   523      * Sets impl to the system-default type of SocketImpl.
   483      * Sets impl to the system-default type of SocketImpl.
   524      * @since 1.4
   484      * @since 1.4
   525      */
   485      */
   526     void setImpl() {
   486     void setImpl() {
   527         SocketImplFactory factory = Socket.factory;
   487         SocketImplFactory factory = Socket.factory;
   528         if (factory != null) {
   488         if (factory != null) {
   529             impl = factory.createSocketImpl();
   489             impl = factory.createSocketImpl();
   530             checkOldImpl();
       
   531         } else {
   490         } else {
   532             // create a SOCKS SocketImpl that delegates to a platform SocketImpl
   491             // create a SOCKS SocketImpl that delegates to a platform SocketImpl
   533             SocketImpl delegate = SocketImpl.createPlatformSocketImpl(false);
   492             SocketImpl delegate = SocketImpl.createPlatformSocketImpl(false);
   534             impl = new SocksSocketImpl(delegate);
   493             impl = new SocksSocketImpl(delegate);
   535         }
   494         }
   536         if (impl != null)
       
   537             impl.setSocket(this);
       
   538     }
   495     }
   539 
   496 
   540     /**
   497     /**
   541      * Get the {@code SocketImpl} attached to this socket, creating
   498      * Get the {@code SocketImpl} attached to this socket, creating
   542      * it if necessary.
   499      * it if necessary.
   594           throw new IllegalArgumentException("connect: timeout can't be negative");
   551           throw new IllegalArgumentException("connect: timeout can't be negative");
   595 
   552 
   596         if (isClosed())
   553         if (isClosed())
   597             throw new SocketException("Socket is closed");
   554             throw new SocketException("Socket is closed");
   598 
   555 
   599         if (!oldImpl && isConnected())
   556         if (isConnected())
   600             throw new SocketException("already connected");
   557             throw new SocketException("already connected");
   601 
   558 
   602         if (!(endpoint instanceof InetSocketAddress))
   559         if (!(endpoint instanceof InetSocketAddress))
   603             throw new IllegalArgumentException("Unsupported address type");
   560             throw new IllegalArgumentException("Unsupported address type");
   604 
   561 
   614             else
   571             else
   615                 security.checkConnect(addr.getHostAddress(), port);
   572                 security.checkConnect(addr.getHostAddress(), port);
   616         }
   573         }
   617         if (!created)
   574         if (!created)
   618             createImpl(true);
   575             createImpl(true);
   619         if (!oldImpl)
   576         impl.connect(epoint, timeout);
   620             impl.connect(epoint, timeout);
       
   621         else if (timeout == 0) {
       
   622             if (epoint.isUnresolved())
       
   623                 impl.connect(addr.getHostName(), port);
       
   624             else
       
   625                 impl.connect(addr, port);
       
   626         } else
       
   627             throw new UnsupportedOperationException("SocketImpl.connect(addr, timeout)");
       
   628         connected = true;
   577         connected = true;
   629         /*
   578         /*
   630          * If the socket was not bound before the connect, it is now because
   579          * If the socket was not bound before the connect, it is now because
   631          * the kernel will have picked an ephemeral port & a local address
   580          * the kernel will have picked an ephemeral port & a local address
   632          */
   581          */
   652      * @see #isBound
   601      * @see #isBound
   653      */
   602      */
   654     public void bind(SocketAddress bindpoint) throws IOException {
   603     public void bind(SocketAddress bindpoint) throws IOException {
   655         if (isClosed())
   604         if (isClosed())
   656             throw new SocketException("Socket is closed");
   605             throw new SocketException("Socket is closed");
   657         if (!oldImpl && isBound())
   606         if (isBound())
   658             throw new SocketException("Already bound");
   607             throw new SocketException("Already bound");
   659 
   608 
   660         if (bindpoint != null && (!(bindpoint instanceof InetSocketAddress)))
   609         if (bindpoint != null && (!(bindpoint instanceof InetSocketAddress)))
   661             throw new IllegalArgumentException("Unsupported address type");
   610             throw new IllegalArgumentException("Unsupported address type");
   662         InetSocketAddress epoint = (InetSocketAddress) bindpoint;
   611         InetSocketAddress epoint = (InetSocketAddress) bindpoint;
   690      */
   639      */
   691     final void postAccept() {
   640     final void postAccept() {
   692         connected = true;
   641         connected = true;
   693         created = true;
   642         created = true;
   694         bound = true;
   643         bound = true;
   695     }
       
   696 
       
   697     void setCreated() {
       
   698         created = true;
       
   699     }
       
   700 
       
   701     void setBound() {
       
   702         bound = true;
       
   703     }
       
   704 
       
   705     void setConnected() {
       
   706         connected = true;
       
   707     }
   644     }
   708 
   645 
   709     /**
   646     /**
   710      * Returns the address to which the socket is connected.
   647      * Returns the address to which the socket is connected.
   711      * <p>
   648      * <p>
   955      * I/O events.
   892      * I/O events.
   956      */
   893      */
   957     private static class SocketInputStream extends InputStream {
   894     private static class SocketInputStream extends InputStream {
   958         private final Socket parent;
   895         private final Socket parent;
   959         private final InputStream in;
   896         private final InputStream in;
       
   897 
   960         SocketInputStream(Socket parent, InputStream in) {
   898         SocketInputStream(Socket parent, InputStream in) {
   961             this.parent = parent;
   899             this.parent = parent;
   962             this.in = in;
   900             this.in = in;
   963         }
   901         }
   964         @Override
   902         @Override
   973         }
   911         }
   974         @Override
   912         @Override
   975         public int available() throws IOException {
   913         public int available() throws IOException {
   976             return in.available();
   914             return in.available();
   977         }
   915         }
       
   916 
   978         @Override
   917         @Override
   979         public void close() throws IOException {
   918         public void close() throws IOException {
   980             parent.close();
   919             parent.close();
   981         }
   920         }
   982     }
   921     }
  1038         }
   977         }
  1039         @Override
   978         @Override
  1040         public void write(byte b[], int off, int len) throws IOException {
   979         public void write(byte b[], int off, int len) throws IOException {
  1041             out.write(b, off, len);
   980             out.write(b, off, len);
  1042         }
   981         }
       
   982 
  1043         @Override
   983         @Override
  1044         public void close() throws IOException {
   984         public void close() throws IOException {
  1045             parent.close();
   985             parent.close();
  1046         }
   986         }
  1047     }
   987     }
  1670      *
  1610      *
  1671      * @return true if the socket was successfully connected to a server
  1611      * @return true if the socket was successfully connected to a server
  1672      * @since 1.4
  1612      * @since 1.4
  1673      */
  1613      */
  1674     public boolean isConnected() {
  1614     public boolean isConnected() {
  1675         // Before 1.3 Sockets were always connected during creation
  1615         return connected;
  1676         return connected || oldImpl;
       
  1677     }
  1616     }
  1678 
  1617 
  1679     /**
  1618     /**
  1680      * Returns the binding state of the socket.
  1619      * Returns the binding state of the socket.
  1681      * <p>
  1620      * <p>
  1687      * @return true if the socket was successfully bound to an address
  1626      * @return true if the socket was successfully bound to an address
  1688      * @since 1.4
  1627      * @since 1.4
  1689      * @see #bind
  1628      * @see #bind
  1690      */
  1629      */
  1691     public boolean isBound() {
  1630     public boolean isBound() {
  1692         // Before 1.3 Sockets were always bound during creation
  1631         return bound;
  1693         return bound || oldImpl;
       
  1694     }
  1632     }
  1695 
  1633 
  1696     /**
  1634     /**
  1697      * Returns the closed state of the socket.
  1635      * Returns the closed state of the socket.
  1698      *
  1636      *