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

Commit 2775f8a1 authored by Yan Yan's avatar Yan Yan Committed by Gerrit Code Review
Browse files

Merge "Use token to identify IKE Session"

parents 92891b4b b93a4055
Loading
Loading
Loading
Loading
+86 −46
Original line number Diff line number Diff line
@@ -2586,13 +2586,13 @@ public class Vpn {

        void onDefaultNetworkLinkPropertiesChanged(@NonNull LinkProperties lp);

        void onChildOpened(
                @NonNull Network network, @NonNull ChildSessionConfiguration childConfig);
        void onDefaultNetworkLost(@NonNull Network network);

        void onChildTransformCreated(
                @NonNull Network network, @NonNull IpSecTransform transform, int direction);
        void onChildOpened(int token, @NonNull ChildSessionConfiguration childConfig);

        void onSessionLost(@NonNull Network network, @Nullable Exception exception);
        void onChildTransformCreated(int token, @NonNull IpSecTransform transform, int direction);

        void onSessionLost(int token, @Nullable Exception exception);
    }

    /**
@@ -2639,6 +2639,13 @@ public class Vpn {
        /** Signal to ensure shutdown is honored even if a new Network is connected. */
        private boolean mIsRunning = true;

        /**
         * The token used by the primary/current/active IKE session.
         *
         * <p>This token MUST be updated when the VPN switches to use a new IKE session.
         */
        private int mCurrentToken = -1;

        @Nullable private IpSecTunnelInterface mTunnelIface;
        @Nullable private IkeSession mSession;
        @Nullable private Network mActiveNetwork;
@@ -2692,22 +2699,25 @@ public class Vpn {
            return Objects.equals(mActiveNetwork, network) && mIsRunning;
        }

        private boolean isActiveToken(int token) {
            return (mCurrentToken == token) && mIsRunning;
        }

        /**
         * Called when an IKE Child session has been opened, signalling completion of the startup.
         *
         * <p>This method is only ever called once per IkeSession, and MUST run on the mExecutor
         * thread in order to ensure consistency of the Ikev2VpnRunner fields.
         */
        public void onChildOpened(
                @NonNull Network network, @NonNull ChildSessionConfiguration childConfig) {
            if (!isActiveNetwork(network)) {
                Log.d(TAG, "onOpened called for obsolete network " + network);
        public void onChildOpened(int token, @NonNull ChildSessionConfiguration childConfig) {
            if (!isActiveToken(token)) {
                Log.d(TAG, "onChildOpened called for obsolete token " + token);

                // Do nothing; this signals that either: (1) a new/better Network was found,
                // and the Ikev2VpnRunner has switched to it in onDefaultNetworkChanged, or (2) this
                // IKE session was already shut down (exited, or an error was encountered somewhere
                // else). In both cases, all resources and sessions are torn down via
                // resetIkeState().
                // and the Ikev2VpnRunner has switched to it by restarting a new IKE session in
                // onDefaultNetworkChanged, or (2) this IKE session was already shut down (exited,
                // or an error was encountered somewhere else). In both cases, all resources and
                // sessions are torn down via resetIkeState().
                return;
            }

@@ -2744,7 +2754,7 @@ public class Vpn {
                    mConfig.dnsServers.clear();
                    mConfig.dnsServers.addAll(dnsAddrStrings);

                    mConfig.underlyingNetworks = new Network[] {network};
                    mConfig.underlyingNetworks = new Network[] {mActiveNetwork};

                    mConfig.disallowedApplications = getAppExclusionList(mPackage);

@@ -2760,7 +2770,8 @@ public class Vpn {
                        return; // Link properties are already sent.
                    } else {
                        // Underlying networks also set in agentConnect()
                        networkAgent.setUnderlyingNetworks(Collections.singletonList(network));
                        networkAgent.setUnderlyingNetworks(
                                Collections.singletonList(mActiveNetwork));
                    }

                    lp = makeLinkProperties(); // Accesses VPN instance fields; must be locked
@@ -2768,8 +2779,8 @@ public class Vpn {

                networkAgent.sendLinkProperties(lp);
            } catch (Exception e) {
                Log.d(TAG, "Error in ChildOpened for network " + network, e);
                onSessionLost(network, e);
                Log.d(TAG, "Error in ChildOpened for token " + token, e);
                onSessionLost(token, e);
            }
        }

@@ -2781,15 +2792,15 @@ public class Vpn {
         * consistency of the Ikev2VpnRunner fields.
         */
        public void onChildTransformCreated(
                @NonNull Network network, @NonNull IpSecTransform transform, int direction) {
            if (!isActiveNetwork(network)) {
                Log.d(TAG, "ChildTransformCreated for obsolete network " + network);
                int token, @NonNull IpSecTransform transform, int direction) {
            if (!isActiveToken(token)) {
                Log.d(TAG, "ChildTransformCreated for obsolete token " + token);

                // Do nothing; this signals that either: (1) a new/better Network was found,
                // and the Ikev2VpnRunner has switched to it in onDefaultNetworkChanged, or (2) this
                // IKE session was already shut down (exited, or an error was encountered somewhere
                // else). In both cases, all resources and sessions are torn down via
                // resetIkeState().
                // and the Ikev2VpnRunner has switched to it by restarting a new IKE session in
                // onDefaultNetworkChanged, or (2) this IKE session was already shut down (exited,
                // or an error was encountered somewhere else). In both cases, all resources and
                // sessions are torn down via resetIkeState().
                return;
            }

@@ -2798,8 +2809,8 @@ public class Vpn {
                // them alive for us
                mIpSecManager.applyTunnelModeTransform(mTunnelIface, direction, transform);
            } catch (IOException e) {
                Log.d(TAG, "Transform application failed for network " + network, e);
                onSessionLost(network, e);
                Log.d(TAG, "Transform application failed for token " + token, e);
                onSessionLost(token, e);
            }
        }

@@ -2857,19 +2868,21 @@ public class Vpn {
                                network);
                NetdUtils.setInterfaceUp(mNetd, mTunnelIface.getInterfaceName());

                mSession = mIkev2SessionCreator.createIkeSession(
                final int token = ++mCurrentToken;
                mSession =
                        mIkev2SessionCreator.createIkeSession(
                                mContext,
                                ikeSessionParams,
                                childSessionParams,
                                mExecutor,
                                new VpnIkev2Utils.IkeSessionCallbackImpl(
                                TAG, IkeV2VpnRunner.this, network),
                                        TAG, IkeV2VpnRunner.this, token),
                                new VpnIkev2Utils.ChildSessionCallbackImpl(
                                TAG, IkeV2VpnRunner.this, network));
                Log.d(TAG, "Ike Session started for network " + network);
                                        TAG, IkeV2VpnRunner.this, token));
                Log.d(TAG, "IKE session started for token " + token);
            } catch (Exception e) {
                Log.i(TAG, "Setup failed for network " + network + ". Aborting", e);
                onSessionLost(network, e);
                Log.i(TAG, "Setup failed for token " + mCurrentToken + ". Aborting", e);
                onSessionLost(mCurrentToken, e);
            }
        }

@@ -2883,6 +2896,29 @@ public class Vpn {
            mUnderlyingLinkProperties = lp;
        }

        /**
         * Handles loss of the default underlying network
         *
         * <p>The Ikev2VpnRunner will kill the IKE session and reset the VPN.
         *
         * <p>This method MUST always be called on the mExecutor thread in order to ensure
         * consistency of the Ikev2VpnRunner fields.
         */
        public void onDefaultNetworkLost(@NonNull Network network) {
            if (!isActiveNetwork(network)) {
                Log.d(TAG, "onDefaultNetworkLost called for obsolete network " + network);

                // Do nothing; this signals that either: (1) a new/better Network was found,
                // and the Ikev2VpnRunner has switched to it by restarting a new IKE session in
                // onDefaultNetworkChanged, or (2) this IKE session was already shut down (exited,
                // or an error was encountered somewhere else). In both cases, all resources and
                // sessions are torn down via resetIkeState().
                return;
            }

            handleSessionLost(null);
        }

        /** Marks the state as FAILED, and disconnects. */
        private void markFailedAndDisconnect(Exception exception) {
            synchronized (Vpn.this) {
@@ -2901,18 +2937,22 @@ public class Vpn {
         * <p>This method MUST always be called on the mExecutor thread in order to ensure
         * consistency of the Ikev2VpnRunner fields.
         */
        public void onSessionLost(@NonNull Network network, @Nullable Exception exception) {
            if (!isActiveNetwork(network)) {
                Log.d(TAG, "onSessionLost() called for obsolete network " + network);
        public void onSessionLost(int token, @Nullable Exception exception) {
            if (!isActiveToken(token)) {
                Log.d(TAG, "onSessionLost() called for obsolete token " + token);

                // Do nothing; this signals that either: (1) a new/better Network was found,
                // and the Ikev2VpnRunner has switched to it in onDefaultNetworkChanged, or (2) this
                // IKE session was already shut down (exited, or an error was encountered somewhere
                // else). In both cases, all resources and sessions are torn down via
                // onSessionLost() and resetIkeState().
                // and the Ikev2VpnRunner has switched to it by restarting a new IKE session in
                // onDefaultNetworkChanged, or (2) this IKE session was already shut down (exited,
                // or an error was encountered somewhere else). In both cases, all resources and
                // sessions are torn down via resetIkeState().
                return;
            }

            handleSessionLost(exception);
        }

        private void handleSessionLost(@Nullable Exception exception) {
            synchronized (Vpn.this) {
                if (exception instanceof IkeProtocolException) {
                    final IkeProtocolException ikeException = (IkeProtocolException) exception;
@@ -3030,7 +3070,7 @@ public class Vpn {

            // Close all obsolete state, but keep VPN alive incase a usable network comes up.
            // (Mirrors VpnService behavior)
            Log.d(TAG, "Resetting state for network: " + network);
            Log.d(TAG, "Resetting state for token: " + mCurrentToken);

            synchronized (Vpn.this) {
                // Since this method handles non-fatal errors only, set mInterface to null to
+23 −24
Original line number Diff line number Diff line
@@ -298,35 +298,35 @@ public class VpnIkev2Utils {
    static class IkeSessionCallbackImpl implements IkeSessionCallback {
        private final String mTag;
        private final Vpn.IkeV2VpnRunnerCallback mCallback;
        private final Network mNetwork;
        private final int mToken;

        IkeSessionCallbackImpl(String tag, Vpn.IkeV2VpnRunnerCallback callback, Network network) {
        IkeSessionCallbackImpl(String tag, Vpn.IkeV2VpnRunnerCallback callback, int token) {
            mTag = tag;
            mCallback = callback;
            mNetwork = network;
            mToken = token;
        }

        @Override
        public void onOpened(@NonNull IkeSessionConfiguration ikeSessionConfig) {
            Log.d(mTag, "IkeOpened for network " + mNetwork);
            Log.d(mTag, "IkeOpened for token " + mToken);
            // Nothing to do here.
        }

        @Override
        public void onClosed() {
            Log.d(mTag, "IkeClosed for network " + mNetwork);
            mCallback.onSessionLost(mNetwork, null); // Server requested session closure. Retry?
            Log.d(mTag, "IkeClosed for token " + mToken);
            mCallback.onSessionLost(mToken, null); // Server requested session closure. Retry?
        }

        @Override
        public void onClosedExceptionally(@NonNull IkeException exception) {
            Log.d(mTag, "IkeClosedExceptionally for network " + mNetwork, exception);
            mCallback.onSessionLost(mNetwork, exception);
            Log.d(mTag, "IkeClosedExceptionally for token " + mToken, exception);
            mCallback.onSessionLost(mToken, exception);
        }

        @Override
        public void onError(@NonNull IkeProtocolException exception) {
            Log.d(mTag, "IkeError for network " + mNetwork, exception);
            Log.d(mTag, "IkeError for token " + mToken, exception);
            // Non-fatal, log and continue.
        }
    }
@@ -334,36 +334,36 @@ public class VpnIkev2Utils {
    static class ChildSessionCallbackImpl implements ChildSessionCallback {
        private final String mTag;
        private final Vpn.IkeV2VpnRunnerCallback mCallback;
        private final Network mNetwork;
        private final int mToken;

        ChildSessionCallbackImpl(String tag, Vpn.IkeV2VpnRunnerCallback callback, Network network) {
        ChildSessionCallbackImpl(String tag, Vpn.IkeV2VpnRunnerCallback callback, int token) {
            mTag = tag;
            mCallback = callback;
            mNetwork = network;
            mToken = token;
        }

        @Override
        public void onOpened(@NonNull ChildSessionConfiguration childConfig) {
            Log.d(mTag, "ChildOpened for network " + mNetwork);
            mCallback.onChildOpened(mNetwork, childConfig);
            Log.d(mTag, "ChildOpened for token " + mToken);
            mCallback.onChildOpened(mToken, childConfig);
        }

        @Override
        public void onClosed() {
            Log.d(mTag, "ChildClosed for network " + mNetwork);
            mCallback.onSessionLost(mNetwork, null);
            Log.d(mTag, "ChildClosed for token " + mToken);
            mCallback.onSessionLost(mToken, null);
        }

        @Override
        public void onClosedExceptionally(@NonNull IkeException exception) {
            Log.d(mTag, "ChildClosedExceptionally for network " + mNetwork, exception);
            mCallback.onSessionLost(mNetwork, exception);
            Log.d(mTag, "ChildClosedExceptionally for token " + mToken, exception);
            mCallback.onSessionLost(mToken, exception);
        }

        @Override
        public void onIpSecTransformCreated(@NonNull IpSecTransform transform, int direction) {
            Log.d(mTag, "ChildTransformCreated; Direction: " + direction + "; network " + mNetwork);
            mCallback.onChildTransformCreated(mNetwork, transform, direction);
            Log.d(mTag, "ChildTransformCreated; Direction: " + direction + "; token " + mToken);
            mCallback.onChildTransformCreated(mToken, transform, direction);
        }

        @Override
@@ -371,8 +371,7 @@ public class VpnIkev2Utils {
            // Nothing to be done; no references to the IpSecTransform are held by the
            // Ikev2VpnRunner (or this callback class), and this transform will be closed by the
            // IKE library.
            Log.d(mTag,
                    "ChildTransformDeleted; Direction: " + direction + "; for network " + mNetwork);
            Log.d(mTag, "ChildTransformDeleted; Direction: " + direction + "; for token " + mToken);
        }
    }

@@ -412,8 +411,8 @@ public class VpnIkev2Utils {

        @Override
        public void onLost(@NonNull Network network) {
            Log.d(mTag, "Tearing down; lost network: " + network);
            mExecutor.execute(() -> mCallback.onSessionLost(network, null));
            Log.d(mTag, "onLost called for network: " + network);
            mExecutor.execute(() -> mCallback.onDefaultNetworkLost(network));
        }
    }