/****************************************************************************
**
** 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_bluez_p.h"
#include "qbluetoothdeviceinfo.h"

#include "bluez/manager_p.h"
#include "bluez/adapter_p.h"
#include "bluez/device_p.h"
#include "bluez/objectmanager_p.h"
#include <QtBluetooth/QBluetoothLocalDevice>
#include "bluez/bluez_data_p.h"

#include <qplatformdefs.h>
#include <QtCore/private/qcore_unix_p.h>

#include <QtCore/QLoggingCategory>

#include <errno.h>
#include <unistd.h>
#include <string.h>

#include <QtCore/QSocketNotifier>

QT_BEGIN_NAMESPACE

Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ)

QBluetoothSocketPrivateBluez::QBluetoothSocketPrivateBluez()
    : QBluetoothSocketBasePrivate()
{
    secFlags = QBluetooth::Authorization;
}

QBluetoothSocketPrivateBluez::~QBluetoothSocketPrivateBluez()
{
    delete readNotifier;
    readNotifier = nullptr;
    delete connectWriteNotifier;
    connectWriteNotifier = nullptr;
}

bool QBluetoothSocketPrivateBluez::ensureNativeSocket(QBluetoothServiceInfo::Protocol type)
{
    if (socket != -1) {
        if (socketType == type)
            return true;

        delete readNotifier;
        readNotifier = nullptr;
        delete connectWriteNotifier;
        connectWriteNotifier = nullptr;
        QT_CLOSE(socket);
    }

    socketType = type;

    switch (type) {
    case QBluetoothServiceInfo::L2capProtocol:
        socket = ::socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
        break;
    case QBluetoothServiceInfo::RfcommProtocol:
        socket = ::socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
        break;
    default:
        socket = -1;
    }

    if (socket == -1)
        return false;

    int flags = fcntl(socket, F_GETFL, 0);
    fcntl(socket, F_SETFL, flags | O_NONBLOCK);

    Q_Q(QBluetoothSocket);
    readNotifier = new QSocketNotifier(socket, QSocketNotifier::Read);
    QObject::connect(readNotifier, SIGNAL(activated(QSocketDescriptor)), this, SLOT(_q_readNotify()));
    connectWriteNotifier = new QSocketNotifier(socket, QSocketNotifier::Write, q);
    QObject::connect(connectWriteNotifier, SIGNAL(activated(QSocketDescriptor)), this, SLOT(_q_writeNotify()));

    connectWriteNotifier->setEnabled(false);
    readNotifier->setEnabled(false);


    return true;
}

void QBluetoothSocketPrivateBluez::connectToServiceHelper(const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode)
{
    Q_Q(QBluetoothSocket);
    int result = -1;

    if (socket == -1 && !ensureNativeSocket(socketType)) {
        errorString = QBluetoothSocket::tr("Unknown socket error");
        q->setSocketError(QBluetoothSocket::UnknownSocketError);
        return;
    }

    // apply preferred security level
    // ignore QBluetooth::Authentication -> not used anymore by kernel
    struct bt_security security;
    memset(&security, 0, sizeof(security));

    if (secFlags & QBluetooth::Authorization)
        security.level = BT_SECURITY_LOW;
    if (secFlags & QBluetooth::Encryption)
        security.level = BT_SECURITY_MEDIUM;
    if (secFlags & QBluetooth::Secure)
        security.level = BT_SECURITY_HIGH;

    if (setsockopt(socket, SOL_BLUETOOTH, BT_SECURITY,
                   &security, sizeof(security)) != 0) {
        qCWarning(QT_BT_BLUEZ) << "Failed to set socket option, closing socket for safety" << errno;
        qCWarning(QT_BT_BLUEZ) << "Error: " << qt_error_string(errno);
        errorString = QBluetoothSocket::tr("Cannot set connection security level");
        q->setSocketError(QBluetoothSocket::UnknownSocketError);
        return;
    }

    if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
        sockaddr_rc addr;

        memset(&addr, 0, sizeof(addr));
        addr.rc_family = AF_BLUETOOTH;
        addr.rc_channel = port;

        convertAddress(address.toUInt64(), addr.rc_bdaddr.b);

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

        result = ::connect(socket, (sockaddr *)&addr, sizeof(addr));
    } else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
        sockaddr_l2 addr;

        memset(&addr, 0, sizeof(addr));
        addr.l2_family = AF_BLUETOOTH;
        // This is an ugly hack but the socket class does what's needed already.
        // For L2CP GATT we need a channel rather than a socket and the LE address type
        // We don't want to make this public API offering for now especially since
        // only Linux (of all platforms supported by this library) supports this type
        // of socket.

#if QT_CONFIG(bluez) && !defined(QT_BLUEZ_NO_BTLE)
        if (lowEnergySocketType) {
            addr.l2_cid = htobs(port);
            addr.l2_bdaddr_type = lowEnergySocketType;
        } else {
            addr.l2_psm = htobs(port);
        }
#else
        addr.l2_psm = htobs(port);
#endif

        convertAddress(address.toUInt64(), addr.l2_bdaddr.b);

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

        result = ::connect(socket, (sockaddr *)&addr, sizeof(addr));
    }

    if (result >= 0 || (result == -1 && errno == EINPROGRESS)) {
        connecting = true;
        q->setSocketState(QBluetoothSocket::ConnectingState);
        q->setOpenMode(openMode);
    } else {
        errorString = qt_error_string(errno);
        q->setSocketError(QBluetoothSocket::UnknownSocketError);
    }
}

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

    if (q->state() != QBluetoothSocket::UnconnectedState
            && q->state() != QBluetoothSocket::ServiceLookupState) {
        qCWarning(QT_BT_BLUEZ) << "QBluetoothSocketPrivateBluez::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::UnknownProtocol) {
        qCWarning(QT_BT_BLUEZ) << "QBluetoothSocket::connectToService cannot "
                                  "connect with 'UnknownProtocol' (type provided by given service)";
        errorString = QBluetoothSocket::tr("Socket type not supported");
        q->setSocketError(QBluetoothSocket::UnsupportedProtocolError);
        return;
    }

    if (service.protocolServiceMultiplexer() > 0) {
        Q_ASSERT(service.socketProtocol() == QBluetoothServiceInfo::L2capProtocol);

        if (!ensureNativeSocket(QBluetoothServiceInfo::L2capProtocol)) {
            errorString = QBluetoothSocket::tr("Unknown socket error");
            q->setSocketError(QBluetoothSocket::UnknownSocketError);
            return;
        }
        connectToServiceHelper(service.device().address(), service.protocolServiceMultiplexer(),
                               openMode);
    } else if (service.serverChannel() > 0) {
        Q_ASSERT(service.socketProtocol() == QBluetoothServiceInfo::RfcommProtocol);

        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_BLUEZ) << "No port, no PSM, and no UUID provided. Unable to connect";
            return;
        }
        qCDebug(QT_BT_BLUEZ) << "Need a port/psm, doing discovery";
        q->doDeviceDiscovery(service, openMode);
    }
}

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

    if (q->state() != QBluetoothSocket::UnconnectedState) {
        qCWarning(QT_BT_BLUEZ) << "QBluetoothSocketPrivateBluez::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_BLUEZ) << "QBluetoothSocketPrivateBluez::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 QBluetoothSocketPrivateBluez::connectToService(
        const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode)
{
    Q_Q(QBluetoothSocket);

    if (q->socketType() == QBluetoothServiceInfo::UnknownProtocol) {
        qCWarning(QT_BT_BLUEZ) << "QBluetoothSocketPrivateBluez::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_BLUEZ) << "QBluetoothSocketPrivateBluez::connectToService called on busy socket";
        errorString = QBluetoothSocket::tr("Trying to connect while connection is in progress");
        q->setSocketError(QBluetoothSocket::OperationError);
        return;
    }
    connectToServiceHelper(address, port, openMode);
}

void QBluetoothSocketPrivateBluez::_q_writeNotify()
{
    Q_Q(QBluetoothSocket);
    if(connecting && state == QBluetoothSocket::ConnectingState){
        int errorno, len;
        len = sizeof(errorno);
        ::getsockopt(socket, SOL_SOCKET, SO_ERROR, &errorno, (socklen_t*)&len);
        if(errorno) {
            errorString = qt_error_string(errorno);
            q->setSocketError(QBluetoothSocket::UnknownSocketError);
            return;
        }

        q->setSocketState(QBluetoothSocket::ConnectedState);

        connectWriteNotifier->setEnabled(false);
        connecting = false;
    }
    else {
        if (txBuffer.size() == 0) {
            connectWriteNotifier->setEnabled(false);
            return;
        }

        char buf[1024];

        int size = txBuffer.read(buf, 1024);
        int writtenBytes = qt_safe_write(socket, buf, size);
        if (writtenBytes < 0) {
            switch (errno) {
            case EAGAIN:
                writtenBytes = 0;
                txBuffer.ungetBlock(buf, size);
                break;
            default:
                // every other case returns error
                errorString = QBluetoothSocket::tr("Network Error: %1").arg(qt_error_string(errno)) ;
                q->setSocketError(QBluetoothSocket::NetworkError);
                break;
            }
        } else {
            if (writtenBytes < size) {
                // add remainder back to buffer
                char* remainder = buf + writtenBytes;
                txBuffer.ungetBlock(remainder, size - writtenBytes);
            }
            if (writtenBytes > 0)
                emit q->bytesWritten(writtenBytes);
        }

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

void QBluetoothSocketPrivateBluez::_q_readNotify()
{
    Q_Q(QBluetoothSocket);
    char *writePointer = buffer.reserve(QPRIVATELINEARBUFFER_BUFFERSIZE);
//    qint64 readFromDevice = q->readData(writePointer, QPRIVATELINEARBUFFER_BUFFERSIZE);
    int readFromDevice = ::read(socket, writePointer, QPRIVATELINEARBUFFER_BUFFERSIZE);
    buffer.chop(QPRIVATELINEARBUFFER_BUFFERSIZE - (readFromDevice < 0 ? 0 : readFromDevice));
    if(readFromDevice <= 0){
        int errsv = errno;
        readNotifier->setEnabled(false);
        connectWriteNotifier->setEnabled(false);
        errorString = qt_error_string(errsv);
        qCWarning(QT_BT_BLUEZ) << Q_FUNC_INFO << socket << "error:" << readFromDevice << errorString;
        if (errsv == EHOSTDOWN)
            q->setSocketError(QBluetoothSocket::HostNotFoundError);
        else if (errsv == ECONNRESET)
            q->setSocketError(QBluetoothSocket::RemoteHostClosedError);
        else
            q->setSocketError(QBluetoothSocket::UnknownSocketError);

        q->disconnectFromService();
    }
    else {
        emit q->readyRead();
    }
}

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

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

    Q_Q(QBluetoothSocket);

    q->setOpenMode(QIODevice::NotOpen);
    q->setSocketState(QBluetoothSocket::UnconnectedState);
    emit q->readChannelFinished();
    emit q->disconnected();
}

QString QBluetoothSocketPrivateBluez::localName() const
{
    const QBluetoothAddress address = localAddress();
    if (address.isNull())
        return QString();

    QBluetoothLocalDevice device(address);
    return device.name();
}

QBluetoothAddress QBluetoothSocketPrivateBluez::localAddress() const
{
    if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
        sockaddr_rc addr;
        socklen_t addrLength = sizeof(addr);

        if (::getsockname(socket, reinterpret_cast<sockaddr *>(&addr), &addrLength) == 0)
            return QBluetoothAddress(convertAddress(addr.rc_bdaddr.b));
    } else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
        sockaddr_l2 addr;
        socklen_t addrLength = sizeof(addr);

        if (::getsockname(socket, reinterpret_cast<sockaddr *>(&addr), &addrLength) == 0)
            return QBluetoothAddress(convertAddress(addr.l2_bdaddr.b));
    }

    return QBluetoothAddress();
}

quint16 QBluetoothSocketPrivateBluez::localPort() const
{
    if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
        sockaddr_rc addr;
        socklen_t addrLength = sizeof(addr);

        if (::getsockname(socket, reinterpret_cast<sockaddr *>(&addr), &addrLength) == 0)
            return addr.rc_channel;
    } else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
        sockaddr_l2 addr;
        socklen_t addrLength = sizeof(addr);

        if (::getsockname(socket, reinterpret_cast<sockaddr *>(&addr), &addrLength) == 0)
            return addr.l2_psm;
    }

    return 0;
}

QString QBluetoothSocketPrivateBluez::peerName() const
{
    quint64 bdaddr;

    if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
        sockaddr_rc addr;
        socklen_t addrLength = sizeof(addr);

        if (::getpeername(socket, reinterpret_cast<sockaddr *>(&addr), &addrLength) < 0)
            return QString();

        convertAddress(addr.rc_bdaddr.b, &bdaddr);
    } else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
        sockaddr_l2 addr;
        socklen_t addrLength = sizeof(addr);

        if (::getpeername(socket, reinterpret_cast<sockaddr *>(&addr), &addrLength) < 0)
            return QString();

        convertAddress(addr.l2_bdaddr.b, &bdaddr);
    } else {
        qCWarning(QT_BT_BLUEZ) << "peerName() called on socket of unknown type";
        return QString();
    }

    const QString peerAddress = QBluetoothAddress(bdaddr).toString();
    const QString localAdapter = localAddress().toString();

    if (isBluez5()) {
        OrgFreedesktopDBusObjectManagerInterface manager(QStringLiteral("org.bluez"),
                                                         QStringLiteral("/"),
                                                         QDBusConnection::systemBus());
        QDBusPendingReply<ManagedObjectList> reply = manager.GetManagedObjects();
        reply.waitForFinished();
        if (reply.isError())
            return QString();

        ManagedObjectList managedObjectList = reply.value();
        for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) {
            const InterfaceList &ifaceList = it.value();

            for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) {
                const QString &iface = jt.key();
                const QVariantMap &ifaceValues = jt.value();

                if (iface == QStringLiteral("org.bluez.Device1")) {
                    if (ifaceValues.value(QStringLiteral("Address")).toString() == peerAddress)
                        return ifaceValues.value(QStringLiteral("Alias")).toString();
                }
            }
        }
        return QString();
    } else {
        OrgBluezManagerInterface manager(QStringLiteral("org.bluez"), QStringLiteral("/"),
                                         QDBusConnection::systemBus());

        QDBusPendingReply<QDBusObjectPath> reply = manager.FindAdapter(localAdapter);
        reply.waitForFinished();
        if (reply.isError())
            return QString();

        OrgBluezAdapterInterface adapter(QStringLiteral("org.bluez"), reply.value().path(),
                                         QDBusConnection::systemBus());

        QDBusPendingReply<QDBusObjectPath> deviceObjectPath = adapter.FindDevice(peerAddress);
        deviceObjectPath.waitForFinished();
        if (deviceObjectPath.isError()) {
            if (deviceObjectPath.error().name() != QStringLiteral("org.bluez.Error.DoesNotExist"))
                return QString();

            deviceObjectPath = adapter.CreateDevice(peerAddress);
            deviceObjectPath.waitForFinished();
            if (deviceObjectPath.isError())
                return QString();
        }

        OrgBluezDeviceInterface device(QStringLiteral("org.bluez"), deviceObjectPath.value().path(),
                                       QDBusConnection::systemBus());

        QDBusPendingReply<QVariantMap> properties = device.GetProperties();
        properties.waitForFinished();
        if (properties.isError())
            return QString();

        return properties.value().value(QStringLiteral("Alias")).toString();
    }
}

QBluetoothAddress QBluetoothSocketPrivateBluez::peerAddress() const
{
    if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
        sockaddr_rc addr;
        socklen_t addrLength = sizeof(addr);

        if (::getpeername(socket, reinterpret_cast<sockaddr *>(&addr), &addrLength) == 0)
            return QBluetoothAddress(convertAddress(addr.rc_bdaddr.b));
    } else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
        sockaddr_l2 addr;
        socklen_t addrLength = sizeof(addr);

        if (::getpeername(socket, reinterpret_cast<sockaddr *>(&addr), &addrLength) == 0)
            return QBluetoothAddress(convertAddress(addr.l2_bdaddr.b));
    }

    return QBluetoothAddress();
}

quint16 QBluetoothSocketPrivateBluez::peerPort() const
{
    if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
        sockaddr_rc addr;
        socklen_t addrLength = sizeof(addr);

        if (::getpeername(socket, reinterpret_cast<sockaddr *>(&addr), &addrLength) == 0)
            return addr.rc_channel;
    } else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
        sockaddr_l2 addr;
        socklen_t addrLength = sizeof(addr);

        if (::getpeername(socket, reinterpret_cast<sockaddr *>(&addr), &addrLength) == 0)
            return addr.l2_psm;
    }

    return 0;
}

qint64 QBluetoothSocketPrivateBluez::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) {
        int sz = ::qt_safe_write(socket, data, maxSize);
        if (sz < 0) {
            switch (errno) {
            case EAGAIN:
                sz = 0;
                break;
            default:
                errorString = QBluetoothSocket::tr("Network Error: %1").arg(qt_error_string(errno));
                q->setSocketError(QBluetoothSocket::NetworkError);
            }
        }

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

        return sz;
    }
    else {

        if(!connectWriteNotifier)
            return -1;

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

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

        return maxSize;
    }
}

qint64 QBluetoothSocketPrivateBluez::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;
    }

    if (!buffer.isEmpty()) {
        int i = buffer.read(data, maxSize);
        return i;
    }

    return 0;
}

void QBluetoothSocketPrivateBluez::close()
{
    if (txBuffer.size() > 0)
        connectWriteNotifier->setEnabled(true);
    else
        abort();
}

bool QBluetoothSocketPrivateBluez::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType_,
                                           QBluetoothSocket::SocketState socketState, QBluetoothSocket::OpenMode openMode)
{
    Q_Q(QBluetoothSocket);
    delete readNotifier;
    readNotifier = nullptr;
    delete connectWriteNotifier;
    connectWriteNotifier = nullptr;

    socketType = socketType_;
    if (socket != -1)
        QT_CLOSE(socket);

    socket = socketDescriptor;

    // ensure that O_NONBLOCK is set on new connections.
    int flags = fcntl(socket, F_GETFL, 0);
    if (!(flags & O_NONBLOCK))
        fcntl(socket, F_SETFL, flags | O_NONBLOCK);

    readNotifier = new QSocketNotifier(socket, QSocketNotifier::Read);
    QObject::connect(readNotifier, SIGNAL(activated(QSocketDescriptor)), this, SLOT(_q_readNotify()));
    connectWriteNotifier = new QSocketNotifier(socket, QSocketNotifier::Write, q);
    QObject::connect(connectWriteNotifier, SIGNAL(activated(QSocketDescriptor)), this, SLOT(_q_writeNotify()));

    q->setSocketState(socketState);
    q->setOpenMode(openMode);

    return true;
}

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

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

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

QT_END_NAMESPACE
