/*
 * Copyright (C) 2017 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 android.net.wifi.aware;

import static android.net.wifi.aware.WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR;

import android.annotation.IntRange;
import android.annotation.NonNull;
import android.net.NetworkSpecifier;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;

import java.util.Arrays;
import java.util.Objects;

/**
 * Network specifier object used to request a Wi-Fi Aware network. Apps should use the
 * {@link WifiAwareNetworkSpecifier.Builder} class to create an instance.
 */
public final class WifiAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable {
    /**
     * TYPE: in band, specific peer: role, client_id, session_id, peer_id, pmk/passphrase optional
     * @hide
     */
    public static final int NETWORK_SPECIFIER_TYPE_IB = 0;

    /**
     * TYPE: in band, any peer: role, client_id, session_id, pmk/passphrase optional
     * [only permitted for RESPONDER]
     * @hide
     */
    public static final int NETWORK_SPECIFIER_TYPE_IB_ANY_PEER = 1;

    /**
     * TYPE: out-of-band: role, client_id, peer_mac, pmk/passphrase optional
     * @hide
     */
    public static final int NETWORK_SPECIFIER_TYPE_OOB = 2;

    /**
     * TYPE: out-of-band, any peer: role, client_id, pmk/passphrase optional
     * [only permitted for RESPONDER]
     * @hide
     */
    public static final int NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER = 3;

    /** @hide */
    public static final int NETWORK_SPECIFIER_TYPE_MAX_VALID = NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER;

    /**
     * One of the NETWORK_SPECIFIER_TYPE_* constants. The type of the network specifier object.
     * @hide
     */
    public final int type;

    /**
     * The role of the device: WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR or
     * WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER.
     * @hide
     */
    public final int role;

    /**
     * The client ID of the device.
     * @hide
     */
    public final int clientId;

    /**
     * The session ID in which context to request a data-path. Only relevant for IB requests.
     * @hide
     */
    public final int sessionId;

    /**
     * The peer ID of the device which the data-path should be connected to. Only relevant for
     * IB requests (i.e. not IB_ANY_PEER or OOB*).
     * @hide
     */
    public final int peerId;

    /**
     * The peer MAC address of the device which the data-path should be connected to. Only relevant
     * for OB requests (i.e. not OOB_ANY_PEER or IB*).
     * @hide
     */
    public final byte[] peerMac;

    /**
     * The PMK of the requested data-path. Can be null. Only one or none of pmk or passphrase should
     * be specified.
     * @hide
     */
    public final byte[] pmk;

    /**
     * The Passphrase of the requested data-path. Can be null. Only one or none of the pmk or
     * passphrase should be specified.
     * @hide
     */
    public final String passphrase;

    /**
     * The port information to be used for this link. This information will be communicated to the
     * peer as part of the layer 2 link setup.
     *
     * Information only allowed on secure links since a single layer-2 link is set up for all
     * requestors. Therefore if multiple apps on a single device request links to the same peer
     * device they all get the same link. However, the link is only set up on the first request -
     * hence only the first can transmit the port information. But we don't want to expose that
     * information to other apps. Limiting to secure links would (usually) imply single app usage.
     *
     * @hide
     */
    public final int port;

    /**
     * The transport protocol information to be used for this link. This information will be
     * communicated to the peer as part of the layer 2 link setup.
     *
     * Information only allowed on secure links since a single layer-2 link is set up for all
     * requestors. Therefore if multiple apps on a single device request links to the same peer
     * device they all get the same link. However, the link is only set up on the first request -
     * hence only the first can transmit the port information. But we don't want to expose that
     * information to other apps. Limiting to secure links would (usually) imply single app usage.
     *
     * @hide
     */
    public final int transportProtocol;

    /** @hide */
    public WifiAwareNetworkSpecifier(int type, int role, int clientId, int sessionId, int peerId,
            byte[] peerMac, byte[] pmk, String passphrase, int port, int transportProtocol) {
        this.type = type;
        this.role = role;
        this.clientId = clientId;
        this.sessionId = sessionId;
        this.peerId = peerId;
        this.peerMac = peerMac;
        this.pmk = pmk;
        this.passphrase = passphrase;
        this.port = port;
        this.transportProtocol = transportProtocol;
    }

    public static final @android.annotation.NonNull Creator<WifiAwareNetworkSpecifier> CREATOR =
            new Creator<WifiAwareNetworkSpecifier>() {
                @Override
                public WifiAwareNetworkSpecifier createFromParcel(Parcel in) {
                    return new WifiAwareNetworkSpecifier(
                        in.readInt(), // type
                        in.readInt(), // role
                        in.readInt(), // clientId
                        in.readInt(), // sessionId
                        in.readInt(), // peerId
                        in.createByteArray(), // peerMac
                        in.createByteArray(), // pmk
                        in.readString(), // passphrase
                        in.readInt(), // port
                        in.readInt()); // transportProtocol
                }

                @Override
                public WifiAwareNetworkSpecifier[] newArray(int size) {
                    return new WifiAwareNetworkSpecifier[size];
                }
            };

    /**
     * Indicates whether the network specifier specifies an OOB (out-of-band) data-path - i.e. a
     * data-path created without a corresponding Aware discovery session.
     *
     * @hide
     */
    public boolean isOutOfBand() {
        return type == NETWORK_SPECIFIER_TYPE_OOB || type == NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(type);
        dest.writeInt(role);
        dest.writeInt(clientId);
        dest.writeInt(sessionId);
        dest.writeInt(peerId);
        dest.writeByteArray(peerMac);
        dest.writeByteArray(pmk);
        dest.writeString(passphrase);
        dest.writeInt(port);
        dest.writeInt(transportProtocol);
    }

    /** @hide */
    @Override
    public boolean canBeSatisfiedBy(NetworkSpecifier other) {
        // MatchAllNetworkSpecifier is taken care in NetworkCapabilities#satisfiedBySpecifier.
        if (other instanceof WifiAwareAgentNetworkSpecifier) {
            return ((WifiAwareAgentNetworkSpecifier) other).satisfiesAwareNetworkSpecifier(this);
        }
        return equals(other);
    }

    /** @hide */
    @Override
    public int hashCode() {
        return Objects.hash(type, role, clientId, sessionId, peerId, Arrays.hashCode(peerMac),
                Arrays.hashCode(pmk), passphrase, port, transportProtocol);
    }

    /** @hide */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }

        if (!(obj instanceof WifiAwareNetworkSpecifier)) {
            return false;
        }

        WifiAwareNetworkSpecifier lhs = (WifiAwareNetworkSpecifier) obj;

        return type == lhs.type
                && role == lhs.role
                && clientId == lhs.clientId
                && sessionId == lhs.sessionId
                && peerId == lhs.peerId
                && Arrays.equals(peerMac, lhs.peerMac)
                && Arrays.equals(pmk, lhs.pmk)
                && Objects.equals(passphrase, lhs.passphrase)
                && port == lhs.port
                && transportProtocol == lhs.transportProtocol;
    }

    /** @hide */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("WifiAwareNetworkSpecifier [");
        sb.append("type=").append(type)
                .append(", role=").append(role)
                .append(", clientId=").append(clientId)
                .append(", sessionId=").append(sessionId)
                .append(", peerId=").append(peerId)
                // masking potential PII (although low impact information)
                .append(", peerMac=").append((peerMac == null) ? "<null>" : "<non-null>")
                // masking PII
                .append(", pmk=").append((pmk == null) ? "<null>" : "<non-null>")
                // masking PII
                .append(", passphrase=").append((passphrase == null) ? "<null>" : "<non-null>")
                .append(", port=").append(port).append(", transportProtocol=")
                .append(transportProtocol)
                .append("]");
        return sb.toString();
    }

    /**
     * A builder class for a Wi-Fi Aware network specifier to set up an Aware connection with a
     * peer.
     */
    public static final class Builder {
        private DiscoverySession mDiscoverySession;
        private PeerHandle mPeerHandle;
        private String mPskPassphrase;
        private byte[] mPmk;
        private int mPort = 0; // invalid value
        private int mTransportProtocol = -1; // invalid value

        /**
         * Create a builder for {@link WifiAwareNetworkSpecifier} used in requests to set up a
         * Wi-Fi Aware connection with a peer.
         *
         * @param discoverySession A Wi-Fi Aware discovery session in whose context the connection
         *                         is created.
         * @param peerHandle The handle of the peer to which the Wi-Fi Aware connection is
         *                   requested. The peer is discovered through Wi-Fi Aware discovery. The
         *                   handle can be obtained through
         * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, byte[], java.util.List)}
         *                   or
         *                   {@link DiscoverySessionCallback#onMessageReceived(PeerHandle, byte[])}.
         */
        public Builder(@NonNull DiscoverySession discoverySession, @NonNull PeerHandle peerHandle) {
            if (discoverySession == null) {
                throw new IllegalArgumentException("Non-null discoverySession required");
            }
            if (peerHandle == null) {
                throw new IllegalArgumentException("Non-null peerHandle required");
            }
            mDiscoverySession = discoverySession;
            mPeerHandle = peerHandle;
        }

        /**
         * Configure the PSK Passphrase for the Wi-Fi Aware connection being requested. This method
         * is optional - if not called, then an Open (unencrypted) connection will be created.
         *
         * @param pskPassphrase The (optional) passphrase to be used to encrypt the link. Use the
         *                      {@link #setPmk(byte[])} to specify a PMK.
         * @return the current {@link Builder} builder, enabling chaining of builder
         *         methods.
         */
        public @NonNull Builder setPskPassphrase(@NonNull String pskPassphrase) {
            if (!WifiAwareUtils.validatePassphrase(pskPassphrase)) {
                throw new IllegalArgumentException("Passphrase must meet length requirements");
            }
            mPskPassphrase = pskPassphrase;
            return this;
        }

        /**
         * Configure the PMK for the Wi-Fi Aware connection being requested. This method
         * is optional - if not called, then an Open (unencrypted) connection will be created.
         *
         * @param pmk A PMK (pairwise master key, see IEEE 802.11i) specifying the key to use for
         *            encrypting the data-path. Use the {@link #setPskPassphrase(String)} to
         *            specify a Passphrase.
         * @return the current {@link Builder} builder, enabling chaining of builder
         *         methods.
         */
        public @NonNull Builder setPmk(@NonNull byte[] pmk) {
            if (!WifiAwareUtils.validatePmk(pmk)) {
                throw new IllegalArgumentException("PMK must 32 bytes");
            }
            mPmk = pmk;
            return this;
        }

        /**
         * Configure the port number which will be used to create a connection over this link. This
         * configuration should only be done on the server device, e.g. the device creating the
         * {@link java.net.ServerSocket}.
         * <p>Notes:
         * <ul>
         *     <li>The server device must be the Publisher device!
         *     <li>The port information can only be specified on secure links, specified using
         *     {@link #setPskPassphrase(String)} or {@link #setPmk(byte[])}.
         * </ul>
         *
         * @param port A positive integer indicating the port to be used for communication.
         * @return the current {@link Builder} builder, enabling chaining of builder
         *         methods.
         */
        public @NonNull Builder setPort(@IntRange(from = 0, to = 65535) int port) {
            if (port <= 0 || port > 65535) {
                throw new IllegalArgumentException("The port must be a positive value (0, 65535]");
            }
            mPort = port;
            return this;
        }

        /**
         * Configure the transport protocol which will be used to create a connection over this
         * link. This configuration should only be done on the server device, e.g. the device
         * creating the {@link java.net.ServerSocket} for TCP.
         * <p>Notes:
         * <ul>
         *     <li>The server device must be the Publisher device!
         *     <li>The transport protocol information can only be specified on secure links,
         *     specified using {@link #setPskPassphrase(String)} or {@link #setPmk(byte[])}.
         * </ul>
         * The transport protocol number is assigned by the Internet Assigned Numbers Authority
         * (IANA) https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml.
         *
         * @param transportProtocol The transport protocol to be used for communication.
         * @return the current {@link Builder} builder, enabling chaining of builder
         *         methods.
         */
        public @NonNull
                Builder setTransportProtocol(@IntRange(from = 0, to = 255) int transportProtocol) {
            if (transportProtocol < 0 || transportProtocol > 255) {
                throw new IllegalArgumentException(
                        "The transport protocol must be in range [0, 255]");
            }
            mTransportProtocol = transportProtocol;
            return this;
        }

        /**
         * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)}
         * for a WiFi Aware connection (link) to the specified peer. The
         * {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
         * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
         * <p> The default builder constructor will initialize a NetworkSpecifier which requests an
         * open (non-encrypted) link. To request an encrypted link use the
         * {@link #setPskPassphrase(String)} or {@link #setPmk(byte[])} builder methods.
         *
         * @return A {@link NetworkSpecifier} to be used to construct
         * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} to pass
         * to {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
         * android.net.ConnectivityManager.NetworkCallback)}
         * [or other varieties of that API].
         */
        public @NonNull WifiAwareNetworkSpecifier build() {
            if (mDiscoverySession == null) {
                throw new IllegalStateException("Null discovery session!?");
            }
            if (mPeerHandle == null) {
                throw new IllegalStateException("Null peerHandle!?");
            }
            if (mPskPassphrase != null & mPmk != null) {
                throw new IllegalStateException(
                        "Can only specify a Passphrase or a PMK - not both!");
            }

            int role = mDiscoverySession instanceof SubscribeDiscoverySession
                    ? WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
                    : WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER;

            if (mPort != 0 || mTransportProtocol != -1) {
                if (role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) {
                    throw new IllegalStateException(
                            "Port and transport protocol information can only "
                                    + "be specified on the Publisher device (which is the server");
                }
                if (TextUtils.isEmpty(mPskPassphrase) && mPmk == null) {
                    throw new IllegalStateException("Port and transport protocol information can "
                            + "only be specified on a secure link");
                }
            }

            return new WifiAwareNetworkSpecifier(
                    WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB, role,
                    mDiscoverySession.mClientId, mDiscoverySession.mSessionId, mPeerHandle.peerId,
                    null, mPmk, mPskPassphrase, mPort, mTransportProtocol);
        }
    }
}
