diff --git a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java b/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java index e78d25a160..f4d9006a70 100644 --- a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java +++ b/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java @@ -31,7 +31,7 @@ import android.net.NetworkUtils; import android.net.SocketKeepalive.InvalidPacketException; import android.net.SocketKeepalive.InvalidSocketException; import android.net.TcpKeepalivePacketData; -import android.net.TcpKeepalivePacketData.TcpSocketInfo; +import android.net.TcpKeepalivePacketDataParcelable; import android.net.TcpRepairWindow; import android.os.Handler; import android.os.MessageQueue; @@ -46,7 +46,6 @@ import com.android.internal.annotations.GuardedBy; import com.android.server.connectivity.KeepaliveTracker.KeepaliveInfo; import java.io.FileDescriptor; -import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.SocketException; @@ -109,8 +108,8 @@ public class TcpKeepaliveController { public static TcpKeepalivePacketData getTcpKeepalivePacket(@NonNull FileDescriptor fd) throws InvalidPacketException, InvalidSocketException { try { - final TcpSocketInfo tsi = switchToRepairMode(fd); - return TcpKeepalivePacketData.tcpKeepalivePacket(tsi); + final TcpKeepalivePacketDataParcelable tcpDetails = switchToRepairMode(fd); + return TcpKeepalivePacketData.tcpKeepalivePacket(tcpDetails); } catch (InvalidPacketException | InvalidSocketException e) { switchOutOfRepairMode(fd); throw e; @@ -120,20 +119,15 @@ public class TcpKeepaliveController { * Switch the tcp socket to repair mode and query detail tcp information. * * @param fd the fd of socket on which to use keepalive offload. - * @return a {@link TcpKeepalivePacketData#TcpSocketInfo} object for current + * @return a {@link TcpKeepalivePacketData#TcpKeepalivePacketDataParcelable} object for current * tcp/ip information. */ - private static TcpSocketInfo switchToRepairMode(FileDescriptor fd) + private static TcpKeepalivePacketDataParcelable switchToRepairMode(FileDescriptor fd) throws InvalidSocketException { if (DBG) Log.i(TAG, "switchToRepairMode to start tcp keepalive : " + fd); + final TcpKeepalivePacketDataParcelable tcpDetails = new TcpKeepalivePacketDataParcelable(); final SocketAddress srcSockAddr; final SocketAddress dstSockAddr; - final InetAddress srcAddress; - final InetAddress dstAddress; - final int srcPort; - final int dstPort; - int seq; - final int ack; final TcpRepairWindow trw; // Query source address and port. @@ -144,8 +138,8 @@ public class TcpKeepaliveController { throw new InvalidSocketException(ERROR_INVALID_SOCKET, e); } if (srcSockAddr instanceof InetSocketAddress) { - srcAddress = getAddress((InetSocketAddress) srcSockAddr); - srcPort = getPort((InetSocketAddress) srcSockAddr); + tcpDetails.srcAddress = getAddress((InetSocketAddress) srcSockAddr); + tcpDetails.srcPort = getPort((InetSocketAddress) srcSockAddr); } else { Log.e(TAG, "Invalid or mismatched SocketAddress"); throw new InvalidSocketException(ERROR_INVALID_SOCKET); @@ -158,8 +152,8 @@ public class TcpKeepaliveController { throw new InvalidSocketException(ERROR_INVALID_SOCKET, e); } if (dstSockAddr instanceof InetSocketAddress) { - dstAddress = getAddress((InetSocketAddress) dstSockAddr); - dstPort = getPort((InetSocketAddress) dstSockAddr); + tcpDetails.dstAddress = getAddress((InetSocketAddress) dstSockAddr); + tcpDetails.dstPort = getPort((InetSocketAddress) dstSockAddr); } else { Log.e(TAG, "Invalid or mismatched peer SocketAddress"); throw new InvalidSocketException(ERROR_INVALID_SOCKET); @@ -178,10 +172,10 @@ public class TcpKeepaliveController { } // Query write sequence number from SEND_QUEUE. Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR_QUEUE, TCP_SEND_QUEUE); - seq = Os.getsockoptInt(fd, IPPROTO_TCP, TCP_QUEUE_SEQ); + tcpDetails.seq = Os.getsockoptInt(fd, IPPROTO_TCP, TCP_QUEUE_SEQ); // Query read sequence number from RECV_QUEUE. Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR_QUEUE, TCP_RECV_QUEUE); - ack = Os.getsockoptInt(fd, IPPROTO_TCP, TCP_QUEUE_SEQ); + tcpDetails.ack = Os.getsockoptInt(fd, IPPROTO_TCP, TCP_QUEUE_SEQ); // Switch to NO_QUEUE to prevent illegal socket read/write in repair mode. Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR_QUEUE, TCP_NO_QUEUE); // Finally, check if socket is still idle. TODO : this check needs to move to @@ -197,6 +191,8 @@ public class TcpKeepaliveController { // Query tcp window size. trw = NetworkUtils.getTcpRepairWindow(fd); + tcpDetails.rcvWnd = trw.rcvWnd; + tcpDetails.rcvWndScale = trw.rcvWndScale; } catch (ErrnoException e) { Log.e(TAG, "Exception reading TCP state from socket", e); if (e.errno == ENOPROTOOPT) { @@ -212,10 +208,9 @@ public class TcpKeepaliveController { // Keepalive sequence number is last sequence number - 1. If it couldn't be retrieved, // then it must be set to -1, so decrement in all cases. - seq = seq - 1; + tcpDetails.seq = tcpDetails.seq - 1; - return new TcpSocketInfo(srcAddress, srcPort, dstAddress, dstPort, seq, ack, trw.rcvWnd, - trw.rcvWndScale); + return tcpDetails; } /** @@ -287,8 +282,8 @@ public class TcpKeepaliveController { switchOutOfRepairMode(fd); } - private static InetAddress getAddress(InetSocketAddress inetAddr) { - return inetAddr.getAddress(); + private static byte [] getAddress(InetSocketAddress inetAddr) { + return inetAddr.getAddress().getAddress(); } private static int getPort(InetSocketAddress inetAddr) { diff --git a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java b/tests/net/java/android/net/TcpKeepalivePacketDataTest.java index 1f2dd275bb..372ffcd057 100644 --- a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java +++ b/tests/net/java/android/net/TcpKeepalivePacketDataTest.java @@ -21,12 +21,9 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import android.net.SocketKeepalive.InvalidPacketException; -import android.net.TcpKeepalivePacketData.TcpSocketInfo; import com.android.internal.util.TestUtils; -import libcore.net.InetAddressUtils; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -37,14 +34,14 @@ import java.nio.ByteBuffer; @RunWith(JUnit4.class) public final class TcpKeepalivePacketDataTest { + private static final byte[] IPV4_KEEPALIVE_SRC_ADDR = {10, 0, 0, 1}; + private static final byte[] IPV4_KEEPALIVE_DST_ADDR = {10, 0, 0, 5}; @Before public void setUp() {} @Test - public void testV4TcpKeepalivePacket() { - final InetAddress srcAddr = InetAddressUtils.parseNumericAddress("192.168.0.1"); - final InetAddress dstAddr = InetAddressUtils.parseNumericAddress("192.168.0.10"); + public void testV4TcpKeepalivePacket() throws Exception { final int srcPort = 1234; final int dstPort = 4321; final int seq = 0x11111111; @@ -52,20 +49,28 @@ public final class TcpKeepalivePacketDataTest { final int wnd = 8000; final int wndScale = 2; TcpKeepalivePacketData resultData = null; - TcpSocketInfo testInfo = new TcpSocketInfo( - srcAddr, srcPort, dstAddr, dstPort, seq, ack, wnd, wndScale); + final TcpKeepalivePacketDataParcelable testInfo = new TcpKeepalivePacketDataParcelable(); + testInfo.srcAddress = IPV4_KEEPALIVE_SRC_ADDR; + testInfo.srcPort = srcPort; + testInfo.dstAddress = IPV4_KEEPALIVE_DST_ADDR; + testInfo.dstPort = dstPort; + testInfo.seq = seq; + testInfo.ack = ack; + testInfo.rcvWnd = wnd; + testInfo.rcvWndScale = wndScale; try { resultData = TcpKeepalivePacketData.tcpKeepalivePacket(testInfo); } catch (InvalidPacketException e) { fail("InvalidPacketException: " + e); } - assertEquals(testInfo.srcAddress, resultData.srcAddress); - assertEquals(testInfo.dstAddress, resultData.dstAddress); + assertEquals(InetAddress.getByAddress(testInfo.srcAddress), resultData.srcAddress); + assertEquals(InetAddress.getByAddress(testInfo.dstAddress), resultData.dstAddress); assertEquals(testInfo.srcPort, resultData.srcPort); assertEquals(testInfo.dstPort, resultData.dstPort); assertEquals(testInfo.seq, resultData.tcpSeq); assertEquals(testInfo.ack, resultData.tcpAck); + assertEquals(testInfo.rcvWnd, resultData.tcpWnd); assertEquals(testInfo.rcvWndScale, resultData.tcpWndScale); TestUtils.assertParcelingIsLossless(resultData, TcpKeepalivePacketData.CREATOR); @@ -78,11 +83,11 @@ public final class TcpKeepalivePacketDataTest { byte[] ip = new byte[4]; buf = ByteBuffer.wrap(packet, 12, 4); buf.get(ip); - assertArrayEquals(ip, srcAddr.getAddress()); + assertArrayEquals(ip, IPV4_KEEPALIVE_SRC_ADDR); // Destination IP address. buf = ByteBuffer.wrap(packet, 16, 4); buf.get(ip); - assertArrayEquals(ip, dstAddr.getAddress()); + assertArrayEquals(ip, IPV4_KEEPALIVE_DST_ADDR); buf = ByteBuffer.wrap(packet, 20, 12); // Source port. @@ -102,25 +107,32 @@ public final class TcpKeepalivePacketDataTest { @Test public void testParcel() throws Exception { - final InetAddress srcAddr = InetAddresses.parseNumericAddress("192.168.0.1"); - final InetAddress dstAddr = InetAddresses.parseNumericAddress("192.168.0.10"); final int srcPort = 1234; final int dstPort = 4321; final int sequence = 0x11111111; final int ack = 0x22222222; final int wnd = 48_000; final int wndScale = 2; + final TcpKeepalivePacketDataParcelable testInfo = new TcpKeepalivePacketDataParcelable(); + testInfo.srcAddress = IPV4_KEEPALIVE_SRC_ADDR; + testInfo.srcPort = srcPort; + testInfo.dstAddress = IPV4_KEEPALIVE_DST_ADDR; + testInfo.dstPort = dstPort; + testInfo.seq = sequence; + testInfo.ack = ack; + testInfo.rcvWnd = wnd; + testInfo.rcvWndScale = wndScale; TcpKeepalivePacketData testData = null; TcpKeepalivePacketDataParcelable resultData = null; - TcpSocketInfo testInfo = new TcpSocketInfo( - srcAddr, srcPort, dstAddr, dstPort, sequence, ack, wnd, wndScale); testData = TcpKeepalivePacketData.tcpKeepalivePacket(testInfo); resultData = testData.toStableParcelable(); - assertArrayEquals(resultData.srcAddress, srcAddr.getAddress()); - assertArrayEquals(resultData.dstAddress, dstAddr.getAddress()); + assertArrayEquals(resultData.srcAddress, IPV4_KEEPALIVE_SRC_ADDR); + assertArrayEquals(resultData.dstAddress, IPV4_KEEPALIVE_DST_ADDR); assertEquals(resultData.srcPort, srcPort); assertEquals(resultData.dstPort, dstPort); assertEquals(resultData.seq, sequence); assertEquals(resultData.ack, ack); + assertEquals(resultData.rcvWnd, wnd); + assertEquals(resultData.rcvWndScale, wndScale); } }