Add TCP_USER_TIMEOUT

Motivation:

See #4174.

Modifications:

Modify transport-native-epoll to allow setting TCP_USER_TIMEOUT.

Result:

Hanging connections that are written into will get timeouted.
This commit is contained in:
Tomas Olvecky 2015-08-31 00:11:39 +02:00 committed by Norman Maurer
parent 2d4a8a75bb
commit 9e7a5693f3
4 changed files with 35 additions and 0 deletions

View File

@ -1271,6 +1271,10 @@ JNIEXPORT void Java_io_netty_channel_epoll_Native_setTcpKeepCnt(JNIEnv* env, jcl
setOption(env, fd, IPPROTO_TCP, TCP_KEEPCNT, &optval, sizeof(optval)); setOption(env, fd, IPPROTO_TCP, TCP_KEEPCNT, &optval, sizeof(optval));
} }
JNIEXPORT void Java_io_netty_channel_epoll_Native_setTcpUserTimeout(JNIEnv* env, jclass clazz, jint fd, jint optval) {
setOption(env, fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &optval, sizeof(optval));
}
JNIEXPORT void JNICALL Java_io_netty_channel_epoll_Native_setIpFreeBind(JNIEnv* env, jclass clazz, jint fd, jint 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)); setOption(env, fd, IPPROTO_IP, IP_FREEBIND, &optval, sizeof(optval));
} }
@ -1391,6 +1395,14 @@ JNIEXPORT jint JNICALL Java_io_netty_channel_epoll_Native_getTcpKeepCnt(JNIEnv*
return optval; return optval;
} }
JNIEXPORT jint JNICALL Java_io_netty_channel_epoll_Native_getTcpUserTimeout(JNIEnv* env, jclass clazz, jint fd) {
int optval;
if (getOption(env, fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &optval, sizeof(optval)) == -1) {
return -1;
}
return optval;
}
JNIEXPORT jint JNICALL Java_io_netty_channel_epoll_Native_isIpFreeBind(JNIEnv* env, jclass clazz, jint fd) { JNIEXPORT jint JNICALL Java_io_netty_channel_epoll_Native_isIpFreeBind(JNIEnv* env, jclass clazz, jint fd) {
int optval; int optval;
if (getOption(env, fd, IPPROTO_TCP, IP_FREEBIND, &optval, sizeof(optval)) == -1) { if (getOption(env, fd, IPPROTO_TCP, IP_FREEBIND, &optval, sizeof(optval)) == -1) {

View File

@ -26,6 +26,7 @@ public final class EpollChannelOption<T> extends ChannelOption<T> {
public static final ChannelOption<Integer> TCP_KEEPIDLE = valueOf("TCP_KEEPIDLE"); public static final ChannelOption<Integer> TCP_KEEPIDLE = valueOf("TCP_KEEPIDLE");
public static final ChannelOption<Integer> TCP_KEEPINTVL = valueOf("TCP_KEEPINTVL"); public static final ChannelOption<Integer> TCP_KEEPINTVL = valueOf("TCP_KEEPINTVL");
public static final ChannelOption<Integer> TCP_KEEPCNT = valueOf("TCP_KEEPCNT"); public static final ChannelOption<Integer> TCP_KEEPCNT = valueOf("TCP_KEEPCNT");
public static final ChannelOption<Integer> TCP_USER_TIMEOUT = valueOf("TCP_USER_TIMEOUT");
public static final ChannelOption<Boolean> IP_FREEBIND = valueOf("IP_FREEBIND"); public static final ChannelOption<Boolean> IP_FREEBIND = valueOf("IP_FREEBIND");
public static final ChannelOption<DomainSocketReadMode> DOMAIN_SOCKET_READ_MODE = public static final ChannelOption<DomainSocketReadMode> DOMAIN_SOCKET_READ_MODE =

View File

@ -94,6 +94,9 @@ public final class EpollSocketChannelConfig extends EpollChannelConfig implement
if (option == EpollChannelOption.TCP_KEEPCNT) { if (option == EpollChannelOption.TCP_KEEPCNT) {
return (T) Integer.valueOf(getTcpKeepCnt()); return (T) Integer.valueOf(getTcpKeepCnt());
} }
if (option == EpollChannelOption.TCP_USER_TIMEOUT) {
return (T) Integer.valueOf(getTcpUserTimeout());
}
return super.getOption(option); return super.getOption(option);
} }
@ -127,6 +130,8 @@ public final class EpollSocketChannelConfig extends EpollChannelConfig implement
setTcpKeepCntl((Integer) value); setTcpKeepCntl((Integer) value);
} else if (option == EpollChannelOption.TCP_KEEPINTVL) { } else if (option == EpollChannelOption.TCP_KEEPINTVL) {
setTcpKeepIntvl((Integer) value); setTcpKeepIntvl((Integer) value);
} else if (option == EpollChannelOption.TCP_USER_TIMEOUT) {
setTcpUserTimeout((Integer) value);
} else { } else {
return super.setOption(option, value); return super.setOption(option, value);
} }
@ -205,6 +210,13 @@ public final class EpollSocketChannelConfig extends EpollChannelConfig implement
return Native.getTcpKeepCnt(channel.fd().intValue()); return Native.getTcpKeepCnt(channel.fd().intValue());
} }
/**
* Get the {@code TCP_USER_TIMEOUT} option on the socket. See {@code man 7 tcp} for more details.
*/
public int getTcpUserTimeout() {
return Native.getTcpUserTimeout(channel.fd().intValue());
}
@Override @Override
public EpollSocketChannelConfig setKeepAlive(boolean keepAlive) { public EpollSocketChannelConfig setKeepAlive(boolean keepAlive) {
Native.setKeepAlive(channel.fd().intValue(), keepAlive ? 1 : 0); Native.setKeepAlive(channel.fd().intValue(), keepAlive ? 1 : 0);
@ -297,6 +309,14 @@ public final class EpollSocketChannelConfig extends EpollChannelConfig implement
return this; return this;
} }
/**
* Set the {@code TCP_USER_TIMEOUT} option on the socket. See {@code man 7 tcp} for more details.
*/
public EpollSocketChannelConfig setTcpUserTimeout(int milliseconds) {
Native.setTcpUserTimeout(channel.fd().intValue(), milliseconds);
return this;
}
@Override @Override
public boolean isAllowHalfClosure() { public boolean isAllowHalfClosure() {
return allowHalfClosure; return allowHalfClosure;

View File

@ -635,6 +635,7 @@ public final class Native {
public static native int getTcpKeepIdle(int fd); public static native int getTcpKeepIdle(int fd);
public static native int getTcpKeepIntvl(int fd); public static native int getTcpKeepIntvl(int fd);
public static native int getTcpKeepCnt(int fd); public static native int getTcpKeepCnt(int fd);
public static native int getTcpUserTimeout(int milliseconds);
public static native int getSoError(int fd); public static native int getSoError(int fd);
public static native int isIpFreeBind(int fd); public static native int isIpFreeBind(int fd);
@ -652,6 +653,7 @@ public final class Native {
public static native void setTcpKeepIdle(int fd, int seconds); public static native void setTcpKeepIdle(int fd, int seconds);
public static native void setTcpKeepIntvl(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 setTcpKeepCnt(int fd, int probes);
public static native void setTcpUserTimeout(int fd, int milliseconds);
public static native void setIpFreeBind(int fd, int freeBind); public static native void setIpFreeBind(int fd, int freeBind);
public static void tcpInfo(int fd, EpollTcpInfo info) { public static void tcpInfo(int fd, EpollTcpInfo info) {
tcpInfo0(fd, info.info); tcpInfo0(fd, info.info);