[#2396] Allow to set TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT in native transport

Motivation:
Allow to set TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT in native transport to offer the user with more flexibility.

Modifications:
Expose methods to set these options and write the JNI implementation.

Result:
User can now use TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT.
This commit is contained in:
Norman Maurer 2014-04-17 21:41:04 +02:00
parent e9161147a5
commit 97553069b6
5 changed files with 122 additions and 2 deletions

View File

@ -1079,6 +1079,18 @@ JNIEXPORT void JNICALL Java_io_netty_channel_epoll_Native_setBroadcast(JNIEnv *
setOption(env, fd, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval));
}
JNIEXPORT void JNICALL Java_io_netty_channel_epoll_Native_setTcpKeepIdle(JNIEnv *env, jclass clazz, jint fd, jint optval) {
setOption(env, fd, SOL_TCP, TCP_KEEPIDLE, &optval, sizeof(optval));
}
JNIEXPORT void JNICALL Java_io_netty_channel_epoll_Native_setTcpKeepIntvl(JNIEnv *env, jclass clazz, jint fd, jint optval) {
setOption(env, fd, SOL_TCP, TCP_KEEPINTVL, &optval, sizeof(optval));
}
JNIEXPORT void Java_io_netty_channel_epoll_Native_setTcpKeepCnt(JNIEnv *env, jclass clazz, jint fd, jint optval) {
setOption(env, fd, SOL_TCP, TCP_KEEPCNT, &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) {
@ -1155,6 +1167,30 @@ JNIEXPORT jint JNICALL Java_io_netty_channel_epoll_Native_isBroadcast(JNIEnv *en
return optval;
}
JNIEXPORT jint JNICALL Java_io_netty_channel_epoll_Native_getTcpKeepIdle(JNIEnv *env, jclass clazz, jint fd) {
int optval;
if (getOption(env, fd, SOL_TCP, TCP_KEEPIDLE, &optval, sizeof(optval)) == -1) {
return -1;
}
return optval;
}
JNIEXPORT jint JNICALL Java_io_netty_channel_epoll_Native_getTcpKeepIntvl(JNIEnv *env, jclass clazz, jint fd) {
int optval;
if (getOption(env, fd, SOL_TCP, TCP_KEEPINTVL, &optval, sizeof(optval)) == -1) {
return -1;
}
return optval;
}
JNIEXPORT jint JNICALL Java_io_netty_channel_epoll_Native_getTcpKeepCnt(JNIEnv *env, jclass clazz, jint fd) {
int optval;
if (getOption(env, fd, SOL_TCP, TCP_KEEPCNT, &optval, sizeof(optval)) == -1) {
return -1;
}
return optval;
}
JNIEXPORT jstring JNICALL Java_io_netty_channel_epoll_Native_kernelVersion(JNIEnv *env, jclass clazz) {
struct utsname name;
@ -1165,4 +1201,4 @@ JNIEXPORT jstring JNICALL Java_io_netty_channel_epoll_Native_kernelVersion(JNIEn
int err = errno;
throwRuntimeException(env, exceptionMessage("Error during uname(...): ", err));
return NULL;
}
}

View File

@ -63,6 +63,10 @@ void Java_io_netty_channel_epoll_Native_setTcpCork(JNIEnv *env, jclass clazz, ji
void Java_io_netty_channel_epoll_Native_setSoLinger(JNIEnv *env, jclass clazz, jint fd, jint optval);
void Java_io_netty_channel_epoll_Native_setTrafficClass(JNIEnv *env, jclass clazz, jint fd, jint optval);
void Java_io_netty_channel_epoll_Native_setBroadcast(JNIEnv *env, jclass clazz, jint fd, jint optval);
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);
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);
jint Java_io_netty_channel_epoll_Native_isTcpNoDelay(JNIEnv *env, jclass clazz, jint fd);
@ -72,4 +76,8 @@ jint Java_io_netty_channel_epoll_Native_isTcpCork(JNIEnv *env, jclass clazz, jin
jint Java_io_netty_channel_epoll_Native_getSoLinger(JNIEnv *env, jclass clazz, jint fd);
jint Java_io_netty_channel_epoll_Native_getTrafficClass(JNIEnv *env, jclass clazz, jint fd);
jint Java_io_netty_channel_epoll_Native_isBroadcast(JNIEnv *env, jclass clazz, jint fd);
jint Java_io_netty_channel_epoll_Native_getTcpKeepIdle(JNIEnv *env, jclass clazz, jint fd);
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);
jstring Java_io_netty_channel_epoll_Native_kernelVersion(JNIEnv *env, jclass clazz);

View File

@ -22,6 +22,9 @@ public final class EpollChannelOption {
public static final ChannelOption<Boolean> TCP_CORK = ChannelOption.valueOf(T, "TCP_CORK");
public static final ChannelOption<Boolean> SO_REUSEPORT = ChannelOption.valueOf(T, "SO_REUSEPORT");
public static final ChannelOption<Boolean> TCP_KEEPIDLE = ChannelOption.valueOf(T, "TCP_KEEPIDLE");
public static final ChannelOption<Boolean> TCP_KEEPINTVL = ChannelOption.valueOf(T, "TCP_KEEPINTVL");
public static final ChannelOption<Boolean> TCP_KEEPCNT = ChannelOption.valueOf(T, "TCP_KEEPCNT");
private EpollChannelOption() { }

View File

@ -50,7 +50,8 @@ public final class EpollSocketChannelConfig extends DefaultChannelConfig
return getOptions(
super.getOptions(),
SO_RCVBUF, SO_SNDBUF, TCP_NODELAY, SO_KEEPALIVE, SO_REUSEADDR, SO_LINGER, IP_TOS,
ALLOW_HALF_CLOSURE, EpollChannelOption.TCP_CORK);
ALLOW_HALF_CLOSURE, EpollChannelOption.TCP_CORK, EpollChannelOption.TCP_KEEPCNT,
EpollChannelOption.TCP_KEEPIDLE, EpollChannelOption.TCP_KEEPINTVL);
}
@SuppressWarnings("unchecked")
@ -83,6 +84,15 @@ public final class EpollSocketChannelConfig extends DefaultChannelConfig
if (option == EpollChannelOption.TCP_CORK) {
return (T) Boolean.valueOf(isTcpCork());
}
if (option == EpollChannelOption.TCP_KEEPIDLE) {
return (T) Integer.valueOf(getTcpKeepIdle());
}
if (option == EpollChannelOption.TCP_KEEPINTVL) {
return (T) Integer.valueOf(getTcpKeepIntvl());
}
if (option == EpollChannelOption.TCP_KEEPCNT) {
return (T) Integer.valueOf(getTcpKeepCnt());
}
return super.getOption(option);
}
@ -108,6 +118,12 @@ public final class EpollSocketChannelConfig extends DefaultChannelConfig
setAllowHalfClosure((Boolean) value);
} else if (option == EpollChannelOption.TCP_CORK) {
setTcpCork((Boolean) value);
} else if (option == EpollChannelOption.TCP_KEEPIDLE) {
setTcpKeepIdle((Integer) value);
} else if (option == EpollChannelOption.TCP_KEEPCNT) {
setTcpKeepCntl((Integer) value);
} else if (option == EpollChannelOption.TCP_KEEPINTVL) {
setTcpKeepIntvl((Integer) value);
} else {
return super.setOption(option, value);
}
@ -150,10 +166,34 @@ public final class EpollSocketChannelConfig extends DefaultChannelConfig
return Native.isTcpNoDelay(channel.fd) == 1;
}
/**
* Get the {@code TCP_CORK} option on the socket. See {@code man 7 tcp} for more details.
*/
public boolean isTcpCork() {
return Native.isTcpCork(channel.fd) == 1;
}
/**
* Get the {@code TCP_KEEPIDLE} option on the socket. See {@code man 7 tcp} for more details.
*/
public int getTcpKeepIdle() {
return Native.getTcpKeepIdle(channel.fd);
}
/**
* Get the {@code TCP_KEEPINTVL} option on the socket. See {@code man 7 tcp} for more details.
*/
public int getTcpKeepIntvl() {
return Native.getTcpKeepIntvl(channel.fd);
}
/**
* Get the {@code TCP_KEEPCNT} option on the socket. See {@code man 7 tcp} for more details.
*/
public int getTcpKeepCnt() {
return Native.getTcpKeepCnt(channel.fd);
}
@Override
public EpollSocketChannelConfig setKeepAlive(boolean keepAlive) {
Native.setKeepAlive(channel.fd, keepAlive ? 1 : 0);
@ -196,6 +236,9 @@ public final class EpollSocketChannelConfig extends DefaultChannelConfig
return this;
}
/**
* Set the {@code TCP_CORK} option on the socket. See {@code man 7 tcp} for more details.
*/
public EpollSocketChannelConfig setTcpCork(boolean tcpCork) {
Native.setTcpCork(channel.fd, tcpCork ? 1 : 0);
return this;
@ -207,6 +250,30 @@ public final class EpollSocketChannelConfig extends DefaultChannelConfig
return this;
}
/**
* Set the {@code TCP_KEEPIDLE} option on the socket. See {@code man 7 tcp} for more details.
*/
public EpollSocketChannelConfig setTcpKeepIdle(int seconds) {
Native.setTcpKeepIdle(channel.fd, seconds);
return this;
}
/**
* Set the {@code TCP_KEEPINTVL} option on the socket. See {@code man 7 tcp} for more details.
*/
public EpollSocketChannelConfig setTcpKeepIntvl(int seconds) {
Native.setTcpKeepIntvl(channel.fd, seconds);
return this;
}
/**
* Set the {@code TCP_KEEPCNT} option on the socket. See {@code man 7 tcp} for more details.
*/
public EpollSocketChannelConfig setTcpKeepCntl(int probes) {
Native.setTcpKeepCnt(channel.fd, probes);
return this;
}
@Override
public boolean isAllowHalfClosure() {
return allowHalfClosure;

View File

@ -179,6 +179,9 @@ final class Native {
public static native int getSoLinger(int fd);
public static native int getTrafficClass(int fd);
public static native int isBroadcast(int fd);
public static native int getTcpKeepIdle(int fd);
public static native int getTcpKeepIntvl(int fd);
public static native int getTcpKeepCnt(int fd);
public static native void setKeepAlive(int fd, int keepAlive);
public static native void setReceiveBufferSize(int fd, int receiveBufferSize);
@ -190,6 +193,9 @@ final class Native {
public static native void setSoLinger(int fd, int soLinger);
public static native void setTrafficClass(int fd, int tcpNoDelay);
public static native void setBroadcast(int fd, int broadcast);
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);
private static NativeInetAddress toNativeInetAddress(InetAddress addr) {
byte[] bytes = addr.getAddress();