src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java
changeset 55081 dd321e3596c0
parent 48737 7c12219870fd
child 55375 96c7427456f9
child 58678 9cf78a70fa4f
equal deleted inserted replaced
55080:ef713640430e 55081:dd321e3596c0
     1 /*
     1 /*
     2  * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    26 
    26 
    27 import java.io.FileDescriptor;
    27 import java.io.FileDescriptor;
    28 import java.io.IOException;
    28 import java.io.IOException;
    29 import java.util.Collections;
    29 import java.util.Collections;
    30 import java.util.HashSet;
    30 import java.util.HashSet;
       
    31 import java.util.Objects;
    31 import java.util.Set;
    32 import java.util.Set;
    32 
    33 
    33 import sun.net.ResourceManager;
    34 import sun.net.ResourceManager;
       
    35 import sun.net.ext.ExtendedSocketOptions;
    34 import sun.security.action.GetPropertyAction;
    36 import sun.security.action.GetPropertyAction;
    35 
    37 
    36 /**
    38 /**
    37  * Abstract datagram and multicast socket implementation base class.
    39  * Abstract datagram and multicast socket implementation base class.
    38  * Note: This is not a public class, so that applets cannot call
    40  * Note: This is not a public class, so that applets cannot call
    83         if (!checkedReusePort) {
    85         if (!checkedReusePort) {
    84             isReusePortAvailable = isReusePortAvailable0();
    86             isReusePortAvailable = isReusePortAvailable0();
    85             checkedReusePort = true;
    87             checkedReusePort = true;
    86         }
    88         }
    87         return isReusePortAvailable;
    89         return isReusePortAvailable;
    88     }
       
    89 
       
    90     /**
       
    91      * Returns a set of SocketOptions supported by this impl and by this impl's
       
    92      * socket (Socket or ServerSocket)
       
    93      *
       
    94      * @return a Set of SocketOptions
       
    95      */
       
    96     @Override
       
    97     protected Set<SocketOption<?>> supportedOptions() {
       
    98         Set<SocketOption<?>> options;
       
    99         if (isReusePortAvailable()) {
       
   100             options = new HashSet<>();
       
   101             options.addAll(super.supportedOptions());
       
   102             options.add(StandardSocketOptions.SO_REUSEPORT);
       
   103             options = Collections.unmodifiableSet(options);
       
   104         } else {
       
   105             options = super.supportedOptions();
       
   106         }
       
   107         return options;
       
   108     }
    90     }
   109 
    91 
   110     /**
    92     /**
   111      * Creates a datagram socket
    93      * Creates a datagram socket
   112      */
    94      */
   398         }
   380         }
   399 
   381 
   400         return result;
   382         return result;
   401     }
   383     }
   402 
   384 
       
   385     static final ExtendedSocketOptions extendedOptions =
       
   386             ExtendedSocketOptions.getInstance();
       
   387 
       
   388     private static final Set<SocketOption<?>> datagramSocketOptions = datagramSocketOptions();
       
   389     private static final Set<SocketOption<?>> multicastSocketOptions = multicastSocketOptions();
       
   390 
       
   391     private static Set<SocketOption<?>> datagramSocketOptions() {
       
   392         HashSet<SocketOption<?>> options = new HashSet<>();
       
   393         options.add(StandardSocketOptions.SO_SNDBUF);
       
   394         options.add(StandardSocketOptions.SO_RCVBUF);
       
   395         options.add(StandardSocketOptions.SO_REUSEADDR);
       
   396         options.add(StandardSocketOptions.IP_TOS);
       
   397         if (isReusePortAvailable())
       
   398             options.add(StandardSocketOptions.SO_REUSEPORT);
       
   399         options.addAll(ExtendedSocketOptions.datagramSocketOptions());
       
   400         return Collections.unmodifiableSet(options);
       
   401     }
       
   402 
       
   403     private static Set<SocketOption<?>> multicastSocketOptions() {
       
   404         HashSet<SocketOption<?>> options = new HashSet<>();
       
   405         options.add(StandardSocketOptions.SO_SNDBUF);
       
   406         options.add(StandardSocketOptions.SO_RCVBUF);
       
   407         options.add(StandardSocketOptions.SO_REUSEADDR);
       
   408         options.add(StandardSocketOptions.IP_TOS);
       
   409         options.add(StandardSocketOptions.IP_MULTICAST_IF);
       
   410         options.add(StandardSocketOptions.IP_MULTICAST_TTL);
       
   411         options.add(StandardSocketOptions.IP_MULTICAST_LOOP);
       
   412         if (isReusePortAvailable())
       
   413             options.add(StandardSocketOptions.SO_REUSEPORT);
       
   414         options.addAll(ExtendedSocketOptions.datagramSocketOptions());
       
   415         return Collections.unmodifiableSet(options);
       
   416     }
       
   417 
       
   418     @Override
       
   419     protected Set<SocketOption<?>> supportedOptions() {
       
   420         if (getDatagramSocket() instanceof MulticastSocket)
       
   421             return multicastSocketOptions;
       
   422         else
       
   423             return datagramSocketOptions;
       
   424     }
       
   425 
       
   426     @Override
       
   427     protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
       
   428         Objects.requireNonNull(name);
       
   429         if (!supportedOptions().contains(name))
       
   430             throw new UnsupportedOperationException("'" + name + "' not supported");
       
   431 
       
   432         if (!name.type().isInstance(value))
       
   433             throw new IllegalArgumentException("Invalid value '" + value + "'");
       
   434 
       
   435         if (isClosed())
       
   436             throw new SocketException("Socket closed");
       
   437 
       
   438         if (name == StandardSocketOptions.SO_SNDBUF) {
       
   439             if (((Integer)value).intValue() < 0)
       
   440                 throw new IllegalArgumentException("Invalid send buffer size:" + value);
       
   441             setOption(SocketOptions.SO_SNDBUF, value);
       
   442         } else if (name == StandardSocketOptions.SO_RCVBUF) {
       
   443             if (((Integer)value).intValue() < 0)
       
   444                 throw new IllegalArgumentException("Invalid recv buffer size:" + value);
       
   445             setOption(SocketOptions.SO_RCVBUF, value);
       
   446         } else if (name == StandardSocketOptions.SO_REUSEADDR) {
       
   447             setOption(SocketOptions.SO_REUSEADDR, value);
       
   448         } else if (name == StandardSocketOptions.SO_REUSEPORT) {
       
   449             setOption(SocketOptions.SO_REUSEPORT, 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.IP_MULTICAST_IF ) {
       
   456             setOption(SocketOptions.IP_MULTICAST_IF2, value);
       
   457         } else if (name == StandardSocketOptions.IP_MULTICAST_TTL) {
       
   458             int i = ((Integer)value).intValue();
       
   459             if (i < 0 || i > 255)
       
   460                 throw new IllegalArgumentException("Invalid TTL/hop value: " + value);
       
   461             setTimeToLive((Integer)value);
       
   462         } else if (name == StandardSocketOptions.IP_MULTICAST_LOOP) {
       
   463             setOption(SocketOptions.IP_MULTICAST_LOOP, value);
       
   464         } else if (extendedOptions.isOptionSupported(name)) {
       
   465             extendedOptions.setOption(fd, name, value);
       
   466         } else {
       
   467             throw new AssertionError("unknown option :" + name);
       
   468         }
       
   469     }
       
   470 
       
   471     @Override
       
   472     @SuppressWarnings("unchecked")
       
   473     protected <T> T getOption(SocketOption<T> name) throws IOException {
       
   474         Objects.requireNonNull(name);
       
   475         if (!supportedOptions().contains(name))
       
   476             throw new UnsupportedOperationException("'" + name + "' not supported");
       
   477 
       
   478         if (isClosed())
       
   479             throw new SocketException("Socket closed");
       
   480 
       
   481         if (name == StandardSocketOptions.SO_SNDBUF) {
       
   482             return (T) getOption(SocketOptions.SO_SNDBUF);
       
   483         } else if (name == StandardSocketOptions.SO_RCVBUF) {
       
   484             return (T) getOption(SocketOptions.SO_RCVBUF);
       
   485         } else if (name == StandardSocketOptions.SO_REUSEADDR) {
       
   486             return (T) getOption(SocketOptions.SO_REUSEADDR);
       
   487         } else if (name == StandardSocketOptions.SO_REUSEPORT) {
       
   488             return (T) getOption(SocketOptions.SO_REUSEPORT);
       
   489         } else if (name == StandardSocketOptions.IP_TOS) {
       
   490             return (T) getOption(SocketOptions.IP_TOS);
       
   491         } else if (name == StandardSocketOptions.IP_MULTICAST_IF) {
       
   492             return (T) getOption(SocketOptions.IP_MULTICAST_IF2);
       
   493         } else if (name == StandardSocketOptions.IP_MULTICAST_TTL) {
       
   494             return (T) ((Integer) getTimeToLive());
       
   495         } else if (name == StandardSocketOptions.IP_MULTICAST_LOOP) {
       
   496             return (T) getOption(SocketOptions.IP_MULTICAST_LOOP);
       
   497         } else if (extendedOptions.isOptionSupported(name)) {
       
   498             return (T) extendedOptions.getOption(fd, name);
       
   499         } else {
       
   500             throw new AssertionError("unknown option: " + name);
       
   501         }
       
   502     }
       
   503 
   403     protected abstract void datagramSocketCreate() throws SocketException;
   504     protected abstract void datagramSocketCreate() throws SocketException;
   404     protected abstract void datagramSocketClose();
   505     protected abstract void datagramSocketClose();
   405     protected abstract void socketSetOption(int opt, Object val)
   506     protected abstract void socketSetOption(int opt, Object val)
   406         throws SocketException;
   507         throws SocketException;
   407     protected abstract Object socketGetOption(int opt) throws SocketException;
   508     protected abstract Object socketGetOption(int opt) throws SocketException;