/*
 * Copyright (C) 2015 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.connectivity;

import static android.system.OsConstants.*;

import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkUtils;
import android.net.RouteInfo;
import android.net.TrafficStats;
import android.net.util.NetworkConstants;
import android.os.SystemClock;
import android.system.ErrnoException;
import android.system.Os;
import android.system.StructTimeval;
import android.text.TextUtils;
import android.util.Pair;

import com.android.internal.util.IndentingPrintWriter;

import libcore.io.IoUtils;

import java.io.Closeable;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * NetworkDiagnostics
 *
 * A simple class to diagnose network connectivity fundamentals.  Current
 * checks performed are:
 *     - ICMPv4/v6 echo requests for all routers
 *     - ICMPv4/v6 echo requests for all DNS servers
 *     - DNS UDP queries to all DNS servers
 *
 * Currently unimplemented checks include:
 *     - report ARP/ND data about on-link neighbors
 *     - DNS TCP queries to all DNS servers
 *     - HTTP DIRECT and PROXY checks
 *     - port 443 blocking/TLS intercept checks
 *     - QUIC reachability checks
 *     - MTU checks
 *
 * The supplied timeout bounds the entire diagnostic process.  Each specific
 * check class must implement this upper bound on measurements in whichever
 * manner is most appropriate and effective.
 *
 * @hide
 */
public class NetworkDiagnostics {
    private static final String TAG = "NetworkDiagnostics";

    private static final InetAddress TEST_DNS4 = NetworkUtils.numericToInetAddress("8.8.8.8");
    private static final InetAddress TEST_DNS6 = NetworkUtils.numericToInetAddress(
            "2001:4860:4860::8888");

    // For brevity elsewhere.
    private static final long now() {
        return SystemClock.elapsedRealtime();
    }

    // Values from RFC 1035 section 4.1.1, names from <arpa/nameser.h>.
    // Should be a member of DnsUdpCheck, but "compiler says no".
    public static enum DnsResponseCode { NOERROR, FORMERR, SERVFAIL, NXDOMAIN, NOTIMP, REFUSED };

    private final Network mNetwork;
    private final LinkProperties mLinkProperties;
    private final Integer mInterfaceIndex;

    private final long mTimeoutMs;
    private final long mStartTime;
    private final long mDeadlineTime;

    // A counter, initialized to the total number of measurements,
    // so callers can wait for completion.
    private final CountDownLatch mCountDownLatch;

    public class Measurement {
        private static final String SUCCEEDED = "SUCCEEDED";
        private static final String FAILED = "FAILED";

        private boolean succeeded;

        // Package private.  TODO: investigate better encapsulation.
        String description = "";
        long startTime;
        long finishTime;
        String result = "";
        Thread thread;

        public boolean checkSucceeded() { return succeeded; }

        void recordSuccess(String msg) {
            maybeFixupTimes();
            succeeded = true;
            result = SUCCEEDED + ": " + msg;
            if (mCountDownLatch != null) {
                mCountDownLatch.countDown();
            }
        }

        void recordFailure(String msg) {
            maybeFixupTimes();
            succeeded = false;
            result = FAILED + ": " + msg;
            if (mCountDownLatch != null) {
                mCountDownLatch.countDown();
            }
        }

        private void maybeFixupTimes() {
            // Allows the caller to just set success/failure and not worry
            // about also setting the correct finishing time.
            if (finishTime == 0) { finishTime = now(); }

            // In cases where, for example, a failure has occurred before the
            // measurement even began, fixup the start time to reflect as much.
            if (startTime == 0) { startTime = finishTime; }
        }

        @Override
        public String toString() {
            return description + ": " + result + " (" + (finishTime - startTime) + "ms)";
        }
    }

    private final Map<InetAddress, Measurement> mIcmpChecks = new HashMap<>();
    private final Map<Pair<InetAddress, InetAddress>, Measurement> mExplicitSourceIcmpChecks =
            new HashMap<>();
    private final Map<InetAddress, Measurement> mDnsUdpChecks = new HashMap<>();
    private final String mDescription;


    public NetworkDiagnostics(Network network, LinkProperties lp, long timeoutMs) {
        mNetwork = network;
        mLinkProperties = lp;
        mInterfaceIndex = getInterfaceIndex(mLinkProperties.getInterfaceName());
        mTimeoutMs = timeoutMs;
        mStartTime = now();
        mDeadlineTime = mStartTime + mTimeoutMs;

        // Hardcode measurements to TEST_DNS4 and TEST_DNS6 in order to test off-link connectivity.
        // We are free to modify mLinkProperties with impunity because ConnectivityService passes us
        // a copy and not the original object. It's easier to do it this way because we don't need
        // to check whether the LinkProperties already contains these DNS servers because
        // LinkProperties#addDnsServer checks for duplicates.
        if (mLinkProperties.isReachable(TEST_DNS4)) {
            mLinkProperties.addDnsServer(TEST_DNS4);
        }
        // TODO: we could use mLinkProperties.isReachable(TEST_DNS6) here, because we won't set any
        // DNS servers for which isReachable() is false, but since this is diagnostic code, be extra
        // careful.
        if (mLinkProperties.hasGlobalIpv6Address() || mLinkProperties.hasIpv6DefaultRoute()) {
            mLinkProperties.addDnsServer(TEST_DNS6);
        }

        for (RouteInfo route : mLinkProperties.getRoutes()) {
            if (route.hasGateway()) {
                InetAddress gateway = route.getGateway();
                prepareIcmpMeasurement(gateway);
                if (route.isIPv6Default()) {
                    prepareExplicitSourceIcmpMeasurements(gateway);
                }
            }
        }
        for (InetAddress nameserver : mLinkProperties.getDnsServers()) {
                prepareIcmpMeasurement(nameserver);
                prepareDnsMeasurement(nameserver);
        }

        mCountDownLatch = new CountDownLatch(totalMeasurementCount());

        startMeasurements();

        mDescription = "ifaces{" + TextUtils.join(",", mLinkProperties.getAllInterfaceNames()) + "}"
                + " index{" + mInterfaceIndex + "}"
                + " network{" + mNetwork + "}"
                + " nethandle{" + mNetwork.getNetworkHandle() + "}";
    }

    private static Integer getInterfaceIndex(String ifname) {
        try {
            NetworkInterface ni = NetworkInterface.getByName(ifname);
            return ni.getIndex();
        } catch (NullPointerException | SocketException e) {
            return null;
        }
    }

    private void prepareIcmpMeasurement(InetAddress target) {
        if (!mIcmpChecks.containsKey(target)) {
            Measurement measurement = new Measurement();
            measurement.thread = new Thread(new IcmpCheck(target, measurement));
            mIcmpChecks.put(target, measurement);
        }
    }

    private void prepareExplicitSourceIcmpMeasurements(InetAddress target) {
        for (LinkAddress l : mLinkProperties.getLinkAddresses()) {
            InetAddress source = l.getAddress();
            if (source instanceof Inet6Address && l.isGlobalPreferred()) {
                Pair<InetAddress, InetAddress> srcTarget = new Pair<>(source, target);
                if (!mExplicitSourceIcmpChecks.containsKey(srcTarget)) {
                    Measurement measurement = new Measurement();
                    measurement.thread = new Thread(new IcmpCheck(source, target, measurement));
                    mExplicitSourceIcmpChecks.put(srcTarget, measurement);
                }
            }
        }
    }

    private void prepareDnsMeasurement(InetAddress target) {
        if (!mDnsUdpChecks.containsKey(target)) {
            Measurement measurement = new Measurement();
            measurement.thread = new Thread(new DnsUdpCheck(target, measurement));
            mDnsUdpChecks.put(target, measurement);
        }
    }

    private int totalMeasurementCount() {
        return mIcmpChecks.size() + mExplicitSourceIcmpChecks.size() + mDnsUdpChecks.size();
    }

    private void startMeasurements() {
        for (Measurement measurement : mIcmpChecks.values()) {
            measurement.thread.start();
        }
        for (Measurement measurement : mExplicitSourceIcmpChecks.values()) {
            measurement.thread.start();
        }
        for (Measurement measurement : mDnsUdpChecks.values()) {
            measurement.thread.start();
        }
    }

    public void waitForMeasurements() {
        try {
            mCountDownLatch.await(mDeadlineTime - now(), TimeUnit.MILLISECONDS);
        } catch (InterruptedException ignored) {}
    }

    public List<Measurement> getMeasurements() {
        // TODO: Consider moving waitForMeasurements() in here to minimize the
        // chance of caller errors.

        ArrayList<Measurement> measurements = new ArrayList(totalMeasurementCount());

        // Sort measurements IPv4 first.
        for (Map.Entry<InetAddress, Measurement> entry : mIcmpChecks.entrySet()) {
            if (entry.getKey() instanceof Inet4Address) {
                measurements.add(entry.getValue());
            }
        }
        for (Map.Entry<Pair<InetAddress, InetAddress>, Measurement> entry :
                mExplicitSourceIcmpChecks.entrySet()) {
            if (entry.getKey().first instanceof Inet4Address) {
                measurements.add(entry.getValue());
            }
        }
        for (Map.Entry<InetAddress, Measurement> entry : mDnsUdpChecks.entrySet()) {
            if (entry.getKey() instanceof Inet4Address) {
                measurements.add(entry.getValue());
            }
        }

        // IPv6 measurements second.
        for (Map.Entry<InetAddress, Measurement> entry : mIcmpChecks.entrySet()) {
            if (entry.getKey() instanceof Inet6Address) {
                measurements.add(entry.getValue());
            }
        }
        for (Map.Entry<Pair<InetAddress, InetAddress>, Measurement> entry :
                mExplicitSourceIcmpChecks.entrySet()) {
            if (entry.getKey().first instanceof Inet6Address) {
                measurements.add(entry.getValue());
            }
        }
        for (Map.Entry<InetAddress, Measurement> entry : mDnsUdpChecks.entrySet()) {
            if (entry.getKey() instanceof Inet6Address) {
                measurements.add(entry.getValue());
            }
        }

        return measurements;
    }

    public void dump(IndentingPrintWriter pw) {
        pw.println(TAG + ":" + mDescription);
        final long unfinished = mCountDownLatch.getCount();
        if (unfinished > 0) {
            // This can't happen unless a caller forgets to call waitForMeasurements()
            // or a measurement isn't implemented to correctly honor the timeout.
            pw.println("WARNING: countdown wait incomplete: "
                    + unfinished + " unfinished measurements");
        }

        pw.increaseIndent();

        String prefix;
        for (Measurement m : getMeasurements()) {
            prefix = m.checkSucceeded() ? "." : "F";
            pw.println(prefix + "  " + m.toString());
        }

        pw.decreaseIndent();
    }


    private class SimpleSocketCheck implements Closeable {
        protected final InetAddress mSource;  // Usually null.
        protected final InetAddress mTarget;
        protected final int mAddressFamily;
        protected final Measurement mMeasurement;
        protected FileDescriptor mFileDescriptor;
        protected SocketAddress mSocketAddress;

        protected SimpleSocketCheck(
                InetAddress source, InetAddress target, Measurement measurement) {
            mMeasurement = measurement;

            if (target instanceof Inet6Address) {
                Inet6Address targetWithScopeId = null;
                if (target.isLinkLocalAddress() && mInterfaceIndex != null) {
                    try {
                        targetWithScopeId = Inet6Address.getByAddress(
                                null, target.getAddress(), mInterfaceIndex);
                    } catch (UnknownHostException e) {
                        mMeasurement.recordFailure(e.toString());
                    }
                }
                mTarget = (targetWithScopeId != null) ? targetWithScopeId : target;
                mAddressFamily = AF_INET6;
            } else {
                mTarget = target;
                mAddressFamily = AF_INET;
            }

            // We don't need to check the scope ID here because we currently only do explicit-source
            // measurements from global IPv6 addresses.
            mSource = source;
        }

        protected SimpleSocketCheck(InetAddress target, Measurement measurement) {
            this(null, target, measurement);
        }

        protected void setupSocket(
                int sockType, int protocol, long writeTimeout, long readTimeout, int dstPort)
                throws ErrnoException, IOException {
            final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_PROBE);
            try {
                mFileDescriptor = Os.socket(mAddressFamily, sockType, protocol);
            } finally {
                TrafficStats.setThreadStatsTag(oldTag);
            }
            // Setting SNDTIMEO is purely for defensive purposes.
            Os.setsockoptTimeval(mFileDescriptor,
                    SOL_SOCKET, SO_SNDTIMEO, StructTimeval.fromMillis(writeTimeout));
            Os.setsockoptTimeval(mFileDescriptor,
                    SOL_SOCKET, SO_RCVTIMEO, StructTimeval.fromMillis(readTimeout));
            // TODO: Use IP_RECVERR/IPV6_RECVERR, pending OsContants availability.
            mNetwork.bindSocket(mFileDescriptor);
            if (mSource != null) {
                Os.bind(mFileDescriptor, mSource, 0);
            }
            Os.connect(mFileDescriptor, mTarget, dstPort);
            mSocketAddress = Os.getsockname(mFileDescriptor);
        }

        protected String getSocketAddressString() {
            // The default toString() implementation is not the prettiest.
            InetSocketAddress inetSockAddr = (InetSocketAddress) mSocketAddress;
            InetAddress localAddr = inetSockAddr.getAddress();
            return String.format(
                    (localAddr instanceof Inet6Address ? "[%s]:%d" : "%s:%d"),
                    localAddr.getHostAddress(), inetSockAddr.getPort());
        }

        @Override
        public void close() {
            IoUtils.closeQuietly(mFileDescriptor);
        }
    }


    private class IcmpCheck extends SimpleSocketCheck implements Runnable {
        private static final int TIMEOUT_SEND = 100;
        private static final int TIMEOUT_RECV = 300;
        private static final int PACKET_BUFSIZE = 512;
        private final int mProtocol;
        private final int mIcmpType;

        public IcmpCheck(InetAddress source, InetAddress target, Measurement measurement) {
            super(source, target, measurement);

            if (mAddressFamily == AF_INET6) {
                mProtocol = IPPROTO_ICMPV6;
                mIcmpType = NetworkConstants.ICMPV6_ECHO_REQUEST_TYPE;
                mMeasurement.description = "ICMPv6";
            } else {
                mProtocol = IPPROTO_ICMP;
                mIcmpType = NetworkConstants.ICMPV4_ECHO_REQUEST_TYPE;
                mMeasurement.description = "ICMPv4";
            }

            mMeasurement.description += " dst{" + mTarget.getHostAddress() + "}";
        }

        public IcmpCheck(InetAddress target, Measurement measurement) {
            this(null, target, measurement);
        }

        @Override
        public void run() {
            // Check if this measurement has already failed during setup.
            if (mMeasurement.finishTime > 0) {
                // If the measurement failed during construction it didn't
                // decrement the countdown latch; do so here.
                mCountDownLatch.countDown();
                return;
            }

            try {
                setupSocket(SOCK_DGRAM, mProtocol, TIMEOUT_SEND, TIMEOUT_RECV, 0);
            } catch (ErrnoException | IOException e) {
                mMeasurement.recordFailure(e.toString());
                return;
            }
            mMeasurement.description += " src{" + getSocketAddressString() + "}";

            // Build a trivial ICMP packet.
            final byte[] icmpPacket = {
                    (byte) mIcmpType, 0, 0, 0, 0, 0, 0, 0  // ICMP header
            };

            int count = 0;
            mMeasurement.startTime = now();
            while (now() < mDeadlineTime - (TIMEOUT_SEND + TIMEOUT_RECV)) {
                count++;
                icmpPacket[icmpPacket.length - 1] = (byte) count;
                try {
                    Os.write(mFileDescriptor, icmpPacket, 0, icmpPacket.length);
                } catch (ErrnoException | InterruptedIOException e) {
                    mMeasurement.recordFailure(e.toString());
                    break;
                }

                try {
                    ByteBuffer reply = ByteBuffer.allocate(PACKET_BUFSIZE);
                    Os.read(mFileDescriptor, reply);
                    // TODO: send a few pings back to back to guesstimate packet loss.
                    mMeasurement.recordSuccess("1/" + count);
                    break;
                } catch (ErrnoException | InterruptedIOException e) {
                    continue;
                }
            }
            if (mMeasurement.finishTime == 0) {
                mMeasurement.recordFailure("0/" + count);
            }

            close();
        }
    }


    private class DnsUdpCheck extends SimpleSocketCheck implements Runnable {
        private static final int TIMEOUT_SEND = 100;
        private static final int TIMEOUT_RECV = 500;
        private static final int RR_TYPE_A = 1;
        private static final int RR_TYPE_AAAA = 28;
        private static final int PACKET_BUFSIZE = 512;

        private final Random mRandom = new Random();

        // Should be static, but the compiler mocks our puny, human attempts at reason.
        private String responseCodeStr(int rcode) {
            try {
                return DnsResponseCode.values()[rcode].toString();
            } catch (IndexOutOfBoundsException e) {
                return String.valueOf(rcode);
            }
        }

        private final int mQueryType;

        public DnsUdpCheck(InetAddress target, Measurement measurement) {
            super(target, measurement);

            // TODO: Ideally, query the target for both types regardless of address family.
            if (mAddressFamily == AF_INET6) {
                mQueryType = RR_TYPE_AAAA;
            } else {
                mQueryType = RR_TYPE_A;
            }

            mMeasurement.description = "DNS UDP dst{" + mTarget.getHostAddress() + "}";
        }

        @Override
        public void run() {
            // Check if this measurement has already failed during setup.
            if (mMeasurement.finishTime > 0) {
                // If the measurement failed during construction it didn't
                // decrement the countdown latch; do so here.
                mCountDownLatch.countDown();
                return;
            }

            try {
                setupSocket(SOCK_DGRAM, IPPROTO_UDP, TIMEOUT_SEND, TIMEOUT_RECV,
                        NetworkConstants.DNS_SERVER_PORT);
            } catch (ErrnoException | IOException e) {
                mMeasurement.recordFailure(e.toString());
                return;
            }
            mMeasurement.description += " src{" + getSocketAddressString() + "}";

            // This needs to be fixed length so it can be dropped into the pre-canned packet.
            final String sixRandomDigits = String.valueOf(mRandom.nextInt(900000) + 100000);
            mMeasurement.description += " qtype{" + mQueryType + "}"
                    + " qname{" + sixRandomDigits + "-android-ds.metric.gstatic.com}";

            // Build a trivial DNS packet.
            final byte[] dnsPacket = getDnsQueryPacket(sixRandomDigits);

            int count = 0;
            mMeasurement.startTime = now();
            while (now() < mDeadlineTime - (TIMEOUT_RECV + TIMEOUT_RECV)) {
                count++;
                try {
                    Os.write(mFileDescriptor, dnsPacket, 0, dnsPacket.length);
                } catch (ErrnoException | InterruptedIOException e) {
                    mMeasurement.recordFailure(e.toString());
                    break;
                }

                try {
                    ByteBuffer reply = ByteBuffer.allocate(PACKET_BUFSIZE);
                    Os.read(mFileDescriptor, reply);
                    // TODO: more correct and detailed evaluation of the response,
                    // possibly adding the returned IP address(es) to the output.
                    final String rcodeStr = (reply.limit() > 3)
                            ? " " + responseCodeStr((int) (reply.get(3)) & 0x0f)
                            : "";
                    mMeasurement.recordSuccess("1/" + count + rcodeStr);
                    break;
                } catch (ErrnoException | InterruptedIOException e) {
                    continue;
                }
            }
            if (mMeasurement.finishTime == 0) {
                mMeasurement.recordFailure("0/" + count);
            }

            close();
        }

        private byte[] getDnsQueryPacket(String sixRandomDigits) {
            byte[] rnd = sixRandomDigits.getBytes(StandardCharsets.US_ASCII);
            return new byte[] {
                (byte) mRandom.nextInt(), (byte) mRandom.nextInt(),  // [0-1]   query ID
                1, 0,  // [2-3]   flags; byte[2] = 1 for recursion desired (RD).
                0, 1,  // [4-5]   QDCOUNT (number of queries)
                0, 0,  // [6-7]   ANCOUNT (number of answers)
                0, 0,  // [8-9]   NSCOUNT (number of name server records)
                0, 0,  // [10-11] ARCOUNT (number of additional records)
                17, rnd[0], rnd[1], rnd[2], rnd[3], rnd[4], rnd[5],
                        '-', 'a', 'n', 'd', 'r', 'o', 'i', 'd', '-', 'd', 's',
                6, 'm', 'e', 't', 'r', 'i', 'c',
                7, 'g', 's', 't', 'a', 't', 'i', 'c',
                3, 'c', 'o', 'm',
                0,  // null terminator of FQDN (root TLD)
                0, (byte) mQueryType,  // QTYPE
                0, 1  // QCLASS, set to 1 = IN (Internet)
            };
        }
    }
}
