/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtBluetooth module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qbluetoothsocket.h"
#include "qbluetoothsocket_win_p.h"

#include <QtCore/qloggingcategory.h>

#include <QtBluetooth/qbluetoothdeviceinfo.h>
#include <QtBluetooth/QBluetoothLocalDevice>
#include <QtCore/QSocketNotifier>

#include <winsock2.h>
#include <ws2bth.h>
#include <bluetoothapis.h>

QT_BEGIN_NAMESPACE

Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINDOWS)

QBluetoothSocketPrivateWin::QBluetoothSocketPrivateWin()
    : QBluetoothSocketBasePrivate()
{
    WSAData wsadata = {};
    ::WSAStartup(MAKEWORD(2, 0), &wsadata);
}

QBluetoothSocketPrivateWin::~QBluetoothSocketPrivateWin()
{
    abort();
}

bool QBluetoothSocketPrivateWin::ensureNativeSocket(QBluetoothServiceInfo::Protocol type)
{
    Q_Q(QBluetoothSocket);

    if (static_cast<SOCKET>(socket) != INVALID_SOCKET) {
        if (socketType == type)
            return true;
        abort();
    }
    socketType = type;

    if (type != QBluetoothServiceInfo::RfcommProtocol) {
        socket = int(INVALID_SOCKET);
        errorString = QBluetoothSocket::tr("Unsupported protocol. Win32 only supports RFCOMM sockets");
        q->setSocketError(QBluetoothSocket::UnsupportedProtocolError);
        return false;
    }

    socket = ::socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);

    if (static_cast<SOCKET>(socket) == INVALID_SOCKET) {
        const int error = ::WSAGetLastError();
        qCWarning(QT_BT_WINDOWS) << "Failed to create socket:" << error << qt_error_string(error);
        errorString = QBluetoothSocket::tr("Failed to create socket");
        q->setSocketError(QBluetoothSocket::UnknownSocketError);
        return false;
    }

    if (!createNotifiers())
        return false;

    return true;
}

void QBluetoothSocketPrivateWin::connectToServiceHelper(const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode)
{
    Q_Q(QBluetoothSocket);

    if (static_cast<SOCKET>(socket) == INVALID_SOCKET && !ensureNativeSocket(socketType))
        return;

    if (!configureSecurity())
        return;

    SOCKADDR_BTH addr = {};
    addr.addressFamily = AF_BTH;
    addr.port = port;
    addr.btAddr = address.toUInt64();

    switch (socketType) {
    case QBluetoothServiceInfo::RfcommProtocol:
        addr.serviceClassId = RFCOMM_PROTOCOL_UUID;
        break;
    default:
        errorString = QBluetoothSocket::tr("Socket type not handled: %1").arg(socketType);
        q->setSocketError(QBluetoothSocket::UnsupportedProtocolError);
        return;
    }

    connectWriteNotifier->setEnabled(true);
    readNotifier->setEnabled(true);
    exceptNotifier->setEnabled(true);

    const int result = ::connect(socket, reinterpret_cast<sockaddr *>(&addr), sizeof(addr));

    const int error = ::WSAGetLastError();
    if (result != SOCKET_ERROR || error == WSAEWOULDBLOCK) {
        q->setSocketState(QBluetoothSocket::ConnectingState);
        q->setOpenMode(openMode);
    } else {
        errorString = qt_error_string(error);
        q->setSocketError(QBluetoothSocket::UnknownSocketError);
    }
}

void QBluetoothSocketPrivateWin::connectToService(
        const QBluetoothServiceInfo &service, QIODevice::OpenMode openMode)
{
    Q_Q(QBluetoothSocket);

    if (q->state() != QBluetoothSocket::UnconnectedState
            && q->state() != QBluetoothSocket::ServiceLookupState) {
        //qCWarning(QT_BT_WINDOWS) << "QBluetoothSocketPrivateWIN::connectToService called on busy socket";
        errorString = QBluetoothSocket::tr("Trying to connect while connection is in progress");
        q->setSocketError(QBluetoothSocket::OperationError);
        return;
    }

    // we are checking the service protocol and not socketType()
    // socketType will change in ensureNativeSocket()
    if (service.socketProtocol() != QBluetoothServiceInfo::RfcommProtocol) {
        qCWarning(QT_BT_WINDOWS) << "QBluetoothSocket::connectToService called with unsupported protocol";
        errorString = QBluetoothSocket::tr("Socket type not supported");
        q->setSocketError(QBluetoothSocket::UnsupportedProtocolError);
        return;
    }

    if (service.serverChannel() > 0) {
        if (!ensureNativeSocket(QBluetoothServiceInfo::RfcommProtocol)) {
            errorString = QBluetoothSocket::tr("Unknown socket error");
            q->setSocketError(QBluetoothSocket::UnknownSocketError);
            return;
        }
        connectToServiceHelper(service.device().address(), service.serverChannel(), openMode);
    } else {
        // try doing service discovery to see if we can find the socket
        if (service.serviceUuid().isNull()
                && !service.serviceClassUuids().contains(QBluetoothUuid::SerialPort)) {
            qCWarning(QT_BT_WINDOWS) << "No port, no PSM, and no UUID provided. Unable to connect";
            return;
        }
        qCDebug(QT_BT_WINDOWS) << "Need a port/psm, doing discovery";
        q->doDeviceDiscovery(service, openMode);
    }
}

void QBluetoothSocketPrivateWin::_q_writeNotify()
{
    Q_Q(QBluetoothSocket);

    if (state == QBluetoothSocket::ConnectingState) {
        q->setSocketState(QBluetoothSocket::ConnectedState);
        connectWriteNotifier->setEnabled(false);
    } else {
        if (txBuffer.isEmpty()) {
            connectWriteNotifier->setEnabled(false);
            return;
        }

        char buf[1024];
        const int size = txBuffer.read(&buf[0], sizeof(buf));
        const int writtenBytes = ::send(socket, &buf[0], size, 0);
        if (writtenBytes == SOCKET_ERROR) {
            // every other case returns error
            const int error = ::WSAGetLastError();
            errorString = QBluetoothSocket::tr("Network Error: %1").arg(qt_error_string(error));
            q->setSocketError(QBluetoothSocket::NetworkError);
        } else if (writtenBytes <= size) {
            // add remainder back to buffer
            const char *remainder = &buf[writtenBytes];
            txBuffer.ungetBlock(remainder, size - writtenBytes);
            if (writtenBytes > 0)
                emit q->bytesWritten(writtenBytes);
        } else {
            errorString = QBluetoothSocket::tr("Logic error: more bytes sent than passed to ::send");
            q->setSocketError(QBluetoothSocket::NetworkError);
        }

        if (!txBuffer.isEmpty()) {
            connectWriteNotifier->setEnabled(true);
        } else if (state == QBluetoothSocket::ClosingState) {
            connectWriteNotifier->setEnabled(false);
            this->close();
        }
    }
}

void QBluetoothSocketPrivateWin::_q_readNotify()
{
    Q_Q(QBluetoothSocket);

    char *writePointer = buffer.reserve(QPRIVATELINEARBUFFER_BUFFERSIZE);
    const int bytesRead = ::recv(socket, writePointer, QPRIVATELINEARBUFFER_BUFFERSIZE, 0);
    if (bytesRead == SOCKET_ERROR) {
        const int error = ::WSAGetLastError();
        buffer.chop(QPRIVATELINEARBUFFER_BUFFERSIZE);
        readNotifier->setEnabled(false);
        connectWriteNotifier->setEnabled(false);
        errorString = qt_error_string(error);
        qCWarning(QT_BT_WINDOWS) << Q_FUNC_INFO << socket << "error:" << error << errorString;
        switch (error) {
        case WSAEHOSTDOWN:
            q->setSocketError(QBluetoothSocket::HostNotFoundError);
            break;
        case WSAECONNRESET:
            q->setSocketError(QBluetoothSocket::RemoteHostClosedError);
            break;
        default:
            q->setSocketError(QBluetoothSocket::UnknownSocketError);
            break;
        }

        q->disconnectFromService();
    } else if (bytesRead == 0) {
        q->setSocketError(QBluetoothSocket::RemoteHostClosedError);
        q->setSocketState(QBluetoothSocket::UnconnectedState);
    } else {
        const int unusedBytes = QPRIVATELINEARBUFFER_BUFFERSIZE -  bytesRead;
        buffer.chop(unusedBytes);
        if (bytesRead > 0)
            emit q->readyRead();
    }
}

void QBluetoothSocketPrivateWin::_q_exceptNotify()
{
    Q_Q(QBluetoothSocket);

    const int error = ::WSAGetLastError();
    errorString = qt_error_string(error);
    q->setSocketError(QBluetoothSocket::UnknownSocketError);

    if (state == QBluetoothSocket::ConnectingState)
        abort();
}

void QBluetoothSocketPrivateWin::connectToService(
        const QBluetoothAddress &address, const QBluetoothUuid &uuid,
        QIODevice::OpenMode openMode)
{
    Q_Q(QBluetoothSocket);

    if (q->state() != QBluetoothSocket::UnconnectedState) {
        qCWarning(QT_BT_WINDOWS) << "QBluetoothSocketPrivateWin::connectToService called on busy socket";
        errorString = QBluetoothSocket::tr("Trying to connect while connection is in progress");
        q->setSocketError(QBluetoothSocket::OperationError);
        return;
    }

    if (q->socketType() == QBluetoothServiceInfo::UnknownProtocol) {
        qCWarning(QT_BT_WINDOWS) << "QBluetoothSocketPrivateWin::connectToService cannot "
                                  "connect with 'UnknownProtocol' (type provided by given service)";
        errorString = QBluetoothSocket::tr("Socket type not supported");
        q->setSocketError(QBluetoothSocket::UnsupportedProtocolError);
        return;
    }

    QBluetoothServiceInfo service;
    QBluetoothDeviceInfo device(address, QString(), QBluetoothDeviceInfo::MiscellaneousDevice);
    service.setDevice(device);
    service.setServiceUuid(uuid);
    q->doDeviceDiscovery(service, openMode);
}

void QBluetoothSocketPrivateWin::connectToService(
        const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode)
{
    Q_Q(QBluetoothSocket);

    if (q->socketType() == QBluetoothServiceInfo::UnknownProtocol) {
        qCWarning(QT_BT_WINDOWS) << "QBluetoothSocketPrivateWin::connectToService cannot "
                                  "connect with 'UnknownProtocol' (type provided by given service)";
        errorString = QBluetoothSocket::tr("Socket type not supported");
        q->setSocketError(QBluetoothSocket::UnsupportedProtocolError);
        return;
    }

    if (q->state() != QBluetoothSocket::UnconnectedState) {
        qCWarning(QT_BT_WINDOWS) << "QBluetoothSocketPrivateWin::connectToService called on busy socket";
        errorString = QBluetoothSocket::tr("Trying to connect while connection is in progress");
        q->setSocketError(QBluetoothSocket::OperationError);
        return;
    }

    q->setOpenMode(openMode);
    connectToServiceHelper(address, port, openMode);
}

void QBluetoothSocketPrivateWin::abort()
{
    delete readNotifier;
    readNotifier = nullptr;
    delete connectWriteNotifier;
    connectWriteNotifier = nullptr;
    delete exceptNotifier;
    exceptNotifier = nullptr;

    // We don't transition through Closing for abort, so
    // we don't call disconnectFromService or QBluetoothSocket::close
    ::closesocket(socket);
    socket = int(INVALID_SOCKET);

    Q_Q(QBluetoothSocket);

    const bool wasConnected = q->state() == QBluetoothSocket::ConnectedState;
    q->setSocketState(QBluetoothSocket::UnconnectedState);
    if (wasConnected) {
        q->setOpenMode(QIODevice::NotOpen);
        emit q->readChannelFinished();
    }
}

QString QBluetoothSocketPrivateWin::localName() const
{
    const QBluetoothAddress localAddr = localAddress();
    if (localAddr == QBluetoothAddress())
        return {};
    const QBluetoothLocalDevice device(localAddr);
    return device.name();
}

QBluetoothAddress QBluetoothSocketPrivateWin::localAddress() const
{
    if (static_cast<SOCKET>(socket) == INVALID_SOCKET)
        return {};
    SOCKADDR_BTH localAddr = {};
    int localAddrLength = sizeof(localAddr);
    const int localResult = ::getsockname(socket, reinterpret_cast<sockaddr *>(&localAddr), &localAddrLength);
    if (localResult == SOCKET_ERROR) {
        const int error = ::WSAGetLastError();
        qCWarning(QT_BT_WINDOWS) << "Error getting local address" << error << qt_error_string(error);
        return {};
    }
    return QBluetoothAddress(localAddr.btAddr);
}

quint16 QBluetoothSocketPrivateWin::localPort() const
{
    if (static_cast<SOCKET>(socket) == INVALID_SOCKET)
        return {};
    SOCKADDR_BTH localAddr = {};
    int localAddrLength = sizeof(localAddr);
    const int localResult = ::getsockname(socket, reinterpret_cast<sockaddr *>(&localAddr), &localAddrLength);
    if (localResult == SOCKET_ERROR) {
        const int error = ::WSAGetLastError();
        qCWarning(QT_BT_WINDOWS) << "Error getting local port" << error << qt_error_string(error);
        return {};
    }
    return localAddr.port;
}

QString QBluetoothSocketPrivateWin::peerName() const
{
    const QBluetoothAddress peerAddr = peerAddress();
    if (peerAddr == QBluetoothAddress())
        return {};
    BLUETOOTH_DEVICE_INFO bdi = {};
    bdi.dwSize = sizeof(bdi);
    bdi.Address.ullLong = peerAddr.toUInt64();
    const DWORD res = ::BluetoothGetDeviceInfo(nullptr, &bdi);
    if (res != ERROR_SUCCESS) {
        qCWarning(QT_BT_WINDOWS) << "Error calling BluetoothGetDeviceInfo" << res << qt_error_string(res);
        return {};
    }
    return QString::fromWCharArray(&bdi.szName[0]);
}

QBluetoothAddress QBluetoothSocketPrivateWin::peerAddress() const
{
    if (static_cast<SOCKET>(socket) == INVALID_SOCKET)
        return {};
    SOCKADDR_BTH peerAddr = {};
    int peerAddrLength = sizeof(peerAddr);
    const int peerResult = ::getpeername(socket, reinterpret_cast<sockaddr *>(&peerAddr), &peerAddrLength);
    if (peerResult == SOCKET_ERROR) {
        const int error = ::WSAGetLastError();
        qCWarning(QT_BT_WINDOWS) << "Error getting peer address and port" << error << qt_error_string(error);
        return {};
    }
    return QBluetoothAddress(peerAddr.btAddr);
}

quint16 QBluetoothSocketPrivateWin::peerPort() const
{
    if (static_cast<SOCKET>(socket) == INVALID_SOCKET)
        return {};
    SOCKADDR_BTH peerAddr = {};
    int peerAddrLength = sizeof(peerAddr);
    const int peerResult = ::getpeername(socket, reinterpret_cast<sockaddr *>(&peerAddr), &peerAddrLength);
    if (peerResult == SOCKET_ERROR) {
        const int error = ::WSAGetLastError();
        qCWarning(QT_BT_WINDOWS) << "Error getting peer address and port" << error << qt_error_string(error);
        return {};
    }
    return peerAddr.port;
}

qint64 QBluetoothSocketPrivateWin::writeData(const char *data, qint64 maxSize)
{
    Q_Q(QBluetoothSocket);

    if (state != QBluetoothSocket::ConnectedState) {
        errorString = QBluetoothSocket::tr("Cannot write while not connected");
        q->setSocketError(QBluetoothSocket::OperationError);
        return -1;
    }

    if (q->openMode() & QIODevice::Unbuffered) {
        const int bytesWritten = ::send(socket, data, maxSize, 0);

        if (bytesWritten == SOCKET_ERROR) {
            const int error = ::WSAGetLastError();
            errorString = QBluetoothSocket::tr("Network Error: %1").arg(qt_error_string(error));
            q->setSocketError(QBluetoothSocket::NetworkError);
        }

        if (bytesWritten > 0)
            emit q->bytesWritten(bytesWritten);

        return bytesWritten;
    } else {

        if (!connectWriteNotifier)
            return -1;

        if (txBuffer.isEmpty()) {
            connectWriteNotifier->setEnabled(true);
            QMetaObject::invokeMethod(this, "_q_writeNotify", Qt::QueuedConnection);
        }

        char *txbuf = txBuffer.reserve(maxSize);
        ::memcpy(txbuf, data, maxSize);

        return maxSize;
    }
}

qint64 QBluetoothSocketPrivateWin::readData(char *data, qint64 maxSize)
{
    Q_Q(QBluetoothSocket);

    if (state != QBluetoothSocket::ConnectedState) {
        errorString = QBluetoothSocket::tr("Cannot read while not connected");
        q->setSocketError(QBluetoothSocket::OperationError);
        return -1;
    }

    const int bytesRead = buffer.read(data, maxSize);
    return bytesRead;
}

void QBluetoothSocketPrivateWin::close()
{
    if (txBuffer.isEmpty())
        abort();
    else
        connectWriteNotifier->setEnabled(true);
}

bool QBluetoothSocketPrivateWin::setSocketDescriptor(int socketDescriptor,
                                                     QBluetoothServiceInfo::Protocol protocol,
                                                     QBluetoothSocket::SocketState socketState,
                                                     QBluetoothSocket::OpenMode openMode)
{
    Q_Q(QBluetoothSocket);

    abort();

    socketType = protocol;
    socket = socketDescriptor;

    if (!createNotifiers())
        return false;
    q->setSocketState(socketState);
    q->setOpenMode(openMode);
    if (socketState == QBluetoothSocket::ConnectedState) {
        connectWriteNotifier->setEnabled(true);
        readNotifier->setEnabled(true);
        exceptNotifier->setEnabled(true);
    }

    return true;
}

qint64 QBluetoothSocketPrivateWin::bytesAvailable() const
{
    return buffer.size();
}

bool QBluetoothSocketPrivateWin::canReadLine() const
{
    return buffer.canReadLine();
}

qint64 QBluetoothSocketPrivateWin::bytesToWrite() const
{
    return txBuffer.size();
}

bool QBluetoothSocketPrivateWin::createNotifiers()
{
    Q_Q(QBluetoothSocket);

    ULONG mode = 1;  // 1 to enable non-blocking socket
    const int result = ::ioctlsocket(socket, FIONBIO, &mode);

    if (result == SOCKET_ERROR) {
        const int error = ::WSAGetLastError();
        errorString = qt_error_string(error);
        q->setSocketError(QBluetoothSocket::UnknownSocketError);
        qCWarning(QT_BT_WINDOWS) << "Error setting socket to non-blocking" << error << errorString;
        abort();
        return false;
    }
    readNotifier = new QSocketNotifier(socket, QSocketNotifier::Read);
    QObject::connect(readNotifier, &QSocketNotifier::activated, this, &QBluetoothSocketPrivateWin::_q_readNotify);
    connectWriteNotifier = new QSocketNotifier(socket, QSocketNotifier::Write, q);
    QObject::connect(connectWriteNotifier, &QSocketNotifier::activated, this, &QBluetoothSocketPrivateWin::_q_writeNotify);
    exceptNotifier = new QSocketNotifier(socket, QSocketNotifier::Exception, q);
    QObject::connect(exceptNotifier, &QSocketNotifier::activated, this, &QBluetoothSocketPrivateWin::_q_exceptNotify);

    connectWriteNotifier->setEnabled(false);
    readNotifier->setEnabled(false);
    exceptNotifier->setEnabled(false);
    return true;
}

bool QBluetoothSocketPrivateWin::configureSecurity()
{
    Q_Q(QBluetoothSocket);

    if (secFlags & QBluetooth::Authorization) {
        ULONG authenticate = TRUE;
        const int result = ::setsockopt(socket, SOL_RFCOMM, SO_BTH_AUTHENTICATE, reinterpret_cast<const char*>(&authenticate), sizeof(authenticate));
        if (result == SOCKET_ERROR) {
            const int error = ::WSAGetLastError();
            qCWarning(QT_BT_WINDOWS) << "Failed to set socket option, closing socket for safety" << error;
            qCWarning(QT_BT_WINDOWS) << "Error: " << qt_error_string(error);
            errorString = QBluetoothSocket::tr("Cannot set connection security level");
            q->setSocketError(QBluetoothSocket::UnknownSocketError);
            return false;
        }
    }

    if (secFlags & QBluetooth::Encryption) {
        ULONG encrypt = TRUE;
        const int result = ::setsockopt(socket, SOL_RFCOMM, SO_BTH_ENCRYPT, reinterpret_cast<const char*>(&encrypt), sizeof(encrypt));
        if (result == SOCKET_ERROR) {
            const int error = ::WSAGetLastError();
            qCWarning(QT_BT_WINDOWS) << "Failed to set socket option, closing socket for safety" << error;
            qCWarning(QT_BT_WINDOWS) << "Error: " << qt_error_string(error);
            errorString = QBluetoothSocket::tr("Cannot set connection security level");
            q->setSocketError(QBluetoothSocket::UnknownSocketError);
            return false;
        }
    }
    return true;
}
QT_END_NAMESPACE
