diff options
-rw-r--r-- | src/com/android/networkstack/netlink/TcpSocketTracker.java | 74 |
1 files changed, 42 insertions, 32 deletions
diff --git a/src/com/android/networkstack/netlink/TcpSocketTracker.java b/src/com/android/networkstack/netlink/TcpSocketTracker.java index 5c30c30..cd21c32 100644 --- a/src/com/android/networkstack/netlink/TcpSocketTracker.java +++ b/src/com/android/networkstack/netlink/TcpSocketTracker.java @@ -63,8 +63,10 @@ import com.android.internal.annotations.VisibleForTesting; import java.io.FileDescriptor; import java.io.InterruptedIOException; import java.net.SocketException; +import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.Base64; import java.util.List; /** @@ -172,39 +174,47 @@ public class TcpSocketTracker { // | struct nlmsghdr | struct rtmsg | struct rtattr| data | // +------------------+---------------+--------------+--------+ final ByteBuffer bytes = mDependencies.recvMesssage(fd); - - while (enoughBytesRemainForValidNlMsg(bytes)) { - final StructNlMsgHdr nlmsghdr = StructNlMsgHdr.parse(bytes); - if (nlmsghdr == null) { - Log.e(TAG, "Badly formatted data."); - break; - } - final int nlmsgLen = nlmsghdr.nlmsg_len; - log("pollSocketsInfo: nlmsghdr=" + nlmsghdr); - // End of the message. Stop parsing. - if (nlmsghdr.nlmsg_type == NLMSG_DONE) break; - - if (nlmsghdr.nlmsg_type != SOCK_DIAG_BY_FAMILY) { - Log.e(TAG, "Expect to get family " + family - + " SOCK_DIAG_BY_FAMILY message but get " + nlmsghdr.nlmsg_type); - break; - } - - if (isValidInetDiagMsgSize(nlmsgLen)) { - // Get the socket cookie value. Composed by two Integers value. - // Corresponds to inet_diag_sockid in - // <linux_src>/include/uapi/linux/inet_diag.h - bytes.position(bytes.position() + IDIAG_COOKIE_OFFSET); - // It's stored in native with 2 int. Parse it as long for convenience. - final long cookie = bytes.getLong(); - // Skip the rest part of StructInetDiagMsg. - bytes.position(bytes.position() - + StructInetDiagMsg.STRUCT_SIZE - IDIAG_COOKIE_OFFSET - Long.BYTES); - final SocketInfo info = parseSockInfo(bytes, family, nlmsgLen, time); - // Update TcpStats based on previous and current socket info. - stat.accumulate(calculateLatestPacketsStat(info, mSocketInfos.get(cookie))); - mSocketInfos.put(cookie, info); + try { + while (enoughBytesRemainForValidNlMsg(bytes)) { + final StructNlMsgHdr nlmsghdr = StructNlMsgHdr.parse(bytes); + if (nlmsghdr == null) { + Log.e(TAG, "Badly formatted data."); + break; + } + final int nlmsgLen = nlmsghdr.nlmsg_len; + log("pollSocketsInfo: nlmsghdr=" + nlmsghdr + ", limit=" + bytes.limit()); + // End of the message. Stop parsing. + if (nlmsghdr.nlmsg_type == NLMSG_DONE) break; + + if (nlmsghdr.nlmsg_type != SOCK_DIAG_BY_FAMILY) { + Log.e(TAG, "Expect to get family " + family + + " SOCK_DIAG_BY_FAMILY message but get " + + nlmsghdr.nlmsg_type); + break; + } + + if (isValidInetDiagMsgSize(nlmsgLen)) { + // Get the socket cookie value. Composed by two Integers value. + // Corresponds to inet_diag_sockid in + // <linux_src>/include/uapi/linux/inet_diag.h + bytes.position(bytes.position() + IDIAG_COOKIE_OFFSET); + // It's stored in native with 2 int. Parse it as long for convenience. + final long cookie = bytes.getLong(); + // Skip the rest part of StructInetDiagMsg. + bytes.position(bytes.position() + + StructInetDiagMsg.STRUCT_SIZE - IDIAG_COOKIE_OFFSET + - Long.BYTES); + final SocketInfo info = parseSockInfo(bytes, family, nlmsgLen, time); + // Update TcpStats based on previous and current socket info. + stat.accumulate( + calculateLatestPacketsStat(info, mSocketInfos.get(cookie))); + mSocketInfos.put(cookie, info); + } } + } catch (IllegalArgumentException | BufferUnderflowException e) { + Log.wtf(TAG, "Unexpected socket info parsing, " + e + ", family " + family + + " buffer:" + bytes + " " + + Base64.getEncoder().encodeToString(bytes.array())); } } // Calculate mLatestReceiveCount, mSentSinceLastRecv and mLatestPacketFailPercentage. |