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 137187977d..3aa984559e 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 @@ -1297,6 +1297,48 @@ JNIEXPORT jint JNICALL Java_io_netty_channel_epoll_Native_getTcpKeepCnt(JNIEnv* 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, SOL_TCP, TCP_INFO, &tcp_info, sizeof(tcp_info)) == -1) { + return; + } + unsigned int cArray[32]; + cArray[0] = tcp_info.tcpi_state; + cArray[1] = tcp_info.tcpi_ca_state; + cArray[2] = tcp_info.tcpi_retransmits; + cArray[3] = tcp_info.tcpi_probes; + cArray[4] = tcp_info.tcpi_backoff; + cArray[5] = tcp_info.tcpi_options; + cArray[6] = tcp_info.tcpi_snd_wscale; + cArray[7] = tcp_info.tcpi_rcv_wscale; + cArray[8] = tcp_info.tcpi_rto; + cArray[9] = tcp_info.tcpi_ato; + cArray[10] = tcp_info.tcpi_snd_mss; + cArray[11] = tcp_info.tcpi_rcv_mss; + cArray[12] = tcp_info.tcpi_unacked; + cArray[13] = tcp_info.tcpi_sacked; + cArray[14] = tcp_info.tcpi_lost; + cArray[15] = tcp_info.tcpi_retrans; + cArray[16] = tcp_info.tcpi_fackets; + cArray[17] = tcp_info.tcpi_last_data_sent; + cArray[18] = tcp_info.tcpi_last_ack_sent; + cArray[19] = tcp_info.tcpi_last_data_recv; + cArray[20] = tcp_info.tcpi_last_ack_recv; + cArray[21] = tcp_info.tcpi_pmtu; + cArray[22] = tcp_info.tcpi_rcv_ssthresh; + cArray[23] = tcp_info.tcpi_rtt; + cArray[24] = tcp_info.tcpi_rttvar; + cArray[25] = tcp_info.tcpi_snd_ssthresh; + cArray[26] = tcp_info.tcpi_snd_cwnd; + cArray[27] = tcp_info.tcpi_advmss; + cArray[28] = tcp_info.tcpi_reordering; + cArray[29] = tcp_info.tcpi_rcv_rtt; + cArray[30] = tcp_info.tcpi_rcv_space; + cArray[31] = tcp_info.tcpi_total_retrans; + + (*env)->SetIntArrayRegion(env, array, 0, 32, cArray); +} + JNIEXPORT jstring JNICALL Java_io_netty_channel_epoll_Native_kernelVersion(JNIEnv* env, jclass clazz) { struct utsname name; 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 58e82bfb8f..7c0eaafdca 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 @@ -38,75 +38,81 @@ #define UIO_MAXIOV 1024 #endif /* UIO_MAXIOV */ -jint Java_io_netty_channel_epoll_Native_eventFd(JNIEnv * env, jclass clazz); -void Java_io_netty_channel_epoll_Native_eventFdWrite(JNIEnv * env, jclass clazz, jint fd, jlong value); -void Java_io_netty_channel_epoll_Native_eventFdRead(JNIEnv * env, jclass clazz, jint fd); -jint Java_io_netty_channel_epoll_Native_epollCreate(JNIEnv * env, jclass clazz); -jint Java_io_netty_channel_epoll_Native_epollWait(JNIEnv * env, jclass clazz, jint efd, jlongArray events, jint timeout); -void Java_io_netty_channel_epoll_Native_epollCtlAdd(JNIEnv * env, jclass clazz, jint efd, jint fd, jint flags, jint id); -void Java_io_netty_channel_epoll_Native_epollCtlMod(JNIEnv * env, jclass clazz, jint efd, jint fd, jint flags, jint id); -void Java_io_netty_channel_epoll_Native_epollCtlDel(JNIEnv * env, jclass clazz, jint efd, jint fd); -jint Java_io_netty_channel_epoll_Native_write0(JNIEnv * env, jclass clazz, jint fd, jobject jbuffer, jint pos, jint limit); -jint Java_io_netty_channel_epoll_Native_writeAddress0(JNIEnv * env, jclass clazz, jint fd, jlong address, jint pos, jint limit); -jlong Java_io_netty_channel_epoll_Native_writev0(JNIEnv * env, jclass clazz, jint fd, jobjectArray buffers, jint offset, jint length); -jlong Java_io_netty_channel_epoll_Native_writevAddresses0(JNIEnv * env, jclass clazz, jint fd, jlong memoryAddress, jint length); -jint Java_io_netty_channel_epoll_Native_sendTo(JNIEnv * env, jclass clazz, jint fd, jobject jbuffer, jint pos, jint limit, jbyteArray address, jint scopeId, jint port); -jint Java_io_netty_channel_epoll_Native_sendToAddress(JNIEnv * env, jclass clazz, jint fd, jlong memoryAddress, jint pos, jint limit, jbyteArray address, jint scopeId, jint port); -jint Java_io_netty_channel_epoll_Native_sendToAddresses(JNIEnv * env, jclass clazz, jint fd, jlong memoryAddress, jint length, jbyteArray address, jint scopeId, jint port); -jint Java_io_netty_channel_epoll_Native_sendmmsg(JNIEnv * env, jclass clazz, jint fd, jobjectArray packets, jint offset, jint len); +jint Java_io_netty_channel_epoll_Native_eventFd(JNIEnv* env, jclass clazz); +void Java_io_netty_channel_epoll_Native_eventFdWrite(JNIEnv* env, jclass clazz, jint fd, jlong value); +void Java_io_netty_channel_epoll_Native_eventFdRead(JNIEnv* env, jclass clazz, jint fd); +jint Java_io_netty_channel_epoll_Native_epollCreate(JNIEnv* env, jclass clazz); +jint Java_io_netty_channel_epoll_Native_epollWait(JNIEnv* env, jclass clazz, jint efd, jlongArray events, jint timeout); +void Java_io_netty_channel_epoll_Native_epollCtlAdd(JNIEnv* env, jclass clazz, jint efd, jint fd, jint flags, jint id); +void Java_io_netty_channel_epoll_Native_epollCtlMod(JNIEnv* env, jclass clazz, jint efd, jint fd, jint flags, jint id); +void Java_io_netty_channel_epoll_Native_epollCtlDel(JNIEnv* env, jclass clazz, jint efd, jint fd); +jint Java_io_netty_channel_epoll_Native_write0(JNIEnv* env, jclass clazz, jint fd, jobject jbuffer, jint pos, jint limit); +jint Java_io_netty_channel_epoll_Native_writeAddress0(JNIEnv* env, jclass clazz, jint fd, jlong address, jint pos, jint limit); +jlong Java_io_netty_channel_epoll_Native_writev0(JNIEnv* env, jclass clazz, jint fd, jobjectArray buffers, jint offset, jint length); +jlong Java_io_netty_channel_epoll_Native_writevAddresses0(JNIEnv* env, jclass clazz, jint fd, jlong memoryAddress, jint length); +jint Java_io_netty_channel_epoll_Native_sendTo(JNIEnv* env, jclass clazz, jint fd, jobject jbuffer, jint pos, jint limit, jbyteArray address, jint scopeId, jint port); +jint Java_io_netty_channel_epoll_Native_sendToAddress(JNIEnv* env, jclass clazz, jint fd, jlong memoryAddress, jint pos, jint limit, jbyteArray address, jint scopeId, jint port); +jint Java_io_netty_channel_epoll_Native_sendToAddresses(JNIEnv* env, jclass clazz, jint fd, jlong memoryAddress, jint length, jbyteArray address, jint scopeId, jint port); +jint Java_io_netty_channel_epoll_Native_sendmmsg(JNIEnv* env, jclass clazz, jint fd, jobjectArray packets, jint offset, jint len); -jint Java_io_netty_channel_epoll_Native_read0(JNIEnv * env, jclass clazz, jint fd, jobject jbuffer, jint pos, jint limit); -jint Java_io_netty_channel_epoll_Native_readAddress0(JNIEnv * env, jclass clazz, jint fd, jlong address, jint pos, jint limit); -jobject Java_io_netty_channel_epoll_Native_recvFrom(JNIEnv * env, jclass clazz, jint fd, jobject jbuffer, jint pos, jint limit); -jobject Java_io_netty_channel_epoll_Native_recvFromAddress(JNIEnv * env, jclass clazz, jint fd, jlong address, jint pos, jint limit); -jint Java_io_netty_channel_epoll_Native_close0(JNIEnv * env, jclass clazz, jint fd); -jint Java_io_netty_channel_epoll_Native_shutdown0(JNIEnv * env, jclass clazz, jint fd, jboolean read, jboolean write); -jint Java_io_netty_channel_epoll_Native_socketStream(JNIEnv * env, jclass clazz); -jint Java_io_netty_channel_epoll_Native_socketDgram(JNIEnv * env, jclass clazz); +jint Java_io_netty_channel_epoll_Native_read0(JNIEnv* env, jclass clazz, jint fd, jobject jbuffer, jint pos, jint limit); +jint Java_io_netty_channel_epoll_Native_readAddress0(JNIEnv* env, jclass clazz, jint fd, jlong address, jint pos, jint limit); +jobject Java_io_netty_channel_epoll_Native_recvFrom(JNIEnv* env, jclass clazz, jint fd, jobject jbuffer, jint pos, jint limit); +jobject Java_io_netty_channel_epoll_Native_recvFromAddress(JNIEnv* env, jclass clazz, jint fd, jlong address, jint pos, jint limit); +jint Java_io_netty_channel_epoll_Native_close0(JNIEnv* env, jclass clazz, jint fd); +jint Java_io_netty_channel_epoll_Native_shutdown0(JNIEnv* env, jclass clazz, jint fd, jboolean read, jboolean write); +jint Java_io_netty_channel_epoll_Native_socketStream(JNIEnv* env, jclass clazz); +jint Java_io_netty_channel_epoll_Native_socketDgram(JNIEnv* env, jclass clazz); +jint Java_io_netty_channel_epoll_Native_socketDomain(JNIEnv* env, jclass clazz); -jint Java_io_netty_channel_epoll_Native_bind(JNIEnv * env, jclass clazz, jint fd, jbyteArray address, jint scopeId, jint port); -jint Java_io_netty_channel_epoll_Native_listen0(JNIEnv * env, jclass clazz, jint fd, jint backlog); -jint Java_io_netty_channel_epoll_Native_connect(JNIEnv * env, jclass clazz, jint fd, jbyteArray address, jint scopeId, jint port); -jint Java_io_netty_channel_epoll_Native_finishConnect0(JNIEnv * env, jclass clazz, jint fd); -jint Java_io_netty_channel_epoll_Native_accept0(JNIEnv * env, jclass clazz, jint fd); -jlong Java_io_netty_channel_epoll_Native_sendfile0(JNIEnv *env, jclass clazz, jint fd, jobject fileRegion, jlong base_off, jlong off, jlong len); -jbyteArray Java_io_netty_channel_epoll_Native_remoteAddress0(JNIEnv * env, jclass clazz, jint fd); -jbyteArray Java_io_netty_channel_epoll_Native_localAddress0(JNIEnv * env, jclass clazz, jint fd); -void Java_io_netty_channel_epoll_Native_setReuseAddress(JNIEnv * env, jclass clazz, jint fd, jint optval); -void Java_io_netty_channel_epoll_Native_setReusePort(JNIEnv * env, jclass clazz, jint fd, jint optval); -void Java_io_netty_channel_epoll_Native_setTcpNoDelay(JNIEnv *env, jclass clazz, jint fd, jint optval); -void Java_io_netty_channel_epoll_Native_setReceiveBufferSize(JNIEnv *env, jclass clazz, jint fd, jint optval); -void Java_io_netty_channel_epoll_Native_setSendBufferSize(JNIEnv *env, jclass clazz, jint fd, jint optval); -void Java_io_netty_channel_epoll_Native_setKeepAlive(JNIEnv *env, jclass clazz, jint fd, jint optval); -void Java_io_netty_channel_epoll_Native_setTcpCork(JNIEnv *env, jclass clazz, jint fd, jint optval); -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_bind(JNIEnv* env, jclass clazz, jint fd, jbyteArray address, jint scopeId, jint port); +jint Java_io_netty_channel_epoll_Native_bindDomainSocket(JNIEnv* env, jclass clazz, jint fd, jstring address); +jint Java_io_netty_channel_epoll_Native_recvFd0(JNIEnv* env, jclass clazz, jint fd); +jint Java_io_netty_channel_epoll_Native_sendFd0(JNIEnv* env, jclass clazz, jint socketFd, jint fd); -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); -jint Java_io_netty_channel_epoll_Native_getReceiveBufferSize(JNIEnv * env, jclass clazz, jint fd); -jint Java_io_netty_channel_epoll_Native_getSendBufferSize(JNIEnv *env, jclass clazz, jint fd); -jint Java_io_netty_channel_epoll_Native_isTcpCork(JNIEnv *env, jclass clazz, jint fd); -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); +jint Java_io_netty_channel_epoll_Native_listen0(JNIEnv* env, jclass clazz, jint fd, jint backlog); +jint Java_io_netty_channel_epoll_Native_connect(JNIEnv* env, jclass clazz, jint fd, jbyteArray address, jint scopeId, jint port); +jint Java_io_netty_channel_epoll_Native_connectDomainSocket(JNIEnv* env, jclass clazz, jint fd, jstring address); +jint Java_io_netty_channel_epoll_Native_finishConnect0(JNIEnv* env, jclass clazz, jint fd); +jint Java_io_netty_channel_epoll_Native_accept0(JNIEnv* env, jclass clazz, jint fd); +jlong Java_io_netty_channel_epoll_Native_sendfile0(JNIEnv* env, jclass clazz, jint fd, jobject fileRegion, jlong base_off, jlong off, jlong len); +jbyteArray Java_io_netty_channel_epoll_Native_remoteAddress0(JNIEnv* env, jclass clazz, jint fd); +jbyteArray Java_io_netty_channel_epoll_Native_localAddress0(JNIEnv* env, jclass clazz, jint fd); +void Java_io_netty_channel_epoll_Native_setReuseAddress(JNIEnv* env, jclass clazz, jint fd, jint optval); +void Java_io_netty_channel_epoll_Native_setReusePort(JNIEnv* env, jclass clazz, jint fd, jint optval); +void Java_io_netty_channel_epoll_Native_setTcpNoDelay(JNIEnv* env, jclass clazz, jint fd, jint optval); +void Java_io_netty_channel_epoll_Native_setReceiveBufferSize(JNIEnv* env, jclass clazz, jint fd, jint optval); +void Java_io_netty_channel_epoll_Native_setSendBufferSize(JNIEnv* env, jclass clazz, jint fd, jint optval); +void Java_io_netty_channel_epoll_Native_setKeepAlive(JNIEnv* env, jclass clazz, jint fd, jint optval); +void Java_io_netty_channel_epoll_Native_setTcpCork(JNIEnv* env, jclass clazz, jint fd, jint optval); +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); -jstring Java_io_netty_channel_epoll_Native_kernelVersion(JNIEnv *env, jclass clazz); -jint Java_io_netty_channel_epoll_Native_iovMax(JNIEnv *env, jclass clazz); -jint Java_io_netty_channel_epoll_Native_uioMaxIov(JNIEnv *env, jclass clazz); -jboolean Java_io_netty_channel_epoll_Native_isSupportingSendmmsg(JNIEnv *env, jclass clazz); +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); +jint Java_io_netty_channel_epoll_Native_getReceiveBufferSize(JNIEnv* env, jclass clazz, jint fd); +jint Java_io_netty_channel_epoll_Native_getSendBufferSize(JNIEnv* env, jclass clazz, jint fd); +jint Java_io_netty_channel_epoll_Native_isTcpCork(JNIEnv* env, jclass clazz, jint fd); +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); -jint Java_io_netty_channel_epoll_Native_errnoEBADF(JNIEnv *env, jclass clazz); -jint Java_io_netty_channel_epoll_Native_errnoEPIPE(JNIEnv *env, jclass clazz); -jint Java_io_netty_channel_epoll_Native_errnoEAGAIN(JNIEnv *env, jclass clazz); -jint Java_io_netty_channel_epoll_Native_errnoEWOULDBLOCK(JNIEnv *env, jclass clazz); -jint Java_io_netty_channel_epoll_Native_errnoEINPROGRESS(JNIEnv *env, jclass clazz); -jstring Java_io_netty_channel_epoll_Native_strError(JNIEnv *env, jclass clazz, jint err); +jstring Java_io_netty_channel_epoll_Native_kernelVersion(JNIEnv* env, jclass clazz); +jint Java_io_netty_channel_epoll_Native_iovMax(JNIEnv* env, jclass clazz); +jint Java_io_netty_channel_epoll_Native_uioMaxIov(JNIEnv* env, jclass clazz); +jboolean Java_io_netty_channel_epoll_Native_isSupportingSendmmsg(JNIEnv* env, jclass clazz); + +jint Java_io_netty_channel_epoll_Native_errnoEBADF(JNIEnv* env, jclass clazz); +jint Java_io_netty_channel_epoll_Native_errnoEPIPE(JNIEnv* env, jclass clazz); +jint Java_io_netty_channel_epoll_Native_errnoEAGAIN(JNIEnv* env, jclass clazz); +jint Java_io_netty_channel_epoll_Native_errnoEWOULDBLOCK(JNIEnv* env, jclass clazz); +jint Java_io_netty_channel_epoll_Native_errnoEINPROGRESS(JNIEnv* env, jclass clazz); +jstring Java_io_netty_channel_epoll_Native_strError(JNIEnv* env, jclass clazz, jint err); diff --git a/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollSocketChannel.java b/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollSocketChannel.java index cda525542c..7941ac9d21 100644 --- a/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollSocketChannel.java +++ b/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollSocketChannel.java @@ -82,6 +82,22 @@ public final class EpollSocketChannel extends AbstractEpollChannel implements So config = new EpollSocketChannelConfig(this); } + /** + * Returns the {@code TCP_INFO} for the current socket. See man 7 tcp. + */ + public EpollTcpInfo tcpInfo() { + return tcpInfo(new EpollTcpInfo()); + } + + /** + * Updates and returns the {@code TCP_INFO} for the current socket. + * See man 7 tcp. + */ + public EpollTcpInfo tcpInfo(EpollTcpInfo info) { + Native.tcpInfo(fd, info); + return info; + } + @Override protected AbstractEpollUnsafe newUnsafe() { return new EpollSocketUnsafe(); diff --git a/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollTcpInfo.java b/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollTcpInfo.java new file mode 100644 index 0000000000..9b47a19c52 --- /dev/null +++ b/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollTcpInfo.java @@ -0,0 +1,193 @@ +/* + * Copyright 2014 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.channel.epoll; + +/** + *

+ * struct tcp_info + * { + * __u8 tcpi_state; + * __u8 tcpi_ca_state; + * __u8 tcpi_retransmits; + * __u8 tcpi_probes; + * __u8 tcpi_backoff; + * __u8 tcpi_options; + * __u8 tcpi_snd_wscale : 4, tcpi_rcv_wscale : 4; + * + * __u32 tcpi_rto; + * __u32 tcpi_ato; + * __u32 tcpi_snd_mss; + * __u32 tcpi_rcv_mss; + * + * __u32 tcpi_unacked; + * __u32 tcpi_sacked; + * __u32 tcpi_lost; + * __u32 tcpi_retrans; + * __u32 tcpi_fackets; + * + * __u32 tcpi_last_data_sent; + * __u32 tcpi_last_ack_sent; + * __u32 tcpi_last_data_recv; + * __u32 tcpi_last_ack_recv; + * + * __u32 tcpi_pmtu; + * __u32 tcpi_rcv_ssthresh; + * __u32 tcpi_rtt; + * __u32 tcpi_rttvar; + * __u32 tcpi_snd_ssthresh; + * __u32 tcpi_snd_cwnd; + * __u32 tcpi_advmss; + * __u32 tcpi_reordering; + * + * __u32 tcpi_rcv_rtt; + * __u32 tcpi_rcv_space; + * + * __u32 tcpi_total_retrans; + * }; + *

+ */ +public final class EpollTcpInfo { + + final int[] info = new int[32]; + + public int state() { + return info[0] & 0xFF; + } + + public int caState() { + return info[1] & 0xFF; + } + + public int retransmits() { + return info[2] & 0xFF; + } + + public int probes() { + return info[3] & 0xFF; + } + + public int backoff() { + return info[4] & 0xFF; + } + + public int options() { + return info[5] & 0xFF; + } + + public int sndWscale() { + return info[6] & 0xFF; + } + + public int rcvWscale() { + return info[7] & 0xFF; + } + + public long rto() { + return info[8] & 0xFFFFFFFFL; + } + + public long ato() { + return info[9] & 0xFFFFFFFFL; + } + + public long sndMss() { + return info[10] & 0xFFFFFFFFL; + } + + public long rcvMss() { + return info[11] & 0xFFFFFFFFL; + } + + public long unacked() { + return info[12] & 0xFFFFFFFFL; + } + + public long sacked() { + return info[13] & 0xFFFFFFFFL; + } + + public long lost() { + return info[14] & 0xFFFFFFFFL; + } + + public long retrans() { + return info[15] & 0xFFFFFFFFL; + } + + public long fackets() { + return info[16] & 0xFFFFFFFFL; + } + + public long lastDataSent() { + return info[17] & 0xFFFFFFFFL; + } + + public long lastAckSent() { + return info[18] & 0xFFFFFFFFL; + } + + public long lastDataRecv() { + return info[19] & 0xFFFFFFFFL; + } + + public long lastAckRecv() { + return info[20] & 0xFFFFFFFFL; + } + + public long pmtu() { + return info[21] & 0xFFFFFFFFL; + } + + public long rcvSsthresh() { + return info[22] & 0xFFFFFFFFL; + } + + public long rtt() { + return info[23] & 0xFFFFFFFFL; + } + + public long rttvar() { + return info[24] & 0xFFFFFFFFL; + } + + public long sndSsthresh() { + return info[25] & 0xFFFFFFFFL; + } + + public long sndCwnd() { + return info[26] & 0xFFFFFFFFL; + } + + public long advmss() { + return info[27] & 0xFFFFFFFFL; + } + + public long reordering() { + return info[28] & 0xFFFFFFFFL; + } + + public long rcvRtt() { + return info[29] & 0xFFFFFFFFL; + } + + public long rcvSpace() { + return info[30] & 0xFFFFFFFFL; + } + + public long totalRetrans() { + return info[31] & 0xFFFFFFFFL; + } +} 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 762c91d9c4..cf9ab02484 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 @@ -515,6 +515,12 @@ final class Native { public static native void setTcpKeepIntvl(int fd, int seconds); public static native void setTcpKeepCnt(int fd, int probes); + public static void tcpInfo(int fd, EpollTcpInfo info) { + tcpInfo0(fd, info.info); + } + + private static native void tcpInfo0(int fd, int[] array); + private static NativeInetAddress toNativeInetAddress(InetAddress addr) { byte[] bytes = addr.getAddress(); if (addr instanceof Inet6Address) { diff --git a/transport-native-epoll/src/test/java/io/netty/channel/epoll/EpollSocketChannelTest.java b/transport-native-epoll/src/test/java/io/netty/channel/epoll/EpollSocketChannelTest.java new file mode 100644 index 0000000000..9637006217 --- /dev/null +++ b/transport-native-epoll/src/test/java/io/netty/channel/epoll/EpollSocketChannelTest.java @@ -0,0 +1,101 @@ +/* + * Copyright 2014 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.channel.epoll; + +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.EventLoopGroup; +import org.junit.Assert; +import org.junit.Test; + +import java.net.InetSocketAddress; + +public class EpollSocketChannelTest { + + @Test + public void testTcpInfo() throws Exception { + EventLoopGroup group = new EpollEventLoopGroup(1); + + try { + Bootstrap bootstrap = new Bootstrap(); + EpollSocketChannel ch = (EpollSocketChannel) bootstrap.group(group) + .channel(EpollSocketChannel.class) + .handler(new ChannelInboundHandlerAdapter()) + .bind(new InetSocketAddress(0)).syncUninterruptibly().channel(); + EpollTcpInfo info = ch.tcpInfo(); + assertTcpInfo0(info); + ch.close().syncUninterruptibly(); + } finally { + group.shutdownGracefully(); + } + } + + @Test + public void testTcpInfoReuse() throws Exception { + EventLoopGroup group = new EpollEventLoopGroup(1); + + try { + Bootstrap bootstrap = new Bootstrap(); + EpollSocketChannel ch = (EpollSocketChannel) bootstrap.group(group) + .channel(EpollSocketChannel.class) + .handler(new ChannelInboundHandlerAdapter()) + .bind(new InetSocketAddress(0)).syncUninterruptibly().channel(); + EpollTcpInfo info = new EpollTcpInfo(); + ch.tcpInfo(info); + assertTcpInfo0(info); + ch.close().syncUninterruptibly(); + } finally { + group.shutdownGracefully(); + } + } + + private static void assertTcpInfo0(EpollTcpInfo info) throws Exception { + Assert.assertNotNull(info); + + Assert.assertTrue(info.state() >= 0); + Assert.assertTrue(info.caState() >= 0); + Assert.assertTrue(info.retransmits() >= 0); + Assert.assertTrue(info.probes() >= 0); + Assert.assertTrue(info.backoff() >= 0); + Assert.assertTrue(info.options() >= 0); + Assert.assertTrue(info.sndWscale() >= 0); + Assert.assertTrue(info.rcvWscale() >= 0); + Assert.assertTrue(info.rto() >= 0); + Assert.assertTrue(info.ato() >= 0); + Assert.assertTrue(info.sndMss() >= 0); + Assert.assertTrue(info.rcvMss() >= 0); + Assert.assertTrue(info.unacked() >= 0); + Assert.assertTrue(info.sacked() >= 0); + Assert.assertTrue(info.lost() >= 0); + Assert.assertTrue(info.retrans() >= 0); + Assert.assertTrue(info.fackets() >= 0); + Assert.assertTrue(info.lastDataSent() >= 0); + Assert.assertTrue(info.lastAckSent() >= 0); + Assert.assertTrue(info.lastDataRecv() >= 0); + Assert.assertTrue(info.lastAckRecv() >= 0); + Assert.assertTrue(info.pmtu() >= 0); + Assert.assertTrue(info.rcvSsthresh() >= 0); + Assert.assertTrue(info.rtt() >= 0); + Assert.assertTrue(info.rttvar() >= 0); + Assert.assertTrue(info.sndSsthresh() >= 0); + Assert.assertTrue(info.sndCwnd() >= 0); + Assert.assertTrue(info.advmss() >= 0); + Assert.assertTrue(info.reordering() >= 0); + Assert.assertTrue(info.rcvRtt() >= 0); + Assert.assertTrue(info.rcvSpace() >= 0); + Assert.assertTrue(info.totalRetrans() >= 0); + } +}