8308593: Add Keepalive Extended Socket Options Support for Windows

Reviewed-by: michaelm, djelinski, vtewari
This commit is contained in:
Terry Chow 2023-07-24 09:03:10 +00:00 committed by Michael McMahon
parent ab821aa24f
commit f3ade388da
9 changed files with 210 additions and 41 deletions

View File

@ -68,8 +68,8 @@ class AIXSocketOptions extends PlatformSocketOptions {
}
@Override
void setTcpkeepAliveProbes(int fd, final int value) throws SocketException {
setTcpkeepAliveProbes0(fd, value);
void setTcpKeepAliveProbes(int fd, final int value) throws SocketException {
setTcpKeepAliveProbes0(fd, value);
}
@Override
@ -83,8 +83,8 @@ class AIXSocketOptions extends PlatformSocketOptions {
}
@Override
int getTcpkeepAliveProbes(int fd) throws SocketException {
return getTcpkeepAliveProbes0(fd);
int getTcpKeepAliveProbes(int fd) throws SocketException {
return getTcpKeepAliveProbes0(fd);
}
@Override
@ -117,11 +117,11 @@ class AIXSocketOptions extends PlatformSocketOptions {
return new UnixDomainPrincipal(user, group);
}
private static native void setTcpkeepAliveProbes0(int fd, int value) throws SocketException;
private static native void setTcpKeepAliveProbes0(int fd, int value) throws SocketException;
private static native void setTcpKeepAliveTime0(int fd, int value) throws SocketException;
private static native void setTcpKeepAliveIntvl0(int fd, int value) throws SocketException;
private static native void setIpDontFragment0(int fd, boolean value, boolean isIPv6) throws SocketException;
private static native int getTcpkeepAliveProbes0(int fd) throws SocketException;
private static native int getTcpKeepAliveProbes0(int fd) throws SocketException;
private static native int getTcpKeepAliveTime0(int fd) throws SocketException;
private static native int getTcpKeepAliveIntvl0(int fd) throws SocketException;
private static native boolean getIpDontFragment0(int fd, boolean isIPv6) throws SocketException;

View File

@ -150,10 +150,10 @@ JNIEXPORT jboolean JNICALL Java_jdk_net_AIXSocketOptions_keepAliveOptionsSupport
/*
* Class: jdk_net_AIXSocketOptions
* Method: setTcpkeepAliveProbes0
* Method: setTcpKeepAliveProbes0
* Signature: (II)V
*/
JNIEXPORT void JNICALL Java_jdk_net_AIXSocketOptions_setTcpkeepAliveProbes0
JNIEXPORT void JNICALL Java_jdk_net_AIXSocketOptions_setTcpKeepAliveProbes0
(JNIEnv *env, jobject unused, jint fd, jint optval) {
jint rv = setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &optval, sizeof (optval));
handleError(env, rv, "set option TCP_KEEPCNT failed");
@ -183,10 +183,10 @@ JNIEXPORT void JNICALL Java_jdk_net_AIXSocketOptions_setTcpKeepAliveIntvl0
/*
* Class: jdk_net_AIXSocketOptions
* Method: getTcpkeepAliveProbes0
* Method: getTcpKeepAliveProbes0
* Signature: (I)I;
*/
JNIEXPORT jint JNICALL Java_jdk_net_AIXSocketOptions_getTcpkeepAliveProbes0
JNIEXPORT jint JNICALL Java_jdk_net_AIXSocketOptions_getTcpKeepAliveProbes0
(JNIEnv *env, jobject unused, jint fd) {
jint optval, rv;
socklen_t sz = sizeof (optval);

View File

@ -68,8 +68,8 @@ class LinuxSocketOptions extends PlatformSocketOptions {
}
@Override
void setTcpkeepAliveProbes(int fd, final int value) throws SocketException {
setTcpkeepAliveProbes0(fd, value);
void setTcpKeepAliveProbes(int fd, final int value) throws SocketException {
setTcpKeepAliveProbes0(fd, value);
}
@Override
@ -83,8 +83,8 @@ class LinuxSocketOptions extends PlatformSocketOptions {
}
@Override
int getTcpkeepAliveProbes(int fd) throws SocketException {
return getTcpkeepAliveProbes0(fd);
int getTcpKeepAliveProbes(int fd) throws SocketException {
return getTcpKeepAliveProbes0(fd);
}
@Override
@ -127,11 +127,11 @@ class LinuxSocketOptions extends PlatformSocketOptions {
return new UnixDomainPrincipal(user, group);
}
private static native void setTcpkeepAliveProbes0(int fd, int value) throws SocketException;
private static native void setTcpKeepAliveProbes0(int fd, int value) throws SocketException;
private static native void setTcpKeepAliveTime0(int fd, int value) throws SocketException;
private static native void setTcpKeepAliveIntvl0(int fd, int value) throws SocketException;
private static native void setIpDontFragment0(int fd, boolean value, boolean isIPv6) throws SocketException;
private static native int getTcpkeepAliveProbes0(int fd) throws SocketException;
private static native int getTcpKeepAliveProbes0(int fd) throws SocketException;
private static native int getTcpKeepAliveTime0(int fd) throws SocketException;
private static native int getTcpKeepAliveIntvl0(int fd) throws SocketException;
private static native boolean getIpDontFragment0(int fd, boolean isIPv6) throws SocketException;

View File

@ -153,10 +153,10 @@ JNIEXPORT jboolean JNICALL Java_jdk_net_LinuxSocketOptions_keepAliveOptionsSuppo
/*
* Class: jdk_net_LinuxSocketOptions
* Method: setTcpkeepAliveProbes0
* Method: setTcpKeepAliveProbes0
* Signature: (II)V
*/
JNIEXPORT void JNICALL Java_jdk_net_LinuxSocketOptions_setTcpkeepAliveProbes0
JNIEXPORT void JNICALL Java_jdk_net_LinuxSocketOptions_setTcpKeepAliveProbes0
(JNIEnv *env, jobject unused, jint fd, jint optval) {
jint rv = setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &optval, sizeof (optval));
handleError(env, rv, "set option TCP_KEEPCNT failed");
@ -186,10 +186,10 @@ JNIEXPORT void JNICALL Java_jdk_net_LinuxSocketOptions_setTcpKeepAliveIntvl0
/*
* Class: jdk_net_LinuxSocketOptions
* Method: getTcpkeepAliveProbes0
* Method: getTcpKeepAliveProbes0
* Signature: (I)I;
*/
JNIEXPORT jint JNICALL Java_jdk_net_LinuxSocketOptions_getTcpkeepAliveProbes0
JNIEXPORT jint JNICALL Java_jdk_net_LinuxSocketOptions_getTcpKeepAliveProbes0
(JNIEnv *env, jobject unused, jint fd) {
jint optval, rv;
socklen_t sz = sizeof (optval);

View File

@ -49,8 +49,8 @@ class MacOSXSocketOptions extends PlatformSocketOptions {
}
@Override
void setTcpkeepAliveProbes(int fd, final int value) throws SocketException {
setTcpkeepAliveProbes0(fd, value);
void setTcpKeepAliveProbes(int fd, final int value) throws SocketException {
setTcpKeepAliveProbes0(fd, value);
}
@Override
@ -69,8 +69,8 @@ class MacOSXSocketOptions extends PlatformSocketOptions {
}
@Override
int getTcpkeepAliveProbes(int fd) throws SocketException {
return getTcpkeepAliveProbes0(fd);
int getTcpKeepAliveProbes(int fd) throws SocketException {
return getTcpKeepAliveProbes0(fd);
}
@Override
@ -103,11 +103,11 @@ class MacOSXSocketOptions extends PlatformSocketOptions {
return new UnixDomainPrincipal(user, group);
}
private static native void setTcpkeepAliveProbes0(int fd, int value) throws SocketException;
private static native void setTcpKeepAliveProbes0(int fd, int value) throws SocketException;
private static native void setTcpKeepAliveTime0(int fd, int value) throws SocketException;
private static native void setTcpKeepAliveIntvl0(int fd, int value) throws SocketException;
private static native void setIpDontFragment0(int fd, boolean value, boolean isIPv6) throws SocketException;
private static native int getTcpkeepAliveProbes0(int fd) throws SocketException;
private static native int getTcpKeepAliveProbes0(int fd) throws SocketException;
private static native int getTcpKeepAliveTime0(int fd) throws SocketException;
private static native int getTcpKeepAliveIntvl0(int fd) throws SocketException;
private static native boolean getIpDontFragment0(int fd, boolean isIPv6) throws SocketException;

View File

@ -96,10 +96,10 @@ JNIEXPORT jboolean JNICALL Java_jdk_net_MacOSXSocketOptions_keepAliveOptionsSupp
/*
* Class: jdk_net_MacOSXSocketOptions
* Method: setTcpkeepAliveProbes0
* Method: setTcpKeepAliveProbes0
* Signature: (II)V
*/
JNIEXPORT void JNICALL Java_jdk_net_MacOSXSocketOptions_setTcpkeepAliveProbes0
JNIEXPORT void JNICALL Java_jdk_net_MacOSXSocketOptions_setTcpKeepAliveProbes0
(JNIEnv *env, jobject unused, jint fd, jint optval) {
jint rv = setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &optval, sizeof (optval));
handleError(env, rv, "set option TCP_KEEPCNT failed");
@ -129,10 +129,10 @@ JNIEXPORT void JNICALL Java_jdk_net_MacOSXSocketOptions_setTcpKeepAliveIntvl0
/*
* Class: jdk_net_MacOSXSocketOptions
* Method: getTcpkeepAliveProbes0
* Method: getTcpKeepAliveProbes0
* Signature: (I)I;
*/
JNIEXPORT jint JNICALL Java_jdk_net_MacOSXSocketOptions_getTcpkeepAliveProbes0
JNIEXPORT jint JNICALL Java_jdk_net_MacOSXSocketOptions_getTcpKeepAliveProbes0
(JNIEnv *env, jobject unused, jint fd) {
jint optval, rv;
socklen_t sz = sizeof (optval);

View File

@ -277,7 +277,7 @@ public final class ExtendedSocketOptions {
if (option == TCP_QUICKACK) {
setQuickAckOption(fd, (boolean) value);
} else if (option == TCP_KEEPCOUNT) {
setTcpkeepAliveProbes(fd, (Integer) value);
setTcpKeepAliveProbes(fd, (Integer) value);
} else if (option == IP_DONTFRAGMENT) {
setIpDontFragment(fd, (Boolean) value, isIPv6);
} else if (option == TCP_KEEPIDLE) {
@ -307,7 +307,7 @@ public final class ExtendedSocketOptions {
if (option == TCP_QUICKACK) {
return getQuickAckOption(fd);
} else if (option == TCP_KEEPCOUNT) {
return getTcpkeepAliveProbes(fd);
return getTcpKeepAliveProbes(fd);
} else if (option == IP_DONTFRAGMENT) {
return getIpDontFragment(fd, isIPv6);
} else if (option == TCP_KEEPIDLE) {
@ -343,9 +343,9 @@ public final class ExtendedSocketOptions {
return platformSocketOptions.getQuickAck(fdAccess.get(fd));
}
private static void setTcpkeepAliveProbes(FileDescriptor fd, int value)
private static void setTcpKeepAliveProbes(FileDescriptor fd, int value)
throws SocketException {
platformSocketOptions.setTcpkeepAliveProbes(fdAccess.get(fd), value);
platformSocketOptions.setTcpKeepAliveProbes(fdAccess.get(fd), value);
}
private static void setTcpKeepAliveTime(FileDescriptor fd, int value)
@ -363,8 +363,8 @@ public final class ExtendedSocketOptions {
platformSocketOptions.setTcpKeepAliveIntvl(fdAccess.get(fd), value);
}
private static int getTcpkeepAliveProbes(FileDescriptor fd) throws SocketException {
return platformSocketOptions.getTcpkeepAliveProbes(fdAccess.get(fd));
private static int getTcpKeepAliveProbes(FileDescriptor fd) throws SocketException {
return platformSocketOptions.getTcpKeepAliveProbes(fdAccess.get(fd));
}
private static boolean getIpDontFragment(FileDescriptor fd, boolean isIPv6) throws SocketException {
@ -438,7 +438,7 @@ public final class ExtendedSocketOptions {
return false;
}
void setTcpkeepAliveProbes(int fd, final int value) throws SocketException {
void setTcpKeepAliveProbes(int fd, final int value) throws SocketException {
throw new UnsupportedOperationException("unsupported TCP_KEEPCNT option");
}
@ -462,7 +462,7 @@ public final class ExtendedSocketOptions {
throw new UnsupportedOperationException("unsupported IP_DONTFRAGMENT option");
}
int getTcpkeepAliveProbes(int fd) throws SocketException {
int getTcpKeepAliveProbes(int fd) throws SocketException {
throw new UnsupportedOperationException("unsupported TCP_KEEPCNT option");
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -41,6 +41,11 @@ class WindowsSocketOptions extends PlatformSocketOptions {
return true;
}
@Override
boolean keepAliveOptionsSupported() {
return keepAliveOptionsSupported0();
}
@Override
void setIpDontFragment(int fd, final boolean value, boolean isIPv6) throws SocketException {
setIpDontFragment0(fd, value, isIPv6);
@ -51,8 +56,45 @@ class WindowsSocketOptions extends PlatformSocketOptions {
return getIpDontFragment0(fd, isIPv6);
}
@Override
void setTcpKeepAliveProbes(int fd, final int value) throws SocketException {
setTcpKeepAliveProbes0(fd, value);
}
@Override
int getTcpKeepAliveProbes(int fd) throws SocketException {
return getTcpKeepAliveProbes0(fd);
}
@Override
void setTcpKeepAliveTime(int fd, final int value) throws SocketException {
setTcpKeepAliveTime0(fd, value);
}
@Override
int getTcpKeepAliveTime(int fd) throws SocketException {
return getTcpKeepAliveTime0(fd);
}
@Override
void setTcpKeepAliveIntvl(int fd, final int value) throws SocketException {
setTcpKeepAliveIntvl0(fd, value);
}
@Override
int getTcpKeepAliveIntvl(int fd) throws SocketException {
return getTcpKeepAliveIntvl0(fd);
}
private static native boolean keepAliveOptionsSupported0();
private static native void setIpDontFragment0(int fd, boolean value, boolean isIPv6) throws SocketException;
private static native boolean getIpDontFragment0(int fd, boolean isIPv6) throws SocketException;
private static native void setTcpKeepAliveProbes0(int fd, int value) throws SocketException;
private static native int getTcpKeepAliveProbes0(int fd) throws SocketException;
private static native void setTcpKeepAliveTime0(int fd, int value) throws SocketException;
private static native int getTcpKeepAliveTime0(int fd) throws SocketException;
private static native void setTcpKeepAliveIntvl0(int fd, int value) throws SocketException;
private static native int getTcpKeepAliveIntvl0(int fd) throws SocketException;
static {
if (System.getSecurityManager() == null) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -34,7 +34,8 @@
static void handleError(JNIEnv *env, jint rv, const char *errmsg) {
if (rv < 0) {
if (errno == ENOPROTOOPT) {
int error = WSAGetLastError();
if (error == WSAENOPROTOOPT) {
JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
"unsupported socket option");
} else {
@ -43,6 +44,57 @@ static void handleError(JNIEnv *env, jint rv, const char *errmsg) {
}
}
static jint socketOptionSupported(jint level, jint optname) {
WSADATA wsaData;
jint error = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (error != 0) {
return 0;
}
SOCKET sock;
jint one = 1;
jint rv;
socklen_t sz = sizeof(one);
/* First try IPv6; fall back to IPv4. */
sock = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET) {
error = WSAGetLastError();
if (error == WSAEPFNOSUPPORT || error == WSAEAFNOSUPPORT) {
sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
}
if (sock == INVALID_SOCKET) {
return 0;
}
}
rv = getsockopt(sock, level, optname, (char*) &one, &sz);
error = WSAGetLastError();
if (rv != 0 && error == WSAENOPROTOOPT) {
rv = 0;
} else {
rv = 1;
}
closesocket(sock);
WSACleanup();
return rv;
}
/*
* Class: jdk_net_WindowsSocketOptions
* Method: keepAliveOptionsSupported0
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_jdk_net_WindowsSocketOptions_keepAliveOptionsSupported0
(JNIEnv *env, jobject unused) {
return socketOptionSupported(IPPROTO_TCP, TCP_KEEPIDLE) && socketOptionSupported(IPPROTO_TCP, TCP_KEEPCNT)
&& socketOptionSupported(IPPROTO_TCP, TCP_KEEPINTVL);
}
/*
* Class: jdk_net_WindowsSocketOptions
* Method: setIpDontFragment0
@ -103,3 +155,78 @@ JNIEXPORT jboolean JNICALL Java_jdk_net_WindowsSocketOptions_getIpDontFragment0
}
}
/*
* Class: jdk_net_WindowsSocketOptions
* Method: setTcpKeepAliveProbes0
* Signature: (II)V
*/
JNIEXPORT void JNICALL Java_jdk_net_WindowsSocketOptions_setTcpKeepAliveProbes0
(JNIEnv *env, jobject unused, jint fd, jint optval) {
jint rv = setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, (char*) &optval, sizeof(optval));
handleError(env, rv, "set option TCP_KEEPCNT failed");
}
/*
* Class: jdk_net_WindowsSocketOptions
* Method: getTcpKeepAliveProbes0
* Signature: (I)I;
*/
JNIEXPORT jint JNICALL Java_jdk_net_WindowsSocketOptions_getTcpKeepAliveProbes0
(JNIEnv *env, jobject unused, jint fd) {
jint optval, rv;
socklen_t sz = sizeof(optval);
rv = getsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, (char*) &optval, &sz);
handleError(env, rv, "get option TCP_KEEPCNT failed");
return optval;
}
/*
* Class: jdk_net_WindowsSocketOptions
* Method: setTcpKeepAliveTime0
* Signature: (II)V
*/
JNIEXPORT void JNICALL Java_jdk_net_WindowsSocketOptions_setTcpKeepAliveTime0
(JNIEnv *env, jobject unused, jint fd, jint optval) {
jint rv = setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, (char*) &optval, sizeof(optval));
handleError(env, rv, "set option TCP_KEEPIDLE failed");
}
/*
* Class: jdk_net_WindowsSocketOptions
* Method: getTcpKeepAliveTime0
* Signature: (I)I;
*/
JNIEXPORT jint JNICALL Java_jdk_net_WindowsSocketOptions_getTcpKeepAliveTime0
(JNIEnv *env, jobject unused, jint fd) {
jint optval, rv;
socklen_t sz = sizeof(optval);
rv = getsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, (char*) &optval, &sz);
handleError(env, rv, "get option TCP_KEEPIDLE failed");
return optval;
}
/*
* Class: jdk_net_WindowsSocketOptions
* Method: setTcpKeepAliveIntvl0
* Signature: (II)V
*/
JNIEXPORT void JNICALL Java_jdk_net_WindowsSocketOptions_setTcpKeepAliveIntvl0
(JNIEnv *env, jobject unused, jint fd, jint optval) {
jint rv = setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, (char*) &optval, sizeof(optval));
handleError(env, rv, "set option TCP_KEEPINTVL failed");
}
/*
* Class: jdk_net_WindowsSocketOptions
* Method: getTcpKeepAliveIntvl0
* Signature: (I)I;
*/
JNIEXPORT jint JNICALL Java_jdk_net_WindowsSocketOptions_getTcpKeepAliveIntvl0
(JNIEnv *env, jobject unused, jint fd) {
jint optval, rv;
socklen_t sz = sizeof(optval);
rv = getsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, (char*) &optval, &sz);
handleError(env, rv, "get option TCP_KEEPINTVL failed");
return optval;
}