diff options
author | Timur Pocheptsov <timur.pocheptsov@qt.io> | 2019-07-04 16:13:44 +0200 |
---|---|---|
committer | Timur Pocheptsov <timur.pocheptsov@qt.io> | 2019-07-15 11:22:23 +0200 |
commit | c1286c3a344593c79feced5c782ff85bca80bfff (patch) | |
tree | ee8e20e7971a2ab4453d3cac15f3a01d5c29ce82 | |
parent | de3e8e85cc5a442dbae966c6956c84ee434ad108 (diff) |
QBluetoothSocket - deduplicate the code (macOS)
Implement the proper interface from QBluetoothSocketBasePrivate,
remove a dummy base class. Remove all public API from
qbluetoothsocket_osx.mm and re-use the code in qbluetoothsocket.cpp.
The code generally is the same, a bit of re-hashin/deletion.
Task-number: QTBUG-75348
Change-Id: I0034dfd283daf9d51775d8f9551b85d2d436aa85
Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
-rw-r--r-- | src/bluetooth/bluetooth.pro | 2 | ||||
-rw-r--r-- | src/bluetooth/osx/osxbt.pri | 2 | ||||
-rw-r--r-- | src/bluetooth/osx/osxbtchanneldelegate.mm | 52 | ||||
-rw-r--r-- | src/bluetooth/osx/osxbtchanneldelegate_p.h | 79 | ||||
-rw-r--r-- | src/bluetooth/osx/osxbtl2capchannel.mm | 8 | ||||
-rw-r--r-- | src/bluetooth/osx/osxbtl2capchannel_p.h | 6 | ||||
-rw-r--r-- | src/bluetooth/osx/osxbtrfcommchannel.mm | 8 | ||||
-rw-r--r-- | src/bluetooth/osx/osxbtrfcommchannel_p.h | 6 | ||||
-rw-r--r-- | src/bluetooth/qbluetoothserver_osx.mm | 4 | ||||
-rw-r--r-- | src/bluetooth/qbluetoothsocket.cpp | 15 | ||||
-rw-r--r-- | src/bluetooth/qbluetoothsocket.h | 16 | ||||
-rw-r--r-- | src/bluetooth/qbluetoothsocket_osx.mm | 839 | ||||
-rw-r--r-- | src/bluetooth/qbluetoothsocket_osx_p.h | 82 | ||||
-rw-r--r-- | src/bluetooth/qbluetoothsocketbase_p.h | 21 |
14 files changed, 367 insertions, 773 deletions
diff --git a/src/bluetooth/bluetooth.pro b/src/bluetooth/bluetooth.pro index 0b14357d..4c7a7876 100644 --- a/src/bluetooth/bluetooth.pro +++ b/src/bluetooth/bluetooth.pro @@ -176,8 +176,6 @@ qtConfig(bluez) { SOURCES -= qbluetoothserviceinfo.cpp SOURCES -= qbluetoothservicediscoveryagent.cpp - SOURCES -= qbluetoothsocket.cpp - SOURCES -= qbluetoothsocketbase.cpp } else:ios|tvos { DEFINES += QT_IOS_BLUETOOTH LIBS_PRIVATE += -framework Foundation -framework CoreBluetooth diff --git a/src/bluetooth/osx/osxbt.pri b/src/bluetooth/osx/osxbt.pri index 89276310..8f6ea0d1 100644 --- a/src/bluetooth/osx/osxbt.pri +++ b/src/bluetooth/osx/osxbt.pri @@ -20,7 +20,6 @@ CONFIG(osx) { osx/osxbtsdpinquiry_p.h \ osx/osxbtrfcommchannel_p.h \ osx/osxbtl2capchannel_p.h \ - osx/osxbtchanneldelegate_p.h \ osx/osxbtservicerecord_p.h \ osx/osxbtsocketlistener_p.h \ osx/osxbtobexsession_p.h \ @@ -37,7 +36,6 @@ CONFIG(osx) { osx/osxbtsdpinquiry.mm \ osx/osxbtrfcommchannel.mm \ osx/osxbtl2capchannel.mm \ - osx/osxbtchanneldelegate.mm \ osx/osxbtservicerecord.mm \ osx/osxbtsocketlistener.mm \ osx/osxbtobexsession.mm \ diff --git a/src/bluetooth/osx/osxbtchanneldelegate.mm b/src/bluetooth/osx/osxbtchanneldelegate.mm deleted file mode 100644 index 822e9d4e..00000000 --- a/src/bluetooth/osx/osxbtchanneldelegate.mm +++ /dev/null @@ -1,52 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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 "osxbtchanneldelegate_p.h" - -QT_BEGIN_NAMESPACE - -namespace OSXBluetooth { - -ChannelDelegate::~ChannelDelegate() -{ -} - -} - -QT_END_NAMESPACE diff --git a/src/bluetooth/osx/osxbtchanneldelegate_p.h b/src/bluetooth/osx/osxbtchanneldelegate_p.h deleted file mode 100644 index 1102e935..00000000 --- a/src/bluetooth/osx/osxbtchanneldelegate_p.h +++ /dev/null @@ -1,79 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef OSXBTCHANNELDELEGATE_P_H -#define OSXBTCHANNELDELEGATE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qglobal.h> - -#include <IOKit/IOReturn.h> - -QT_BEGIN_NAMESPACE - -namespace OSXBluetooth { - -class ChannelDelegate -{ -public: - virtual ~ChannelDelegate(); - - virtual void setChannelError(IOReturn errorCode) = 0; - virtual void channelOpenComplete() = 0; - virtual void channelClosed() = 0; - - virtual void readChannelData(void *data, std::size_t size) = 0; - virtual void writeComplete() = 0; -}; - -} - -QT_END_NAMESPACE - -#endif diff --git a/src/bluetooth/osx/osxbtl2capchannel.mm b/src/bluetooth/osx/osxbtl2capchannel.mm index dc8468a0..03e3a982 100644 --- a/src/bluetooth/osx/osxbtl2capchannel.mm +++ b/src/bluetooth/osx/osxbtl2capchannel.mm @@ -37,10 +37,10 @@ ** ****************************************************************************/ -#include "osxbtchanneldelegate_p.h" #include "osxbtl2capchannel_p.h" #include "qbluetoothaddress.h" #include "osxbtutility_p.h" +#include "btdelegates_p.h" #include <QtCore/qloggingcategory.h> #include <QtCore/qdebug.h> @@ -49,13 +49,13 @@ QT_USE_NAMESPACE @implementation QT_MANGLE_NAMESPACE(OSXBTL2CAPChannel) { - QT_PREPEND_NAMESPACE(OSXBluetooth)::ChannelDelegate *delegate; + QT_PREPEND_NAMESPACE(DarwinBluetooth)::ChannelDelegate *delegate; IOBluetoothDevice *device; IOBluetoothL2CAPChannel *channel; bool connected; } -- (id)initWithDelegate:(OSXBluetooth::ChannelDelegate *)aDelegate +- (id)initWithDelegate:(DarwinBluetooth::ChannelDelegate *)aDelegate { Q_ASSERT_X(aDelegate, Q_FUNC_INFO, "invalid delegate (null)"); @@ -69,7 +69,7 @@ QT_USE_NAMESPACE return self; } -- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(OSXBluetooth::ChannelDelegate) *)aDelegate +- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(DarwinBluetooth::ChannelDelegate) *)aDelegate channel:(IOBluetoothL2CAPChannel *)aChannel { // This type of channel does not require connect, it's created with diff --git a/src/bluetooth/osx/osxbtl2capchannel_p.h b/src/bluetooth/osx/osxbtl2capchannel_p.h index 512087b4..42eec8e7 100644 --- a/src/bluetooth/osx/osxbtl2capchannel_p.h +++ b/src/bluetooth/osx/osxbtl2capchannel_p.h @@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE class QBluetoothAddress; -namespace OSXBluetooth { +namespace DarwinBluetooth { class ChannelDelegate; @@ -73,8 +73,8 @@ QT_END_NAMESPACE @interface QT_MANGLE_NAMESPACE(OSXBTL2CAPChannel) : NSObject<IOBluetoothL2CAPChannelDelegate> -- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(OSXBluetooth)::ChannelDelegate *)aDelegate; -- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(OSXBluetooth)::ChannelDelegate *)aDelegate +- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(DarwinBluetooth)::ChannelDelegate *)aDelegate; +- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(DarwinBluetooth)::ChannelDelegate *)aDelegate channel:(IOBluetoothL2CAPChannel *)aChannel; - (void)dealloc; diff --git a/src/bluetooth/osx/osxbtrfcommchannel.mm b/src/bluetooth/osx/osxbtrfcommchannel.mm index 00b67ee0..d2d3e2f8 100644 --- a/src/bluetooth/osx/osxbtrfcommchannel.mm +++ b/src/bluetooth/osx/osxbtrfcommchannel.mm @@ -37,22 +37,22 @@ ** ****************************************************************************/ -#include "osxbtchanneldelegate_p.h" #include "osxbtrfcommchannel_p.h" #include "qbluetoothaddress.h" #include "osxbtutility_p.h" +#include "btdelegates_p.h" QT_USE_NAMESPACE @implementation QT_MANGLE_NAMESPACE(OSXBTRFCOMMChannel) { - QT_PREPEND_NAMESPACE(OSXBluetooth)::ChannelDelegate *delegate; + QT_PREPEND_NAMESPACE(DarwinBluetooth)::ChannelDelegate *delegate; IOBluetoothDevice *device; IOBluetoothRFCOMMChannel *channel; bool connected; } -- (id)initWithDelegate:(OSXBluetooth::ChannelDelegate *)aDelegate +- (id)initWithDelegate:(DarwinBluetooth::ChannelDelegate *)aDelegate { Q_ASSERT_X(aDelegate, Q_FUNC_INFO, "invalid delegate (null)"); @@ -66,7 +66,7 @@ QT_USE_NAMESPACE return self; } -- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(OSXBluetooth::ChannelDelegate) *)aDelegate +- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(DarwinBluetooth::ChannelDelegate) *)aDelegate channel:(IOBluetoothRFCOMMChannel *)aChannel { // This type of channel does not require connect, it's created with diff --git a/src/bluetooth/osx/osxbtrfcommchannel_p.h b/src/bluetooth/osx/osxbtrfcommchannel_p.h index 775999ed..44416cce 100644 --- a/src/bluetooth/osx/osxbtrfcommchannel_p.h +++ b/src/bluetooth/osx/osxbtrfcommchannel_p.h @@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE class QBluetoothAddress; -namespace OSXBluetooth { +namespace DarwinBluetooth { class ChannelDelegate; @@ -73,8 +73,8 @@ QT_END_NAMESPACE @interface QT_MANGLE_NAMESPACE(OSXBTRFCOMMChannel) : NSObject<IOBluetoothRFCOMMChannelDelegate> -- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(OSXBluetooth)::ChannelDelegate *)aDelegate; -- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(OSXBluetooth)::ChannelDelegate *)aDelegate +- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(DarwinBluetooth)::ChannelDelegate *)aDelegate; +- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(DarwinBluetooth)::ChannelDelegate *)aDelegate channel:(IOBluetoothRFCOMMChannel *)aChannel; - (void)dealloc; diff --git a/src/bluetooth/qbluetoothserver_osx.mm b/src/bluetooth/qbluetoothserver_osx.mm index 325381c8..9674331d 100644 --- a/src/bluetooth/qbluetoothserver_osx.mm +++ b/src/bluetooth/qbluetoothserver_osx.mm @@ -389,10 +389,10 @@ QBluetoothSocket *QBluetoothServer::nextPendingConnection() d_ptr->pendingConnections.pop_front(); if (d_ptr->serverType == ServiceInfo::RfcommProtocol) { - if (!newSocket->d_ptr->setChannel(channel.getAs<IOBluetoothRFCOMMChannel>())) + if (!static_cast<QBluetoothSocketPrivate *>(newSocket->d_ptr)->setRFCOMChannel(channel.getAs<IOBluetoothRFCOMMChannel>())) return nullptr; } else { - if (!newSocket->d_ptr->setChannel(channel.getAs<IOBluetoothL2CAPChannel>())) + if (!static_cast<QBluetoothSocketPrivate *>(newSocket->d_ptr)->setL2CAPChannel(channel.getAs<IOBluetoothL2CAPChannel>())) return nullptr; } diff --git a/src/bluetooth/qbluetoothsocket.cpp b/src/bluetooth/qbluetoothsocket.cpp index db7c8be4..b1f75741 100644 --- a/src/bluetooth/qbluetoothsocket.cpp +++ b/src/bluetooth/qbluetoothsocket.cpp @@ -47,6 +47,8 @@ #include "qbluetoothsocket_android_p.h" #elif defined(QT_WINRT_BLUETOOTH) #include "qbluetoothsocket_winrt_p.h" +#elif defined(QT_OSX_BLUETOOTH) +#include "qbluetoothsocket_osx_p.h" #else #include "qbluetoothsocket_dummy_p.h" #endif @@ -267,6 +269,8 @@ static QBluetoothSocketBasePrivate *createSocketPrivate() return new QBluetoothSocketPrivateAndroid(); #elif defined(QT_WINRT_BLUETOOTH) return new QBluetoothSocketPrivateWinRT(); +#elif defined(QT_OSX_BLUETOOTH) + return new QBluetoothSocketPrivate(); #else return new QBluetoothSocketPrivateDummy(); #endif @@ -513,6 +517,9 @@ QString QBluetoothSocket::errorString() const */ void QBluetoothSocket::setPreferredSecurityFlags(QBluetooth::SecurityFlags flags) { +#ifdef QT_OSX_BLUETOOTH + return; // not supported on macOS. +#endif Q_D(QBluetoothSocketBase); if (d->secFlags != flags) d->secFlags = flags; @@ -534,8 +541,13 @@ void QBluetoothSocket::setPreferredSecurityFlags(QBluetooth::SecurityFlags flags */ QBluetooth::SecurityFlags QBluetoothSocket::preferredSecurityFlags() const { +#if QT_OSX_BLUETOOTH + // not supported on macOS - platform always uses encryption + return QBluetooth::Secure; +#else Q_D(const QBluetoothSocketBase); return d->secFlags; +#endif // QT_OSX_BLUETOOTH } /*! @@ -559,6 +571,9 @@ void QBluetoothSocket::setSocketState(QBluetoothSocket::SocketState state) emit disconnected(); } if(state == ListeningState){ +#ifdef QT_OSX_BLUETOOTH + qCWarning(QT_BT) << "listening socket is not supported by IOBluetooth"; +#endif // TODO: look at this, is this really correct? // if we're a listening socket we can't handle connects? if (d->readNotifier) { diff --git a/src/bluetooth/qbluetoothsocket.h b/src/bluetooth/qbluetoothsocket.h index d2535544..256a95dc 100644 --- a/src/bluetooth/qbluetoothsocket.h +++ b/src/bluetooth/qbluetoothsocket.h @@ -52,21 +52,14 @@ QT_BEGIN_NAMESPACE -#ifndef QT_OSX_BLUETOOTH + class QBluetoothSocketBasePrivate; -#else -class QBluetoothSocketPrivate; -#endif class Q_BLUETOOTH_EXPORT QBluetoothSocket : public QIODevice { Q_OBJECT -#ifndef QT_OSX_BLUETOOTH - Q_DECLARE_PRIVATE(QBluetoothSocketBase) -#else - Q_DECLARE_PRIVATE(QBluetoothSocket) -#endif + Q_DECLARE_PRIVATE(QBluetoothSocketBase) friend class QBluetoothServer; friend class QBluetoothServerPrivate; @@ -187,11 +180,8 @@ protected: QBluetoothServiceInfo::Protocol socketType, QObject *parent = nullptr); #endif -#ifndef QT_OSX_BLUETOOTH + QBluetoothSocketBasePrivate *d_ptr; -#else - QBluetoothSocketPrivate *d_ptr; -#endif private: friend class QLowEnergyControllerPrivateBluez; diff --git a/src/bluetooth/qbluetoothsocket_osx.mm b/src/bluetooth/qbluetoothsocket_osx.mm index 7f630146..f74c14f8 100644 --- a/src/bluetooth/qbluetoothsocket_osx.mm +++ b/src/bluetooth/qbluetoothsocket_osx.mm @@ -43,6 +43,9 @@ // dependencies problem. #include "qbluetoothsocketbase_p.h" #include "qbluetoothsocket_osx_p.h" + +#include "osx/osxbtrfcommchannel_p.h" +#include "osx/osxbtl2capchannel_p.h" #include "qbluetoothlocaldevice.h" #include "qbluetoothdeviceinfo.h" #include "osx/osxbtutility_p.h" @@ -57,30 +60,294 @@ QT_BEGIN_NAMESPACE +namespace { + +using DarwinBluetooth::RetainPolicy; +using ObjCL2CAPChannel = QT_MANGLE_NAMESPACE(OSXBTL2CAPChannel); +using ObjCRFCOMMChannel = QT_MANGLE_NAMESPACE(OSXBTRFCOMMChannel); + +} // unnamed namespace + QBluetoothSocketPrivate::QBluetoothSocketPrivate() - : writeChunk(std::numeric_limits<UInt16>::max()), - openMode(QIODevice::NotOpen), // That's what is set in public class' ctors. - state(QBluetoothSocket::UnconnectedState), - socketType(QBluetoothServiceInfo::UnknownProtocol), - socketError(QBluetoothSocket::NoSocketError), - isConnecting(false) + : writeChunk(std::numeric_limits<UInt16>::max()) { q_ptr = nullptr; } QBluetoothSocketPrivate::~QBluetoothSocketPrivate() { - // "Empty" dtor to make a shared pointer happy (parametrized with - // incomplete type in the header file). +} + +bool QBluetoothSocketPrivate::ensureNativeSocket(QBluetoothServiceInfo::Protocol type) +{ + // For now - very simplistic, we don't call it in this file, public class + // only calls it in a ctor, setting the protocol RFCOMM (in case of Android) + // or, indeed, doing, socket-related initialization in BlueZ backend. + Q_ASSERT(socketType == QBluetoothServiceInfo::UnknownProtocol); + socketType = type; + return type != QBluetoothServiceInfo::UnknownProtocol; +} + +QString QBluetoothSocketPrivate::localName() const +{ + const QBluetoothLocalDevice device; + return device.name(); +} + +QBluetoothAddress QBluetoothSocketPrivate::localAddress() const +{ + const QBluetoothLocalDevice device; + return device.address(); +} + +quint16 QBluetoothSocketPrivate::localPort() const +{ + return 0; +} + +QString QBluetoothSocketPrivate::peerName() const +{ + QT_BT_MAC_AUTORELEASEPOOL; + + NSString *nsName = nil; + if (socketType == QBluetoothServiceInfo::RfcommProtocol) { + if (rfcommChannel) + nsName = [rfcommChannel.getAs<ObjCRFCOMMChannel>() peerName]; + } else if (socketType == QBluetoothServiceInfo::L2capProtocol) { + if (l2capChannel) + nsName = [l2capChannel.getAs<ObjCL2CAPChannel>() peerName]; + } + + if (nsName) + return QString::fromNSString(nsName); + + return QString(); +} + +QBluetoothAddress QBluetoothSocketPrivate::peerAddress() const +{ + BluetoothDeviceAddress addr = {}; + if (socketType == QBluetoothServiceInfo::RfcommProtocol) { + if (rfcommChannel) + addr = [rfcommChannel.getAs<ObjCRFCOMMChannel>() peerAddress]; + } else if (socketType == QBluetoothServiceInfo::L2capProtocol) { + if (l2capChannel) + addr = [l2capChannel.getAs<ObjCL2CAPChannel>() peerAddress]; + } + + return OSXBluetooth::qt_address(&addr); +} + +quint16 QBluetoothSocketPrivate::peerPort() const +{ + if (socketType == QBluetoothServiceInfo::RfcommProtocol) { + if (rfcommChannel) + return [rfcommChannel.getAs<ObjCRFCOMMChannel>() getChannelID]; + } else if (socketType == QBluetoothServiceInfo::L2capProtocol) { + if (l2capChannel) + return [l2capChannel.getAs<ObjCL2CAPChannel>() getPSM]; + } + + return 0; +} + +void QBluetoothSocketPrivate::abort() +{ + // Can never be called while we're in connectToService: + Q_ASSERT_X(!isConnecting, Q_FUNC_INFO, "internal inconsistency - " + "still in connectToService()"); + + if (socketType == QBluetoothServiceInfo::RfcommProtocol) + rfcommChannel.reset(); + else if (socketType == QBluetoothServiceInfo::L2capProtocol) + l2capChannel.reset(); + + Q_ASSERT(q_ptr); + + q_ptr->setSocketState(QBluetoothSocket::UnconnectedState); + emit q_ptr->readChannelFinished(); + emit q_ptr->disconnected(); + +} + +void QBluetoothSocketPrivate::close() +{ + // Can never be called while we're in connectToService: + Q_ASSERT_X(!isConnecting, Q_FUNC_INFO, "internal inconsistency - " + "still in connectToService()"); + + if (!txBuffer.size()) + abort(); +} + + +qint64 QBluetoothSocketPrivate::writeData(const char *data, qint64 maxSize) +{ + Q_ASSERT_X(data, Q_FUNC_INFO, "invalid data (null)"); + Q_ASSERT_X(maxSize > 0, Q_FUNC_INFO, "invalid data size"); + + if (state != QBluetoothSocket::ConnectedState) { + errorString = QCoreApplication::translate(SOCKET, SOC_NOWRITE); + q_ptr->setSocketError(QBluetoothSocket::OperationError); + return -1; + } + + // We do not have a real socket API under the hood, + // IOBluetoothL2CAPChannel is buffered (writeAsync). + + if (!txBuffer.size()) + QMetaObject::invokeMethod(this, "_q_writeNotify", Qt::QueuedConnection); + + char *dst = txBuffer.reserve(int(maxSize)); + std::copy(data, data + maxSize, dst); + + return maxSize; +} + +qint64 QBluetoothSocketPrivate::readData(char *data, qint64 maxSize) +{ + if (!data) + return 0; + + if (state != QBluetoothSocket::ConnectedState) { + errorString = QCoreApplication::translate(SOCKET, SOC_NOREAD); + q_ptr->setSocketError(QBluetoothSocket::OperationError); + return -1; + } + + if (!buffer.isEmpty()) + return buffer.read(data, int(maxSize)); + + return 0; +} + +qint64 QBluetoothSocketPrivate::bytesAvailable() const +{ + return buffer.size(); +} + +bool QBluetoothSocketPrivate::canReadLine() const +{ + return buffer.canReadLine(); +} + +qint64 QBluetoothSocketPrivate::bytesToWrite() const +{ + return txBuffer.size(); +} + +bool QBluetoothSocketPrivate::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType, + QBluetoothSocket::SocketState socketState, QIODevice::OpenMode openMode) +{ + Q_UNUSED(socketDescriptor) + Q_UNUSED(socketType) + Q_UNUSED(socketState) + Q_UNUSED(openMode) + + qCWarning(QT_BT_OSX) << "setting a socket descriptor is not supported by IOBluetooth"; + // Noop on macOS. + return true; +} + +void QBluetoothSocketPrivate::connectToServiceHelper(const QBluetoothAddress &address, quint16 port, + QIODevice::OpenMode openMode) +{ + Q_UNUSED(address) + Q_UNUSED(port) + Q_UNUSED(openMode) +} + +void QBluetoothSocketPrivate::connectToService(const QBluetoothServiceInfo &service, QIODevice::OpenMode openMode) +{ + Q_ASSERT(q_ptr); + + OSXBluetooth::qt_test_iobluetooth_runloop(); + + if (state!= QBluetoothSocket::UnconnectedState && state != QBluetoothSocket::ServiceLookupState) { + qCWarning(QT_BT_OSX) << "called on a busy socket"; + errorString = QCoreApplication::translate(SOCKET, SOC_CONNECT_IN_PROGRESS); + q_ptr->setSocketError(QBluetoothSocket::OperationError); + return; + } + + // Report this problem early, potentially avoid device discovery: + if (service.socketProtocol() == QBluetoothServiceInfo::UnknownProtocol) { + qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "cannot connect with 'UnknownProtocol' type"; + errorString = QCoreApplication::translate(SOCKET, SOC_NETWORK_ERROR); + q_ptr->setSocketError(QBluetoothSocket::UnsupportedProtocolError); + return; + } + + socketType = service.socketProtocol(); + + if (service.protocolServiceMultiplexer() > 0) { + connectToService(service.device().address(), + quint16(service.protocolServiceMultiplexer()), + openMode); + } else if (service.serverChannel() > 0) { + connectToService(service.device().address(), + quint16(service.serverChannel()), + openMode); + } else { + // Try service discovery. + if (service.serviceUuid().isNull()) { + qCWarning(QT_BT_OSX) << "No port, no PSM, and no " + "UUID provided, unable to connect"; + return; + } + + q_ptr->doDeviceDiscovery(service, openMode); + } +} + +void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid, + QIODevice::OpenMode openMode) +{ + Q_ASSERT(q_ptr); + + OSXBluetooth::qt_test_iobluetooth_runloop(); + + // Report this problem early, avoid device discovery: + if (socketType == QBluetoothServiceInfo::UnknownProtocol) { + qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "cannot connect with 'UnknownProtocol' type"; + errorString = QCoreApplication::translate(SOCKET, SOC_NETWORK_ERROR); + q_ptr->setSocketError(QBluetoothSocket::UnsupportedProtocolError); + return; + } + + if (state != QBluetoothSocket::UnconnectedState) { + qCWarning(QT_BT_OSX) << "called on a busy socket"; + errorString = QCoreApplication::translate(SOCKET, SOC_CONNECT_IN_PROGRESS); + q_ptr->setSocketError(QBluetoothSocket::OperationError); + return; + } + + QBluetoothDeviceInfo device(address, QString(), QBluetoothDeviceInfo::MiscellaneousDevice); + QBluetoothServiceInfo service; + service.setDevice(device); + service.setServiceUuid(uuid); + q_ptr->doDeviceDiscovery(service, openMode); } void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode mode) { - Q_ASSERT_X(state == QBluetoothSocket::ServiceLookupState - || state == QBluetoothSocket::UnconnectedState, + Q_ASSERT(q_ptr); + + OSXBluetooth::qt_test_iobluetooth_runloop(); + + if (socketType == QBluetoothServiceInfo::UnknownProtocol) { + qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "cannot connect with 'UnknownProtocol' type"; + errorString = QCoreApplication::translate(SOCKET, SOC_NETWORK_ERROR); + q_ptr->setSocketError(QBluetoothSocket::UnsupportedProtocolError); + return; + } + + Q_ASSERT_X(state == QBluetoothSocket::ServiceLookupState || state == QBluetoothSocket::UnconnectedState, Q_FUNC_INFO, "invalid state"); + q_ptr->setOpenMode(mode); + socketError = QBluetoothSocket::NoSocketError; errorString.clear(); buffer.clear(); @@ -100,15 +367,15 @@ void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address, openMode = mode; if (socketType == QBluetoothServiceInfo::RfcommProtocol) { - rfcommChannel.reset([[ObjCRFCOMMChannel alloc] initWithDelegate:this]); + rfcommChannel.reset([[ObjCRFCOMMChannel alloc] initWithDelegate:this], RetainPolicy::noInitialRetain); if (rfcommChannel) - status = [rfcommChannel connectAsyncToDevice:address withChannelID:port]; + status = [rfcommChannel.getAs<ObjCRFCOMMChannel>() connectAsyncToDevice:address withChannelID:port]; else status = kIOReturnNoMemory; } else if (socketType == QBluetoothServiceInfo::L2capProtocol) { - l2capChannel.reset([[ObjCL2CAPChannel alloc] initWithDelegate:this]); + l2capChannel.reset([[ObjCL2CAPChannel alloc] initWithDelegate:this], RetainPolicy::noInitialRetain); if (l2capChannel) - status = [l2capChannel connectAsyncToDevice:address withPSM:port]; + status = [l2capChannel.getAs<ObjCL2CAPChannel>() connectAsyncToDevice:address withPSM:port]; else status = kIOReturnNoMemory; } @@ -148,84 +415,6 @@ void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address, } } -void QBluetoothSocketPrivate::close() -{ - // Can never be called while we're in connectToService: - Q_ASSERT_X(!isConnecting, Q_FUNC_INFO, "internal inconsistency - " - "still in connectToService()"); - - if (!txBuffer.size()) - abort(); -} - -void QBluetoothSocketPrivate::abort() -{ - // Can never be called while we're in connectToService: - Q_ASSERT_X(!isConnecting, Q_FUNC_INFO, "internal inconsistency - " - "still in connectToService()"); - - if (socketType == QBluetoothServiceInfo::RfcommProtocol) - rfcommChannel.reset(nil); - else if (socketType == QBluetoothServiceInfo::L2capProtocol) - l2capChannel.reset(nil); -} - -quint64 QBluetoothSocketPrivate::bytesAvailable() const -{ - return buffer.size(); -} - -QString QBluetoothSocketPrivate::peerName() const -{ - QT_BT_MAC_AUTORELEASEPOOL; - - NSString *nsName = nil; - if (socketType == QBluetoothServiceInfo::RfcommProtocol) { - if (rfcommChannel) - nsName = [rfcommChannel peerName]; - } else if (socketType == QBluetoothServiceInfo::L2capProtocol) { - if (l2capChannel) - nsName = [l2capChannel peerName]; - } - - if (nsName) - return QString::fromNSString(nsName); - - return QString(); -} - -QBluetoothAddress QBluetoothSocketPrivate::peerAddress() const -{ - BluetoothDeviceAddress addr = {}; - if (socketType == QBluetoothServiceInfo::RfcommProtocol) { - if (rfcommChannel) - addr = [rfcommChannel peerAddress]; - } else if (socketType == QBluetoothServiceInfo::L2capProtocol) { - if (l2capChannel) - addr = [l2capChannel peerAddress]; - } - - return OSXBluetooth::qt_address(&addr); -} - -quint16 QBluetoothSocketPrivate::peerPort() const -{ - if (socketType == QBluetoothServiceInfo::RfcommProtocol) { - if (rfcommChannel) - return [rfcommChannel getChannelID]; - } else if (socketType == QBluetoothServiceInfo::L2capProtocol) { - if (l2capChannel) - return [l2capChannel getPSM]; - } - - return 0; -} - -void QBluetoothSocketPrivate::_q_readNotify() -{ - // Noop. -} - void QBluetoothSocketPrivate::_q_writeNotify() { Q_ASSERT_X(socketType == QBluetoothServiceInfo::L2capProtocol @@ -238,14 +427,14 @@ void QBluetoothSocketPrivate::_q_writeNotify() if (txBuffer.size()) { const bool isL2CAP = socketType == QBluetoothServiceInfo::L2capProtocol; writeChunk.resize(isL2CAP ? std::numeric_limits<UInt16>::max() : - [rfcommChannel getMTU]); + [rfcommChannel.getAs<ObjCRFCOMMChannel>() getMTU]); const int size = txBuffer.read(writeChunk.data(), writeChunk.size()); IOReturn status = kIOReturnError; if (!isL2CAP) - status = [rfcommChannel writeAsync:writeChunk.data() length:UInt16(size)]; + status = [rfcommChannel.getAs<ObjCRFCOMMChannel>() writeAsync:writeChunk.data() length:UInt16(size)]; else - status = [l2capChannel writeAsync:writeChunk.data() length:UInt16(size)]; + status = [l2capChannel.getAs<ObjCL2CAPChannel>() writeAsync:writeChunk.data() length:UInt16(size)]; if (status != kIOReturnSuccess) { errorString = QCoreApplication::translate(SOCKET, SOC_NETWORK_ERROR); @@ -260,21 +449,22 @@ void QBluetoothSocketPrivate::_q_writeNotify() close(); } -bool QBluetoothSocketPrivate::setChannel(IOBluetoothRFCOMMChannel *channel) +bool QBluetoothSocketPrivate::setRFCOMChannel(void *generic) { // A special case "constructor": on OS X we do not have a real listening socket, // instead a bluetooth server "listens" for channel open notifications and // creates (if asked by a user later) a "socket" object // for this connection. This function initializes // a "socket" from such an external channel (reported by a notification). - + auto channel = static_cast<IOBluetoothRFCOMMChannel *>(generic); // It must be a newborn socket! Q_ASSERT_X(socketError == QBluetoothSocket::NoSocketError && state == QBluetoothSocket::UnconnectedState && !rfcommChannel && !l2capChannel, Q_FUNC_INFO, "unexpected socket state"); openMode = QIODevice::ReadWrite; - rfcommChannel.reset([[ObjCRFCOMMChannel alloc] initWithDelegate:this channel:channel]); + rfcommChannel.reset([[ObjCRFCOMMChannel alloc] initWithDelegate:this channel:channel], + RetainPolicy::noInitialRetain); if (rfcommChannel) {// We do not handle errors, up to an external user. q_ptr->setOpenMode(QIODevice::ReadWrite); state = QBluetoothSocket::ConnectedState; @@ -284,13 +474,14 @@ bool QBluetoothSocketPrivate::setChannel(IOBluetoothRFCOMMChannel *channel) return rfcommChannel; } -bool QBluetoothSocketPrivate::setChannel(IOBluetoothL2CAPChannel *channel) +bool QBluetoothSocketPrivate::setL2CAPChannel(void *generic) { // A special case "constructor": on OS X we do not have a real listening socket, // instead a bluetooth server "listens" for channel open notifications and // creates (if asked by a user later) a "socket" object // for this connection. This function initializes // a "socket" from such an external channel (reported by a notification). + auto channel = static_cast<IOBluetoothL2CAPChannel *>(generic); // It must be a newborn socket! Q_ASSERT_X(socketError == QBluetoothSocket::NoSocketError @@ -298,7 +489,7 @@ bool QBluetoothSocketPrivate::setChannel(IOBluetoothL2CAPChannel *channel) Q_FUNC_INFO, "unexpected socket state"); openMode = QIODevice::ReadWrite; - l2capChannel.reset([[ObjCL2CAPChannel alloc] initWithDelegate:this channel:channel]); + l2capChannel.reset([[ObjCL2CAPChannel alloc] initWithDelegate:this channel:channel], RetainPolicy::noInitialRetain); if (l2capChannel) {// We do not handle errors, up to an external user. q_ptr->setOpenMode(QIODevice::ReadWrite); state = QBluetoothSocket::ConnectedState; @@ -308,7 +499,6 @@ bool QBluetoothSocketPrivate::setChannel(IOBluetoothL2CAPChannel *channel) return l2capChannel; } - void QBluetoothSocketPrivate::setChannelError(IOReturn errorCode) { Q_UNUSED(errorCode) @@ -365,7 +555,7 @@ void QBluetoothSocketPrivate::readChannelData(void *data, std::size_t size) Q_ASSERT_X(q_ptr, Q_FUNC_INFO, "invalid q_ptr (null)"); const char *src = static_cast<char *>(data); - char *dst = buffer.reserve(size); + char *dst = buffer.reserve(int(size)); std::copy(src, src + size, dst); if (!isConnecting) { @@ -379,449 +569,4 @@ void QBluetoothSocketPrivate::writeComplete() _q_writeNotify(); } -qint64 QBluetoothSocketPrivate::writeData(const char *data, qint64 maxSize) -{ - Q_ASSERT_X(data, Q_FUNC_INFO, "invalid data (null)"); - Q_ASSERT_X(maxSize > 0, Q_FUNC_INFO, "invalid data size"); - - if (state != QBluetoothSocket::ConnectedState) { - errorString = QCoreApplication::translate(SOCKET, SOC_NOWRITE); - q_ptr->setSocketError(QBluetoothSocket::OperationError); - return -1; - } - - // We do not have a real socket API under the hood, - // IOBluetoothL2CAPChannel buffered (writeAsync). - - if (!txBuffer.size()) - QMetaObject::invokeMethod(this, "_q_writeNotify", Qt::QueuedConnection); - - char *dst = txBuffer.reserve(maxSize); - std::copy(data, data + maxSize, dst); - - return maxSize; -} - -QBluetoothSocket::QBluetoothSocket(QBluetoothServiceInfo::Protocol socketType, QObject *parent) - : QIODevice(parent), - d_ptr(new QBluetoothSocketPrivate) -{ - d_ptr->q_ptr = this; - d_ptr->socketType = socketType; - - setOpenMode(NotOpen); -} - -QBluetoothSocket::QBluetoothSocket(QObject *parent) - : QIODevice(parent), - d_ptr(new QBluetoothSocketPrivate) -{ - d_ptr->q_ptr = this; - setOpenMode(NotOpen); -} - -QBluetoothSocket::~QBluetoothSocket() -{ - delete d_ptr; -} - -bool QBluetoothSocket::isSequential() const -{ - return true; -} - -qint64 QBluetoothSocket::bytesAvailable() const -{ - return QIODevice::bytesAvailable() + d_ptr->bytesAvailable(); -} - -qint64 QBluetoothSocket::bytesToWrite() const -{ - return d_ptr->txBuffer.size(); -} - -void QBluetoothSocket::connectToService(const QBluetoothServiceInfo &service, OpenMode openMode) -{ - OSXBluetooth::qt_test_iobluetooth_runloop(); - - if (state() != UnconnectedState && state() != ServiceLookupState) { - qCWarning(QT_BT_OSX) << "called on a busy socket"; - d_ptr->errorString = QCoreApplication::translate(SOCKET, SOC_CONNECT_IN_PROGRESS); - setSocketError(OperationError); - return; - } - - // Report this problem early, potentially avoid device discovery: - if (service.socketProtocol() == QBluetoothServiceInfo::UnknownProtocol) { - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "cannot connect with 'UnknownProtocol' type"; - d_ptr->errorString = QCoreApplication::translate(SOCKET, SOC_NETWORK_ERROR); - setSocketError(QBluetoothSocket::UnsupportedProtocolError); - return; - } - - d_ptr->socketType = service.socketProtocol(); - - if (service.protocolServiceMultiplexer() > 0) { - d_ptr->connectToService(service.device().address(), - service.protocolServiceMultiplexer(), - openMode); - } else if (service.serverChannel() > 0) { - d_ptr->connectToService(service.device().address(), - service.serverChannel(), openMode); - } else { - // Try service discovery. - if (service.serviceUuid().isNull()) { - qCWarning(QT_BT_OSX) << "No port, no PSM, and no " - "UUID provided, unable to connect"; - return; - } - - doDeviceDiscovery(service, openMode); - } -} - -void QBluetoothSocket::connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid, - OpenMode openMode) -{ - OSXBluetooth::qt_test_iobluetooth_runloop(); - - // Report this problem early, avoid device discovery: - if (socketType() == QBluetoothServiceInfo::UnknownProtocol) { - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "cannot connect with 'UnknownProtocol' type"; - d_ptr->errorString = QCoreApplication::translate(SOCKET, SOC_NETWORK_ERROR); - setSocketError(QBluetoothSocket::UnsupportedProtocolError); - return; - } - - if (state() != QBluetoothSocket::UnconnectedState) { - qCWarning(QT_BT_OSX) << "called on a busy socket"; - d_ptr->errorString = QCoreApplication::translate(SOCKET, SOC_CONNECT_IN_PROGRESS); - setSocketError(QBluetoothSocket::OperationError); - return; - } - - QBluetoothDeviceInfo device(address, QString(), QBluetoothDeviceInfo::MiscellaneousDevice); - QBluetoothServiceInfo service; - service.setDevice(device); - service.setServiceUuid(uuid); - doDeviceDiscovery(service, openMode); -} - -void QBluetoothSocket::connectToService(const QBluetoothAddress &address, quint16 port, - OpenMode openMode) -{ - OSXBluetooth::qt_test_iobluetooth_runloop(); - - if (socketType() == QBluetoothServiceInfo::UnknownProtocol) { - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "cannot connect with 'UnknownProtocol' type"; - d_ptr->errorString = QCoreApplication::translate(SOCKET, SOC_NETWORK_ERROR); - setSocketError(QBluetoothSocket::UnsupportedProtocolError); - return; - } - - if (state() != QBluetoothSocket::UnconnectedState) { - qCWarning(QT_BT_OSX) << "called on a busy socket"; - d_ptr->errorString = QCoreApplication::translate(SOCKET, SOC_CONNECT_IN_PROGRESS); - setSocketError(OperationError); - return; - } - - setOpenMode(openMode); - d_ptr->connectToService(address, port, openMode); -} - -QBluetoothServiceInfo::Protocol QBluetoothSocket::socketType() const -{ - return d_ptr->socketType; -} - -QBluetoothSocket::SocketState QBluetoothSocket::state() const -{ - return d_ptr->state; -} - -QBluetoothSocket::SocketError QBluetoothSocket::error() const -{ - return d_ptr->socketError; -} - -QString QBluetoothSocket::errorString() const -{ - return d_ptr->errorString; -} - -void QBluetoothSocket::setSocketState(QBluetoothSocket::SocketState state) -{ - const SocketState oldState = d_ptr->state; - d_ptr->state = state; - if (oldState != d_ptr->state) - emit stateChanged(state); - - if (state == ListeningState) { - // We can register for L2CAP/RFCOMM open notifications, - // that's different from 'listen' and is implemented - // in QBluetoothServer. - qCWarning(QT_BT_OSX) << "listening sockets are not supported"; - } -} - -bool QBluetoothSocket::canReadLine() const -{ - return d_ptr->buffer.canReadLine() || QIODevice::canReadLine(); -} - -void QBluetoothSocket::setSocketError(QBluetoothSocket::SocketError socketError) -{ - d_ptr->socketError = socketError; - emit error(socketError); -} - -void QBluetoothSocket::doDeviceDiscovery(const QBluetoothServiceInfo &service, OpenMode openMode) -{ - OSXBluetooth::qt_test_iobluetooth_runloop(); - - setSocketState(ServiceLookupState); - - if (d_ptr->discoveryAgent) - d_ptr->discoveryAgent->stop(); - - d_ptr->discoveryAgent.reset(new QBluetoothServiceDiscoveryAgent(this)); - d_ptr->discoveryAgent->setRemoteAddress(service.device().address()); - - connect(d_ptr->discoveryAgent.data(), SIGNAL(serviceDiscovered(QBluetoothServiceInfo)), - this, SLOT(serviceDiscovered(QBluetoothServiceInfo))); - connect(d_ptr->discoveryAgent.data(), SIGNAL(finished()), - this, SLOT(discoveryFinished())); - - d_ptr->openMode = openMode; - - if (!service.serviceUuid().isNull()) - d_ptr->discoveryAgent->setUuidFilter(service.serviceUuid()); - - if (!service.serviceClassUuids().isEmpty()) - d_ptr->discoveryAgent->setUuidFilter(service.serviceClassUuids()); - - Q_ASSERT_X(!d_ptr->discoveryAgent->uuidFilter().isEmpty(), Q_FUNC_INFO, - "invalid service info"); - - d_ptr->discoveryAgent->start(QBluetoothServiceDiscoveryAgent::FullDiscovery); -} - -void QBluetoothSocket::serviceDiscovered(const QBluetoothServiceInfo &service) -{ - if (service.protocolServiceMultiplexer() != 0 || service.serverChannel() != 0) { - d_ptr->discoveryAgent->stop(); - connectToService(service, d_ptr->openMode); - } -} - -void QBluetoothSocket::discoveryFinished() -{ - d_ptr->errorString = QCoreApplication::translate(SOCKET, SOC_SERVICE_NOT_FOUND); - setSocketState(UnconnectedState); - setSocketError(ServiceNotFoundError); -} - -void QBluetoothSocket::abort() -{ - if (state() == UnconnectedState) - return; - - setOpenMode(NotOpen); - - if (state() == ServiceLookupState && d_ptr->discoveryAgent) { - d_ptr->discoveryAgent->disconnect(); - d_ptr->discoveryAgent->stop(); - d_ptr->discoveryAgent.reset(); - } - - setSocketState(QBluetoothSocket::ClosingState); - d_ptr->abort(); - - setSocketState(QBluetoothSocket::UnconnectedState); - emit readChannelFinished(); - emit disconnected(); -} - -void QBluetoothSocket::disconnectFromService() -{ - close(); -} - -QString QBluetoothSocket::localName() const -{ - const QBluetoothLocalDevice device; - return device.name(); -} - -QBluetoothAddress QBluetoothSocket::localAddress() const -{ - const QBluetoothLocalDevice device; - return device.address(); -} - -quint16 QBluetoothSocket::localPort() const -{ - return 0; -} - -QString QBluetoothSocket::peerName() const -{ - return d_ptr->peerName(); -} - -QBluetoothAddress QBluetoothSocket::peerAddress() const -{ - return d_ptr->peerAddress(); -} - -quint16 QBluetoothSocket::peerPort() const -{ - return d_ptr->peerPort(); -} - -qint64 QBluetoothSocket::writeData(const char *data, qint64 maxSize) -{ - if (!data || maxSize <= 0) { - d_ptr->errorString = QCoreApplication::translate(SOCKET, SOC_INVAL_DATASIZE); - setSocketError(QBluetoothSocket::OperationError); - return -1; - } - - return d_ptr->writeData(data, maxSize); -} - -qint64 QBluetoothSocketPrivate::readData(char *data, qint64 maxSize) -{ - if (state != QBluetoothSocket::ConnectedState) { - errorString = QCoreApplication::translate(SOCKET, SOC_NOREAD); - q_ptr->setSocketError(QBluetoothSocket::OperationError); - return -1; - } - - if (!buffer.isEmpty()) - return buffer.read(data, maxSize); - - return 0; -} - -qint64 QBluetoothSocket::readData(char *data, qint64 maxSize) -{ - return d_ptr->readData(data, maxSize); -} - -void QBluetoothSocket::close() -{ - if (state() == UnconnectedState) - return; - - setOpenMode(NotOpen); - - if (state() == ServiceLookupState && d_ptr->discoveryAgent) { - d_ptr->discoveryAgent->disconnect(); - d_ptr->discoveryAgent->stop(); - d_ptr->discoveryAgent.reset(); - } - - setSocketState(ClosingState); - - d_ptr->close(); - - setSocketState(UnconnectedState); - emit readChannelFinished(); - emit disconnected(); -} - -bool QBluetoothSocket::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType, - SocketState socketState, OpenMode openMode) -{ - Q_UNUSED(socketDescriptor) - Q_UNUSED(socketType) - Q_UNUSED(socketState) - Q_UNUSED(openMode) - - // Noop on OS X. - return true; -} - -int QBluetoothSocket::socketDescriptor() const -{ - return -1; -} - -/* not supported on OS X */ -void QBluetoothSocket::setPreferredSecurityFlags(QBluetooth::SecurityFlags flags) -{ - Q_UNUSED(flags) -} - -/* not supported on OS X - platform always uses encryption */ -QBluetooth::SecurityFlags QBluetoothSocket::preferredSecurityFlags() const -{ - return QBluetooth::Secure; -} - -#ifndef QT_NO_DEBUG_STREAM - -QDebug operator<<(QDebug debug, QBluetoothSocket::SocketError error) -{ - switch (error) { - case QBluetoothSocket::UnknownSocketError: - debug << "QBluetoothSocket::UnknownSocketError"; - break; - case QBluetoothSocket::HostNotFoundError: - debug << "QBluetoothSocket::HostNotFoundError"; - break; - case QBluetoothSocket::RemoteHostClosedError: - debug << "QBluetoothSocket::RemoteHostClosedError"; - break; - case QBluetoothSocket::ServiceNotFoundError: - debug << "QBluetoothSocket::ServiceNotFoundError"; - break; - case QBluetoothSocket::NetworkError: - debug << "QBluetoothSocket::NetworkError"; - break; - case QBluetoothSocket::UnsupportedProtocolError: - debug << "QBluetoothSocket::UnsupportedProtocolError"; - break; - default: - debug << "QBluetoothSocket::SocketError(" << (int)error << ")"; - } - return debug; -} - -QDebug operator<<(QDebug debug, QBluetoothSocket::SocketState state) -{ - switch (state) { - case QBluetoothSocket::UnconnectedState: - debug << "QBluetoothSocket::UnconnectedState"; - break; - case QBluetoothSocket::ConnectingState: - debug << "QBluetoothSocket::ConnectingState"; - break; - case QBluetoothSocket::ConnectedState: - debug << "QBluetoothSocket::ConnectedState"; - break; - case QBluetoothSocket::BoundState: - debug << "QBluetoothSocket::BoundState"; - break; - case QBluetoothSocket::ClosingState: - debug << "QBluetoothSocket::ClosingState"; - break; - case QBluetoothSocket::ListeningState: - debug << "QBluetoothSocket::ListeningState"; - break; - case QBluetoothSocket::ServiceLookupState: - debug << "QBluetoothSocket::ServiceLookupState"; - break; - default: - debug << "QBluetoothSocket::SocketState(" << (int)state << ")"; - } - return debug; -} - -#endif // QT_NO_DEBUG_STREAM - -#include "moc_qbluetoothsocket.cpp" - QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothsocket_osx_p.h b/src/bluetooth/qbluetoothsocket_osx_p.h index dcc684b8..1291878c 100644 --- a/src/bluetooth/qbluetoothsocket_osx_p.h +++ b/src/bluetooth/qbluetoothsocket_osx_p.h @@ -53,12 +53,11 @@ #ifdef QT_OSX_BLUETOOTH -#include "osx/osxbtchanneldelegate_p.h" -#include "osx/osxbtrfcommchannel_p.h" -#include "osx/osxbtl2capchannel_p.h" +#include "qbluetoothsocketbase_p.h" #include "qbluetoothserviceinfo.h" -#include "osx/osxbtutility_p.h" +#include "osx/btdelegates_p.h" #include "qbluetoothsocket.h" +#include "osx/btraii_p.h" #ifndef QPRIVATELINEARBUFFER_BUFFERSIZE #define QPRIVATELINEARBUFFER_BUFFERSIZE Q_INT64_C(16384) @@ -74,14 +73,11 @@ #include <QtCore/qstring.h> #include <QtCore/qvector.h> -@class IOBluetoothRFCOMMChannel; -@class IOBluetoothL2CAPChannel; - QT_BEGIN_NAMESPACE class QBluetoothAddress; -class QBluetoothSocketPrivate : public QBluetoothSocketBasePrivate, public OSXBluetooth::ChannelDelegate +class QBluetoothSocketPrivate : public QBluetoothSocketBasePrivate, public DarwinBluetooth::ChannelDelegate { friend class QBluetoothSocket; friend class QBluetoothServer; @@ -90,25 +86,47 @@ public: QBluetoothSocketPrivate(); ~QBluetoothSocketPrivate(); - void connectToService(const QBluetoothAddress &address, quint16 port, - QIODevice::OpenMode openMode); + // + bool ensureNativeSocket(QBluetoothServiceInfo::Protocol type) override; + + QString localName() const override; + QBluetoothAddress localAddress() const override; + quint16 localPort() const override; + + QString peerName() const override; + QBluetoothAddress peerAddress() const override; + quint16 peerPort() const override; - void close(); - void abort(); + void abort() override; + void close() override; - quint64 bytesAvailable() const; + qint64 writeData(const char *data, qint64 maxSize) override; + qint64 readData(char *data, qint64 maxSize) override; - QString peerName() const; - QBluetoothAddress peerAddress() const; - quint16 peerPort() const; + qint64 bytesAvailable() const override; + bool canReadLine() const override; + qint64 bytesToWrite() const override; - void _q_readNotify(); - void _q_writeNotify() override; + bool setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType, + QBluetoothSocket::SocketState socketState, + QBluetoothSocket::OpenMode openMode) override; + + void connectToServiceHelper(const QBluetoothAddress &address, quint16 port, + QIODevice::OpenMode openMode) override; + void connectToService(const QBluetoothServiceInfo &service, + QIODevice::OpenMode openMode) override; + void connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid, + QIODevice::OpenMode openMode) override; + + void connectToService(const QBluetoothAddress &address, quint16 port, + QIODevice::OpenMode openMode) override; + + void _q_writeNotify(); private: // Create a socket from an external source (without connectToService). - bool setChannel(IOBluetoothRFCOMMChannel *channel); - bool setChannel(IOBluetoothL2CAPChannel *channel); + bool setRFCOMChannel(void *channel); + bool setL2CAPChannel(void *channel); // L2CAP and RFCOMM delegate void setChannelError(IOReturn errorCode) override; @@ -117,33 +135,15 @@ private: void readChannelData(void *data, std::size_t size) override; void writeComplete() override; - qint64 writeData(const char *data, qint64 maxSize); - qint64 readData(char *data, qint64 maxSize); - - QScopedPointer<QBluetoothServiceDiscoveryAgent> discoveryAgent; - - QPrivateLinearBuffer buffer; - QPrivateLinearBuffer txBuffer; QVector<char> writeChunk; - // Probably, not needed. - QIODevice::OpenMode openMode; - - QBluetoothSocket::SocketState state; - QBluetoothServiceInfo::Protocol socketType; - - QBluetoothSocket::SocketError socketError; - QString errorString; - - typedef QT_MANGLE_NAMESPACE(OSXBTL2CAPChannel) ObjCL2CAPChannel; - typedef OSXBluetooth::ObjCScopedPointer<ObjCL2CAPChannel> L2CAPChannel; + using L2CAPChannel = DarwinBluetooth::ScopedPointer; L2CAPChannel l2capChannel; - typedef QT_MANGLE_NAMESPACE(OSXBTRFCOMMChannel) ObjCRFCOMMChannel; - typedef OSXBluetooth::ObjCScopedPointer<ObjCRFCOMMChannel> RFCOMMChannel; + using RFCOMMChannel = L2CAPChannel; RFCOMMChannel rfcommChannel; // A trick to deal with channel open too fast (synchronously). - bool isConnecting; + bool isConnecting = false; }; QT_END_NAMESPACE diff --git a/src/bluetooth/qbluetoothsocketbase_p.h b/src/bluetooth/qbluetoothsocketbase_p.h index 410dcbbd..d1894e96 100644 --- a/src/bluetooth/qbluetoothsocketbase_p.h +++ b/src/bluetooth/qbluetoothsocketbase_p.h @@ -89,7 +89,6 @@ QT_FORWARD_DECLARE_CLASS(QBluetoothServiceDiscoveryAgent) QT_BEGIN_NAMESPACE -#ifndef QT_OSX_BLUETOOTH class QBluetoothSocketBasePrivate : public QObject { Q_OBJECT @@ -198,26 +197,6 @@ static inline quint64 convertAddress(const quint8 (&from)[6], quint64 *to = null return result; } -#else // QT_OSX_BLUETOOTH - -// QBluetoothSocketPrivate on macOS can not contain -// Q_OBJECT (moc does not parse Objective-C syntax). -// But QBluetoothSocket still requires QMetaObject::invokeMethod -// to work. Here's the trick: -class QBluetoothSocketBasePrivate : public QObject -{ -// The most important part of it: - Q_OBJECT -public slots: - virtual void _q_writeNotify() = 0; - -protected: - Q_DECLARE_PUBLIC(QBluetoothSocket) - QBluetoothSocket *q_ptr; -}; - -#endif // QT_OSX_BLUETOOTH - QT_END_NAMESPACE #endif // QBLUETOOTHSOCKETBASE_P_H |