Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d0d07a12 authored by Chiachang Wang's avatar Chiachang Wang Committed by Gerrit Code Review
Browse files

Merge "Cleanup in TcpInfo"

parents fb73cd70 0745fd84
Loading
Loading
Loading
Loading
+26 −19
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@
package com.android.networkstack.netlink;

import android.util.Log;
import android.util.Range;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -25,8 +24,9 @@ import com.android.internal.annotations.VisibleForTesting;

import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;

/**
@@ -91,42 +91,44 @@ public class TcpInfo {
    }

    private static final String TAG = "TcpInfo";
    private final LinkedHashMap<Field, Number> mFieldsValues = new LinkedHashMap<Field, Number>();
    private final Map<Field, Number> mFieldsValues;

    private TcpInfo(@NonNull ByteBuffer bytes, int infolen) {
        final int start = bytes.position();
        final LinkedHashMap<Field, Number> fields = new LinkedHashMap<>();
        for (final Field field : Field.values()) {
            switch (field.size) {
                case Byte.BYTES:
                    mFieldsValues.put(field, getByte(bytes, start, infolen));
                    fields.put(field, getByte(bytes, start, infolen));
                    break;
                case Integer.BYTES:
                    mFieldsValues.put(field, getInt(bytes, start, infolen));
                    fields.put(field, getInt(bytes, start, infolen));
                    break;
                case Long.BYTES:
                    mFieldsValues.put(field, getLong(bytes, start, infolen));
                    fields.put(field, getLong(bytes, start, infolen));
                    break;
                default:
                    Log.e(TAG, "Unexpected size:" + field.size);
            }
        }

        mFieldsValues = Collections.unmodifiableMap(fields);
    }

    @VisibleForTesting
    TcpInfo(@NonNull HashMap<Field, Number> info) {
    TcpInfo(@NonNull Map<Field, Number> info) {
        final LinkedHashMap<Field, Number> fields = new LinkedHashMap<>();
        for (final Field field : Field.values()) {
            mFieldsValues.put(field, info.get(field));
            fields.put(field, info.get(field));
        }
        mFieldsValues = Collections.unmodifiableMap(fields);
    }

    /** Parse a TcpInfo from a giving ByteBuffer with a specific length. */
    @Nullable
    public static TcpInfo parse(@NonNull ByteBuffer bytes, int infolen) {
        try {
            TcpInfo info = new TcpInfo(bytes, infolen);
            return info;
        } catch (BufferUnderflowException e) {
            return new TcpInfo(bytes, infolen);
        } catch (BufferUnderflowException | IllegalArgumentException e) {
            Log.e(TAG, "parsing error.", e);
            return null;
        }
@@ -135,10 +137,15 @@ public class TcpInfo {
    /**
     * Helper function for handling different struct tcp_info versions in the kernel.
     */
    private static boolean isValidOffset(int start, int len, int pos, int targetBytes) {
        final Range a = new Range(start, start + len);
        final Range b = new Range(pos, pos + targetBytes);
        return a.contains(b);
    private static boolean isValidTargetPosition(int start, int len, int pos, int targetBytes)
            throws IllegalArgumentException {
        // Equivalent to new Range(start, start + len).contains(new Range(pos, pos + targetBytes))
        if (len < 0 || targetBytes < 0) throw new IllegalArgumentException();
        // Check that start < pos < start + len
        if (pos < start || pos > start + len) return false;
        // Pos is inside the range and targetBytes is positive. Offset is valid if end of 2nd range
        // is below end of 1st range.
        return pos + targetBytes <= start + len;
    }

    /** Get value for specific key. */
@@ -149,21 +156,21 @@ public class TcpInfo {

    @Nullable
    private static Byte getByte(@NonNull ByteBuffer buffer, int start, int len) {
        if (!isValidOffset(start, len, buffer.position(), Byte.BYTES)) return null;
        if (!isValidTargetPosition(start, len, buffer.position(), Byte.BYTES)) return null;

        return buffer.get();
    }

    @Nullable
    private static Integer getInt(@NonNull ByteBuffer buffer, int start, int len) {
        if (!isValidOffset(start, len, buffer.position(), Integer.BYTES)) return null;
        if (!isValidTargetPosition(start, len, buffer.position(), Integer.BYTES)) return null;

        return buffer.getInt();
    }

    @Nullable
    private static Long getLong(@NonNull ByteBuffer buffer, int start, int len) {
        if (!isValidOffset(start, len, buffer.position(), Long.BYTES)) return null;
        if (!isValidTargetPosition(start, len, buffer.position(), Long.BYTES)) return null;

        return buffer.getLong();
    }
+10 −9
Original line number Diff line number Diff line
@@ -27,7 +27,8 @@ import org.junit.Test;
import org.junit.runner.RunWith;

import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

@RunWith(AndroidJUnit4.class)
@SmallTest
@@ -92,7 +93,7 @@ public class TcpInfoTest {
    @Test
    public void testParseTcpInfo() {
        final ByteBuffer buffer = ByteBuffer.wrap(TCP_INFO_BYTES);
        final HashMap<TcpInfo.Field, Number> expected = makeTestTcpInfoHash();
        final Map<TcpInfo.Field, Number> expected = makeTestTcpInfoHash();
        final TcpInfo parsedInfo = TcpInfo.parse(buffer, TCP_INFO_LENGTH_V1);

        assertEquals(parsedInfo, new TcpInfo(expected));
@@ -102,7 +103,7 @@ public class TcpInfoTest {
    public void testValidOffset() {
        final ByteBuffer buffer = ByteBuffer.wrap(TCP_INFO_BYTES);

        final HashMap<TcpInfo.Field, Number> expected = makeShortTestTcpInfoHash();
        final Map<TcpInfo.Field, Number> expected = makeShortTestTcpInfoHash();
        final TcpInfo parsedInfo = TcpInfo.parse(buffer, SHORT_TEST_TCP_INFO);

        assertEquals(parsedInfo, new TcpInfo(expected));
@@ -131,7 +132,7 @@ public class TcpInfoTest {
    @Test
    public void testMalformedTcpInfo() {
        final ByteBuffer buffer = ByteBuffer.wrap(MALFORMED_TCP_INFO_BYTES);
        final HashMap<TcpInfo.Field, Number> expected = makeShortTestTcpInfoHash();
        final Map<TcpInfo.Field, Number> expected = makeShortTestTcpInfoHash();

        TcpInfo parsedInfo = TcpInfo.parse(buffer, SHORT_TEST_TCP_INFO);
        assertEquals(parsedInfo, new TcpInfo(expected));
@@ -144,7 +145,7 @@ public class TcpInfoTest {
    public void testGetValue() {
        ByteBuffer buffer = ByteBuffer.wrap(TCP_INFO_BYTES);

        final HashMap<TcpInfo.Field, Number> expected = makeShortTestTcpInfoHash();
        final Map<TcpInfo.Field, Number> expected = makeShortTestTcpInfoHash();
        expected.put(TcpInfo.Field.MAX_PACING_RATE, 10_000L);
        expected.put(TcpInfo.Field.FACKETS, 10);

@@ -165,8 +166,8 @@ public class TcpInfoTest {
    }

    // Make a TcpInfo contains only first 8 bytes.
    private HashMap<TcpInfo.Field, Number> makeShortTestTcpInfoHash() {
        final HashMap<TcpInfo.Field, Number> info = new HashMap<TcpInfo.Field, Number>();
    private Map<TcpInfo.Field, Number> makeShortTestTcpInfoHash() {
        final Map<TcpInfo.Field, Number> info = new LinkedHashMap<>();
        info.put(TcpInfo.Field.STATE, (byte) 0x01);
        info.put(TcpInfo.Field.CASTATE, (byte) 0x00);
        info.put(TcpInfo.Field.RETRANSMITS, (byte) 0x00);
@@ -179,8 +180,8 @@ public class TcpInfoTest {
        return info;
    }

    private HashMap<TcpInfo.Field, Number> makeTestTcpInfoHash() {
        final HashMap<TcpInfo.Field, Number> info = makeShortTestTcpInfoHash();
    private Map<TcpInfo.Field, Number> makeTestTcpInfoHash() {
        final Map<TcpInfo.Field, Number> info = makeShortTestTcpInfoHash();
        info.put(TcpInfo.Field.RTO, 1806666);
        info.put(TcpInfo.Field.ATO, 0);
        info.put(TcpInfo.Field.SND_MSS, 1326);