From f65717be827cc8d141daafc96cc6b8e11028aa92 Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Mon, 27 Jul 2015 13:48:07 +0200 Subject: [PATCH] Add support for IP_FREEBIND when using native transport Motivation: IP_FREEBIND allows to bind to addresses without the address up yet or even the interface configured yet. Modifications: Add support for IP_FREEBIND. Result: It's now possible to use IP_FREEBIND when using the native epoll transport. --- .../main/c/io_netty_channel_epoll_Native.c | 12 ++++++++++ .../main/c/io_netty_channel_epoll_Native.h | 2 ++ .../channel/epoll/EpollChannelOption.java | 2 ++ .../epoll/EpollServerSocketChannelConfig.java | 24 ++++++++++++++++++- .../java/io/netty/channel/epoll/Native.java | 3 ++- 5 files changed, 41 insertions(+), 2 deletions(-) diff --git a/transport-native-epoll/src/main/c/io_netty_channel_epoll_Native.c b/transport-native-epoll/src/main/c/io_netty_channel_epoll_Native.c index a277d1695a..480bf50a1c 100644 --- a/transport-native-epoll/src/main/c/io_netty_channel_epoll_Native.c +++ b/transport-native-epoll/src/main/c/io_netty_channel_epoll_Native.c @@ -1248,6 +1248,10 @@ JNIEXPORT void Java_io_netty_channel_epoll_Native_setTcpKeepCnt(JNIEnv* env, jcl setOption(env, fd, IPPROTO_TCP, TCP_KEEPCNT, &optval, sizeof(optval)); } +JNIEXPORT void JNICALL Java_io_netty_channel_epoll_Native_setIpFreeBind(JNIEnv* env, jclass clazz, jint fd, jint optval) { + setOption(env, fd, IPPROTO_IP, IP_FREEBIND, &optval, sizeof(optval)); +} + JNIEXPORT jint JNICALL Java_io_netty_channel_epoll_Native_isReuseAddresss(JNIEnv* env, jclass clazz, jint fd) { int optval; if (getOption(env, fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1) { @@ -1364,6 +1368,14 @@ JNIEXPORT jint JNICALL Java_io_netty_channel_epoll_Native_getTcpKeepCnt(JNIEnv* return optval; } +JNIEXPORT jint JNICALL Java_io_netty_channel_epoll_Native_isIpFreeBind(JNIEnv* env, jclass clazz, jint fd) { + int optval; + if (getOption(env, fd, IPPROTO_TCP, IP_FREEBIND, &optval, sizeof(optval)) == -1) { + return -1; + } + return optval; +} + JNIEXPORT void JNICALL Java_io_netty_channel_epoll_Native_tcpInfo0(JNIEnv* env, jclass clazz, jint fd, jintArray array) { struct tcp_info tcp_info; if (getOption(env, fd, IPPROTO_TCP, TCP_INFO, &tcp_info, sizeof(tcp_info)) == -1) { diff --git a/transport-native-epoll/src/main/c/io_netty_channel_epoll_Native.h b/transport-native-epoll/src/main/c/io_netty_channel_epoll_Native.h index 4708557ab1..380bd3b20f 100644 --- a/transport-native-epoll/src/main/c/io_netty_channel_epoll_Native.h +++ b/transport-native-epoll/src/main/c/io_netty_channel_epoll_Native.h @@ -87,6 +87,7 @@ void Java_io_netty_channel_epoll_Native_setBroadcast(JNIEnv* env, jclass clazz, void Java_io_netty_channel_epoll_Native_setTcpKeepIdle(JNIEnv* env, jclass clazz, jint fd, jint optval); void Java_io_netty_channel_epoll_Native_setTcpKeepIntvl(JNIEnv* env, jclass clazz, jint fd, jint optval); void Java_io_netty_channel_epoll_Native_setTcpKeepCnt(JNIEnv* env, jclass clazz, jint fd, jint optval); +void Java_io_netty_channel_epoll_Native_setIpFreeBind(JNIEnv* env, jclass clazz, jint fd, jint optval); jint Java_io_netty_channel_epoll_Native_isReuseAddresss(JNIEnv* env, jclass clazz, jint fd); jint Java_io_netty_channel_epoll_Native_isReusePort(JNIEnv* env, jclass clazz, jint fd); @@ -102,6 +103,7 @@ jint Java_io_netty_channel_epoll_Native_getTcpKeepIdle(JNIEnv* env, jclass clazz jint Java_io_netty_channel_epoll_Native_getTcpKeepIntvl(JNIEnv* env, jclass clazz, jint fd); jint Java_io_netty_channel_epoll_Native_getTcpKeepCnt(JNIEnv* env, jclass clazz, jint fd); jint Java_io_netty_channel_epoll_Native_getSoError(JNIEnv* env, jclass clazz, jint fd); +jint Java_io_netty_channel_epoll_Native_isIpFreeBind(JNIEnv* env, jclass clazz, jint fd); jstring Java_io_netty_channel_epoll_Native_kernelVersion(JNIEnv* env, jclass clazz); jint Java_io_netty_channel_epoll_Native_iovMax(JNIEnv* env, jclass clazz); diff --git a/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollChannelOption.java b/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollChannelOption.java index 061b077140..c3fec22a22 100644 --- a/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollChannelOption.java +++ b/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollChannelOption.java @@ -28,6 +28,8 @@ public final class EpollChannelOption extends ChannelOption { public static final ChannelOption TCP_KEEPIDLE = ChannelOption.valueOf(T, "TCP_KEEPIDLE"); public static final ChannelOption TCP_KEEPINTVL = ChannelOption.valueOf(T, "TCP_KEEPINTVL"); public static final ChannelOption TCP_KEEPCNT = ChannelOption.valueOf(T, "TCP_KEEPCNT"); + public static final ChannelOption IP_FREEBIND = ChannelOption.valueOf("IP_FREEBIND"); + public static final ChannelOption DOMAIN_SOCKET_READ_MODE = ChannelOption.valueOf(T, "DOMAIN_SOCKET_READ_MODE"); public static final ChannelOption EPOLL_MODE = diff --git a/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollServerSocketChannelConfig.java b/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollServerSocketChannelConfig.java index c1ee1c0d52..e6888eb55e 100644 --- a/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollServerSocketChannelConfig.java +++ b/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollServerSocketChannelConfig.java @@ -37,7 +37,7 @@ public final class EpollServerSocketChannelConfig extends EpollServerChannelConf @Override public Map, Object> getOptions() { - return getOptions(super.getOptions(), EpollChannelOption.SO_REUSEPORT); + return getOptions(super.getOptions(), EpollChannelOption.SO_REUSEPORT, EpollChannelOption.IP_FREEBIND); } @SuppressWarnings("unchecked") @@ -46,6 +46,9 @@ public final class EpollServerSocketChannelConfig extends EpollServerChannelConf if (option == EpollChannelOption.SO_REUSEPORT) { return (T) Boolean.valueOf(isReusePort()); } + if (option == EpollChannelOption.IP_FREEBIND) { + return (T) Boolean.valueOf(isFreeBind()); + } return super.getOption(option); } @@ -55,6 +58,8 @@ public final class EpollServerSocketChannelConfig extends EpollServerChannelConf if (option == EpollChannelOption.SO_REUSEPORT) { setReusePort((Boolean) value); + } else if (option == EpollChannelOption.IP_FREEBIND) { + setFreeBind((Boolean) value); } else { return super.setOption(option, value); } @@ -157,4 +162,21 @@ public final class EpollServerSocketChannelConfig extends EpollServerChannelConf Native.setReusePort(channel.fd().intValue(), reusePort ? 1 : 0); return this; } + + /** + * Returns {@code true} if IP_FREEBIND is enabled, + * {@code false} otherwise. + */ + public boolean isFreeBind() { + return Native.isIpFreeBind(channel.fd().intValue()) != 0; + } + + /** + * If {@code true} is used IP_FREEBIND is enabled, + * {@code false} for disable it. Default is disabled. + */ + public EpollServerSocketChannelConfig setFreeBind(boolean freeBind) { + Native.setIpFreeBind(channel.fd().intValue(), freeBind ? 1: 0); + return this; + } } diff --git a/transport-native-epoll/src/main/java/io/netty/channel/epoll/Native.java b/transport-native-epoll/src/main/java/io/netty/channel/epoll/Native.java index ede80dcef6..492d3f8680 100644 --- a/transport-native-epoll/src/main/java/io/netty/channel/epoll/Native.java +++ b/transport-native-epoll/src/main/java/io/netty/channel/epoll/Native.java @@ -635,6 +635,7 @@ public final class Native { public static native int getTcpKeepIntvl(int fd); public static native int getTcpKeepCnt(int fd); public static native int getSoError(int fd); + public static native int isIpFreeBind(int fd); public static native void setKeepAlive(int fd, int keepAlive); public static native void setReceiveBufferSize(int fd, int receiveBufferSize); @@ -650,7 +651,7 @@ public final class Native { public static native void setTcpKeepIdle(int fd, int seconds); public static native void setTcpKeepIntvl(int fd, int seconds); public static native void setTcpKeepCnt(int fd, int probes); - + public static native void setIpFreeBind(int fd, int freeBind); public static void tcpInfo(int fd, EpollTcpInfo info) { tcpInfo0(fd, info.info); }