diff --git a/transport-native-unix-common-tests/src/main/java/io/netty/channel/unix/tests/SocketTest.java b/transport-native-unix-common-tests/src/main/java/io/netty/channel/unix/tests/SocketTest.java index b5707baf1e..6e65fcc450 100644 --- a/transport-native-unix-common-tests/src/main/java/io/netty/channel/unix/tests/SocketTest.java +++ b/transport-native-unix-common-tests/src/main/java/io/netty/channel/unix/tests/SocketTest.java @@ -91,7 +91,8 @@ public abstract class SocketTest { @Test public void testTrafficClass() throws IOException { - final int value = 0x1; + // IPTOS_THROUGHPUT + final int value = 0x08; socket.setTrafficClass(value); assertEquals(value, socket.getTrafficClass()); } diff --git a/transport-native-unix-common/src/main/c/netty_unix_socket.c b/transport-native-unix-common/src/main/c/netty_unix_socket.c index fa655ccd6e..dee418d7ef 100644 --- a/transport-native-unix-common/src/main/c/netty_unix_socket.c +++ b/transport-native-unix-common/src/main/c/netty_unix_socket.c @@ -755,18 +755,26 @@ static void netty_unix_socket_setSoLinger(JNIEnv* env, jclass clazz, jint fd, ji } static void netty_unix_socket_setTrafficClass(JNIEnv* env, jclass clazz, jint fd, jint optval) { - /* Try to set the ipv6 equivalent, but don't throw if this is an ipv4 only socket. */ - int rc = netty_unix_socket_setOption0(fd, IPPROTO_IPV6, IPV6_TCLASS, &optval, sizeof(optval)); - if (rc < 0 && errno != ENOPROTOOPT) { - netty_unix_socket_setOptionHandleError(env, errno); - } + if (socketType == AF_INET6) { + // This call will put an exception on the stack to be processed once the JNI calls completes if + // setsockopt failed and return a negative value. + int rc = netty_unix_socket_setOption(env, fd, IPPROTO_IPV6, IPV6_TCLASS, &optval, sizeof(optval)); - /* Linux allows both ipv4 and ipv6 families to be set */ + if (rc >= 0) { +/* Linux allows both ipv4 and ipv6 families to be set */ #ifdef __linux__ - else { + // Previous call successful now try to set also for ipv4 + if (netty_unix_socket_setOption0(fd, IPPROTO_IP, IP_TOS, &optval, sizeof(optval)) == -1) { + if (errno != ENOPROTOOPT) { + // throw exception + netty_unix_socket_setOptionHandleError(env, errno); + } + } +#endif + } + } else { netty_unix_socket_setOption(env, fd, IPPROTO_IP, IP_TOS, &optval, sizeof(optval)); } -#endif } static jint netty_unix_socket_isKeepAlive(JNIEnv* env, jclass clazz, jint fd) { @@ -814,15 +822,23 @@ static jint netty_unix_socket_getSoLinger(JNIEnv* env, jclass clazz, jint fd) { } static jint netty_unix_socket_getTrafficClass(JNIEnv* env, jclass clazz, jint fd) { - /* macOS may throw an error if IPv6 is supported and it is not consulted first */ int optval; - if (netty_unix_socket_getOption0(fd, IPPROTO_IPV6, IPV6_TCLASS, &optval, sizeof(optval)) == -1) { - if (errno != ENOPROTOOPT || netty_unix_socket_getOption0(fd, IPPROTO_IP, IP_TOS, &optval, sizeof(optval)) == -1) { - netty_unix_socket_getOptionHandleError(env, errno); - return -1; + if (socketType == AF_INET6) { + if (netty_unix_socket_getOption0(fd, IPPROTO_IPV6, IPV6_TCLASS, &optval, sizeof(optval)) == -1) { + if (errno == ENOPROTOOPT) { + if (netty_unix_socket_getOption(env, fd, IPPROTO_IP, IP_TOS, &optval, sizeof(optval)) == -1) { + return -1; + } + } else { + netty_unix_socket_getOptionHandleError(env, errno); + return -1; + } } + } else { + if (netty_unix_socket_getOption(env, fd, IPPROTO_IP, IP_TOS, &optval, sizeof(optval)) == -1) { + return -1; + } } - return optval; }