Allowed Netty Epoll/Kqueue to work in IPv6 Only environments
Motivation: In some environments, IPv4 may be disabled (at a kernel level). Google has such an environment for testing v4 -> v6 transition paths. This give confidence that code is v6 ready. Modifications: Change native socket code to ignore failures of trying to enter dual stack mode. This change has been made to Google's internal JDK, and will/should be upstreamed to OpenJDK eventually. Results: Netty works in IPv6 only environments Fixes: #6993
This commit is contained in:
parent
a91df58ca1
commit
3d22b24244
|
@ -188,17 +188,40 @@ static int socket_type(JNIEnv* env) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void netty_unix_socket_optionHandleError(JNIEnv* env, int err, char* method) {
|
||||||
|
if (err == EBADF) {
|
||||||
|
netty_unix_errors_throwClosedChannelException(env);
|
||||||
|
} else {
|
||||||
|
netty_unix_errors_throwChannelExceptionErrorNo(env, method, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void netty_unix_socket_setOptionHandleError(JNIEnv* env, int err) {
|
||||||
|
netty_unix_socket_optionHandleError(env, err, "setsockopt() failed: ");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int netty_unix_socket_setOption0(jint fd, int level, int optname, const void* optval, socklen_t len) {
|
||||||
|
return setsockopt(fd, level, optname, optval, len);
|
||||||
|
}
|
||||||
|
|
||||||
static jint _socket(JNIEnv* env, jclass clazz, int type) {
|
static jint _socket(JNIEnv* env, jclass clazz, int type) {
|
||||||
int fd = nettyNonBlockingSocket(socketType, type, 0);
|
int fd = nettyNonBlockingSocket(socketType, type, 0);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
return -errno;
|
return -errno;
|
||||||
} else if (socketType == AF_INET6) {
|
} else if (socketType == AF_INET6) {
|
||||||
// Allow to listen /connect ipv4 and ipv6
|
// Try to allow listen /connect ipv4 and ipv6
|
||||||
int optval = 0;
|
int optval = 0;
|
||||||
if (netty_unix_socket_setOption(env, fd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval)) < 0) {
|
if (netty_unix_socket_setOption0(fd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval)) < 0) {
|
||||||
// Something went wrong so close the fd and return here. setOption(...) itself throws the exception already.
|
if (errno != EAFNOSUPPORT) {
|
||||||
close(fd);
|
netty_unix_socket_setOptionHandleError(env, errno);
|
||||||
return -1;
|
// Something went wrong so close the fd and return here. setOption(...) itself throws the exception already.
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// else we failed to enable dual stack mode.
|
||||||
|
// It is assumed the socket is re‐stricted to sending and receiving IPv6 packets only.
|
||||||
|
// Don't close fd and don't return -1. At best we can do is log.
|
||||||
|
// TODO: bubble this up to an actual Logger.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fd;
|
return fd;
|
||||||
|
@ -289,26 +312,10 @@ static jobject _recvFrom(JNIEnv* env, jint fd, void* buffer, jint pos, jint limi
|
||||||
return createDatagramSocketAddress(env, &addr, res);
|
return createDatagramSocketAddress(env, &addr, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void netty_unix_socket_optionHandleError(JNIEnv* env, int err, char* method) {
|
|
||||||
if (err == EBADF) {
|
|
||||||
netty_unix_errors_throwClosedChannelException(env);
|
|
||||||
} else {
|
|
||||||
netty_unix_errors_throwChannelExceptionErrorNo(env, method, err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netty_unix_socket_setOptionHandleError(JNIEnv* env, int err) {
|
|
||||||
netty_unix_socket_optionHandleError(env, err, "setsockopt() failed: ");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netty_unix_socket_getOptionHandleError(JNIEnv* env, int err) {
|
static void netty_unix_socket_getOptionHandleError(JNIEnv* env, int err) {
|
||||||
netty_unix_socket_optionHandleError(env, err, "getsockopt() failed: ");
|
netty_unix_socket_optionHandleError(env, err, "getsockopt() failed: ");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int netty_unix_socket_setOption0(jint fd, int level, int optname, const void* optval, socklen_t len) {
|
|
||||||
return setsockopt(fd, level, optname, optval, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int netty_unix_socket_getOption0(jint fd, int level, int optname, void* optval, socklen_t optlen) {
|
static int netty_unix_socket_getOption0(jint fd, int level, int optname, void* optval, socklen_t optlen) {
|
||||||
return getsockopt(fd, level, optname, optval, &optlen);
|
return getsockopt(fd, level, optname, optval, &optlen);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user