src/share/classes/sun/nio/ch/DatagramChannelImpl.java

Print this page
rev 7398 : 8032808: Support Solaris SO_FLOW_SLA socket option
Reviewed-by: michaelm
rev 7400 : 8029607: Type of Service (TOS) cannot be set in IPv6 header
Reviewed-by: alanb


  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 
  26 package sun.nio.ch;
  27 
  28 import java.io.FileDescriptor;
  29 import java.io.IOException;
  30 import java.net.*;
  31 import java.nio.ByteBuffer;
  32 import java.nio.channels.*;
  33 import java.nio.channels.spi.*;
  34 import java.util.*;
  35 import sun.net.ResourceManager;

  36 
  37 
  38 /**
  39  * An implementation of DatagramChannels.
  40  */
  41 
  42 class DatagramChannelImpl
  43     extends DatagramChannel
  44     implements SelChImpl
  45 {
  46 
  47     // Used to make native read and write calls
  48     private static NativeDispatcher nd = new DatagramDispatcher();
  49 
  50     // Our file descriptor
  51     private final FileDescriptor fd;
  52 
  53     // fd value needed for dev/poll. This value will remain valid
  54     // even after the value in the file descriptor object has been set to -1
  55     private final int fdVal;


 177     public SocketAddress getRemoteAddress() throws IOException {
 178         synchronized (stateLock) {
 179             if (!isOpen())
 180                 throw new ClosedChannelException();
 181             return remoteAddress;
 182         }
 183     }
 184 
 185     @Override
 186     public <T> DatagramChannel setOption(SocketOption<T> name, T value)
 187         throws IOException
 188     {
 189         if (name == null)
 190             throw new NullPointerException();
 191         if (!supportedOptions().contains(name))
 192             throw new UnsupportedOperationException("'" + name + "' not supported");
 193 
 194         synchronized (stateLock) {
 195             ensureOpen();
 196 
 197             if (name == StandardSocketOptions.IP_TOS) {
 198                 // IPv4 only; no-op for IPv6
 199                 if (family == StandardProtocolFamily.INET) {
 200                     Net.setSocketOption(fd, family, name, value);
 201                 }
 202                 return this;
 203             }
 204 
 205             if (name == StandardSocketOptions.IP_MULTICAST_TTL ||
 206                 name == StandardSocketOptions.IP_MULTICAST_LOOP)
 207             {
 208                 // options are protocol dependent
 209                 Net.setSocketOption(fd, family, name, value);
 210                 return this;
 211             }
 212 
 213             if (name == StandardSocketOptions.IP_MULTICAST_IF) {
 214                 if (value == null)
 215                     throw new IllegalArgumentException("Cannot set IP_MULTICAST_IF to 'null'");
 216                 NetworkInterface interf = (NetworkInterface)value;
 217                 if (family == StandardProtocolFamily.INET6) {
 218                     int index = interf.getIndex();
 219                     if (index == -1)
 220                         throw new IOException("Network interface cannot be identified");
 221                     Net.setInterface6(fd, index);
 222                 } else {
 223                     // need IPv4 address to identify interface
 224                     Inet4Address target = Net.anyInet4Address(interf);
 225                     if (target == null)


 238 
 239             // remaining options don't need any special handling
 240             Net.setSocketOption(fd, Net.UNSPEC, name, value);
 241             return this;
 242         }
 243     }
 244 
 245     @Override
 246     @SuppressWarnings("unchecked")
 247     public <T> T getOption(SocketOption<T> name)
 248         throws IOException
 249     {
 250         if (name == null)
 251             throw new NullPointerException();
 252         if (!supportedOptions().contains(name))
 253             throw new UnsupportedOperationException("'" + name + "' not supported");
 254 
 255         synchronized (stateLock) {
 256             ensureOpen();
 257 
 258             if (name == StandardSocketOptions.IP_TOS) {
 259                 // IPv4 only; always return 0 on IPv6
 260                 if (family == StandardProtocolFamily.INET) {
 261                     return (T) Net.getSocketOption(fd, family, name);
 262                 } else {
 263                     return (T) Integer.valueOf(0);
 264                 }
 265             }
 266 
 267             if (name == StandardSocketOptions.IP_MULTICAST_TTL ||
 268                 name == StandardSocketOptions.IP_MULTICAST_LOOP)
 269             {
 270                 return (T) Net.getSocketOption(fd, family, name);
 271             }
 272 
 273             if (name == StandardSocketOptions.IP_MULTICAST_IF) {
 274                 if (family == StandardProtocolFamily.INET) {
 275                     int address = Net.getInterface4(fd);
 276                     if (address == 0)
 277                         return null;    // default interface
 278 
 279                     InetAddress ia = Net.inet4FromInt(address);
 280                     NetworkInterface ni = NetworkInterface.getByInetAddress(ia);
 281                     if (ni == null)
 282                         throw new IOException("Unable to map address to interface");
 283                     return (T) ni;
 284                 } else {
 285                     int index = Net.getInterface6(fd);
 286                     if (index == 0)
 287                         return null;    // default interface


 300             }
 301 
 302             // no special handling
 303             return (T) Net.getSocketOption(fd, Net.UNSPEC, name);
 304         }
 305     }
 306 
 307     private static class DefaultOptionsHolder {
 308         static final Set<SocketOption<?>> defaultOptions = defaultOptions();
 309 
 310         private static Set<SocketOption<?>> defaultOptions() {
 311             HashSet<SocketOption<?>> set = new HashSet<SocketOption<?>>(8);
 312             set.add(StandardSocketOptions.SO_SNDBUF);
 313             set.add(StandardSocketOptions.SO_RCVBUF);
 314             set.add(StandardSocketOptions.SO_REUSEADDR);
 315             set.add(StandardSocketOptions.SO_BROADCAST);
 316             set.add(StandardSocketOptions.IP_TOS);
 317             set.add(StandardSocketOptions.IP_MULTICAST_IF);
 318             set.add(StandardSocketOptions.IP_MULTICAST_TTL);
 319             set.add(StandardSocketOptions.IP_MULTICAST_LOOP);



 320             return Collections.unmodifiableSet(set);
 321         }
 322     }
 323 
 324     @Override
 325     public final Set<SocketOption<?>> supportedOptions() {
 326         return DefaultOptionsHolder.defaultOptions;
 327     }
 328 
 329     private void ensureOpen() throws ClosedChannelException {
 330         if (!isOpen())
 331             throw new ClosedChannelException();
 332     }
 333 
 334     private SocketAddress sender;       // Set by receive0 (## ugh)
 335 
 336     public SocketAddress receive(ByteBuffer dst) throws IOException {
 337         if (dst.isReadOnly())
 338             throw new IllegalArgumentException("Read-only buffer");
 339         if (dst == null)




  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 
  26 package sun.nio.ch;
  27 
  28 import java.io.FileDescriptor;
  29 import java.io.IOException;
  30 import java.net.*;
  31 import java.nio.ByteBuffer;
  32 import java.nio.channels.*;
  33 import java.nio.channels.spi.*;
  34 import java.util.*;
  35 import sun.net.ResourceManager;
  36 import sun.net.ExtendedOptionsImpl;
  37 
  38 
  39 /**
  40  * An implementation of DatagramChannels.
  41  */
  42 
  43 class DatagramChannelImpl
  44     extends DatagramChannel
  45     implements SelChImpl
  46 {
  47 
  48     // Used to make native read and write calls
  49     private static NativeDispatcher nd = new DatagramDispatcher();
  50 
  51     // Our file descriptor
  52     private final FileDescriptor fd;
  53 
  54     // fd value needed for dev/poll. This value will remain valid
  55     // even after the value in the file descriptor object has been set to -1
  56     private final int fdVal;


 178     public SocketAddress getRemoteAddress() throws IOException {
 179         synchronized (stateLock) {
 180             if (!isOpen())
 181                 throw new ClosedChannelException();
 182             return remoteAddress;
 183         }
 184     }
 185 
 186     @Override
 187     public <T> DatagramChannel setOption(SocketOption<T> name, T value)
 188         throws IOException
 189     {
 190         if (name == null)
 191             throw new NullPointerException();
 192         if (!supportedOptions().contains(name))
 193             throw new UnsupportedOperationException("'" + name + "' not supported");
 194 
 195         synchronized (stateLock) {
 196             ensureOpen();
 197 
 198             if (name == StandardSocketOptions.IP_TOS ||
 199                 name == StandardSocketOptions.IP_MULTICAST_TTL ||







 200                 name == StandardSocketOptions.IP_MULTICAST_LOOP)
 201             {
 202                 // options are protocol dependent
 203                 Net.setSocketOption(fd, family, name, value);
 204                 return this;
 205             }
 206 
 207             if (name == StandardSocketOptions.IP_MULTICAST_IF) {
 208                 if (value == null)
 209                     throw new IllegalArgumentException("Cannot set IP_MULTICAST_IF to 'null'");
 210                 NetworkInterface interf = (NetworkInterface)value;
 211                 if (family == StandardProtocolFamily.INET6) {
 212                     int index = interf.getIndex();
 213                     if (index == -1)
 214                         throw new IOException("Network interface cannot be identified");
 215                     Net.setInterface6(fd, index);
 216                 } else {
 217                     // need IPv4 address to identify interface
 218                     Inet4Address target = Net.anyInet4Address(interf);
 219                     if (target == null)


 232 
 233             // remaining options don't need any special handling
 234             Net.setSocketOption(fd, Net.UNSPEC, name, value);
 235             return this;
 236         }
 237     }
 238 
 239     @Override
 240     @SuppressWarnings("unchecked")
 241     public <T> T getOption(SocketOption<T> name)
 242         throws IOException
 243     {
 244         if (name == null)
 245             throw new NullPointerException();
 246         if (!supportedOptions().contains(name))
 247             throw new UnsupportedOperationException("'" + name + "' not supported");
 248 
 249         synchronized (stateLock) {
 250             ensureOpen();
 251 
 252             if (name == StandardSocketOptions.IP_TOS ||
 253                 name == StandardSocketOptions.IP_MULTICAST_TTL ||








 254                 name == StandardSocketOptions.IP_MULTICAST_LOOP)
 255             {
 256                 return (T) Net.getSocketOption(fd, family, name);
 257             }
 258 
 259             if (name == StandardSocketOptions.IP_MULTICAST_IF) {
 260                 if (family == StandardProtocolFamily.INET) {
 261                     int address = Net.getInterface4(fd);
 262                     if (address == 0)
 263                         return null;    // default interface
 264 
 265                     InetAddress ia = Net.inet4FromInt(address);
 266                     NetworkInterface ni = NetworkInterface.getByInetAddress(ia);
 267                     if (ni == null)
 268                         throw new IOException("Unable to map address to interface");
 269                     return (T) ni;
 270                 } else {
 271                     int index = Net.getInterface6(fd);
 272                     if (index == 0)
 273                         return null;    // default interface


 286             }
 287 
 288             // no special handling
 289             return (T) Net.getSocketOption(fd, Net.UNSPEC, name);
 290         }
 291     }
 292 
 293     private static class DefaultOptionsHolder {
 294         static final Set<SocketOption<?>> defaultOptions = defaultOptions();
 295 
 296         private static Set<SocketOption<?>> defaultOptions() {
 297             HashSet<SocketOption<?>> set = new HashSet<SocketOption<?>>(8);
 298             set.add(StandardSocketOptions.SO_SNDBUF);
 299             set.add(StandardSocketOptions.SO_RCVBUF);
 300             set.add(StandardSocketOptions.SO_REUSEADDR);
 301             set.add(StandardSocketOptions.SO_BROADCAST);
 302             set.add(StandardSocketOptions.IP_TOS);
 303             set.add(StandardSocketOptions.IP_MULTICAST_IF);
 304             set.add(StandardSocketOptions.IP_MULTICAST_TTL);
 305             set.add(StandardSocketOptions.IP_MULTICAST_LOOP);
 306             if (ExtendedOptionsImpl.flowSupported()) {
 307                 set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA);
 308             }
 309             return Collections.unmodifiableSet(set);
 310         }
 311     }
 312 
 313     @Override
 314     public final Set<SocketOption<?>> supportedOptions() {
 315         return DefaultOptionsHolder.defaultOptions;
 316     }
 317 
 318     private void ensureOpen() throws ClosedChannelException {
 319         if (!isOpen())
 320             throw new ClosedChannelException();
 321     }
 322 
 323     private SocketAddress sender;       // Set by receive0 (## ugh)
 324 
 325     public SocketAddress receive(ByteBuffer dst) throws IOException {
 326         if (dst.isReadOnly())
 327             throw new IllegalArgumentException("Read-only buffer");
 328         if (dst == null)