/*
 * 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) {
            if (this.mIpConfig.equals(ipConfig)) {
                if (DBG) Log.d(TAG, "ipConfig have not changed,so ignore setIpConfig");
                return;
            }
            this.mIpConfig = ipConfig;
            if (mNetworkInfo.getDetailedState() != DetailedState.DISCONNECTED) {
                restart();
            }
        }

        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();
            }
        }

        void restart(){
            if (DBG) Log.d(TAG, "reconnecting Etherent");
            stop();
            start();
        }

        @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();
    }
}
