From 167faeec86ed4d9c9f099f5180784c7b0cb9aa42 Mon Sep 17 00:00:00 2001 From: Alex Blasche Date: Mon, 25 Aug 2014 13:40:04 +0200 Subject: Fix L2CP socket connections L2CP's psm (the RFCOMM port equivalent) was never published via SDP. Therefore the service client could not get the required information to connect to the server. After this patch Qt properly publishes the psm. Also, QBluetoothSocket::connect() initiated a service discovery to obtain the missing psm. Since the published SDP entry didn't contain one, protocolServiceMultiplexer() always returned 0 and another service discovery was initiated. This caused a crash inside QBluetoothSocket because the 1st QBluetoothServiceDiscoveryAgent instance was deleted in favor of the 2nd. The patch changes the client behavior such that it doesn't crash if the service discovery didn't turn up a valid psm/port. It improves the robustness in case of an error and avoids a second service discovery (which wouldn't turn up more information anyway). The bug only affected Bluez as it is the only platform supporting pure L2CP sockets. Last but not least a capability to test L2CP sockets was added to bttestui. Change-Id: I46c88a67c2baa4782ea908e645dcd4db9422dbba Reviewed-by: Fabian Bumberger --- dist/changes-5.3.2 | 2 ++ src/bluetooth/qbluetoothserver.cpp | 4 +++- src/bluetooth/qbluetoothsocket.cpp | 4 +++- tests/bttestui/btlocaldevice.cpp | 22 +++++++++++++++------- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/dist/changes-5.3.2 b/dist/changes-5.3.2 index 59a52917..e700e85e 100644 --- a/dist/changes-5.3.2 +++ b/dist/changes-5.3.2 @@ -45,3 +45,5 @@ Linux ----- - Removed undesirable system header includes from the Bluez code base. + - Fixed incomplete SDP entries when using L2CP sockets and avoided + crash on client side when incomplete SDP entry is encountered. diff --git a/src/bluetooth/qbluetoothserver.cpp b/src/bluetooth/qbluetoothserver.cpp index 3123b032..667c3306 100644 --- a/src/bluetooth/qbluetoothserver.cpp +++ b/src/bluetooth/qbluetoothserver.cpp @@ -226,6 +226,8 @@ QBluetoothServiceInfo QBluetoothServer::listen(const QBluetoothUuid &uuid, const QBluetoothServiceInfo::Sequence protocolDescriptorList; QBluetoothServiceInfo::Sequence protocol; protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::L2cap)); + if (d->serverType == QBluetoothServiceInfo::L2capProtocol) + protocol << QVariant::fromValue(serverPort()); protocolDescriptorList.append(QVariant::fromValue(protocol)); protocol.clear(); //! [listen] @@ -233,10 +235,10 @@ QBluetoothServiceInfo QBluetoothServer::listen(const QBluetoothUuid &uuid, const //! [listen2] protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::Rfcomm)) << QVariant::fromValue(quint8(serverPort())); + protocolDescriptorList.append(QVariant::fromValue(protocol)); //! [listen2] } //! [listen3] - protocolDescriptorList.append(QVariant::fromValue(protocol)); serviceInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, protocolDescriptorList); bool result = serviceInfo.registerService(); diff --git a/src/bluetooth/qbluetoothsocket.cpp b/src/bluetooth/qbluetoothsocket.cpp index 0c514887..87456a2e 100644 --- a/src/bluetooth/qbluetoothsocket.cpp +++ b/src/bluetooth/qbluetoothsocket.cpp @@ -572,10 +572,12 @@ void QBluetoothSocket::serviceDiscovered(const QBluetoothServiceInfo &service) { Q_D(QBluetoothSocket); qCDebug(QT_BT) << "FOUND SERVICE!" << service; - if(service.protocolServiceMultiplexer() != 0 || service.serverChannel() != 0) { + if (service.protocolServiceMultiplexer() > 0 || service.serverChannel() > 0) { connectToService(service, d->openMode); d->discoveryAgent->deleteLater(); d->discoveryAgent = 0; + } else { + qCDebug(QT_BT) << "Could not find port/psm for potential remote service"; } } diff --git a/tests/bttestui/btlocaldevice.cpp b/tests/bttestui/btlocaldevice.cpp index 8c85599f..a14709ee 100644 --- a/tests/bttestui/btlocaldevice.cpp +++ b/tests/bttestui/btlocaldevice.cpp @@ -49,6 +49,9 @@ //same uuid as examples/bluetooth/btchat #define TEST_SERVICE_UUID "e8e10f95-1a70-4b27-9ccf-02010264e9c8" +#define SOCKET_PROTOCOL QBluetoothServiceInfo::RfcommProtocol +//#define SOCKET_PROTOCOL QBluetoothServiceInfo::L2capProtocol + BtLocalDevice::BtLocalDevice(QObject *parent) : QObject(parent) { @@ -87,7 +90,7 @@ BtLocalDevice::BtLocalDevice(QObject *parent) : connect(serviceAgent, SIGNAL(error(QBluetoothServiceDiscoveryAgent::Error)), this, SLOT(serviceDiscoveryError(QBluetoothServiceDiscoveryAgent::Error))); - socket = new QBluetoothSocket(this); + socket = new QBluetoothSocket(SOCKET_PROTOCOL, this); connect(socket, SIGNAL(stateChanged(QBluetoothSocket::SocketState)), this, SLOT(socketStateChanged(QBluetoothSocket::SocketState))); connect(socket, SIGNAL(error(QBluetoothSocket::SocketError)), @@ -96,7 +99,7 @@ BtLocalDevice::BtLocalDevice(QObject *parent) : connect(socket, SIGNAL(disconnected()), this, SLOT(socketDisconnected())); connect(socket, SIGNAL(readyRead()), this, SLOT(readData())); - server = new QBluetoothServer(QBluetoothServiceInfo::RfcommProtocol, this); + server = new QBluetoothServer(SOCKET_PROTOCOL, this); server->setSecurityFlags(QBluetooth::NoSecurity); connect(server, SIGNAL(newConnection()), this, SLOT(serverNewConnection())); connect(server, SIGNAL(error(QBluetoothServer::Error)), @@ -537,16 +540,21 @@ void BtLocalDevice::serverListenPort() QBluetoothServiceInfo::Sequence protocolDescriptorList; QBluetoothServiceInfo::Sequence protocol; protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::L2cap)); + if (server->serverType() == QBluetoothServiceInfo::L2capProtocol) + protocol << QVariant::fromValue(server->serverPort()); protocolDescriptorList.append(QVariant::fromValue(protocol)); - protocol.clear(); - protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::Rfcomm)) - << QVariant::fromValue(quint8(server->serverPort())); - protocolDescriptorList.append(QVariant::fromValue(protocol)); + + if (server->serverType() == QBluetoothServiceInfo::RfcommProtocol) { + protocol.clear(); + protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::Rfcomm)) + << QVariant::fromValue(quint8(server->serverPort())); + protocolDescriptorList.append(QVariant::fromValue(protocol)); + } serviceInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, protocolDescriptorList); //Register service - qDebug() << "###### Registering service on" << localDevice->address().toString(); + qDebug() << "###### Registering service on" << localDevice->address().toString() << server->serverPort(); bool result = serviceInfo.registerService(localDevice->address()); if (!result) { server->close(); -- cgit v1.2.3