src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java
changeset 55081 dd321e3596c0
parent 54689 b28b7f631301
child 55226 ce8bab2c4185
child 57382 14e01d39c01a
equal deleted inserted replaced
55080:ef713640430e 55081:dd321e3596c0
    33 import java.security.AccessController;
    33 import java.security.AccessController;
    34 import java.security.PrivilegedActionException;
    34 import java.security.PrivilegedActionException;
    35 import java.security.PrivilegedExceptionAction;
    35 import java.security.PrivilegedExceptionAction;
    36 import java.util.Collections;
    36 import java.util.Collections;
    37 import java.util.HashSet;
    37 import java.util.HashSet;
       
    38 import java.util.Objects;
    38 import java.util.Set;
    39 import java.util.Set;
    39 
    40 
    40 import sun.net.ConnectionResetException;
    41 import sun.net.ConnectionResetException;
    41 import sun.net.NetHooks;
    42 import sun.net.NetHooks;
    42 import sun.net.PlatformSocketImpl;
    43 import sun.net.PlatformSocketImpl;
    43 import sun.net.ResourceManager;
    44 import sun.net.ResourceManager;
       
    45 import sun.net.ext.ExtendedSocketOptions;
    44 import sun.net.util.SocketExceptions;
    46 import sun.net.util.SocketExceptions;
    45 
    47 
    46 /**
    48 /**
    47  * Default Socket Implementation. This implementation does
    49  * Default Socket Implementation. This implementation does
    48  * not implement any security checks.
    50  * not implement any security checks.
    82 
    84 
    83    /* whether this Socket is a stream (TCP) socket or not (UDP)
    85    /* whether this Socket is a stream (TCP) socket or not (UDP)
    84     */
    86     */
    85     protected boolean stream;
    87     protected boolean stream;
    86 
    88 
       
    89     /* whether this is a server or not */
       
    90     final boolean isServer;
       
    91 
    87     /**
    92     /**
    88      * Load net library into runtime.
    93      * Load net library into runtime.
    89      */
    94      */
    90     static {
    95     static {
    91         java.security.AccessController.doPrivileged(
    96         java.security.AccessController.doPrivileged(
   110         }
   115         }
   111         return isReusePortAvailable;
   116         return isReusePortAvailable;
   112     }
   117     }
   113 
   118 
   114     AbstractPlainSocketImpl(boolean isServer) {
   119     AbstractPlainSocketImpl(boolean isServer) {
   115         super(isServer);
   120         this.isServer = isServer;
   116     }
       
   117 
       
   118     /**
       
   119      * Returns a set of SocketOptions supported by this impl and by this impl's
       
   120      * socket (Socket or ServerSocket)
       
   121      *
       
   122      * @return a Set of SocketOptions
       
   123      */
       
   124     @Override
       
   125     protected Set<SocketOption<?>> supportedOptions() {
       
   126         Set<SocketOption<?>> options;
       
   127         if (isReusePortAvailable()) {
       
   128             options = new HashSet<>();
       
   129             options.addAll(super.supportedOptions());
       
   130             options.add(StandardSocketOptions.SO_REUSEPORT);
       
   131             options = Collections.unmodifiableSet(options);
       
   132         } else {
       
   133             options = super.supportedOptions();
       
   134         }
       
   135         return options;
       
   136     }
   121     }
   137 
   122 
   138     /**
   123     /**
   139      * Creates a socket with a boolean that specifies whether this
   124      * Creates a socket with a boolean that specifies whether this
   140      * is a stream socket (true) or an unconnected UDP socket (false).
   125      * is a stream socket (true) or an unconnected UDP socket (false).
   389             ret = socketGetOption(opt, null);
   374             ret = socketGetOption(opt, null);
   390             return Boolean.valueOf(ret != -1);
   375             return Boolean.valueOf(ret != -1);
   391         // should never get here
   376         // should never get here
   392         default:
   377         default:
   393             return null;
   378             return null;
       
   379         }
       
   380     }
       
   381 
       
   382     static final ExtendedSocketOptions extendedOptions =
       
   383             ExtendedSocketOptions.getInstance();
       
   384 
       
   385     private static final Set<SocketOption<?>> clientSocketOptions = clientSocketOptions();
       
   386     private static final Set<SocketOption<?>> serverSocketOptions = serverSocketOptions();
       
   387 
       
   388     private static Set<SocketOption<?>> clientSocketOptions() {
       
   389         HashSet<SocketOption<?>> options = new HashSet<>();
       
   390         options.add(StandardSocketOptions.SO_KEEPALIVE);
       
   391         options.add(StandardSocketOptions.SO_SNDBUF);
       
   392         options.add(StandardSocketOptions.SO_RCVBUF);
       
   393         options.add(StandardSocketOptions.SO_REUSEADDR);
       
   394         options.add(StandardSocketOptions.SO_LINGER);
       
   395         options.add(StandardSocketOptions.IP_TOS);
       
   396         options.add(StandardSocketOptions.TCP_NODELAY);
       
   397         if (isReusePortAvailable())
       
   398             options.add(StandardSocketOptions.SO_REUSEPORT);
       
   399         options.addAll(ExtendedSocketOptions.clientSocketOptions());
       
   400         return Collections.unmodifiableSet(options);
       
   401     }
       
   402 
       
   403     private static Set<SocketOption<?>> serverSocketOptions() {
       
   404         HashSet<SocketOption<?>> options = new HashSet<>();
       
   405         options.add(StandardSocketOptions.SO_RCVBUF);
       
   406         options.add(StandardSocketOptions.SO_REUSEADDR);
       
   407         options.add(StandardSocketOptions.IP_TOS);
       
   408         if (isReusePortAvailable())
       
   409             options.add(StandardSocketOptions.SO_REUSEPORT);
       
   410         options.addAll(ExtendedSocketOptions.serverSocketOptions());
       
   411         return Collections.unmodifiableSet(options);
       
   412     }
       
   413 
       
   414     @Override
       
   415     protected Set<SocketOption<?>> supportedOptions() {
       
   416         if (isServer)
       
   417             return serverSocketOptions;
       
   418         else
       
   419             return clientSocketOptions;
       
   420     }
       
   421 
       
   422     @Override
       
   423     protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
       
   424         Objects.requireNonNull(name);
       
   425         if (!supportedOptions().contains(name))
       
   426             throw new UnsupportedOperationException("'" + name + "' not supported");
       
   427 
       
   428         if (!name.type().isInstance(value))
       
   429             throw new IllegalArgumentException("Invalid value '" + value + "'");
       
   430 
       
   431         if (isClosedOrPending())
       
   432             throw new SocketException("Socket closed");
       
   433 
       
   434         if (name == StandardSocketOptions.SO_KEEPALIVE) {
       
   435             setOption(SocketOptions.SO_KEEPALIVE, value);
       
   436         } else if (name == StandardSocketOptions.SO_SNDBUF) {
       
   437             if (((Integer)value).intValue() < 0)
       
   438                 throw new IllegalArgumentException("Invalid send buffer size:" + value);
       
   439             setOption(SocketOptions.SO_SNDBUF, value);
       
   440         } else if (name == StandardSocketOptions.SO_RCVBUF) {
       
   441             if (((Integer)value).intValue() < 0)
       
   442                 throw new IllegalArgumentException("Invalid recv buffer size:" + value);
       
   443             setOption(SocketOptions.SO_RCVBUF, value);
       
   444         } else if (name == StandardSocketOptions.SO_REUSEADDR) {
       
   445             setOption(SocketOptions.SO_REUSEADDR, value);
       
   446         } else if (name == StandardSocketOptions.SO_REUSEPORT) {
       
   447             setOption(SocketOptions.SO_REUSEPORT, value);
       
   448         } else if (name == StandardSocketOptions.SO_LINGER ) {
       
   449             setOption(SocketOptions.SO_LINGER, value);
       
   450         } else if (name == StandardSocketOptions.IP_TOS) {
       
   451             int i = ((Integer)value).intValue();
       
   452             if (i < 0 || i > 255)
       
   453                 throw new IllegalArgumentException("Invalid IP_TOS value: " + value);
       
   454             setOption(SocketOptions.IP_TOS, value);
       
   455         } else if (name == StandardSocketOptions.TCP_NODELAY) {
       
   456             setOption(SocketOptions.TCP_NODELAY, value);
       
   457         } else if (extendedOptions.isOptionSupported(name)) {
       
   458             extendedOptions.setOption(fd, name, value);
       
   459         } else {
       
   460             throw new AssertionError("unknown option: " + name);
       
   461         }
       
   462     }
       
   463 
       
   464     @Override
       
   465     @SuppressWarnings("unchecked")
       
   466     protected <T> T getOption(SocketOption<T> name) throws IOException {
       
   467         Objects.requireNonNull(name);
       
   468         if (!supportedOptions().contains(name))
       
   469             throw new UnsupportedOperationException("'" + name + "' not supported");
       
   470 
       
   471         if (isClosedOrPending())
       
   472             throw new SocketException("Socket closed");
       
   473 
       
   474         if (name == StandardSocketOptions.SO_KEEPALIVE) {
       
   475             return (T)getOption(SocketOptions.SO_KEEPALIVE);
       
   476         } else if (name == StandardSocketOptions.SO_SNDBUF) {
       
   477             return (T)getOption(SocketOptions.SO_SNDBUF);
       
   478         } else if (name == StandardSocketOptions.SO_RCVBUF) {
       
   479             return (T)getOption(SocketOptions.SO_RCVBUF);
       
   480         } else if (name == StandardSocketOptions.SO_REUSEADDR) {
       
   481             return (T)getOption(SocketOptions.SO_REUSEADDR);
       
   482         } else if (name == StandardSocketOptions.SO_REUSEPORT) {
       
   483             return (T)getOption(SocketOptions.SO_REUSEPORT);
       
   484         } else if (name == StandardSocketOptions.SO_LINGER) {
       
   485             return (T)getOption(SocketOptions.SO_LINGER);
       
   486         } else if (name == StandardSocketOptions.IP_TOS) {
       
   487             return (T)getOption(SocketOptions.IP_TOS);
       
   488         } else if (name == StandardSocketOptions.TCP_NODELAY) {
       
   489             return (T)getOption(SocketOptions.TCP_NODELAY);
       
   490         } else if (extendedOptions.isOptionSupported(name)) {
       
   491             return (T) extendedOptions.getOption(fd, name);
       
   492         } else {
       
   493             throw new AssertionError("unknown option: " + name);
   394         }
   494         }
   395     }
   495     }
   396 
   496 
   397     /**
   497     /**
   398      * The workhorse of the connection operation.  Tries several times to
   498      * The workhorse of the connection operation.  Tries several times to