mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-20 11:04:34 +02:00
8250521: Configure initial RTO to use minimal retry for loopback connections on Windows
Reviewed-by: alanb
This commit is contained in:
parent
7332181372
commit
c2fa441d8d
3 changed files with 87 additions and 4 deletions
|
@ -770,6 +770,57 @@ NET_EnableFastTcpLoopback(int fd) {
|
|||
return result == SOCKET_ERROR ? WSAGetLastError() : 0;
|
||||
}
|
||||
|
||||
int
|
||||
IsWindows10RS3OrGreater() {
|
||||
OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0 };
|
||||
DWORDLONG const cond_mask = VerSetConditionMask(
|
||||
VerSetConditionMask(
|
||||
VerSetConditionMask(
|
||||
0, VER_MAJORVERSION, VER_GREATER_EQUAL),
|
||||
VER_MINORVERSION, VER_GREATER_EQUAL),
|
||||
VER_BUILDNUMBER, VER_GREATER_EQUAL);
|
||||
|
||||
osvi.dwMajorVersion = HIBYTE(_WIN32_WINNT_WIN10);
|
||||
osvi.dwMinorVersion = LOBYTE(_WIN32_WINNT_WIN10);
|
||||
osvi.dwBuildNumber = 16299; // RS3 (Redstone 3)
|
||||
|
||||
return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER, cond_mask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortens the default Windows socket
|
||||
* connect timeout. Recommended for usage
|
||||
* on the loopback adapter only.
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
NET_EnableFastTcpLoopbackConnect(int fd) {
|
||||
TCP_INITIAL_RTO_PARAMETERS rto = {
|
||||
TCP_INITIAL_RTO_UNSPECIFIED_RTT, // Use the default or overriden by the Administrator
|
||||
1 // Minimum possible value before Windows 10 RS3
|
||||
};
|
||||
|
||||
/**
|
||||
* In Windows 10 RS3+ we can use the no retransmissions flag to
|
||||
* completely remove the timeout delay, which is fixed to 500ms
|
||||
* if Windows receives RST when the destination port is not open.
|
||||
*/
|
||||
if (IsWindows10RS3OrGreater()) {
|
||||
rto.MaxSynRetransmissions = TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS;
|
||||
}
|
||||
|
||||
DWORD result_byte_count = -1;
|
||||
int result = WSAIoctl(fd, // descriptor identifying a socket
|
||||
SIO_TCP_INITIAL_RTO, // dwIoControlCode
|
||||
&rto, // pointer to TCP_INITIAL_RTO_PARAMETERS structure
|
||||
sizeof(rto), // size, in bytes, of the input buffer
|
||||
NULL, // pointer to output buffer
|
||||
0, // size of output buffer
|
||||
&result_byte_count, // number of bytes returned
|
||||
NULL, // OVERLAPPED structure
|
||||
NULL); // completion routine
|
||||
return (result == SOCKET_ERROR) ? WSAGetLastError() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* See net_util.h for documentation
|
||||
*/
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <WS2tcpip.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <icmpapi.h>
|
||||
#include <mstcpip.h>
|
||||
|
||||
/* used to disable connection reset messages on Windows XP */
|
||||
#ifndef SIO_UDP_CONNRESET
|
||||
|
@ -86,10 +87,29 @@ struct ipv6bind {
|
|||
|
||||
#define GET_PORT(X) ((X)->sa.sa_family == AF_INET ? (X)->sa4.sin_port : (X)->sa6.sin6_port)
|
||||
|
||||
/**
|
||||
* With dual socket implementation the
|
||||
* IPv4 addresseses might be mapped as IPv6.
|
||||
* The IPv4 loopback adapter address will
|
||||
* be mapped as the following IPv6 ::ffff:127.0.0.1.
|
||||
* For example, this is done by NET_InetAddressToSockaddr.
|
||||
*/
|
||||
#define IN6_IS_ADDR_V4MAPPED_LOOPBACK(x) ( \
|
||||
(((x)->s6_words[0] == 0) && \
|
||||
((x)->s6_words[1] == 0) && \
|
||||
((x)->s6_words[2] == 0) && \
|
||||
((x)->s6_words[3] == 0) && \
|
||||
((x)->s6_words[4] == 0) && \
|
||||
((x)->s6_words[5] == 0xFFFF) && \
|
||||
((x)->s6_words[6] == 0x007F) && \
|
||||
((x)->s6_words[7] == 0x0100)) \
|
||||
)
|
||||
|
||||
#define IS_LOOPBACK_ADDRESS(x) ( \
|
||||
((x)->sa.sa_family == AF_INET) ? \
|
||||
(ntohl((x)->sa4.sin_addr.s_addr) == INADDR_LOOPBACK) : \
|
||||
(IN6ADDR_ISLOOPBACK(x)) \
|
||||
((IN6_IS_ADDR_LOOPBACK(&(x)->sa6.sin6_addr)) || \
|
||||
(IN6_IS_ADDR_V4MAPPED_LOOPBACK(&(x)->sa6.sin6_addr))) \
|
||||
)
|
||||
|
||||
JNIEXPORT int JNICALL NET_SocketClose(int fd);
|
||||
|
@ -119,6 +139,8 @@ JNIEXPORT int JNICALL NET_BindV6(struct ipv6bind *b, jboolean exclBind);
|
|||
JNIEXPORT int JNICALL NET_WinBind(int s, SOCKETADDRESS *sa, int len,
|
||||
jboolean exclBind);
|
||||
|
||||
JNIEXPORT jint JNICALL NET_EnableFastTcpLoopbackConnect(int fd);
|
||||
|
||||
/* XP versions of the native routines */
|
||||
|
||||
JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByName0_XP
|
||||
|
|
|
@ -226,13 +226,25 @@ Java_sun_nio_ch_Net_connect0(JNIEnv *env, jclass clazz, jboolean preferIPv6, job
|
|||
{
|
||||
SOCKETADDRESS sa;
|
||||
int rv;
|
||||
int so_rv;
|
||||
int sa_len = 0;
|
||||
SOCKET s = (SOCKET)fdval(env, fdo);
|
||||
int type = 0, optlen = sizeof(type);
|
||||
|
||||
if (NET_InetAddressToSockaddr(env, iao, port, &sa, &sa_len, preferIPv6) != 0) {
|
||||
return IOS_THROWN;
|
||||
}
|
||||
|
||||
so_rv = getsockopt(s, SOL_SOCKET, SO_TYPE, (char*)&type, &optlen);
|
||||
|
||||
/**
|
||||
* Windows has a very long socket connect timeout of 2 seconds.
|
||||
* If it's the loopback adapter we can shorten the wait interval.
|
||||
*/
|
||||
if (so_rv == 0 && type == SOCK_STREAM && IS_LOOPBACK_ADDRESS(&sa)) {
|
||||
NET_EnableFastTcpLoopbackConnect((jint)s);
|
||||
}
|
||||
|
||||
rv = connect(s, &sa.sa, sa_len);
|
||||
if (rv != 0) {
|
||||
int err = WSAGetLastError();
|
||||
|
@ -243,9 +255,7 @@ Java_sun_nio_ch_Net_connect0(JNIEnv *env, jclass clazz, jboolean preferIPv6, job
|
|||
return IOS_THROWN;
|
||||
} else {
|
||||
/* Enable WSAECONNRESET errors when a UDP socket is connected */
|
||||
int type = 0, optlen = sizeof(type);
|
||||
rv = getsockopt(s, SOL_SOCKET, SO_TYPE, (char*)&type, &optlen);
|
||||
if (rv == 0 && type == SOCK_DGRAM) {
|
||||
if (so_rv == 0 && type == SOCK_DGRAM) {
|
||||
setConnectionReset(s, TRUE);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue