src/java.base/share/classes/java/net/DatagramSocketImpl.java
changeset 55081 dd321e3596c0
parent 47216 71c04702a3d5
child 55500 80abfee2afaf
child 58678 9cf78a70fa4f
equal deleted inserted replaced
55080:ef713640430e 55081:dd321e3596c0
     1 /*
     1 /*
     2  * Copyright (c) 1996, 2016, 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
    25 
    25 
    26 package java.net;
    26 package java.net;
    27 
    27 
    28 import java.io.FileDescriptor;
    28 import java.io.FileDescriptor;
    29 import java.io.IOException;
    29 import java.io.IOException;
       
    30 import java.util.Objects;
    30 import java.util.Set;
    31 import java.util.Set;
    31 
    32 
    32 /**
    33 /**
    33  * Abstract datagram and multicast socket implementation base class.
    34  * Abstract datagram and multicast socket implementation base class.
    34  * @author Pavani Diwanji
    35  * @author Pavani Diwanji
   263     }
   264     }
   264 
   265 
   265     /**
   266     /**
   266      * Called to set a socket option.
   267      * Called to set a socket option.
   267      *
   268      *
       
   269      * @implSpec
       
   270      * The default implementation of this method first checks that the given
       
   271      * socket option {code name} is not null, then throws {@code
       
   272      * UnsupportedOperationException}. Subclasses should override this method
       
   273      * with an appropriate implementation.
       
   274      *
   268      * @param <T> The type of the socket option value
   275      * @param <T> The type of the socket option value
   269      * @param name The socket option
   276      * @param name The socket option
   270      *
       
   271      * @param value The value of the socket option. A value of {@code null}
   277      * @param value The value of the socket option. A value of {@code null}
   272      *              may be valid for some options.
   278      *              may be valid for some options.
   273      *
   279      *
   274      * @throws UnsupportedOperationException if the DatagramSocketImpl does not
   280      * @throws UnsupportedOperationException if the DatagramSocketImpl does not
   275      *         support the option
   281      *         support the option
   276      *
   282      * @throws IllegalArgumentException if the value is not valid for
       
   283      *         the option
       
   284      * @throws IOException if an I/O error occurs, or if the socket is closed
   277      * @throws NullPointerException if name is {@code null}
   285      * @throws NullPointerException if name is {@code null}
   278      * @throws IOException if an I/O problem occurs while attempting to set the option
   286      *
   279      * @since 9
   287      * @since 9
   280      */
   288      */
   281     protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
   289     protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
   282         if (name == StandardSocketOptions.SO_SNDBUF) {
   290         Objects.requireNonNull(name);
   283             setOption(SocketOptions.SO_SNDBUF, value);
   291         throw new UnsupportedOperationException("'" + name + "' not supported");
   284         } else if (name == StandardSocketOptions.SO_RCVBUF) {
       
   285             setOption(SocketOptions.SO_RCVBUF, value);
       
   286         } else if (name == StandardSocketOptions.SO_REUSEADDR) {
       
   287             setOption(SocketOptions.SO_REUSEADDR, value);
       
   288         } else if (name == StandardSocketOptions.SO_REUSEPORT &&
       
   289             supportedOptions().contains(name)) {
       
   290             setOption(SocketOptions.SO_REUSEPORT, value);
       
   291         } else if (name == StandardSocketOptions.IP_TOS) {
       
   292             setOption(SocketOptions.IP_TOS, value);
       
   293         } else if (name == StandardSocketOptions.IP_MULTICAST_IF &&
       
   294             (getDatagramSocket() instanceof MulticastSocket)) {
       
   295             setOption(SocketOptions.IP_MULTICAST_IF2, value);
       
   296         } else if (name == StandardSocketOptions.IP_MULTICAST_TTL &&
       
   297             (getDatagramSocket() instanceof MulticastSocket)) {
       
   298             if (! (value instanceof Integer)) {
       
   299                 throw new IllegalArgumentException("not an integer");
       
   300             }
       
   301             setTimeToLive((Integer)value);
       
   302         } else if (name == StandardSocketOptions.IP_MULTICAST_LOOP &&
       
   303             (getDatagramSocket() instanceof MulticastSocket)) {
       
   304             setOption(SocketOptions.IP_MULTICAST_LOOP, value);
       
   305         } else {
       
   306             throw new UnsupportedOperationException("unsupported option");
       
   307         }
       
   308     }
   292     }
   309 
   293 
   310     /**
   294     /**
   311      * Called to get a socket option.
   295      * Called to get a socket option.
   312      *
   296      *
   313      * @return the socket option
   297      * @implSpec
       
   298      * The default implementation of this method first checks that the given
       
   299      * socket option {code name} is not null, then throws {@code
       
   300      * UnsupportedOperationException}. Subclasses should override this method
       
   301      * with an appropriate implementation.
       
   302      *
   314      * @param <T> The type of the socket option value
   303      * @param <T> The type of the socket option value
   315      * @param name The socket option
   304      * @param name The socket option
       
   305      * @return the socket option
   316      *
   306      *
   317      * @throws UnsupportedOperationException if the DatagramSocketImpl does not
   307      * @throws UnsupportedOperationException if the DatagramSocketImpl does not
   318      *         support the option
   308      *         support the option
   319      *
   309      * @throws IOException if an I/O error occurs, or if the socket is closed
   320      * @throws NullPointerException if name is {@code null}
   310      * @throws NullPointerException if name is {@code null}
   321      * @throws IOException if an I/O problem occurs while attempting to set the option
       
   322      *
   311      *
   323      * @since 9
   312      * @since 9
   324      */
   313      */
   325     @SuppressWarnings("unchecked")
       
   326     protected <T> T getOption(SocketOption<T> name) throws IOException {
   314     protected <T> T getOption(SocketOption<T> name) throws IOException {
   327         if (name == StandardSocketOptions.SO_SNDBUF) {
   315         Objects.requireNonNull(name);
   328             return (T) getOption(SocketOptions.SO_SNDBUF);
   316         throw new UnsupportedOperationException("'" + name + "' not supported");
   329         } else if (name == StandardSocketOptions.SO_RCVBUF) {
       
   330             return (T) getOption(SocketOptions.SO_RCVBUF);
       
   331         } else if (name == StandardSocketOptions.SO_REUSEADDR) {
       
   332             return (T) getOption(SocketOptions.SO_REUSEADDR);
       
   333         } else if (name == StandardSocketOptions.SO_REUSEPORT &&
       
   334             supportedOptions().contains(name)) {
       
   335             return (T) getOption(SocketOptions.SO_REUSEPORT);
       
   336         } else if (name == StandardSocketOptions.IP_TOS) {
       
   337             return (T) getOption(SocketOptions.IP_TOS);
       
   338         } else if (name == StandardSocketOptions.IP_MULTICAST_IF &&
       
   339             (getDatagramSocket() instanceof MulticastSocket)) {
       
   340             return (T) getOption(SocketOptions.IP_MULTICAST_IF2);
       
   341         } else if (name == StandardSocketOptions.IP_MULTICAST_TTL &&
       
   342             (getDatagramSocket() instanceof MulticastSocket)) {
       
   343             Integer ttl = getTimeToLive();
       
   344             return (T)ttl;
       
   345         } else if (name == StandardSocketOptions.IP_MULTICAST_LOOP &&
       
   346             (getDatagramSocket() instanceof MulticastSocket)) {
       
   347             return (T) getOption(SocketOptions.IP_MULTICAST_LOOP);
       
   348         } else {
       
   349             throw new UnsupportedOperationException("unsupported option");
       
   350         }
       
   351     }
       
   352 
       
   353     private static final Set<SocketOption<?>> dgSocketOptions;
       
   354 
       
   355     private static final Set<SocketOption<?>> mcSocketOptions;
       
   356 
       
   357     static {
       
   358         dgSocketOptions = Set.of(StandardSocketOptions.SO_SNDBUF,
       
   359                                  StandardSocketOptions.SO_RCVBUF,
       
   360                                  StandardSocketOptions.SO_REUSEADDR,
       
   361                                  StandardSocketOptions.IP_TOS);
       
   362 
       
   363         mcSocketOptions = Set.of(StandardSocketOptions.SO_SNDBUF,
       
   364                                  StandardSocketOptions.SO_RCVBUF,
       
   365                                  StandardSocketOptions.SO_REUSEADDR,
       
   366                                  StandardSocketOptions.IP_TOS,
       
   367                                  StandardSocketOptions.IP_MULTICAST_IF,
       
   368                                  StandardSocketOptions.IP_MULTICAST_TTL,
       
   369                                  StandardSocketOptions.IP_MULTICAST_LOOP);
       
   370     }
   317     }
   371 
   318 
   372     /**
   319     /**
   373      * Returns a set of SocketOptions supported by this impl
   320      * Returns a set of SocketOptions supported by this impl
   374      * and by this impl's socket (DatagramSocket or MulticastSocket)
   321      * and by this impl's socket (DatagramSocket or MulticastSocket)
   375      *
   322      *
       
   323      * @implSpec
       
   324      * The default implementation of this method returns an empty set.
       
   325      * Subclasses should override this method with an appropriate implementation.
       
   326      *
   376      * @return a Set of SocketOptions
   327      * @return a Set of SocketOptions
   377      *
   328      *
   378      * @since 9
   329      * @since 9
   379      */
   330      */
   380     protected Set<SocketOption<?>> supportedOptions() {
   331     protected Set<SocketOption<?>> supportedOptions() {
   381         if (getDatagramSocket() instanceof MulticastSocket) {
   332         return Set.of();
   382             return mcSocketOptions;
       
   383         } else {
       
   384             return dgSocketOptions;
       
   385         }
       
   386     }
   333     }
   387 }
   334 }