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

Commit 21caf8d6 authored by Mark Chien's avatar Mark Chien Committed by Gerrit Code Review
Browse files

Merge "Restrict scope of switch Repair Mode"

parents 3af01e2f 656fbe92
Loading
Loading
Loading
Loading
+3 −9
Original line number Diff line number Diff line
@@ -42,7 +42,6 @@ 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.util.IpUtils;
import android.os.Binder;
import android.os.Handler;
@@ -492,19 +491,14 @@ public class KeepaliveTracker {
            return;
        }

        TcpKeepalivePacketData packet = null;
        final TcpKeepalivePacketData packet;
        try {
            TcpSocketInfo tsi = TcpKeepaliveController.switchToRepairMode(fd);
            packet = TcpKeepalivePacketData.tcpKeepalivePacket(tsi);
            packet = TcpKeepaliveController.getTcpKeepalivePacket(fd);
        } catch (InvalidPacketException | InvalidSocketException e) {
            try {
                TcpKeepaliveController.switchOutOfRepairMode(fd);
            } catch (ErrnoException e1) {
                Log.e(TAG, "Couldn't move fd out of repair mode after failure to start keepalive");
            }
            notifyErrorCallback(cb, e.error);
            return;
        }

        KeepaliveInfo ki = new KeepaliveInfo(cb, nai, packet, intervalSeconds,
                KeepaliveInfo.TYPE_TCP, fd);
        Log.d(TAG, "Created keepalive: " + ki.toString());
+34 −18
Original line number Diff line number Diff line
@@ -28,7 +28,9 @@ import static android.system.OsConstants.TIOCOUTQ;

import android.annotation.NonNull;
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.TcpRepairWindow;
import android.os.Handler;
@@ -103,16 +105,25 @@ public class TcpKeepaliveController {
        mFdHandlerQueue = connectivityServiceHandler.getLooper().getQueue();
    }

    /** Build tcp keepalive packet. */
    public static TcpKeepalivePacketData getTcpKeepalivePacket(@NonNull FileDescriptor fd)
            throws InvalidPacketException, InvalidSocketException {
        try {
            final TcpSocketInfo tsi = switchToRepairMode(fd);
            return TcpKeepalivePacketData.tcpKeepalivePacket(tsi);
        } catch (InvalidPacketException | InvalidSocketException e) {
            switchOutOfRepairMode(fd);
            throw e;
        }
    }
    /**
     * Switch the tcp socket to repair mode and query tcp socket information.
     * Switch the tcp socket to repair mode and query detail tcp information.
     *
     * @param fd the fd of socket on which to use keepalive offload
     * @param fd the fd of socket on which to use keepalive offload.
     * @return a {@link TcpKeepalivePacketData#TcpSocketInfo} object for current
     * tcp/ip information.
     */
    // TODO : make this private. It's far too confusing that this gets called from outside
    // at a time that nobody can understand.
    public static TcpSocketInfo switchToRepairMode(FileDescriptor fd)
    private static TcpSocketInfo switchToRepairMode(FileDescriptor fd)
            throws InvalidSocketException {
        if (DBG) Log.i(TAG, "switchToRepairMode to start tcp keepalive : " + fd);
        final SocketAddress srcSockAddr;
@@ -157,10 +168,12 @@ public class TcpKeepaliveController {
        // Query sequence and ack number
        dropAllIncomingPackets(fd, true);
        try {
            // Enter tcp repair mode.
            // Switch to tcp repair mode.
            Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR, TCP_REPAIR_ON);

            // Check if socket is idle.
            if (!isSocketIdle(fd)) {
                Log.e(TAG, "Socket is not idle");
                throw new InvalidSocketException(ERROR_SOCKET_NOT_IDLE);
            }
            // Query write sequence number from SEND_QUEUE.
@@ -173,9 +186,14 @@ public class TcpKeepaliveController {
            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
            // after starting polling to prevent a race.
            if (!isSocketIdle(fd)) {
            if (!isReceiveQueueEmpty(fd)) {
                Log.e(TAG, "Fatal: receive queue of this socket is not empty");
                throw new InvalidSocketException(ERROR_INVALID_SOCKET);
            }
            if (!isSendQueueEmpty(fd)) {
                Log.e(TAG, "Socket is not idle");
                throw new InvalidSocketException(ERROR_SOCKET_NOT_IDLE);
            }

            // Query tcp window size.
            trw = NetworkUtils.getTcpRepairWindow(fd);
@@ -205,10 +223,13 @@ public class TcpKeepaliveController {
     *
     * @param fd the fd of socket to switch back to normal.
     */
    // TODO : make this private.
    public static void switchOutOfRepairMode(@NonNull final FileDescriptor fd)
            throws ErrnoException {
    private static void switchOutOfRepairMode(@NonNull final FileDescriptor fd) {
        try {
            Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR, TCP_REPAIR_OFF);
        } catch (ErrnoException e) {
            Log.e(TAG, "Cannot switch socket out of repair mode", e);
            // Well, there is not much to do here to recover
        }
    }

    /**
@@ -262,13 +283,8 @@ public class TcpKeepaliveController {
            mListeners.remove(slot);
        }
        mFdHandlerQueue.removeOnFileDescriptorEventListener(fd);
        try {
        if (DBG) Log.d(TAG, "Moving socket out of repair mode for stop : " + fd);
        switchOutOfRepairMode(fd);
        } catch (ErrnoException e) {
            Log.e(TAG, "Cannot switch socket out of repair mode", e);
            // Well, there is not much to do here to recover
        }
    }

    private static InetAddress getAddress(InetSocketAddress inetAddr) {