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

import static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.ANQP3GPPNetwork;
import static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.ANQPDomName;
import static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.ANQPIPAddrAvailability;
import static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.ANQPNAIRealm;
import static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.ANQPRoamingConsortium;
import static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.ANQPVenueName;
import static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.ANQPVenueUrl;
import static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.HSConnCapability;
import static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.HSFriendlyName;
import static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.HSOSUProviders;
import static com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType.HSWANMetrics;

import android.annotation.NonNull;
import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback;
import android.net.wifi.SecurityParams;
import android.net.wifi.SupplicantState;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiSsid;
import android.util.Log;

import com.android.server.wifi.hotspot2.AnqpEvent;
import com.android.server.wifi.hotspot2.IconEvent;
import com.android.server.wifi.hotspot2.WnmData;
import com.android.server.wifi.hotspot2.anqp.ANQPElement;
import com.android.server.wifi.hotspot2.anqp.ANQPParser;
import com.android.server.wifi.hotspot2.anqp.Constants;
import com.android.server.wifi.util.NativeUtil;

import java.io.IOException;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

abstract class SupplicantStaIfaceCallbackImpl extends ISupplicantStaIfaceCallback.Stub {
    private static final String TAG = SupplicantStaIfaceCallbackImpl.class.getSimpleName();
    private final SupplicantStaIfaceHal mStaIfaceHal;
    private final String mIfaceName;
    private final Object mLock;
    private final WifiMonitor mWifiMonitor;
    // Used to help check for PSK password mismatch & EAP connection failure.
    private int mStateBeforeDisconnect = State.INACTIVE;
    private String mCurrentSsid = null;

    SupplicantStaIfaceCallbackImpl(@NonNull SupplicantStaIfaceHal staIfaceHal,
            @NonNull String ifaceName,
            @NonNull Object lock,
            @NonNull WifiMonitor wifiMonitor) {
        mStaIfaceHal = staIfaceHal;
        mIfaceName = ifaceName;
        mLock = lock;
        mWifiMonitor = wifiMonitor;
    }

    /**
     * Converts the supplicant state received from HIDL to the equivalent framework state.
     */
    protected static SupplicantState supplicantHidlStateToFrameworkState(int state) {
        switch (state) {
            case ISupplicantStaIfaceCallback.State.DISCONNECTED:
                return SupplicantState.DISCONNECTED;
            case ISupplicantStaIfaceCallback.State.IFACE_DISABLED:
                return SupplicantState.INTERFACE_DISABLED;
            case ISupplicantStaIfaceCallback.State.INACTIVE:
                return SupplicantState.INACTIVE;
            case ISupplicantStaIfaceCallback.State.SCANNING:
                return SupplicantState.SCANNING;
            case ISupplicantStaIfaceCallback.State.AUTHENTICATING:
                return SupplicantState.AUTHENTICATING;
            case ISupplicantStaIfaceCallback.State.ASSOCIATING:
                return SupplicantState.ASSOCIATING;
            case ISupplicantStaIfaceCallback.State.ASSOCIATED:
                return SupplicantState.ASSOCIATED;
            case ISupplicantStaIfaceCallback.State.FOURWAY_HANDSHAKE:
                return SupplicantState.FOUR_WAY_HANDSHAKE;
            case ISupplicantStaIfaceCallback.State.GROUP_HANDSHAKE:
                return SupplicantState.GROUP_HANDSHAKE;
            case ISupplicantStaIfaceCallback.State.COMPLETED:
                return SupplicantState.COMPLETED;
            default:
                throw new IllegalArgumentException("Invalid state: " + state);
        }
    }


    /**
     * Parses the provided payload into an ANQP element.
     *
     * @param infoID  Element type.
     * @param payload Raw payload bytes.
     * @return AnqpElement instance on success, null on failure.
     */
    private ANQPElement parseAnqpElement(Constants.ANQPElementType infoID,
                                         ArrayList<Byte> payload) {
        synchronized (mLock) {
            try {
                return Constants.getANQPElementID(infoID) != null
                        ? ANQPParser.parseElement(
                        infoID, ByteBuffer.wrap(NativeUtil.byteArrayFromArrayList(payload)))
                        : ANQPParser.parseHS20Element(
                        infoID, ByteBuffer.wrap(NativeUtil.byteArrayFromArrayList(payload)));
            } catch (IOException | BufferUnderflowException e) {
                Log.e(TAG, "Failed parsing ANQP element payload: " + infoID, e);
                return null;
            }
        }
    }

    /**
     * Parse the ANQP element data and add to the provided elements map if successful.
     *
     * @param elementsMap Map to add the parsed out element to.
     * @param infoID  Element type.
     * @param payload Raw payload bytes.
     */
    private void addAnqpElementToMap(Map<Constants.ANQPElementType, ANQPElement> elementsMap,
                                     Constants.ANQPElementType infoID,
                                     ArrayList<Byte> payload) {
        synchronized (mLock) {
            if (payload == null || payload.isEmpty()) return;
            ANQPElement element = parseAnqpElement(infoID, payload);
            if (element != null) {
                elementsMap.put(infoID, element);
            }
        }
    }

    @Override
    public void onNetworkAdded(int id) {
        synchronized (mLock) {
            mStaIfaceHal.logCallback("onNetworkAdded id=" + id);
        }
    }

    @Override
    public void onNetworkRemoved(int id) {
        synchronized (mLock) {
            mStaIfaceHal.logCallback("onNetworkRemoved id=" + id);
            // Reset state since network has been removed.
            mStateBeforeDisconnect = State.INACTIVE;
        }
    }

    /**
     * Added to plumb the new {@code filsHlpSent} param from the V1.3 callback version.
     */
    public void onStateChanged(int newState, byte[/* 6 */] bssid, int id, ArrayList<Byte> ssid,
            boolean filsHlpSent) {
        synchronized (mLock) {
            mStaIfaceHal.logCallback("onStateChanged");
            SupplicantState newSupplicantState =
                    supplicantHidlStateToFrameworkState(newState);
            WifiSsid wifiSsid =
                    WifiSsid.createFromByteArray(NativeUtil.byteArrayFromArrayList(ssid));
            String bssidStr = NativeUtil.macAddressFromByteArray(bssid);
            if (newState != State.DISCONNECTED) {
                // onStateChanged(DISCONNECTED) may come before onDisconnected(), so add this
                // cache to track the state before the disconnect.
                mStateBeforeDisconnect = newState;
            }

            if (newState == State.ASSOCIATING || newState == State.ASSOCIATED
                    || newState == State.COMPLETED) {
                mStaIfaceHal.updateOnLinkedNetworkRoaming(mIfaceName, id);
            }

            if (newState == State.COMPLETED) {
                mWifiMonitor.broadcastNetworkConnectionEvent(
                        mIfaceName, mStaIfaceHal.getCurrentNetworkId(mIfaceName), filsHlpSent,
                        wifiSsid, bssidStr);
            } else if (newState == State.ASSOCIATING) {
                mCurrentSsid = NativeUtil.encodeSsid(ssid);
            }
            mWifiMonitor.broadcastSupplicantStateChangeEvent(
                    mIfaceName, mStaIfaceHal.getCurrentNetworkId(mIfaceName), wifiSsid,
                    bssidStr, newSupplicantState);
        }
    }

    @Override
    public void onStateChanged(int newState, byte[/* 6 */] bssid, int id, ArrayList<Byte> ssid) {
        onStateChanged(newState, bssid, id, ssid, false);
    }

    public void onAnqpQueryDone(byte[/* 6 */] bssid,
            ISupplicantStaIfaceCallback.AnqpData data,
            ISupplicantStaIfaceCallback.Hs20AnqpData hs20Data,
            android.hardware.wifi.supplicant.V1_4.ISupplicantStaIfaceCallback.AnqpData dataV14) {
        Map<Constants.ANQPElementType, ANQPElement> elementsMap = new HashMap<>();
        addAnqpElementToMap(elementsMap, ANQPVenueName, data.venueName);
        addAnqpElementToMap(elementsMap, ANQPRoamingConsortium, data.roamingConsortium);
        addAnqpElementToMap(
                elementsMap, ANQPIPAddrAvailability, data.ipAddrTypeAvailability);
        addAnqpElementToMap(elementsMap, ANQPNAIRealm, data.naiRealm);
        addAnqpElementToMap(elementsMap, ANQP3GPPNetwork, data.anqp3gppCellularNetwork);
        addAnqpElementToMap(elementsMap, ANQPDomName, data.domainName);
        if (dataV14 != null) {
            addAnqpElementToMap(elementsMap, ANQPVenueUrl, dataV14.venueUrl);
        }
        addAnqpElementToMap(elementsMap, HSFriendlyName, hs20Data.operatorFriendlyName);
        addAnqpElementToMap(elementsMap, HSWANMetrics, hs20Data.wanMetrics);
        addAnqpElementToMap(elementsMap, HSConnCapability, hs20Data.connectionCapability);
        addAnqpElementToMap(elementsMap, HSOSUProviders, hs20Data.osuProvidersList);
        mWifiMonitor.broadcastAnqpDoneEvent(
                mIfaceName, new AnqpEvent(NativeUtil.macAddressToLong(bssid), elementsMap));
    }
    @Override
    public void onAnqpQueryDone(byte[/* 6 */] bssid,
                                ISupplicantStaIfaceCallback.AnqpData data,
                                ISupplicantStaIfaceCallback.Hs20AnqpData hs20Data) {
        synchronized (mLock) {
            mStaIfaceHal.logCallback("onAnqpQueryDone");
            onAnqpQueryDone(bssid, data, hs20Data, null /* v1.4 element */);
        }
    }

    @Override
    public void onHs20IconQueryDone(byte[/* 6 */] bssid, String fileName,
                                    ArrayList<Byte> data) {
        synchronized (mLock) {
            mStaIfaceHal.logCallback("onHs20IconQueryDone");
            mWifiMonitor.broadcastIconDoneEvent(
                    mIfaceName,
                    new IconEvent(NativeUtil.macAddressToLong(bssid), fileName, data.size(),
                            NativeUtil.byteArrayFromArrayList(data)));
        }
    }

    @Override
    public void onHs20SubscriptionRemediation(byte[/* 6 */] bssid, byte osuMethod, String url) {
        synchronized (mLock) {
            mStaIfaceHal.logCallback("onHs20SubscriptionRemediation");
            mWifiMonitor.broadcastWnmEvent(
                    mIfaceName,
                    WnmData.createRemediationEvent(NativeUtil.macAddressToLong(bssid), url,
                            osuMethod));
        }
    }

    @Override
    public void onHs20DeauthImminentNotice(byte[/* 6 */] bssid, int reasonCode,
                                           int reAuthDelayInSec, String url) {
        synchronized (mLock) {
            mStaIfaceHal.logCallback("onHs20DeauthImminentNotice");
            mWifiMonitor.broadcastWnmEvent(
                    mIfaceName,
                    WnmData.createDeauthImminentEvent(NativeUtil.macAddressToLong(bssid), url,
                            reasonCode == WnmData.ESS, reAuthDelayInSec));
        }
    }

    @Override
    public void onDisconnected(byte[/* 6 */] bssid, boolean locallyGenerated, int reasonCode) {
        synchronized (mLock) {
            mStaIfaceHal.logCallback("onDisconnected");
            if (mStaIfaceHal.isVerboseLoggingEnabled()) {
                Log.e(TAG, "onDisconnected state=" + mStateBeforeDisconnect
                        + " locallyGenerated=" + locallyGenerated
                        + " reasonCode=" + reasonCode);
            }
            WifiConfiguration curConfiguration =
                    mStaIfaceHal.getCurrentNetworkLocalConfig(mIfaceName);
            if (curConfiguration != null) {
                if (mStateBeforeDisconnect == State.FOURWAY_HANDSHAKE
                        && WifiConfigurationUtil.isConfigForPskNetwork(curConfiguration)
                        && (!locallyGenerated || reasonCode != ReasonCode.IE_IN_4WAY_DIFFERS)) {
                    mWifiMonitor.broadcastAuthenticationFailureEvent(
                            mIfaceName, WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD, -1);
                } else if (mStateBeforeDisconnect == State.ASSOCIATED
                        && WifiConfigurationUtil.isConfigForEapNetwork(curConfiguration)) {
                    mWifiMonitor.broadcastAuthenticationFailureEvent(
                            mIfaceName, WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE, -1);
                }
            }
            mWifiMonitor.broadcastNetworkDisconnectionEvent(
                    mIfaceName, locallyGenerated, reasonCode, mCurrentSsid,
                    NativeUtil.macAddressFromByteArray(bssid));
        }
    }

    private void handleAssocRejectEvent(AssocRejectEventInfo assocRejectInfo) {
        boolean isWrongPwd = false;
        WifiConfiguration curConfiguration =
                mStaIfaceHal.getCurrentNetworkLocalConfig(mIfaceName);
        if (curConfiguration != null) {
            if (!assocRejectInfo.timedOut) {
                Log.d(TAG, "flush PMK cache due to association rejection for config id "
                        + curConfiguration.networkId + ".");
                mStaIfaceHal.removePmkCacheEntry(curConfiguration.networkId);
            }
            // Special handling for WPA3-Personal networks. If the password is
            // incorrect, the AP will send association rejection, with status code 1
            // (unspecified failure). In SAE networks, the password authentication
            // is not related to the 4-way handshake. In this case, we will send an
            // authentication failure event up.
            if (assocRejectInfo.statusCode == StatusCode.UNSPECIFIED_FAILURE) {
                // Network Selection status is guaranteed to be initialized
                SecurityParams params = curConfiguration.getNetworkSelectionStatus()
                        .getCandidateSecurityParams();
                if (params != null
                        && params.getSecurityType() == WifiConfiguration.SECURITY_TYPE_SAE) {
                    mStaIfaceHal.logCallback("SAE incorrect password");
                    isWrongPwd = true;
                }
            } else if (assocRejectInfo.statusCode == StatusCode.CHALLENGE_FAIL
                    && WifiConfigurationUtil.isConfigForWepNetwork(curConfiguration)) {
                mStaIfaceHal.logCallback("WEP incorrect password");
                isWrongPwd = true;
            }
        }

        if (isWrongPwd) {
            mWifiMonitor.broadcastAuthenticationFailureEvent(
                    mIfaceName, WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD, -1);
        }
        mWifiMonitor.broadcastAssociationRejectionEvent(mIfaceName, assocRejectInfo);
        mStateBeforeDisconnect = State.INACTIVE;
    }

    public void onAssociationRejected(android.hardware.wifi.supplicant.V1_4
            .ISupplicantStaIfaceCallback.AssociationRejectionData assocRejectData) {
        AssocRejectEventInfo assocRejectInfo = new AssocRejectEventInfo(assocRejectData);
        handleAssocRejectEvent(assocRejectInfo);
    }

    @Override
    public void onAssociationRejected(byte[/* 6 */] bssid, int statusCode, boolean timedOut) {
        synchronized (mLock) {
            AssocRejectEventInfo assocRejectInfo = new AssocRejectEventInfo(
                    mCurrentSsid,
                    NativeUtil.macAddressFromByteArray(bssid),
                    statusCode, timedOut);
            handleAssocRejectEvent(assocRejectInfo);
        }
    }

    @Override
    public void onAuthenticationTimeout(byte[/* 6 */] bssid) {
        synchronized (mLock) {
            mStaIfaceHal.logCallback("onAuthenticationTimeout");
            mWifiMonitor.broadcastAuthenticationFailureEvent(
                    mIfaceName, WifiManager.ERROR_AUTH_FAILURE_TIMEOUT, -1);
            mStateBeforeDisconnect = State.INACTIVE;
        }
    }

    @Override
    public void onBssidChanged(byte reason, byte[/* 6 */] bssid) {
        synchronized (mLock) {
            mStaIfaceHal.logCallback("onBssidChanged");
            if (reason == BssidChangeReason.ASSOC_START) {
                mWifiMonitor.broadcastTargetBssidEvent(
                        mIfaceName, NativeUtil.macAddressFromByteArray(bssid));
            } else if (reason == BssidChangeReason.ASSOC_COMPLETE) {
                mWifiMonitor.broadcastAssociatedBssidEvent(
                        mIfaceName, NativeUtil.macAddressFromByteArray(bssid));
            }
        }
    }

    public void onEapFailure(int errorCode) {
        synchronized (mLock) {
            mStaIfaceHal.logCallback("onEapFailure");
            mWifiMonitor.broadcastAuthenticationFailureEvent(
                    mIfaceName, WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE, errorCode);
            mStateBeforeDisconnect = State.INACTIVE;
        }
    }


    @Override
    public void onEapFailure() {
        onEapFailure(-1);
    }

    @Override
    public void onWpsEventSuccess() {
        mStaIfaceHal.logCallback("onWpsEventSuccess");
        synchronized (mLock) {
            mWifiMonitor.broadcastWpsSuccessEvent(mIfaceName);
        }
    }

    @Override
    public void onWpsEventFail(byte[/* 6 */] bssid, short configError, short errorInd) {
        synchronized (mLock) {
            mStaIfaceHal.logCallback("onWpsEventFail");
            if (configError == WpsConfigError.MSG_TIMEOUT
                    && errorInd == WpsErrorIndication.NO_ERROR) {
                mWifiMonitor.broadcastWpsTimeoutEvent(mIfaceName);
            } else {
                mWifiMonitor.broadcastWpsFailEvent(mIfaceName, configError, errorInd);
            }
        }
    }

    @Override
    public void onWpsEventPbcOverlap() {
        synchronized (mLock) {
            mStaIfaceHal.logCallback("onWpsEventPbcOverlap");
            mWifiMonitor.broadcastWpsOverlapEvent(mIfaceName);
        }
    }

    @Override
    public void onExtRadioWorkStart(int id) {
        synchronized (mLock) {
            mStaIfaceHal.logCallback("onExtRadioWorkStart");
        }
    }

    @Override
    public void onExtRadioWorkTimeout(int id) {
        synchronized (mLock) {
            mStaIfaceHal.logCallback("onExtRadioWorkTimeout");
        }
    }
}
