--- old/src/jdk.net/share/classes/jdk/net/ExtendedSocketOptions.java 2017-09-27 14:02:47.411017970 +0530 +++ new/src/jdk.net/share/classes/jdk/net/ExtendedSocketOptions.java 2017-09-27 14:02:47.287012194 +0530 @@ -68,19 +68,54 @@ ExtSocketOption("SO_FLOW_SLA", SocketFlow.class); + /** + * SO_QUICKACK. + * + * The value of this socket option is a {@code Boolean} that represents + * whether the option is enabled or disabled. The socket option is specific + * to stream-oriented sockets using the TCP/IP protocol. + * + * The exact semantics of this socket option are socket type and system + * dependent. + * + * This socket option usually enable TCP_QUICKACK mode if set or disable + * TCP_QUICKACK mode if cleared. + * + * When TCP_QUICKACK is enabled, acks are sent immediately, rather than + * delayed if needed in accordance to normal TCP operation.This flag is not + * permanent, it only enables a switch to or from TCP_QUICKACK mode. + * + * Subsequent operation of the TCP protocol will once again enter/leave + * TCP_QUICKACK mode depending on internal protocol processing and factors + * such as delayed ack timeouts occurring and data transfer. + * + * @since 10 + */ + public static final SocketOption SO_QUICKACK + = new ExtSocketOption("SO_QUICKACK", Boolean.class); + private static final PlatformSocketOptions platformSocketOptions = PlatformSocketOptions.get(); private static final boolean flowSupported = platformSocketOptions.flowSupported(); + private static final boolean quickAckSupported = + platformSocketOptions.quickAckSupported(); private static final Set> extendedOptions = options(); static Set> options() { - if (flowSupported) - return Set.of(SO_FLOW_SLA); - else + if (flowSupported) { + if (quickAckSupported) { + return Set.of(SO_FLOW_SLA, SO_QUICKACK); + } else { + return Set.of(SO_FLOW_SLA); + } + } else if (quickAckSupported) { + return Set.of(SO_QUICKACK); + } else { return Collections.>emptySet(); + } } static { @@ -105,6 +140,9 @@ assert flowSupported; SocketFlow flow = checkValueType(value, option.type()); setFlowOption(fd, flow); + } else if (option == SO_QUICKACK) { + assert quickAckSupported; + setQuickAckOption(fd, (boolean)value); } else { throw new InternalError("Unexpected option " + option); } @@ -127,6 +165,8 @@ SocketFlow flow = SocketFlow.create(); getFlowOption(fd, flow); return flow; + } else if (option == SO_QUICKACK) { + return getQuickAckOption(fd); } else { throw new InternalError("Unexpected option " + option); } @@ -156,12 +196,21 @@ } private static void getFlowOption(FileDescriptor fd, SocketFlow f) - throws SocketException - { + throws SocketException { int status = platformSocketOptions.getFlowOption(fdAccess.get(fd), f); f.status(status); // augment the given flow with the status } + private static void setQuickAckOption(FileDescriptor fd, boolean on) + throws SocketException { + platformSocketOptions.setQuickAck(fdAccess.get(fd), on == true ? 1 : 0); + } + + private static Object getQuickAckOption(FileDescriptor fd) + throws SocketException { + return platformSocketOptions.getQuickAck(fdAccess.get(fd)); + } + static class PlatformSocketOptions { protected PlatformSocketOptions() {} @@ -184,9 +233,13 @@ return System.getProperty("os.name"); } }); - if ("SunOS".equals(osname)) + if ("SunOS".equals(osname)) { return newInstance("jdk.net.SolarisSocketOptions"); - return new PlatformSocketOptions(); + } else if ("Linux".equals(osname)) { + return newInstance("jdk.net.LinuxSocketOptions"); + } else { + return new PlatformSocketOptions(); + } } private static final PlatformSocketOptions instance = create(); @@ -208,5 +261,17 @@ boolean flowSupported() { return false; } + + void setQuickAck(int fd, int on) throws SocketException { + throw new UnsupportedOperationException("unsupported socket option"); + } + + Object getQuickAck(int fd) throws SocketException { + throw new UnsupportedOperationException("unsupported socket option"); + } + + boolean quickAckSupported() { + return false; + } } }