< prev index next >

src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java

Print this page


   1 /*
   2  * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   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
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package java.net;
  26 
  27 import java.io.FileDescriptor;
  28 import java.io.IOException;
  29 import java.util.Collections;
  30 import java.util.HashSet;

  31 import java.util.Set;
  32 
  33 import sun.net.ResourceManager;

  34 import sun.security.action.GetPropertyAction;
  35 
  36 /**
  37  * Abstract datagram and multicast socket implementation base class.
  38  * Note: This is not a public class, so that applets cannot call
  39  * into the implementation directly and hence cannot bypass the
  40  * security checks present in the DatagramSocket and MulticastSocket
  41  * classes.
  42  *
  43  * @author Pavani Diwanji
  44  */
  45 
  46 abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
  47 {
  48     /* timeout value for receive() */
  49     int timeout = 0;
  50     boolean connected = false;
  51     private int trafficClass = 0;
  52     protected InetAddress connectedAddress = null;
  53     private int connectedPort = -1;


  71                     return null;
  72                 }
  73             });
  74     }
  75 
  76     private static volatile boolean checkedReusePort;
  77     private static volatile boolean isReusePortAvailable;
  78 
  79     /**
  80      * Tells whether SO_REUSEPORT is supported.
  81      */
  82     static boolean isReusePortAvailable() {
  83         if (!checkedReusePort) {
  84             isReusePortAvailable = isReusePortAvailable0();
  85             checkedReusePort = true;
  86         }
  87         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     }
 109 
 110     /**
 111      * Creates a datagram socket
 112      */
 113     protected synchronized void create() throws SocketException {
 114         ResourceManager.beforeUdpCreate();
 115         fd = new FileDescriptor();
 116         try {
 117             datagramSocketCreate();
 118             SocketCleanable.register(fd);
 119         } catch (SocketException ioe) {
 120             ResourceManager.afterUdpClose();
 121             fd = null;
 122             throw ioe;
 123         }
 124     }
 125 
 126     /**
 127      * Binds a datagram socket to a local port.
 128      */
 129     protected synchronized void bind(int lport, InetAddress laddr)
 130         throws SocketException {


 381             case SO_RCVBUF:
 382             case SO_SNDBUF:
 383             case IP_MULTICAST_LOOP:
 384             case SO_REUSEADDR:
 385             case SO_BROADCAST:
 386                 result = socketGetOption(optID);
 387                 break;
 388 
 389             case SO_REUSEPORT:
 390                 if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
 391                     throw new UnsupportedOperationException("unsupported option");
 392                 }
 393                 result = socketGetOption(optID);
 394                 break;
 395 
 396             default:
 397                 throw new SocketException("invalid option: " + optID);
 398         }
 399 
 400         return result;























































































































 401     }
 402 
 403     protected abstract void datagramSocketCreate() throws SocketException;
 404     protected abstract void datagramSocketClose();
 405     protected abstract void socketSetOption(int opt, Object val)
 406         throws SocketException;
 407     protected abstract Object socketGetOption(int opt) throws SocketException;
 408 
 409     protected abstract void connect0(InetAddress address, int port) throws SocketException;
 410     protected abstract void disconnect0(int family);
 411 
 412     protected boolean nativeConnectDisabled() {
 413         return connectDisabled;
 414     }
 415 
 416     abstract int dataAvailable();
 417     private static native boolean isReusePortAvailable0();
 418 }
   1 /*
   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.
   4  *
   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
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package java.net;
  26 
  27 import java.io.FileDescriptor;
  28 import java.io.IOException;
  29 import java.util.Collections;
  30 import java.util.HashSet;
  31 import java.util.Objects;
  32 import java.util.Set;
  33 
  34 import sun.net.ResourceManager;
  35 import sun.net.ext.ExtendedSocketOptions;
  36 import sun.security.action.GetPropertyAction;
  37 
  38 /**
  39  * Abstract datagram and multicast socket implementation base class.
  40  * Note: This is not a public class, so that applets cannot call
  41  * into the implementation directly and hence cannot bypass the
  42  * security checks present in the DatagramSocket and MulticastSocket
  43  * classes.
  44  *
  45  * @author Pavani Diwanji
  46  */
  47 
  48 abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
  49 {
  50     /* timeout value for receive() */
  51     int timeout = 0;
  52     boolean connected = false;
  53     private int trafficClass = 0;
  54     protected InetAddress connectedAddress = null;
  55     private int connectedPort = -1;


  73                     return null;
  74                 }
  75             });
  76     }
  77 
  78     private static volatile boolean checkedReusePort;
  79     private static volatile boolean isReusePortAvailable;
  80 
  81     /**
  82      * Tells whether SO_REUSEPORT is supported.
  83      */
  84     static boolean isReusePortAvailable() {
  85         if (!checkedReusePort) {
  86             isReusePortAvailable = isReusePortAvailable0();
  87             checkedReusePort = true;
  88         }
  89         return isReusePortAvailable;
  90     }
  91 
  92     /**




















  93      * Creates a datagram socket
  94      */
  95     protected synchronized void create() throws SocketException {
  96         ResourceManager.beforeUdpCreate();
  97         fd = new FileDescriptor();
  98         try {
  99             datagramSocketCreate();
 100             SocketCleanable.register(fd);
 101         } catch (SocketException ioe) {
 102             ResourceManager.afterUdpClose();
 103             fd = null;
 104             throw ioe;
 105         }
 106     }
 107 
 108     /**
 109      * Binds a datagram socket to a local port.
 110      */
 111     protected synchronized void bind(int lport, InetAddress laddr)
 112         throws SocketException {


 363             case SO_RCVBUF:
 364             case SO_SNDBUF:
 365             case IP_MULTICAST_LOOP:
 366             case SO_REUSEADDR:
 367             case SO_BROADCAST:
 368                 result = socketGetOption(optID);
 369                 break;
 370 
 371             case SO_REUSEPORT:
 372                 if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
 373                     throw new UnsupportedOperationException("unsupported option");
 374                 }
 375                 result = socketGetOption(optID);
 376                 break;
 377 
 378             default:
 379                 throw new SocketException("invalid option: " + optID);
 380         }
 381 
 382         return result;
 383     }
 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 
 504     protected abstract void datagramSocketCreate() throws SocketException;
 505     protected abstract void datagramSocketClose();
 506     protected abstract void socketSetOption(int opt, Object val)
 507         throws SocketException;
 508     protected abstract Object socketGetOption(int opt) throws SocketException;
 509 
 510     protected abstract void connect0(InetAddress address, int port) throws SocketException;
 511     protected abstract void disconnect0(int family);
 512 
 513     protected boolean nativeConnectDisabled() {
 514         return connectDisabled;
 515     }
 516 
 517     abstract int dataAvailable();
 518     private static native boolean isReusePortAvailable0();
 519 }
< prev index next >