/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.ethernet;

import static android.net.ConnectivityManager.TYPE_ETHERNET;
import static android.net.shared.LinkPropertiesParcelableUtil.toStableParcelable;
import static com.android.internal.util.Preconditions.checkNotNull;

import android.annotation.NonNull;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.IpConfiguration;
import android.net.IpConfiguration.IpAssignment;
import android.net.IpConfiguration.ProxySettings;
import android.net.LinkProperties;
import android.net.NetworkAgent;
import android.net.NetworkCapabilities;
import android.net.NetworkFactory;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkRequest;
import android.net.NetworkSpecifier;
import android.net.StringNetworkSpecifier;
import android.net.ip.IIpClient;
import android.net.ip.IpClientCallbacks;
import android.net.ip.IpClientUtil;
import android.net.shared.ProvisioningConfiguration;
import android.net.util.InterfaceParams;
import android.os.ConditionVariable;
import android.os.Handler;
import android.os.RemoteException;
import android.text.TextUtils;
import android.util.AndroidRuntimeException;
import android.util.Log;
import android.util.SparseArray;

import com.android.internal.util.IndentingPrintWriter;

import java.io.FileDescriptor;
import java.lang.Math;
import java.util.concurrent.ConcurrentHashMap;

/**
 * {@link NetworkFactory} that represents Ethernet networks.
 *
 * This class reports a static network score of 70 when it is tracking an interface and that
 * interface's link is up, and a score of 0 otherwise.
 */
public class EthernetNetworkFactory extends NetworkFactory {
    private final static String TAG = EthernetNetworkFactory.class.getSimpleName();
    final static boolean DBG = true;

    private final static int NETWORK_SCORE = 70;
    private static final String NETWORK_TYPE = "Ethernet";

    private final ConcurrentHashMap<String, NetworkInterfaceState> mTrackingInterfaces =
            new ConcurrentHashMap<>();
    private final Handler mHandler;
    private final Context mContext;

    public static class ConfigurationException extends AndroidRuntimeException {
        public ConfigurationException(String msg) {
            super(msg);
        }
    }

    public EthernetNetworkFactory(Handler handler, Context context, NetworkCapabilities filter) {
        super(handler.getLooper(), context, NETWORK_TYPE, filter);

        mHandler = handler;
        mContext = context;

        setScoreFilter(NETWORK_SCORE);
    }

    @Override
    public boolean acceptRequest(NetworkRequest request, int score) {
        if (request.type == NetworkRequest.Type.TRACK_DEFAULT) {
            return false;
        }

        if (DBG) {
            Log.d(TAG, "acceptRequest, request: " + request + ", score: " + score);
        }

        return networkForRequest(request) != null;
    }

    @Override
    protected void needNetworkFor(NetworkRequest networkRequest, int score) {
        NetworkInterfaceState network = networkForRequest(networkRequest);

        if (network == null) {
            Log.e(TAG, "needNetworkFor, failed to get a network for " + networkRequest);
            return;
        }

        if (++network.refCount == 1) {
            network.start();
        }
    }

    @Override
    protected void releaseNetworkFor(NetworkRequest networkRequest) {
        NetworkInterfaceState network = networkForRequest(networkRequest);
        if (network == null) {
            Log.e(TAG, "needNetworkFor, failed to get a network for " + networkRequest);
            return;
        }

        if (--network.refCount == 1) {
            network.stop();
        }
    }

    /**
     * Returns an array of available interface names. The array is sorted: unrestricted interfaces
     * goes first, then sorted by name.
     */
    String[] getAvailableInterfaces(boolean includeRestricted) {
        return mTrackingInterfaces.values()
                .stream()
                .filter(iface -> !iface.isRestricted() || includeRestricted)
                .sorted((iface1, iface2) -> {
                    int r = Boolean.compare(iface1.isRestricted(), iface2.isRestricted());
                    return r == 0 ? iface1.name.compareTo(iface2.name) : r;
                })
                .map(iface -> iface.name)
                .toArray(String[]::new);
    }

    void addInterface(String ifaceName, String hwAddress, NetworkCapabilities capabilities,
             IpConfiguration ipConfiguration) {
        if (mTrackingInterfaces.containsKey(ifaceName)) {
            Log.e(TAG, "Interface with name " + ifaceName + " already exists.");
            return;
        }

        if (DBG) {
            Log.d(TAG, "addInterface, iface: " + ifaceName + ", capabilities: " + capabilities);
        }

        NetworkInterfaceState iface = new NetworkInterfaceState(
                ifaceName, hwAddress, mHandler, mContext, capabilities);
        iface.setIpConfig(ipConfiguration);
        mTrackingInterfaces.put(ifaceName, iface);

        updateCapabilityFilter();
    }

    private void updateCapabilityFilter() {
        NetworkCapabilities capabilitiesFilter = new NetworkCapabilities();
        capabilitiesFilter.clearAll();

        for (NetworkInterfaceState iface:  mTrackingInterfaces.values()) {
            capabilitiesFilter.combineCapabilities(iface.mCapabilities);
        }

        if (DBG) Log.d(TAG, "updateCapabilityFilter: " + capabilitiesFilter);
        setCapabilityFilter(capabilitiesFilter);
    }

    void removeInterface(String interfaceName) {
        NetworkInterfaceState iface = mTrackingInterfaces.remove(interfaceName);
        if (iface != null) {
            iface.stop();
        }

        updateCapabilityFilter();
    }

    /** Returns true if state has been modified */
    boolean updateInterfaceLinkState(String ifaceName, boolean up) {
        if (!mTrackingInterfaces.containsKey(ifaceName)) {
            return false;
        }

        if (DBG) {
            Log.d(TAG, "updateInterfaceLinkState, iface: " + ifaceName + ", up: " + up);
        }

        NetworkInterfaceState iface = mTrackingInterfaces.get(ifaceName);
        return iface.updateLinkState(up);
    }

    boolean hasInterface(String interfacName) {
        return mTrackingInterfaces.containsKey(interfacName);
    }

    void updateIpConfiguration(String iface, IpConfiguration ipConfiguration) {
        NetworkInterfaceState network = mTrackingInterfaces.get(iface);
        if (network != null) {
            network.setIpConfig(ipConfiguration);
        }
    }

    private NetworkInterfaceState networkForRequest(NetworkRequest request) {
        String requestedIface = null;

        NetworkSpecifier specifier = request.networkCapabilities.getNetworkSpecifier();
        if (specifier instanceof StringNetworkSpecifier) {
            requestedIface = ((StringNetworkSpecifier) specifier).specifier;
        }

        NetworkInterfaceState network = null;
        if (!TextUtils.isEmpty(requestedIface)) {
            NetworkInterfaceState n = mTrackingInterfaces.get(requestedIface);
            if (n != null && n.statisified(request.networkCapabilities)) {
                network = n;
            }
        } else {
            for (NetworkInterfaceState n : mTrackingInterfaces.values()) {
                if (n.statisified(request.networkCapabilities)) {
                    network = n;
                    break;
                }
            }
        }

        if (DBG) {
            Log.i(TAG, "networkForRequest, request: " + request + ", network: " + network);
        }

        return network;
    }

    private static class NetworkInterfaceState {
        final String name;

        private final String mHwAddress;
        private final NetworkCapabilities mCapabilities;
        private final Handler mHandler;
        private final Context mContext;
        private final NetworkInfo mNetworkInfo;

        private static String sTcpBufferSizes = null;  // Lazy initialized.

        private boolean mLinkUp;
        private LinkProperties mLinkProperties = new LinkProperties();

        private volatile IIpClient mIpClient;
        private IpClientCallbacksImpl mIpClientCallback;
        private NetworkAgent mNetworkAgent;
        private IpConfiguration mIpConfig;

        /**
         * An object to contain all transport type information, including base network score and
         * the legacy transport type it maps to (if any)
         */
        private static class TransportInfo {
            final int mLegacyType;
            final int mScore;

            private TransportInfo(int legacyType, int score) {
                mLegacyType = legacyType;
                mScore = score;
            }
        }

        /**
         * A map of TRANSPORT_* types to TransportInfo, making scoring and legacy type information
         * available for each type an ethernet interface could propagate.
         *
         * Unfortunately, base scores for the various transports are not yet centrally located.
         * They've been lifted from the corresponding NetworkFactory files in the meantime.
         *
         * Additionally, there are no legacy type equivalents to LOWPAN or WIFI_AWARE. These types
         * are set to TYPE_NONE to match the behavior of their own network factories.
         */
        private static final SparseArray<TransportInfo> sTransports = new SparseArray();
        static {
            // LowpanInterfaceTracker.NETWORK_SCORE
            sTransports.put(NetworkCapabilities.TRANSPORT_LOWPAN,
                    new TransportInfo(ConnectivityManager.TYPE_NONE, 30));
            // WifiAwareDataPathStateManager.NETWORK_FACTORY_SCORE_AVAIL
            sTransports.put(NetworkCapabilities.TRANSPORT_WIFI_AWARE,
                    new TransportInfo(ConnectivityManager.TYPE_NONE, 1));
            // EthernetNetworkFactory.NETWORK_SCORE
            sTransports.put(NetworkCapabilities.TRANSPORT_ETHERNET,
                    new TransportInfo(ConnectivityManager.TYPE_ETHERNET, 70));
            // BluetoothTetheringNetworkFactory.NETWORK_SCORE
            sTransports.put(NetworkCapabilities.TRANSPORT_BLUETOOTH,
                    new TransportInfo(ConnectivityManager.TYPE_BLUETOOTH, 69));
            // WifiNetworkFactory.SCORE_FILTER / NetworkAgent.WIFI_BASE_SCORE
            sTransports.put(NetworkCapabilities.TRANSPORT_WIFI,
                    new TransportInfo(ConnectivityManager.TYPE_WIFI, 60));
            // TelephonyNetworkFactory.TELEPHONY_NETWORK_SCORE
            sTransports.put(NetworkCapabilities.TRANSPORT_CELLULAR,
                    new TransportInfo(ConnectivityManager.TYPE_MOBILE, 50));
        }

        long refCount = 0;

        private class IpClientCallbacksImpl extends IpClientCallbacks {
            private final ConditionVariable mIpClientStartCv = new ConditionVariable(false);
            private final ConditionVariable mIpClientShutdownCv = new ConditionVariable(false);

            @Override
            public void onIpClientCreated(IIpClient ipClient) {
                mIpClient = ipClient;
                mIpClientStartCv.open();
            }

            private void awaitIpClientStart() {
                mIpClientStartCv.block();
            }

            private void awaitIpClientShutdown() {
                mIpClientShutdownCv.block();
            }

            @Override
            public void onProvisioningSuccess(LinkProperties newLp) {
                mHandler.post(() -> onIpLayerStarted(newLp));
            }

            @Override
            public void onProvisioningFailure(LinkProperties newLp) {
                mHandler.post(() -> onIpLayerStopped(newLp));
            }

            @Override
            public void onLinkPropertiesChange(LinkProperties newLp) {
                mHandler.post(() -> updateLinkProperties(newLp));
            }

            @Override
            public void onQuit() {
                mIpClient = null;
                mIpClientShutdownCv.open();
            }
        }

        private static void shutdownIpClient(IIpClient ipClient) {
            try {
                ipClient.shutdown();
            } catch (RemoteException e) {
                Log.e(TAG, "Error stopping IpClient", e);
            }
        }

        NetworkInterfaceState(String ifaceName, String hwAddress, Handler handler, Context context,
                @NonNull NetworkCapabilities capabilities) {
            name = ifaceName;
            mCapabilities = checkNotNull(capabilities);
            mHandler = handler;
            mContext = context;
            int legacyType = ConnectivityManager.TYPE_NONE;
            int[] transportTypes = mCapabilities.getTransportTypes();
            if (transportTypes.length > 0) {
                legacyType = getLegacyType(transportTypes[0]);
            } else {
                // Should never happen as transport is always one of ETHERNET or a valid override
                throw new ConfigurationException("Network Capabilities do not have an associated "
                        + "transport type.");
            }

            mHwAddress = hwAddress;
            mNetworkInfo = new NetworkInfo(legacyType, 0, NETWORK_TYPE, "");
            mNetworkInfo.setExtraInfo(mHwAddress);
            mNetworkInfo.setIsAvailable(true);
        }

        void setIpConfig(IpConfiguration ipConfig) {
            this.mIpConfig = ipConfig;
        }

        boolean statisified(NetworkCapabilities requestedCapabilities) {
            return requestedCapabilities.satisfiedByNetworkCapabilities(mCapabilities);
        }

        boolean isRestricted() {
            return mCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
        }

        /**
         * Determines the legacy transport type from a NetworkCapabilities transport type. Defaults
         * to legacy TYPE_NONE if there is no known conversion
         */
        private static int getLegacyType(int transport) {
            TransportInfo transportInfo = sTransports.get(transport, /* if dne */ null);
            if (transportInfo != null) {
                return transportInfo.mLegacyType;
            }
            return ConnectivityManager.TYPE_NONE;
        }

        /**
         * Determines the network score based on the transport associated with the interface.
         * Ethernet interfaces could propagate a transport types forward. Since we can't
         * get more information about the statuses of the interfaces on the other end of the local
         * interface, we'll best-effort assign the score as the base score of the assigned transport
         * when the link is up. When the link is down, the score is set to zero.
         *
         * This function is called with the purpose of assigning and updating the network score of
         * the member NetworkAgent.
         */
        private int getNetworkScore() {
            // never set the network score below 0.
            if (!mLinkUp) {
                return 0;
            }

            int[] transportTypes = mCapabilities.getTransportTypes();
            if (transportTypes.length < 1) {
                Log.w(TAG, "Network interface '" + mLinkProperties.getInterfaceName() + "' has no "
                        + "transport type associated with it. Score set to zero");
                return 0;
            }
            TransportInfo transportInfo = sTransports.get(transportTypes[0], /* if dne */ null);
            if (transportInfo != null) {
                return transportInfo.mScore;
            }
            return 0;
        }

        private void start() {
            if (mIpClient != null) {
                if (DBG) Log.d(TAG, "IpClient already started");
                return;
            }
            if (DBG) {
                Log.d(TAG, String.format("starting IpClient(%s): mNetworkInfo=%s", name,
                        mNetworkInfo));
            }

            mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddress);
            mIpClientCallback = new IpClientCallbacksImpl();
            IpClientUtil.makeIpClient(mContext, name, mIpClientCallback);
            mIpClientCallback.awaitIpClientStart();
            if (sTcpBufferSizes == null) {
                sTcpBufferSizes = mContext.getResources().getString(
                        com.android.internal.R.string.config_ethernet_tcp_buffers);
            }
            provisionIpClient(mIpClient, mIpConfig, sTcpBufferSizes);
        }

        void onIpLayerStarted(LinkProperties linkProperties) {
            if (mNetworkAgent != null) {
                Log.e(TAG, "Already have a NetworkAgent - aborting new request");
                stop();
                return;
            }
            mLinkProperties = linkProperties;
            mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, mHwAddress);
            mNetworkInfo.setIsAvailable(true);

            // Create our NetworkAgent.
            mNetworkAgent = new NetworkAgent(mHandler.getLooper(), mContext,
                    NETWORK_TYPE, mNetworkInfo, mCapabilities, mLinkProperties,
                    getNetworkScore()) {
                public void unwanted() {
                    if (this == mNetworkAgent) {
                        stop();
                    } else if (mNetworkAgent != null) {
                        Log.d(TAG, "Ignoring unwanted as we have a more modern " +
                                "instance");
                    }  // Otherwise, we've already called stop.
                }
            };
        }

        void onIpLayerStopped(LinkProperties linkProperties) {
            // This cannot happen due to provisioning timeout, because our timeout is 0. It can only
            // happen if we're provisioned and we lose provisioning.
            stop();
            // If the interface has disappeared provisioning will fail over and over again, so
            // there is no point in starting again
            if (null != InterfaceParams.getByName(name)) {
                start();
            }
        }

        void updateLinkProperties(LinkProperties linkProperties) {
            mLinkProperties = linkProperties;
            if (mNetworkAgent != null) {
                mNetworkAgent.sendLinkProperties(linkProperties);
            }
        }

        /** Returns true if state has been modified */
        boolean updateLinkState(boolean up) {
            if (mLinkUp == up) return false;
            mLinkUp = up;

            stop();
            if (up) {
                start();
            }

            return true;
        }

        void stop() {
            // Invalidate all previous start requests
            if (mIpClient != null) {
                shutdownIpClient(mIpClient);
                mIpClientCallback.awaitIpClientShutdown();
                mIpClient = null;
            }
            mIpClientCallback = null;

            // ConnectivityService will only forget our NetworkAgent if we send it a NetworkInfo object
            // with a state of DISCONNECTED or SUSPENDED. So we can't simply clear our NetworkInfo here:
            // that sets the state to IDLE, and ConnectivityService will still think we're connected.
            //
            mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddress);
            if (mNetworkAgent != null) {
                updateAgent();
                mNetworkAgent = null;
            }
            clear();
        }

        private void updateAgent() {
            if (mNetworkAgent == null) return;
            if (DBG) {
                Log.i(TAG, "Updating mNetworkAgent with: " +
                        mCapabilities + ", " +
                        mNetworkInfo + ", " +
                        mLinkProperties);
            }
            mNetworkAgent.sendNetworkCapabilities(mCapabilities);
            mNetworkAgent.sendNetworkInfo(mNetworkInfo);
            mNetworkAgent.sendLinkProperties(mLinkProperties);

            // As a note, getNetworkScore() is fairly expensive to calculate. This is fine for now
            // since the agent isn't updated frequently. Consider caching the score in the future if
            // agent updating is required more often
            mNetworkAgent.sendNetworkScore(getNetworkScore());
        }

        private void clear() {
            mLinkProperties.clear();
            mNetworkInfo.setDetailedState(DetailedState.IDLE, null, null);
            mNetworkInfo.setIsAvailable(false);
        }

        private static void provisionIpClient(IIpClient ipClient, IpConfiguration config,
                String tcpBufferSizes) {
            if (config.getProxySettings() == ProxySettings.STATIC ||
                    config.getProxySettings() == ProxySettings.PAC) {
                try {
                    ipClient.setHttpProxy(toStableParcelable(config.getHttpProxy()));
                } catch (RemoteException e) {
                    e.rethrowFromSystemServer();
                }
            }

            if (!TextUtils.isEmpty(tcpBufferSizes)) {
                try {
                    ipClient.setTcpBufferSizes(tcpBufferSizes);
                } catch (RemoteException e) {
                    e.rethrowFromSystemServer();
                }
            }

            final ProvisioningConfiguration provisioningConfiguration;
            if (config.getIpAssignment() == IpAssignment.STATIC) {
                provisioningConfiguration = new ProvisioningConfiguration.Builder()
                        .withStaticConfiguration(config.getStaticIpConfiguration())
                        .build();
            } else {
                provisioningConfiguration = new ProvisioningConfiguration.Builder()
                        .withProvisioningTimeoutMs(0)
                        .build();
            }

            try {
                ipClient.startProvisioning(provisioningConfiguration.toStableParcelable());
            } catch (RemoteException e) {
                e.rethrowFromSystemServer();
            }
        }

        @Override
        public String toString() {
            return getClass().getSimpleName() + "{ "
                    + "refCount: " + refCount + ", "
                    + "iface: " + name + ", "
                    + "up: " + mLinkUp + ", "
                    + "hwAddress: " + mHwAddress + ", "
                    + "networkInfo: " + mNetworkInfo + ", "
                    + "networkCapabilities: " + mCapabilities + ", "
                    + "networkAgent: " + mNetworkAgent + ", "
                    + "score: " + getNetworkScore() + ", "
                    + "ipClient: " + mIpClient + ","
                    + "linkProperties: " + mLinkProperties
                    + "}";
        }
    }

    void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) {
        super.dump(fd, pw, args);
        pw.println(getClass().getSimpleName());
        pw.println("Tracking interfaces:");
        pw.increaseIndent();
        for (String iface: mTrackingInterfaces.keySet()) {
            NetworkInterfaceState ifaceState = mTrackingInterfaces.get(iface);
            pw.println(iface + ":" + ifaceState);
            pw.increaseIndent();
            final IIpClient ipClient = ifaceState.mIpClient;
            if (ipClient != null) {
                IpClientUtil.dumpIpClient(ipClient, fd, pw, args);
            } else {
                pw.println("IpClient is null");
            }
            pw.decreaseIndent();
        }
        pw.decreaseIndent();
    }
}
