src/share/classes/sun/nio/ch/SocketChannelImpl.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.NetHooks;

  36 import sun.misc.IoTrace;
  37 
  38 /**
  39  * An implementation of SocketChannels
  40  */
  41 
  42 class SocketChannelImpl
  43     extends SocketChannel
  44     implements SelChImpl
  45 {
  46 
  47     // Used to make native read and write calls
  48     private static NativeDispatcher nd;
  49 
  50     // Our file descriptor object
  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;


 155         synchronized (stateLock) {
 156             if (!isOpen())
 157                 throw new ClosedChannelException();
 158             return remoteAddress;
 159         }
 160     }
 161 
 162     @Override
 163     public <T> SocketChannel setOption(SocketOption<T> name, T value)
 164         throws IOException
 165     {
 166         if (name == null)
 167             throw new NullPointerException();
 168         if (!supportedOptions().contains(name))
 169             throw new UnsupportedOperationException("'" + name + "' not supported");
 170 
 171         synchronized (stateLock) {
 172             if (!isOpen())
 173                 throw new ClosedChannelException();
 174 
 175             // special handling for IP_TOS: no-op when IPv6
 176             if (name == StandardSocketOptions.IP_TOS) {
 177                 if (!Net.isIPv6Available())
 178                     Net.setSocketOption(fd, StandardProtocolFamily.INET, name, value);

 179                 return this;
 180             } else if (name == StandardSocketOptions.SO_REUSEADDR &&
 181                            Net.useExclusiveBind())
 182             {
 183                 // SO_REUSEADDR emulated when using exclusive bind
 184                 isReuseAddress = (Boolean)value;
 185                 return this;
 186             }
 187 
 188             // no options that require special handling
 189             Net.setSocketOption(fd, Net.UNSPEC, name, value);
 190             return this;
 191         }
 192     }
 193 
 194     @Override
 195     @SuppressWarnings("unchecked")
 196     public <T> T getOption(SocketOption<T> name)
 197         throws IOException
 198     {
 199         if (name == null)
 200             throw new NullPointerException();
 201         if (!supportedOptions().contains(name))
 202             throw new UnsupportedOperationException("'" + name + "' not supported");
 203 
 204         synchronized (stateLock) {
 205             if (!isOpen())
 206                 throw new ClosedChannelException();
 207 
 208             if (name == StandardSocketOptions.SO_REUSEADDR &&
 209                     Net.useExclusiveBind())
 210             {
 211                 // SO_REUSEADDR emulated when using exclusive bind
 212                 return (T)Boolean.valueOf(isReuseAddress);
 213             }
 214 
 215             // special handling for IP_TOS: always return 0 when IPv6
 216             if (name == StandardSocketOptions.IP_TOS) {
 217                 return (Net.isIPv6Available()) ? (T) Integer.valueOf(0) :
 218                     (T) Net.getSocketOption(fd, StandardProtocolFamily.INET, name);

 219             }
 220 
 221             // no options that require special handling
 222             return (T) Net.getSocketOption(fd, Net.UNSPEC, name);
 223         }
 224     }
 225 
 226     private static class DefaultOptionsHolder {
 227         static final Set<SocketOption<?>> defaultOptions = defaultOptions();
 228 
 229         private static Set<SocketOption<?>> defaultOptions() {
 230             HashSet<SocketOption<?>> set = new HashSet<SocketOption<?>>(8);
 231             set.add(StandardSocketOptions.SO_SNDBUF);
 232             set.add(StandardSocketOptions.SO_RCVBUF);
 233             set.add(StandardSocketOptions.SO_KEEPALIVE);
 234             set.add(StandardSocketOptions.SO_REUSEADDR);
 235             set.add(StandardSocketOptions.SO_LINGER);
 236             set.add(StandardSocketOptions.TCP_NODELAY);
 237             // additional options required by socket adaptor
 238             set.add(StandardSocketOptions.IP_TOS);
 239             set.add(ExtendedSocketOption.SO_OOBINLINE);



 240             return Collections.unmodifiableSet(set);
 241         }
 242     }
 243 
 244     @Override
 245     public final Set<SocketOption<?>> supportedOptions() {
 246         return DefaultOptionsHolder.defaultOptions;
 247     }
 248 
 249     private boolean ensureReadOpen() throws ClosedChannelException {
 250         synchronized (stateLock) {
 251             if (!isOpen())
 252                 throw new ClosedChannelException();
 253             if (!isConnected())
 254                 throw new NotYetConnectedException();
 255             if (!isInputOpen)
 256                 return false;
 257             else
 258                 return true;
 259         }




  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.NetHooks;
  36 import sun.net.ExtendedOptionsImpl;
  37 import sun.misc.IoTrace;
  38 
  39 /**
  40  * An implementation of SocketChannels
  41  */
  42 
  43 class SocketChannelImpl
  44     extends SocketChannel
  45     implements SelChImpl
  46 {
  47 
  48     // Used to make native read and write calls
  49     private static NativeDispatcher nd;
  50 
  51     // Our file descriptor object
  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;


 156         synchronized (stateLock) {
 157             if (!isOpen())
 158                 throw new ClosedChannelException();
 159             return remoteAddress;
 160         }
 161     }
 162 
 163     @Override
 164     public <T> SocketChannel setOption(SocketOption<T> name, T value)
 165         throws IOException
 166     {
 167         if (name == null)
 168             throw new NullPointerException();
 169         if (!supportedOptions().contains(name))
 170             throw new UnsupportedOperationException("'" + name + "' not supported");
 171 
 172         synchronized (stateLock) {
 173             if (!isOpen())
 174                 throw new ClosedChannelException();
 175 

 176             if (name == StandardSocketOptions.IP_TOS) {
 177                 ProtocolFamily family = Net.isIPv6Available() ?
 178                     StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
 179                 Net.setSocketOption(fd, family, name, value);
 180                 return this;
 181             }
 182 
 183             if (name == StandardSocketOptions.SO_REUSEADDR && Net.useExclusiveBind()) {
 184                 // SO_REUSEADDR emulated when using exclusive bind
 185                 isReuseAddress = (Boolean)value;
 186                 return this;
 187             }
 188 
 189             // no options that require special handling
 190             Net.setSocketOption(fd, Net.UNSPEC, name, value);
 191             return this;
 192         }
 193     }
 194 
 195     @Override
 196     @SuppressWarnings("unchecked")
 197     public <T> T getOption(SocketOption<T> name)
 198         throws IOException
 199     {
 200         if (name == null)
 201             throw new NullPointerException();
 202         if (!supportedOptions().contains(name))
 203             throw new UnsupportedOperationException("'" + name + "' not supported");
 204 
 205         synchronized (stateLock) {
 206             if (!isOpen())
 207                 throw new ClosedChannelException();
 208 
 209             if (name == StandardSocketOptions.SO_REUSEADDR &&
 210                     Net.useExclusiveBind())
 211             {
 212                 // SO_REUSEADDR emulated when using exclusive bind
 213                 return (T)Boolean.valueOf(isReuseAddress);
 214             }
 215 
 216             // special handling for IP_TOS: always return 0 when IPv6
 217             if (name == StandardSocketOptions.IP_TOS) {
 218                 ProtocolFamily family = Net.isIPv6Available() ?
 219                     StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
 220                 return (T) Net.getSocketOption(fd, family, name);
 221             }
 222 
 223             // no options that require special handling
 224             return (T) Net.getSocketOption(fd, Net.UNSPEC, name);
 225         }
 226     }
 227 
 228     private static class DefaultOptionsHolder {
 229         static final Set<SocketOption<?>> defaultOptions = defaultOptions();
 230 
 231         private static Set<SocketOption<?>> defaultOptions() {
 232             HashSet<SocketOption<?>> set = new HashSet<SocketOption<?>>(8);
 233             set.add(StandardSocketOptions.SO_SNDBUF);
 234             set.add(StandardSocketOptions.SO_RCVBUF);
 235             set.add(StandardSocketOptions.SO_KEEPALIVE);
 236             set.add(StandardSocketOptions.SO_REUSEADDR);
 237             set.add(StandardSocketOptions.SO_LINGER);
 238             set.add(StandardSocketOptions.TCP_NODELAY);
 239             // additional options required by socket adaptor
 240             set.add(StandardSocketOptions.IP_TOS);
 241             set.add(ExtendedSocketOption.SO_OOBINLINE);
 242             if (ExtendedOptionsImpl.flowSupported()) {
 243                 set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA);
 244             }
 245             return Collections.unmodifiableSet(set);
 246         }
 247     }
 248 
 249     @Override
 250     public final Set<SocketOption<?>> supportedOptions() {
 251         return DefaultOptionsHolder.defaultOptions;
 252     }
 253 
 254     private boolean ensureReadOpen() throws ClosedChannelException {
 255         synchronized (stateLock) {
 256             if (!isOpen())
 257                 throw new ClosedChannelException();
 258             if (!isConnected())
 259                 throw new NotYetConnectedException();
 260             if (!isInputOpen)
 261                 return false;
 262             else
 263                 return true;
 264         }