Loading services/core/java/com/android/server/connectivity/KeepaliveTracker.java +3 −9 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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()); Loading services/core/java/com/android/server/connectivity/TcpKeepaliveController.java +34 −18 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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. Loading @@ -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); Loading Loading @@ -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 } } /** Loading Loading @@ -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) { Loading Loading
services/core/java/com/android/server/connectivity/KeepaliveTracker.java +3 −9 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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()); Loading
services/core/java/com/android/server/connectivity/TcpKeepaliveController.java +34 −18 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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. Loading @@ -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); Loading Loading @@ -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 } } /** Loading Loading @@ -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) { Loading