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;
}
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;
if (netty_unix_socket_getOption(env, fd, IPPROTO_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;
jlong cArray[32];
// Expand to 64 bits, then cast away unsigned-ness.
cArray[0] = (jlong) (uint64_t) tcp_info.tcpi_state;
cArray[1] = (jlong) (uint64_t) tcp_info.tcpi_ca_state;
cArray[2] = (jlong) (uint64_t) tcp_info.tcpi_retransmits;
cArray[3] = (jlong) (uint64_t) tcp_info.tcpi_probes;
cArray[4] = (jlong) (uint64_t) tcp_info.tcpi_backoff;
cArray[5] = (jlong) (uint64_t) tcp_info.tcpi_options;
cArray[6] = (jlong) (uint64_t) tcp_info.tcpi_snd_wscale;
cArray[7] = (jlong) (uint64_t) tcp_info.tcpi_rcv_wscale;
cArray[8] = (jlong) (uint64_t) tcp_info.tcpi_rto;
cArray[9] = (jlong) (uint64_t) tcp_info.tcpi_ato;
cArray[10] = (jlong) (uint64_t) tcp_info.tcpi_snd_mss;
cArray[11] = (jlong) (uint64_t) tcp_info.tcpi_rcv_mss;
cArray[12] = (jlong) (uint64_t) tcp_info.tcpi_unacked;
cArray[13] = (jlong) (uint64_t) tcp_info.tcpi_sacked;
cArray[14] = (jlong) (uint64_t) tcp_info.tcpi_lost;
cArray[15] = (jlong) (uint64_t) tcp_info.tcpi_retrans;
cArray[16] = (jlong) (uint64_t) tcp_info.tcpi_fackets;
cArray[17] = (jlong) (uint64_t) tcp_info.tcpi_last_data_sent;
cArray[18] = (jlong) (uint64_t) tcp_info.tcpi_last_ack_sent;
cArray[19] = (jlong) (uint64_t) tcp_info.tcpi_last_data_recv;
cArray[20] = (jlong) (uint64_t) tcp_info.tcpi_last_ack_recv;
cArray[21] = (jlong) (uint64_t) tcp_info.tcpi_pmtu;
cArray[22] = (jlong) (uint64_t) tcp_info.tcpi_rcv_ssthresh;
cArray[23] = (jlong) (uint64_t) tcp_info.tcpi_rtt;
cArray[24] = (jlong) (uint64_t) tcp_info.tcpi_rttvar;
cArray[25] = (jlong) (uint64_t) tcp_info.tcpi_snd_ssthresh;
cArray[26] = (jlong) (uint64_t) tcp_info.tcpi_snd_cwnd;
cArray[27] = (jlong) (uint64_t) tcp_info.tcpi_advmss;
cArray[28] = (jlong) (uint64_t) tcp_info.tcpi_reordering;
cArray[29] = (jlong) (uint64_t) tcp_info.tcpi_rcv_rtt;
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) {
@ -286,7 +287,7 @@ static const JNINativeMethod fixed_method_table[] = {
{ "getTcpUserTimeout", "(I)I", (void *) netty_epoll_linuxsocket_getTcpUserTimeout },
{ "isIpFreeBind", "(I)I", (void *) netty_epoll_linuxsocket_isIpFreeBind },
{ "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 }
};

View File

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