Merge "Restrict scope of switch Repair Mode"

am: 19b1610698

Change-Id: Ie655ad82d0441aa6ad6fc45a6e63dc2a53338148
This commit is contained in:
Mark Chien
2019-03-21 00:18:11 -07:00
committed by android-build-merger
2 changed files with 37 additions and 27 deletions

View File

@@ -42,7 +42,6 @@ import android.net.NetworkUtils;
import android.net.SocketKeepalive.InvalidPacketException; import android.net.SocketKeepalive.InvalidPacketException;
import android.net.SocketKeepalive.InvalidSocketException; import android.net.SocketKeepalive.InvalidSocketException;
import android.net.TcpKeepalivePacketData; import android.net.TcpKeepalivePacketData;
import android.net.TcpKeepalivePacketData.TcpSocketInfo;
import android.net.util.IpUtils; import android.net.util.IpUtils;
import android.os.Binder; import android.os.Binder;
import android.os.Handler; import android.os.Handler;
@@ -492,19 +491,14 @@ public class KeepaliveTracker {
return; return;
} }
TcpKeepalivePacketData packet = null; final TcpKeepalivePacketData packet;
try { try {
TcpSocketInfo tsi = TcpKeepaliveController.switchToRepairMode(fd); packet = TcpKeepaliveController.getTcpKeepalivePacket(fd);
packet = TcpKeepalivePacketData.tcpKeepalivePacket(tsi);
} catch (InvalidPacketException | InvalidSocketException e) { } 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); notifyErrorCallback(cb, e.error);
return; return;
} }
KeepaliveInfo ki = new KeepaliveInfo(cb, nai, packet, intervalSeconds, KeepaliveInfo ki = new KeepaliveInfo(cb, nai, packet, intervalSeconds,
KeepaliveInfo.TYPE_TCP, fd); KeepaliveInfo.TYPE_TCP, fd);
Log.d(TAG, "Created keepalive: " + ki.toString()); Log.d(TAG, "Created keepalive: " + ki.toString());

View File

@@ -28,7 +28,9 @@ import static android.system.OsConstants.TIOCOUTQ;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.net.NetworkUtils; import android.net.NetworkUtils;
import android.net.SocketKeepalive.InvalidPacketException;
import android.net.SocketKeepalive.InvalidSocketException; import android.net.SocketKeepalive.InvalidSocketException;
import android.net.TcpKeepalivePacketData;
import android.net.TcpKeepalivePacketData.TcpSocketInfo; import android.net.TcpKeepalivePacketData.TcpSocketInfo;
import android.net.TcpRepairWindow; import android.net.TcpRepairWindow;
import android.os.Handler; import android.os.Handler;
@@ -103,16 +105,25 @@ public class TcpKeepaliveController {
mFdHandlerQueue = connectivityServiceHandler.getLooper().getQueue(); 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 * @return a {@link TcpKeepalivePacketData#TcpSocketInfo} object for current
* tcp/ip information. * tcp/ip information.
*/ */
// TODO : make this private. It's far too confusing that this gets called from outside private static TcpSocketInfo switchToRepairMode(FileDescriptor fd)
// at a time that nobody can understand.
public static TcpSocketInfo switchToRepairMode(FileDescriptor fd)
throws InvalidSocketException { throws InvalidSocketException {
if (DBG) Log.i(TAG, "switchToRepairMode to start tcp keepalive : " + fd); if (DBG) Log.i(TAG, "switchToRepairMode to start tcp keepalive : " + fd);
final SocketAddress srcSockAddr; final SocketAddress srcSockAddr;
@@ -157,10 +168,12 @@ public class TcpKeepaliveController {
// Query sequence and ack number // Query sequence and ack number
dropAllIncomingPackets(fd, true); dropAllIncomingPackets(fd, true);
try { try {
// Enter tcp repair mode. // Switch to tcp repair mode.
Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR, TCP_REPAIR_ON); Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR, TCP_REPAIR_ON);
// Check if socket is idle. // Check if socket is idle.
if (!isSocketIdle(fd)) { if (!isSocketIdle(fd)) {
Log.e(TAG, "Socket is not idle");
throw new InvalidSocketException(ERROR_SOCKET_NOT_IDLE); throw new InvalidSocketException(ERROR_SOCKET_NOT_IDLE);
} }
// Query write sequence number from SEND_QUEUE. // 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); 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 // Finally, check if socket is still idle. TODO : this check needs to move to
// after starting polling to prevent a race. // 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); 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. // Query tcp window size.
trw = NetworkUtils.getTcpRepairWindow(fd); trw = NetworkUtils.getTcpRepairWindow(fd);
@@ -205,10 +223,13 @@ public class TcpKeepaliveController {
* *
* @param fd the fd of socket to switch back to normal. * @param fd the fd of socket to switch back to normal.
*/ */
// TODO : make this private. private static void switchOutOfRepairMode(@NonNull final FileDescriptor fd) {
public static void switchOutOfRepairMode(@NonNull final FileDescriptor fd) try {
throws ErrnoException {
Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR, TCP_REPAIR_OFF); 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); mListeners.remove(slot);
} }
mFdHandlerQueue.removeOnFileDescriptorEventListener(fd); mFdHandlerQueue.removeOnFileDescriptorEventListener(fd);
try {
if (DBG) Log.d(TAG, "Moving socket out of repair mode for stop : " + fd); if (DBG) Log.d(TAG, "Moving socket out of repair mode for stop : " + fd);
switchOutOfRepairMode(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) { private static InetAddress getAddress(InetSocketAddress inetAddr) {