Bluetooth multiplexer integration and assorted fixes
This commit is contained in:
parent
cda1280456
commit
0b6224fc0e
10 changed files with 145 additions and 173 deletions
|
@ -25,22 +25,24 @@
|
|||
#include "bluetoothuploadjob.h"
|
||||
#include "bluetoothdownloadjob.h"
|
||||
#include "core_debug.h"
|
||||
#include "connectionmultiplexer.h"
|
||||
#include "multiplexchannel.h"
|
||||
|
||||
BluetoothDeviceLink::BluetoothDeviceLink(const QString& deviceId, LinkProvider* parent, QBluetoothSocket* socket)
|
||||
BluetoothDeviceLink::BluetoothDeviceLink(const QString& deviceId, LinkProvider* parent, ConnectionMultiplexer* connection, QSharedPointer<MultiplexChannel> socket)
|
||||
: DeviceLink(deviceId, parent)
|
||||
, mSocketReader(new DeviceLineReader(socket, this))
|
||||
, mBluetoothSocket(socket)
|
||||
, mSocketReader(new DeviceLineReader(socket.data(), this))
|
||||
, mConnection(connection)
|
||||
, mChannel(socket)
|
||||
, mPairingHandler(new BluetoothPairingHandler(this))
|
||||
{
|
||||
connect(mSocketReader, SIGNAL(readyRead()),
|
||||
this, SLOT(dataReceived()));
|
||||
connect(mSocketReader, &DeviceLineReader::readyRead, this, &BluetoothDeviceLink::dataReceived);
|
||||
|
||||
//We take ownership of the socket.
|
||||
//We take ownership of the connection.
|
||||
//When the link provider destroys us,
|
||||
//the socket (and the reader) will be
|
||||
//destroyed as well
|
||||
mBluetoothSocket->setParent(this);
|
||||
connect(mBluetoothSocket, SIGNAL(disconnected()), this, SLOT(deleteLater()));
|
||||
mConnection->setParent(this);
|
||||
connect(socket.data(), &MultiplexChannel::aboutToClose, this, &QObject::deleteLater);
|
||||
}
|
||||
|
||||
QString BluetoothDeviceLink::name()
|
||||
|
@ -51,10 +53,11 @@ QString BluetoothDeviceLink::name()
|
|||
bool BluetoothDeviceLink::sendPacket(NetworkPacket& np)
|
||||
{
|
||||
if (np.hasPayload()) {
|
||||
BluetoothUploadJob* uploadJob = new BluetoothUploadJob(np.payload(), mBluetoothSocket->peerAddress(), this);
|
||||
BluetoothUploadJob* uploadJob = new BluetoothUploadJob(np.payload(), mConnection, this);
|
||||
np.setPayloadTransferInfo(uploadJob->transferInfo());
|
||||
uploadJob->start();
|
||||
}
|
||||
//TODO: handle too-big packets
|
||||
int written = mSocketReader->write(np.serialize());
|
||||
return (written != -1);
|
||||
}
|
||||
|
@ -89,8 +92,7 @@ void BluetoothDeviceLink::dataReceived()
|
|||
}
|
||||
|
||||
if (packet.hasPayloadTransferInfo()) {
|
||||
BluetoothDownloadJob* downloadJob = new BluetoothDownloadJob(mBluetoothSocket->peerAddress(),
|
||||
packet.payloadTransferInfo(), this);
|
||||
BluetoothDownloadJob* downloadJob = new BluetoothDownloadJob(mConnection, packet.payloadTransferInfo(), this);
|
||||
downloadJob->start();
|
||||
packet.setPayload(downloadJob->payload(), packet.payloadSize());
|
||||
}
|
||||
|
@ -98,6 +100,6 @@ void BluetoothDeviceLink::dataReceived()
|
|||
Q_EMIT receivedPacket(packet);
|
||||
|
||||
if (mSocketReader->bytesAvailable() > 0) {
|
||||
QMetaObject::invokeMethod(this, "dataReceived", Qt::QueuedConnection);
|
||||
QMetaObject::invokeMethod(this, &BluetoothDeviceLink::dataReceived, Qt::QueuedConnection);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,13 +29,16 @@
|
|||
#include "../devicelinereader.h"
|
||||
#include "bluetoothpairinghandler.h"
|
||||
|
||||
class ConnectionMultiplexer;
|
||||
class MultiplexChannel;
|
||||
|
||||
class KDECONNECTCORE_EXPORT BluetoothDeviceLink
|
||||
: public DeviceLink
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
BluetoothDeviceLink(const QString& deviceId, LinkProvider* parent, QBluetoothSocket* socket);
|
||||
BluetoothDeviceLink(const QString& deviceId, LinkProvider* parent, ConnectionMultiplexer* connection, QSharedPointer<MultiplexChannel> socket);
|
||||
|
||||
virtual QString name() override;
|
||||
bool sendPacket(NetworkPacket& np) override;
|
||||
|
@ -50,7 +53,8 @@ private Q_SLOTS:
|
|||
|
||||
private:
|
||||
DeviceLineReader* mSocketReader;
|
||||
QBluetoothSocket* mBluetoothSocket;
|
||||
ConnectionMultiplexer* mConnection;
|
||||
QSharedPointer<MultiplexChannel> mChannel;
|
||||
BluetoothPairingHandler* mPairingHandler;
|
||||
|
||||
void sendMessage(const QString mMessage);
|
||||
|
|
|
@ -19,13 +19,14 @@
|
|||
*/
|
||||
|
||||
#include "bluetoothdownloadjob.h"
|
||||
#include "connectionmultiplexer.h"
|
||||
#include "multiplexchannel.h"
|
||||
|
||||
BluetoothDownloadJob::BluetoothDownloadJob(const QBluetoothAddress& remoteAddress, const QVariantMap& transferInfo, QObject* parent)
|
||||
BluetoothDownloadJob::BluetoothDownloadJob(ConnectionMultiplexer *connection, const QVariantMap& transferInfo, QObject* parent)
|
||||
: QObject(parent)
|
||||
, mRemoteAddress(remoteAddress)
|
||||
, mTransferUuid(QBluetoothUuid(transferInfo.value(QStringLiteral("uuid")).toString()))
|
||||
, mSocket(new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol))
|
||||
{
|
||||
QBluetoothUuid id{transferInfo.value(QStringLiteral("uuid")).toString()};
|
||||
mSocket = QSharedPointer<MultiplexChannel>{connection->getChannel(id).release()};
|
||||
}
|
||||
|
||||
QSharedPointer<QIODevice> BluetoothDownloadJob::payload() const
|
||||
|
@ -35,7 +36,4 @@ QSharedPointer<QIODevice> BluetoothDownloadJob::payload() const
|
|||
|
||||
void BluetoothDownloadJob::start()
|
||||
{
|
||||
connect(mSocket.data(), &QBluetoothSocket::disconnected, mSocket.data(), &QBluetoothSocket::readyRead);
|
||||
connect(mSocket.data(), &QBluetoothSocket::disconnected, mSocket.data(), &QBluetoothSocket::readChannelFinished);
|
||||
mSocket->connectToService(mRemoteAddress, mTransferUuid, QIODevice::ReadOnly);
|
||||
}
|
||||
|
|
|
@ -29,19 +29,20 @@
|
|||
#include <QBluetoothUuid>
|
||||
#include <QBluetoothSocket>
|
||||
|
||||
class ConnectionMultiplexer;
|
||||
class MultiplexChannel;
|
||||
|
||||
class BluetoothDownloadJob
|
||||
: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit BluetoothDownloadJob(const QBluetoothAddress& remoteAddress, const QVariantMap& transferInfo, QObject* parent = 0);
|
||||
explicit BluetoothDownloadJob(ConnectionMultiplexer *connection, const QVariantMap& transferInfo, QObject* parent = 0);
|
||||
|
||||
QSharedPointer<QIODevice> payload() const;
|
||||
void start();
|
||||
private:
|
||||
QBluetoothAddress mRemoteAddress;
|
||||
QBluetoothUuid mTransferUuid;
|
||||
QSharedPointer<QBluetoothSocket> mSocket;
|
||||
QSharedPointer<MultiplexChannel> mSocket;
|
||||
};
|
||||
|
||||
#endif // BLUETOOTHDOWNLOADJOB_H
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
#include "bluetoothlinkprovider.h"
|
||||
#include "core_debug.h"
|
||||
#include "connectionmultiplexer.h"
|
||||
#include "multiplexchannel.h"
|
||||
|
||||
#include <KSharedConfig>
|
||||
#include <KConfigGroup>
|
||||
|
@ -42,8 +44,11 @@ BluetoothLinkProvider::BluetoothLinkProvider()
|
|||
|
||||
mServiceDiscoveryAgent = new QBluetoothServiceDiscoveryAgent(this);
|
||||
mServiceDiscoveryAgent->setUuidFilter(mServiceUuid);
|
||||
connect(mServiceDiscoveryAgent, SIGNAL(finished()), this, SLOT(serviceDiscoveryFinished()));
|
||||
connect(connectTimer, SIGNAL(timeout()), mServiceDiscoveryAgent, SLOT(start()));
|
||||
connect(connectTimer, &QTimer::timeout, this, [this]() {
|
||||
mServiceDiscoveryAgent->start();
|
||||
});
|
||||
|
||||
connect(mServiceDiscoveryAgent, &QBluetoothServiceDiscoveryAgent::serviceDiscovered, this, &BluetoothLinkProvider::serviceDiscovered);
|
||||
}
|
||||
|
||||
void BluetoothLinkProvider::onStart()
|
||||
|
@ -111,95 +116,94 @@ void BluetoothLinkProvider::addLink(BluetoothDeviceLink* deviceLink, const QStri
|
|||
mLinks[deviceId] = deviceLink;
|
||||
}
|
||||
|
||||
//I'm the new device and I found an existing device
|
||||
void BluetoothLinkProvider::serviceDiscoveryFinished()
|
||||
{
|
||||
const QList<QBluetoothServiceInfo> services = mServiceDiscoveryAgent->discoveredServices();
|
||||
void BluetoothLinkProvider::serviceDiscovered(const QBluetoothServiceInfo& old_info) {
|
||||
auto info = old_info;
|
||||
info.setServiceUuid(mServiceUuid);
|
||||
if (mSockets.contains(info.device().address())) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (QBluetoothServiceInfo info : services) {
|
||||
if (mSockets.contains(info.device().address())) {
|
||||
continue;
|
||||
}
|
||||
QBluetoothSocket* socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol);
|
||||
|
||||
QBluetoothSocket* socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol);
|
||||
//Delay before sending data
|
||||
QPointer<QBluetoothSocket> deleteableSocket = socket;
|
||||
connect(socket, &QBluetoothSocket::connected, this, [this,deleteableSocket]() {
|
||||
QTimer::singleShot(500, this, [this,deleteableSocket]() {
|
||||
clientConnected(deleteableSocket);
|
||||
});
|
||||
});
|
||||
connect(socket, SIGNAL(error(QBluetoothSocket::SocketError)), this, SLOT(connectError()));
|
||||
|
||||
connect(socket, SIGNAL(connected()), this, SLOT(clientConnected()));
|
||||
connect(socket, SIGNAL(error(QBluetoothSocket::SocketError)), this, SLOT(connectError()));
|
||||
socket->connectToService(info);
|
||||
|
||||
socket->connectToService(info);
|
||||
qCDebug(KDECONNECT_CORE()) << "Connecting to" << info.device().address();
|
||||
|
||||
qCDebug(KDECONNECT_CORE()) << "Connecting to" << info.device().address();
|
||||
|
||||
if (socket->error() != QBluetoothSocket::NoSocketError) {
|
||||
qCWarning(KDECONNECT_CORE) << "Socket connection error:" << socket->errorString();
|
||||
}
|
||||
if (socket->error() != QBluetoothSocket::NoSocketError) {
|
||||
qCWarning(KDECONNECT_CORE) << "Socket connection error:" << socket->errorString();
|
||||
}
|
||||
}
|
||||
|
||||
//I'm the new device and I'm connected to the existing device. Time to get data.
|
||||
void BluetoothLinkProvider::clientConnected()
|
||||
void BluetoothLinkProvider::clientConnected(QPointer<QBluetoothSocket> socket)
|
||||
{
|
||||
QBluetoothSocket* socket = qobject_cast<QBluetoothSocket*>(sender());
|
||||
if (!socket) return;
|
||||
|
||||
qCDebug(KDECONNECT_CORE()) << "Connected to" << socket->peerAddress();
|
||||
auto peer = socket->peerAddress();
|
||||
|
||||
qCDebug(KDECONNECT_CORE()) << "Connected to" << peer;
|
||||
|
||||
if (mSockets.contains(socket->peerAddress())) {
|
||||
qCWarning(KDECONNECT_CORE()) << "Duplicate connection to" << socket->peerAddress();
|
||||
qCWarning(KDECONNECT_CORE()) << "Duplicate connection to" << peer;
|
||||
socket->close();
|
||||
socket->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
mSockets.insert(socket->peerAddress(), socket);
|
||||
ConnectionMultiplexer *multiplexer = new ConnectionMultiplexer(socket, this);
|
||||
|
||||
disconnect(socket, SIGNAL(connected()), this, SLOT(clientConnected()));
|
||||
mSockets.insert(peer, multiplexer);
|
||||
disconnect(socket, nullptr, this, nullptr);
|
||||
|
||||
connect(socket, SIGNAL(readyRead()), this, SLOT(clientIdentityReceived()));
|
||||
connect(socket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));
|
||||
auto channel = QSharedPointer<MultiplexChannel>{multiplexer->getDefaultChannel().release()};
|
||||
connect(channel.data(), &MultiplexChannel::readyRead, this, [this,peer,channel] () { clientIdentityReceived(peer, channel); });
|
||||
connect(channel.data(), &MultiplexChannel::aboutToClose, this, [this,peer,channel] () { socketDisconnected(peer, channel.data()); });
|
||||
|
||||
if (channel->bytesAvailable()) clientIdentityReceived(peer, channel);
|
||||
if (!channel->isOpen()) socketDisconnected(peer, channel.data());
|
||||
}
|
||||
|
||||
//I'm the new device and the existing device sent me data.
|
||||
void BluetoothLinkProvider::clientIdentityReceived()
|
||||
void BluetoothLinkProvider::clientIdentityReceived(const QBluetoothAddress &peer, QSharedPointer<MultiplexChannel> socket)
|
||||
{
|
||||
QBluetoothSocket* socket = qobject_cast<QBluetoothSocket*>(sender());
|
||||
if (!socket) return;
|
||||
socket->startTransaction();
|
||||
|
||||
QByteArray identityArray;
|
||||
|
||||
if (socket->property("identityArray").isValid()) {
|
||||
identityArray = socket->property("identityArray").toByteArray();
|
||||
}
|
||||
|
||||
while (!identityArray.contains('\n') && socket->bytesAvailable() > 0) {
|
||||
identityArray += socket->readAll();
|
||||
}
|
||||
if (!identityArray.contains('\n')) {
|
||||
// This method will get retriggered when more data is available.
|
||||
socket->setProperty("identityArray", identityArray);
|
||||
QByteArray identityArray = socket->readLine();
|
||||
if (identityArray.isEmpty()) {
|
||||
socket->rollbackTransaction();
|
||||
return;
|
||||
}
|
||||
socket->setProperty("identityArray", QVariant());
|
||||
socket->commitTransaction();
|
||||
|
||||
disconnect(socket, SIGNAL(readyRead()), this, SLOT(clientIdentityReceived()));
|
||||
disconnect(socket.data(), &MultiplexChannel::readyRead, this, nullptr);
|
||||
|
||||
NetworkPacket receivedPacket;
|
||||
bool success = NetworkPacket::unserialize(identityArray, &receivedPacket);
|
||||
|
||||
if (!success || receivedPacket.type() != PACKET_TYPE_IDENTITY) {
|
||||
qCWarning(KDECONNECT_CORE) << "Not an identity packet";
|
||||
mSockets.remove(socket->peerAddress());
|
||||
mSockets.remove(peer);
|
||||
socket->close();
|
||||
socket->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(KDECONNECT_CORE()) << "Received identity packet from" << socket->peerAddress();
|
||||
qCDebug(KDECONNECT_CORE()) << "Received identity packet from" << peer;
|
||||
|
||||
disconnect(socket, SIGNAL(error(QBluetoothSocket::SocketError)), this, SLOT(connectError()));
|
||||
//TODO?
|
||||
//disconnect(socket, SIGNAL(error(QBluetoothSocket::SocketError)), this, SLOT(connectError()));
|
||||
|
||||
const QString& deviceId = receivedPacket.get<QString>(QStringLiteral("deviceId"));
|
||||
BluetoothDeviceLink* deviceLink = new BluetoothDeviceLink(deviceId, this, socket);
|
||||
BluetoothDeviceLink* deviceLink = new BluetoothDeviceLink(deviceId, this, mSockets[peer], socket);
|
||||
|
||||
NetworkPacket np2;
|
||||
NetworkPacket::createIdentityPacket(&np2);
|
||||
|
@ -232,65 +236,66 @@ void BluetoothLinkProvider::serverNewConnection()
|
|||
|
||||
qCDebug(KDECONNECT_CORE()) << "Received connection from" << socket->peerAddress();
|
||||
|
||||
if (mSockets.contains(socket->peerAddress())) {
|
||||
qCDebug(KDECONNECT_CORE()) << "Duplicate connection from" << socket->peerAddress();
|
||||
QBluetoothAddress peer = socket->peerAddress();
|
||||
|
||||
if (mSockets.contains(peer)) {
|
||||
qCDebug(KDECONNECT_CORE()) << "Duplicate connection from" << peer;
|
||||
socket->close();
|
||||
socket->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
connect(socket, SIGNAL(readyRead()), this, SLOT(serverDataReceived()));
|
||||
connect(socket, SIGNAL(error(QBluetoothSocket::SocketError)), this, SLOT(connectError()));
|
||||
connect(socket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));
|
||||
ConnectionMultiplexer *multiplexer = new ConnectionMultiplexer(socket, this);
|
||||
|
||||
mSockets.insert(peer, multiplexer);
|
||||
disconnect(socket, nullptr, this, nullptr);
|
||||
|
||||
auto channel = QSharedPointer<MultiplexChannel>{multiplexer->getDefaultChannel().release()};
|
||||
connect(channel.data(), &MultiplexChannel::readyRead, this, [this,peer,channel] () { serverDataReceived(peer, channel); });
|
||||
connect(channel.data(), &MultiplexChannel::aboutToClose, this, [this,peer,channel] () { socketDisconnected(peer, channel.data()); });
|
||||
|
||||
if (!channel->isOpen()) {
|
||||
socketDisconnected(peer, channel.data());
|
||||
return;
|
||||
}
|
||||
|
||||
NetworkPacket np2;
|
||||
NetworkPacket::createIdentityPacket(&np2);
|
||||
socket->write(np2.serialize());
|
||||
|
||||
qCDebug(KDECONNECT_CORE()) << "Sent identity packet to" << socket->peerAddress();
|
||||
|
||||
mSockets.insert(socket->peerAddress(), socket);
|
||||
}
|
||||
|
||||
//I'm the existing device and this is the answer to my identity packet (data received)
|
||||
void BluetoothLinkProvider::serverDataReceived()
|
||||
void BluetoothLinkProvider::serverDataReceived(const QBluetoothAddress &peer, QSharedPointer<MultiplexChannel> socket)
|
||||
{
|
||||
QBluetoothSocket* socket = qobject_cast<QBluetoothSocket*>(sender());
|
||||
if (!socket) return;
|
||||
|
||||
QByteArray identityArray;
|
||||
if (socket->property("identityArray").isValid()) {
|
||||
identityArray = socket->property("identityArray").toByteArray();
|
||||
}
|
||||
socket->startTransaction();
|
||||
identityArray = socket->readLine();
|
||||
|
||||
while (!identityArray.contains('\n') && socket->bytesAvailable() > 0) {
|
||||
identityArray += socket->readAll();
|
||||
}
|
||||
if (!identityArray.contains('\n')) {
|
||||
// This method will get retriggered when more data is available.
|
||||
socket->setProperty("identityArray", identityArray);
|
||||
if (identityArray.isEmpty()) {
|
||||
socket->rollbackTransaction();
|
||||
return;
|
||||
}
|
||||
socket->setProperty("identityArray", QVariant());
|
||||
socket->commitTransaction();
|
||||
|
||||
disconnect(socket, SIGNAL(readyRead()), this, SLOT(serverDataReceived()));
|
||||
disconnect(socket, SIGNAL(error(QBluetoothSocket::SocketError)), this, SLOT(connectError()));
|
||||
disconnect(socket.data(), &MultiplexChannel::readyRead, this, nullptr);
|
||||
|
||||
NetworkPacket receivedPacket;
|
||||
bool success = NetworkPacket::unserialize(identityArray, &receivedPacket);
|
||||
|
||||
if (!success || receivedPacket.type() != PACKET_TYPE_IDENTITY) {
|
||||
qCWarning(KDECONNECT_CORE) << "Not an identity packet.";
|
||||
mSockets.remove(socket->peerAddress());
|
||||
mSockets.remove(peer);
|
||||
socket->close();
|
||||
socket->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(KDECONNECT_CORE()) << "Received identity packet from" << socket->peerAddress();
|
||||
qCDebug(KDECONNECT_CORE()) << "Received identity packet from" << peer;
|
||||
|
||||
const QString& deviceId = receivedPacket.get<QString>(QStringLiteral("deviceId"));
|
||||
BluetoothDeviceLink* deviceLink = new BluetoothDeviceLink(deviceId, this, socket);
|
||||
BluetoothDeviceLink* deviceLink = new BluetoothDeviceLink(deviceId, this, mSockets[peer], socket);
|
||||
|
||||
connect(deviceLink, SIGNAL(destroyed(QObject*)),
|
||||
this, SLOT(deviceLinkDestroyed(QObject*)));
|
||||
|
@ -310,14 +315,12 @@ void BluetoothLinkProvider::deviceLinkDestroyed(QObject* destroyedDeviceLink)
|
|||
}
|
||||
}
|
||||
|
||||
void BluetoothLinkProvider::socketDisconnected()
|
||||
void BluetoothLinkProvider::socketDisconnected(const QBluetoothAddress &peer, MultiplexChannel *socket)
|
||||
{
|
||||
QBluetoothSocket* socket = qobject_cast<QBluetoothSocket*>(sender());
|
||||
if (!socket) return;
|
||||
qCDebug(KDECONNECT_CORE()) << "Disconnected";
|
||||
disconnect(socket, nullptr, this, nullptr);
|
||||
|
||||
disconnect(socket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));
|
||||
|
||||
mSockets.remove(mSockets.key(socket));
|
||||
mSockets.remove(peer);
|
||||
}
|
||||
|
||||
BluetoothLinkProvider::~BluetoothLinkProvider()
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
#include "../linkprovider.h"
|
||||
|
||||
class BluetoothDeviceLink;
|
||||
class ConnectionMultiplexer;
|
||||
class MultiplexChannel;
|
||||
|
||||
class KDECONNECTCORE_EXPORT BluetoothLinkProvider
|
||||
: public LinkProvider
|
||||
|
@ -53,16 +55,17 @@ public Q_SLOTS:
|
|||
virtual void onStart() override;
|
||||
virtual void onStop() override;
|
||||
void connectError();
|
||||
void serviceDiscoveryFinished();
|
||||
|
||||
private Q_SLOTS:
|
||||
void deviceLinkDestroyed(QObject* destroyedDeviceLink);
|
||||
void socketDisconnected();
|
||||
void socketDisconnected(const QBluetoothAddress &peerAddress, MultiplexChannel *socket);
|
||||
|
||||
void serverNewConnection();
|
||||
void serverDataReceived();
|
||||
void clientConnected();
|
||||
void clientIdentityReceived();
|
||||
void serverDataReceived(const QBluetoothAddress &peerAddress, QSharedPointer<MultiplexChannel> socket);
|
||||
void clientConnected(QPointer<QBluetoothSocket> socket);
|
||||
void clientIdentityReceived(const QBluetoothAddress &peerAddress, QSharedPointer<MultiplexChannel> socket);
|
||||
|
||||
void serviceDiscovered(const QBluetoothServiceInfo &info);
|
||||
|
||||
private:
|
||||
void addLink(BluetoothDeviceLink* deviceLink, const QString& deviceId);
|
||||
|
@ -76,7 +79,7 @@ private:
|
|||
|
||||
QMap<QString, DeviceLink*> mLinks;
|
||||
|
||||
QMap<QBluetoothAddress, QBluetoothSocket*> mSockets;
|
||||
QMap<QBluetoothAddress, ConnectionMultiplexer*> mSockets;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -20,19 +20,19 @@
|
|||
*/
|
||||
|
||||
#include "bluetoothuploadjob.h"
|
||||
#include "connectionmultiplexer.h"
|
||||
#include "multiplexchannel.h"
|
||||
|
||||
#include <QBluetoothSocket>
|
||||
#include "core_debug.h"
|
||||
#include <QCoreApplication>
|
||||
|
||||
BluetoothUploadJob::BluetoothUploadJob(const QSharedPointer<QIODevice>& data, const QBluetoothAddress& remoteAddress, QObject* parent)
|
||||
BluetoothUploadJob::BluetoothUploadJob(const QSharedPointer<QIODevice>& data, ConnectionMultiplexer *connection, QObject* parent)
|
||||
: QObject(parent)
|
||||
, mData(data)
|
||||
, mRemoteAddress(remoteAddress)
|
||||
, mTransferUuid(QBluetoothUuid::createUuid())
|
||||
, mServer(new QBluetoothServer(QBluetoothServiceInfo::RfcommProtocol, this))
|
||||
, mTransferUuid(connection->newChannel())
|
||||
{
|
||||
mServer->setSecurityFlags(QBluetooth::Encryption | QBluetooth::Secure);
|
||||
mSocket = QSharedPointer<MultiplexChannel>{connection->getChannel(mTransferUuid).release()};
|
||||
}
|
||||
|
||||
QVariantMap BluetoothUploadJob::transferInfo() const
|
||||
|
@ -44,45 +44,20 @@ QVariantMap BluetoothUploadJob::transferInfo() const
|
|||
|
||||
void BluetoothUploadJob::start()
|
||||
{
|
||||
connect(mServer, &QBluetoothServer::newConnection, this, &BluetoothUploadJob::newConnection);
|
||||
mServiceInfo = mServer->listen(mTransferUuid, QStringLiteral("KDE Connect Transfer Job"));
|
||||
Q_ASSERT(mServiceInfo.isValid());
|
||||
}
|
||||
|
||||
void BluetoothUploadJob::newConnection()
|
||||
{
|
||||
m_socket = mServer->nextPendingConnection();
|
||||
Q_ASSERT(m_socket);
|
||||
m_socket->setParent(this);
|
||||
connect(m_socket, &QBluetoothSocket::disconnected, this, &BluetoothUploadJob::deleteLater);
|
||||
|
||||
if (m_socket->peerAddress() != mRemoteAddress) {
|
||||
m_socket->close();
|
||||
} else {
|
||||
mServer->close();
|
||||
disconnect(mServer, &QBluetoothServer::newConnection, this, &BluetoothUploadJob::newConnection);
|
||||
mServiceInfo.unregisterService();
|
||||
|
||||
if (!mData->open(QIODevice::ReadOnly)) {
|
||||
qCWarning(KDECONNECT_CORE) << "error when opening the input to upload";
|
||||
m_socket->close();
|
||||
deleteLater();
|
||||
return;
|
||||
}
|
||||
if (!mData->open(QIODevice::ReadOnly)) {
|
||||
qCWarning(KDECONNECT_CORE) << "error when opening the input to upload";
|
||||
return; //TODO: Handle error, clean up...
|
||||
}
|
||||
|
||||
connect(m_socket, &QBluetoothSocket::bytesWritten, this, &BluetoothUploadJob::writeSome);
|
||||
connect(m_socket, &QBluetoothSocket::disconnected, this, &BluetoothUploadJob::closeConnection);
|
||||
connect(mSocket.data(), &MultiplexChannel::bytesWritten, this, &BluetoothUploadJob::writeSome);
|
||||
connect(mSocket.data(), &MultiplexChannel::aboutToClose, this, &BluetoothUploadJob::closeConnection);
|
||||
writeSome();
|
||||
}
|
||||
|
||||
void BluetoothUploadJob::writeSome() {
|
||||
Q_ASSERT(m_socket);
|
||||
|
||||
bool errorOccurred = false;
|
||||
while (m_socket->bytesToWrite() == 0 && mData->bytesAvailable() && m_socket->isWritable()) {
|
||||
while (mSocket->bytesToWrite() == 0 && mData->bytesAvailable() && mSocket->isWritable()) {
|
||||
qint64 bytes = qMin<qint64>(mData->bytesAvailable(), 4096);
|
||||
int bytesWritten = m_socket->write(mData->read(bytes));
|
||||
int bytesWritten = mSocket->write(mData->read(bytes));
|
||||
|
||||
if (bytesWritten < 0) {
|
||||
qCWarning(KDECONNECT_CORE()) << "error when writing data to bluetooth upload" << bytes << mData->bytesAvailable();
|
||||
|
@ -92,18 +67,8 @@ void BluetoothUploadJob::writeSome() {
|
|||
}
|
||||
|
||||
if (mData->atEnd() || errorOccurred) {
|
||||
disconnect(m_socket, &QBluetoothSocket::bytesWritten, this, &BluetoothUploadJob::writeSome);
|
||||
mData->close();
|
||||
|
||||
connect(m_socket, &QBluetoothSocket::bytesWritten, this, &BluetoothUploadJob::finishWrites);
|
||||
finishWrites();
|
||||
}
|
||||
}
|
||||
|
||||
void BluetoothUploadJob::finishWrites() {
|
||||
Q_ASSERT(m_socket);
|
||||
if (m_socket->bytesToWrite() == 0) {
|
||||
closeConnection();
|
||||
mSocket->close();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,30 +30,28 @@
|
|||
#include <QBluetoothUuid>
|
||||
#include <QBluetoothServer>
|
||||
|
||||
class ConnectionMultiplexer;
|
||||
class MultiplexChannel;
|
||||
|
||||
class BluetoothUploadJob
|
||||
: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit BluetoothUploadJob(const QSharedPointer<QIODevice>& data, const QBluetoothAddress& remoteAddress, QObject* parent = 0);
|
||||
explicit BluetoothUploadJob(const QSharedPointer<QIODevice>& data, ConnectionMultiplexer *connection, QObject* parent = 0);
|
||||
|
||||
QVariantMap transferInfo() const;
|
||||
void start();
|
||||
|
||||
private:
|
||||
QSharedPointer<QIODevice> mData;
|
||||
QBluetoothAddress mRemoteAddress;
|
||||
QBluetoothUuid mTransferUuid;
|
||||
QBluetoothServer* mServer;
|
||||
QBluetoothServiceInfo mServiceInfo;
|
||||
QBluetoothSocket* m_socket;
|
||||
QSharedPointer<MultiplexChannel> mSocket;
|
||||
|
||||
void closeConnection();
|
||||
|
||||
private Q_SLOTS:
|
||||
void newConnection();
|
||||
void writeSome();
|
||||
void finishWrites();
|
||||
};
|
||||
|
||||
#endif // BLUETOOTHUPLOADJOB_H
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
/**
|
||||
* The default channel uuid. This channel is opened implicitely (without communication).
|
||||
*/
|
||||
constexpr const char DEFAULT_CHANNEL_UUID[] = "a0d0aaf4-1072-4d81-aa35-902a954b1266";
|
||||
#define DEFAULT_CHANNEL_UUID "a0d0aaf4-1072-4d81-aa35-902a954b1266"
|
||||
|
||||
//Message type constants
|
||||
constexpr char MESSAGE_PROTOCOL_VERSION = 0;
|
||||
|
@ -60,7 +60,7 @@ ConnectionMultiplexer::ConnectionMultiplexer(QBluetoothSocket *socket, QObject *
|
|||
QMetaObject::invokeMethod(this, &ConnectionMultiplexer::bytesWritten, Qt::QueuedConnection);
|
||||
|
||||
//Always open the default channel
|
||||
addChannel(QBluetoothUuid{QString{DEFAULT_CHANNEL_UUID}});
|
||||
addChannel(QBluetoothUuid{QStringLiteral(DEFAULT_CHANNEL_UUID)});
|
||||
|
||||
//Immediately check if we can read stuff ("readyRead" may not be called in that case)
|
||||
if (mSocket->bytesAvailable()) {
|
||||
|
@ -283,7 +283,7 @@ std::unique_ptr<MultiplexChannel> ConnectionMultiplexer::getChannel(QBluetoothUu
|
|||
}
|
||||
|
||||
std::unique_ptr<MultiplexChannel> ConnectionMultiplexer::getDefaultChannel() {
|
||||
return getChannel(QBluetoothUuid{QString{DEFAULT_CHANNEL_UUID}});
|
||||
return getChannel(QBluetoothUuid{QStringLiteral(DEFAULT_CHANNEL_UUID)});
|
||||
}
|
||||
|
||||
void ConnectionMultiplexer::bytesWritten() {
|
||||
|
|
|
@ -25,10 +25,8 @@ DeviceLineReader::DeviceLineReader(QIODevice* device, QObject* parent)
|
|||
: QObject(parent)
|
||||
, m_device(device)
|
||||
{
|
||||
connect(m_device, SIGNAL(readyRead()),
|
||||
this, SLOT(dataReceived()));
|
||||
connect(m_device, SIGNAL(disconnected()),
|
||||
this, SIGNAL(disconnected()));
|
||||
connect(m_device, &QIODevice::readyRead, this, &DeviceLineReader::dataReceived);
|
||||
connect(m_device, &QIODevice::aboutToClose, this, &DeviceLineReader::disconnected);
|
||||
}
|
||||
|
||||
void DeviceLineReader::dataReceived()
|
||||
|
|
Loading…
Reference in a new issue