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

import android.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.os.ParcelUuid;
import android.util.Log;

import java.io.Closeable;
import java.io.IOException;

/**
 * A listening Bluetooth socket.
 *
 * <p>The interface for Bluetooth Sockets is similar to that of TCP sockets:
 * {@link java.net.Socket} and {@link java.net.ServerSocket}. On the server
 * side, use a {@link BluetoothServerSocket} to create a listening server
 * socket. When a connection is accepted by the {@link BluetoothServerSocket},
 * it will return a new {@link BluetoothSocket} to manage the connection.
 * On the client side, use a single {@link BluetoothSocket} to both initiate
 * an outgoing connection and to manage the connection.
 *
 * <p>For Bluetooth BR/EDR, the most common type of socket is RFCOMM, which is the type supported by
 * the Android APIs. RFCOMM is a connection-oriented, streaming transport over Bluetooth BR/EDR. It
 * is also known as the Serial Port Profile (SPP). To create a listening
 * {@link BluetoothServerSocket} that's ready for incoming Bluetooth BR/EDR connections, use {@link
 * BluetoothAdapter#listenUsingRfcommWithServiceRecord
 * BluetoothAdapter.listenUsingRfcommWithServiceRecord()}.
 *
 * <p>For Bluetooth LE, the socket uses LE Connection-oriented Channel (CoC). LE CoC is a
 * connection-oriented, streaming transport over Bluetooth LE and has a credit-based flow control.
 * Correspondingly, use {@link BluetoothAdapter#listenUsingL2capChannel
 * BluetoothAdapter.listenUsingL2capChannel()} to create a listening {@link BluetoothServerSocket}
 * that's ready for incoming Bluetooth LE CoC connections. For LE CoC, you can use {@link #getPsm()}
 * to get the protocol/service multiplexer (PSM) value that the peer needs to use to connect to your
 * socket.
 *
 * <p> After the listening {@link BluetoothServerSocket} is created, call {@link #accept()} to
 * listen for incoming connection requests. This call will block until a connection is established,
 * at which point, it will return a {@link BluetoothSocket} to manage the connection. Once the
 * {@link BluetoothSocket} is acquired, it's a good idea to call {@link #close()} on the {@link
 * BluetoothServerSocket} when it's no longer needed for accepting
 * connections. Closing the {@link BluetoothServerSocket} will <em>not</em> close the returned
 * {@link BluetoothSocket}.
 *
 * <p>{@link BluetoothServerSocket} is thread
 * safe. In particular, {@link #close} will always immediately abort ongoing
 * operations and close the server socket.
 *
 * <p class="note"><strong>Note:</strong>
 * Requires the {@link android.Manifest.permission#BLUETOOTH} permission.
 *
 * <div class="special reference">
 * <h3>Developer Guides</h3>
 * <p>For more information about using Bluetooth, read the
 * <a href="{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> developer guide.</p>
 * </div>
 *
 * {@see BluetoothSocket}
 */
public final class BluetoothServerSocket implements Closeable {

    private static final String TAG = "BluetoothServerSocket";
    private static final boolean DBG = false;
    @UnsupportedAppUsage
    /*package*/ final BluetoothSocket mSocket;
    private Handler mHandler;
    private int mMessage;
    private int mChannel;

    /**
     * Construct a socket for incoming connections.
     *
     * @param type type of socket
     * @param auth require the remote device to be authenticated
     * @param encrypt require the connection to be encrypted
     * @param port remote port
     * @throws IOException On error, for example Bluetooth not available, or insufficient
     * privileges
     */
    /*package*/ BluetoothServerSocket(int type, boolean auth, boolean encrypt, int port)
            throws IOException {
        mChannel = port;
        mSocket = new BluetoothSocket(type, -1, auth, encrypt, null, port, null);
        if (port == BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
            mSocket.setExcludeSdp(true);
        }
    }

    /**
     * Construct a socket for incoming connections.
     *
     * @param type type of socket
     * @param auth require the remote device to be authenticated
     * @param encrypt require the connection to be encrypted
     * @param port remote port
     * @param mitm enforce man-in-the-middle protection for authentication.
     * @param min16DigitPin enforce a minimum length of 16 digits for a sec mode 2 connection
     * @throws IOException On error, for example Bluetooth not available, or insufficient
     * privileges
     */
    /*package*/ BluetoothServerSocket(int type, boolean auth, boolean encrypt, int port,
            boolean mitm, boolean min16DigitPin)
            throws IOException {
        mChannel = port;
        mSocket = new BluetoothSocket(type, -1, auth, encrypt, null, port, null, mitm,
                min16DigitPin);
        if (port == BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
            mSocket.setExcludeSdp(true);
        }
    }

    /**
     * Construct a socket for incoming connections.
     *
     * @param type type of socket
     * @param auth require the remote device to be authenticated
     * @param encrypt require the connection to be encrypted
     * @param uuid uuid
     * @throws IOException On error, for example Bluetooth not available, or insufficient
     * privileges
     */
    /*package*/ BluetoothServerSocket(int type, boolean auth, boolean encrypt, ParcelUuid uuid)
            throws IOException {
        mSocket = new BluetoothSocket(type, -1, auth, encrypt, null, -1, uuid);
        // TODO: This is the same as mChannel = -1 - is this intentional?
        mChannel = mSocket.getPort();
    }


    /**
     * Block until a connection is established.
     * <p>Returns a connected {@link BluetoothSocket} on successful connection.
     * <p>Once this call returns, it can be called again to accept subsequent
     * incoming connections.
     * <p>{@link #close} can be used to abort this call from another thread.
     *
     * @return a connected {@link BluetoothSocket}
     * @throws IOException on error, for example this call was aborted, or timeout
     */
    public BluetoothSocket accept() throws IOException {
        return accept(-1);
    }

    /**
     * Block until a connection is established, with timeout.
     * <p>Returns a connected {@link BluetoothSocket} on successful connection.
     * <p>Once this call returns, it can be called again to accept subsequent
     * incoming connections.
     * <p>{@link #close} can be used to abort this call from another thread.
     *
     * @return a connected {@link BluetoothSocket}
     * @throws IOException on error, for example this call was aborted, or timeout
     */
    public BluetoothSocket accept(int timeout) throws IOException {
        return mSocket.accept(timeout);
    }

    /**
     * Immediately close this socket, and release all associated resources.
     * <p>Causes blocked calls on this socket in other threads to immediately
     * throw an IOException.
     * <p>Closing the {@link BluetoothServerSocket} will <em>not</em>
     * close any {@link BluetoothSocket} received from {@link #accept()}.
     */
    public void close() throws IOException {
        if (DBG) Log.d(TAG, "BluetoothServerSocket:close() called. mChannel=" + mChannel);
        synchronized (this) {
            if (mHandler != null) {
                mHandler.obtainMessage(mMessage).sendToTarget();
            }
        }
        mSocket.close();
    }

    /*package*/
    synchronized void setCloseHandler(Handler handler, int message) {
        mHandler = handler;
        mMessage = message;
    }

    /*package*/ void setServiceName(String serviceName) {
        mSocket.setServiceName(serviceName);
    }

    /**
     * Returns the channel on which this socket is bound.
     *
     * @hide
     */
    public int getChannel() {
        return mChannel;
    }

    /**
     * Returns the assigned dynamic protocol/service multiplexer (PSM) value for the listening L2CAP
     * Connection-oriented Channel (CoC) server socket. This server socket must be returned by the
     * {@link BluetoothAdapter#listenUsingL2capChannel()} or {@link
     * BluetoothAdapter#listenUsingInsecureL2capChannel()}. The returned value is undefined if this
     * method is called on non-L2CAP server sockets.
     *
     * @return the assigned PSM or LE_PSM value depending on transport
     */
    public int getPsm() {
        return mChannel;
    }

    /**
     * Sets the channel on which future sockets are bound.
     * Currently used only when a channel is auto generated.
     */
    /*package*/ void setChannel(int newChannel) {
        /* TODO: From a design/architecture perspective this is wrong.
         *       The bind operation should be conducted through this class
         *       and the resulting port should be kept in mChannel, and
         *       not set from BluetoothAdapter. */
        if (mSocket != null) {
            if (mSocket.getPort() != newChannel) {
                Log.w(TAG, "The port set is different that the underlying port. mSocket.getPort(): "
                        + mSocket.getPort() + " requested newChannel: " + newChannel);
            }
        }
        mChannel = newChannel;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("ServerSocket: Type: ");
        switch (mSocket.getConnectionType()) {
            case BluetoothSocket.TYPE_RFCOMM: {
                sb.append("TYPE_RFCOMM");
                break;
            }
            case BluetoothSocket.TYPE_L2CAP: {
                sb.append("TYPE_L2CAP");
                break;
            }
            case BluetoothSocket.TYPE_L2CAP_LE: {
                sb.append("TYPE_L2CAP_LE");
                break;
            }
            case BluetoothSocket.TYPE_SCO: {
                sb.append("TYPE_SCO");
                break;
            }
        }
        sb.append(" Channel: ").append(mChannel);
        return sb.toString();
    }
}
