Correctly handle unsigned int values returned from TCP_INFO

Motivation:

We used an int[] to store all values that are returned in the struct for TCP_INFO which is not good enough as it uses usigned int values.

Modifications:

- Change int[] to long[] and correctly cast values.

Result:

No more truncated values.
This commit is contained in:
Norman Maurer 2017-07-22 16:31:42 +02:00
parent 34fdc7a33e
commit efb2d141c1
3 changed files with 71 additions and 70 deletions

View File

@ -178,46 +178,47 @@ static jint netty_epoll_linuxsocket_isIpTransparent(JNIEnv* env, jclass clazz, j
return optval; return optval;
} }
static void netty_epoll_linuxsocket_getTcpInfo(JNIEnv* env, jclass clazz, jint fd, jintArray array) { static void netty_epoll_linuxsocket_getTcpInfo(JNIEnv* env, jclass clazz, jint fd, jlongArray array) {
struct tcp_info tcp_info; struct tcp_info tcp_info;
if (netty_unix_socket_getOption(env, fd, IPPROTO_TCP, TCP_INFO, &tcp_info, sizeof(tcp_info)) == -1) { if (netty_unix_socket_getOption(env, fd, IPPROTO_TCP, TCP_INFO, &tcp_info, sizeof(tcp_info)) == -1) {
return; return;
} }
unsigned int cArray[32]; jlong cArray[32];
cArray[0] = tcp_info.tcpi_state; // Expand to 64 bits, then cast away unsigned-ness.
cArray[1] = tcp_info.tcpi_ca_state; cArray[0] = (jlong) (uint64_t) tcp_info.tcpi_state;
cArray[2] = tcp_info.tcpi_retransmits; cArray[1] = (jlong) (uint64_t) tcp_info.tcpi_ca_state;
cArray[3] = tcp_info.tcpi_probes; cArray[2] = (jlong) (uint64_t) tcp_info.tcpi_retransmits;
cArray[4] = tcp_info.tcpi_backoff; cArray[3] = (jlong) (uint64_t) tcp_info.tcpi_probes;
cArray[5] = tcp_info.tcpi_options; cArray[4] = (jlong) (uint64_t) tcp_info.tcpi_backoff;
cArray[6] = tcp_info.tcpi_snd_wscale; cArray[5] = (jlong) (uint64_t) tcp_info.tcpi_options;
cArray[7] = tcp_info.tcpi_rcv_wscale; cArray[6] = (jlong) (uint64_t) tcp_info.tcpi_snd_wscale;
cArray[8] = tcp_info.tcpi_rto; cArray[7] = (jlong) (uint64_t) tcp_info.tcpi_rcv_wscale;
cArray[9] = tcp_info.tcpi_ato; cArray[8] = (jlong) (uint64_t) tcp_info.tcpi_rto;
cArray[10] = tcp_info.tcpi_snd_mss; cArray[9] = (jlong) (uint64_t) tcp_info.tcpi_ato;
cArray[11] = tcp_info.tcpi_rcv_mss; cArray[10] = (jlong) (uint64_t) tcp_info.tcpi_snd_mss;
cArray[12] = tcp_info.tcpi_unacked; cArray[11] = (jlong) (uint64_t) tcp_info.tcpi_rcv_mss;
cArray[13] = tcp_info.tcpi_sacked; cArray[12] = (jlong) (uint64_t) tcp_info.tcpi_unacked;
cArray[14] = tcp_info.tcpi_lost; cArray[13] = (jlong) (uint64_t) tcp_info.tcpi_sacked;
cArray[15] = tcp_info.tcpi_retrans; cArray[14] = (jlong) (uint64_t) tcp_info.tcpi_lost;
cArray[16] = tcp_info.tcpi_fackets; cArray[15] = (jlong) (uint64_t) tcp_info.tcpi_retrans;
cArray[17] = tcp_info.tcpi_last_data_sent; cArray[16] = (jlong) (uint64_t) tcp_info.tcpi_fackets;
cArray[18] = tcp_info.tcpi_last_ack_sent; cArray[17] = (jlong) (uint64_t) tcp_info.tcpi_last_data_sent;
cArray[19] = tcp_info.tcpi_last_data_recv; cArray[18] = (jlong) (uint64_t) tcp_info.tcpi_last_ack_sent;
cArray[20] = tcp_info.tcpi_last_ack_recv; cArray[19] = (jlong) (uint64_t) tcp_info.tcpi_last_data_recv;
cArray[21] = tcp_info.tcpi_pmtu; cArray[20] = (jlong) (uint64_t) tcp_info.tcpi_last_ack_recv;
cArray[22] = tcp_info.tcpi_rcv_ssthresh; cArray[21] = (jlong) (uint64_t) tcp_info.tcpi_pmtu;
cArray[23] = tcp_info.tcpi_rtt; cArray[22] = (jlong) (uint64_t) tcp_info.tcpi_rcv_ssthresh;
cArray[24] = tcp_info.tcpi_rttvar; cArray[23] = (jlong) (uint64_t) tcp_info.tcpi_rtt;
cArray[25] = tcp_info.tcpi_snd_ssthresh; cArray[24] = (jlong) (uint64_t) tcp_info.tcpi_rttvar;
cArray[26] = tcp_info.tcpi_snd_cwnd; cArray[25] = (jlong) (uint64_t) tcp_info.tcpi_snd_ssthresh;
cArray[27] = tcp_info.tcpi_advmss; cArray[26] = (jlong) (uint64_t) tcp_info.tcpi_snd_cwnd;
cArray[28] = tcp_info.tcpi_reordering; cArray[27] = (jlong) (uint64_t) tcp_info.tcpi_advmss;
cArray[29] = tcp_info.tcpi_rcv_rtt; cArray[28] = (jlong) (uint64_t) tcp_info.tcpi_reordering;
cArray[30] = tcp_info.tcpi_rcv_space; cArray[29] = (jlong) (uint64_t) tcp_info.tcpi_rcv_rtt;
cArray[31] = tcp_info.tcpi_total_retrans; cArray[30] = (jlong) (uint64_t) tcp_info.tcpi_rcv_space;
cArray[31] = (jlong) (uint64_t) tcp_info.tcpi_total_retrans;
(*env)->SetIntArrayRegion(env, array, 0, 32, cArray); (*env)->SetLongArrayRegion(env, array, 0, 32, cArray);
} }
static jint netty_epoll_linuxsocket_isTcpCork(JNIEnv* env, jclass clazz, jint fd) { static jint netty_epoll_linuxsocket_isTcpCork(JNIEnv* env, jclass clazz, jint fd) {
@ -286,7 +287,7 @@ static const JNINativeMethod fixed_method_table[] = {
{ "getTcpUserTimeout", "(I)I", (void *) netty_epoll_linuxsocket_getTcpUserTimeout }, { "getTcpUserTimeout", "(I)I", (void *) netty_epoll_linuxsocket_getTcpUserTimeout },
{ "isIpFreeBind", "(I)I", (void *) netty_epoll_linuxsocket_isIpFreeBind }, { "isIpFreeBind", "(I)I", (void *) netty_epoll_linuxsocket_isIpFreeBind },
{ "isIpTransparent", "(I)I", (void *) netty_epoll_linuxsocket_isIpTransparent }, { "isIpTransparent", "(I)I", (void *) netty_epoll_linuxsocket_isIpTransparent },
{ "getTcpInfo", "(I[I)V", (void *) netty_epoll_linuxsocket_getTcpInfo }, { "getTcpInfo", "(I[J)V", (void *) netty_epoll_linuxsocket_getTcpInfo },
{ "setTcpMd5Sig", "(I[BI[B)V", (void *) netty_epoll_linuxsocket_setTcpMd5Sig } { "setTcpMd5Sig", "(I[BI[B)V", (void *) netty_epoll_linuxsocket_setTcpMd5Sig }
}; };

View File

@ -61,133 +61,133 @@ package io.netty.channel.epoll;
*/ */
public final class EpollTcpInfo { public final class EpollTcpInfo {
final int[] info = new int[32]; final long[] info = new long[32];
public int state() { public int state() {
return info[0] & 0xFF; return (int) info[0];
} }
public int caState() { public int caState() {
return info[1] & 0xFF; return (int) info[1];
} }
public int retransmits() { public int retransmits() {
return info[2] & 0xFF; return (int) info[2];
} }
public int probes() { public int probes() {
return info[3] & 0xFF; return (int) info[3];
} }
public int backoff() { public int backoff() {
return info[4] & 0xFF; return (int) info[4];
} }
public int options() { public int options() {
return info[5] & 0xFF; return (int) info[5];
} }
public int sndWscale() { public int sndWscale() {
return info[6] & 0xFF; return (int) info[6];
} }
public int rcvWscale() { public int rcvWscale() {
return info[7] & 0xFF; return (int) info[7];
} }
public long rto() { public long rto() {
return info[8] & 0xFFFFFFFFL; return info[8];
} }
public long ato() { public long ato() {
return info[9] & 0xFFFFFFFFL; return info[9];
} }
public long sndMss() { public long sndMss() {
return info[10] & 0xFFFFFFFFL; return info[10];
} }
public long rcvMss() { public long rcvMss() {
return info[11] & 0xFFFFFFFFL; return info[11];
} }
public long unacked() { public long unacked() {
return info[12] & 0xFFFFFFFFL; return info[12];
} }
public long sacked() { public long sacked() {
return info[13] & 0xFFFFFFFFL; return info[13];
} }
public long lost() { public long lost() {
return info[14] & 0xFFFFFFFFL; return info[14];
} }
public long retrans() { public long retrans() {
return info[15] & 0xFFFFFFFFL; return info[15];
} }
public long fackets() { public long fackets() {
return info[16] & 0xFFFFFFFFL; return info[16];
} }
public long lastDataSent() { public long lastDataSent() {
return info[17] & 0xFFFFFFFFL; return info[17];
} }
public long lastAckSent() { public long lastAckSent() {
return info[18] & 0xFFFFFFFFL; return info[18];
} }
public long lastDataRecv() { public long lastDataRecv() {
return info[19] & 0xFFFFFFFFL; return info[19];
} }
public long lastAckRecv() { public long lastAckRecv() {
return info[20] & 0xFFFFFFFFL; return info[20];
} }
public long pmtu() { public long pmtu() {
return info[21] & 0xFFFFFFFFL; return info[21];
} }
public long rcvSsthresh() { public long rcvSsthresh() {
return info[22] & 0xFFFFFFFFL; return info[22];
} }
public long rtt() { public long rtt() {
return info[23] & 0xFFFFFFFFL; return info[23];
} }
public long rttvar() { public long rttvar() {
return info[24] & 0xFFFFFFFFL; return info[24];
} }
public long sndSsthresh() { public long sndSsthresh() {
return info[25] & 0xFFFFFFFFL; return info[25];
} }
public long sndCwnd() { public long sndCwnd() {
return info[26] & 0xFFFFFFFFL; return info[26];
} }
public long advmss() { public long advmss() {
return info[27] & 0xFFFFFFFFL; return info[27];
} }
public long reordering() { public long reordering() {
return info[28] & 0xFFFFFFFFL; return info[28];
} }
public long rcvRtt() { public long rcvRtt() {
return info[29] & 0xFFFFFFFFL; return info[29];
} }
public long rcvSpace() { public long rcvSpace() {
return info[30] & 0xFFFFFFFFL; return info[30];
} }
public long totalRetrans() { public long totalRetrans() {
return info[31] & 0xFFFFFFFFL; return info[31];
} }
} }

View File

@ -154,7 +154,7 @@ final class LinuxSocket extends Socket {
private static native int getTcpUserTimeout(int fd) throws IOException; private static native int getTcpUserTimeout(int fd) throws IOException;
private static native int isIpFreeBind(int fd) throws IOException; private static native int isIpFreeBind(int fd) throws IOException;
private static native int isIpTransparent(int fd) throws IOException; private static native int isIpTransparent(int fd) throws IOException;
private static native void getTcpInfo(int fd, int[] array) throws IOException; private static native void getTcpInfo(int fd, long[] array) throws IOException;
private static native PeerCredentials getPeerCredentials(int fd) throws IOException; private static native PeerCredentials getPeerCredentials(int fd) throws IOException;
private static native void setTcpDeferAccept(int fd, int deferAccept) throws IOException; private static native void setTcpDeferAccept(int fd, int deferAccept) throws IOException;