| /**************************************************************************** |
| ** |
| ** 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 |