//I'm the existing device, a new device is kindly introducing itself. //I will create a TcpSocket and try to connect. This can result in either connected() or connectError(). void LanLinkProvider::newUdpConnection() { while (mUdpServer->hasPendingDatagrams()) { QByteArray datagram; datagram.resize(mUdpServer->pendingDatagramSize()); QHostAddress sender; mUdpServer->readDatagram(datagram.data(), datagram.size(), &sender); NetworkPackage* receivedPackage = new NetworkPackage(""); bool success = NetworkPackage::unserialize(datagram, receivedPackage); if (!success || receivedPackage->type() != PACKAGE_TYPE_IDENTITY) { delete receivedPackage; continue; } if (receivedPackage->get<QString>("deviceId") == KdeConnectConfig::instance()->deviceId()) { //qCDebug(KDECONNECT_CORE) << "Ignoring my own broadcast"; delete receivedPackage; continue; } int tcpPort = receivedPackage->get<int>("tcpPort", port); //qCDebug(KDECONNECT_CORE) << "Received Udp identity package from" << sender << " asking for a tcp connection on port " << tcpPort; QTcpSocket* socket = new QTcpSocket(this); receivedIdentityPackages[socket].np = receivedPackage; receivedIdentityPackages[socket].sender = sender; connect(socket, SIGNAL(connected()), this, SLOT(connected())); connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(connectError())); socket->connectToHost(sender, tcpPort); } }
QDebug operator<<(QDebug s, const NetworkPackage& pkg) { s.nospace() << "NetworkPackage(" << pkg.type() << ':' << pkg.body(); if (pkg.hasPayload()) { s.nospace() << ":withpayload"; } s.nospace() << ')'; return s.space(); }
//I'm the new device and this is the answer to my UDP identity package (data received) void LanLinkProvider::dataReceived() { QSslSocket* socket = qobject_cast<QSslSocket*>(sender()); const QByteArray data = socket->readLine(); //qCDebug(KDECONNECT_CORE) << "LanLinkProvider received reply:" << data; NetworkPackage* np = new NetworkPackage(QLatin1String("")); bool success = NetworkPackage::unserialize(data, np); if (!success) { delete np; return; } if (np->type() != PACKAGE_TYPE_IDENTITY) { qCWarning(KDECONNECT_CORE) << "LanLinkProvider/newConnection: Expected identity, received " << np->type(); delete np; return; } // Needed in "encrypted" if ssl is used, similar to "connected" receivedIdentityPackages[socket].np = np; const QString& deviceId = np->get<QString>(QStringLiteral("deviceId")); //qCDebug(KDECONNECT_CORE) << "Handshaking done (i'm the new device)"; //This socket will now be owned by the LanDeviceLink or we don't want more data to be received, forget about it disconnect(socket, &QIODevice::readyRead, this, &LanLinkProvider::dataReceived); if (np->get<int>(QStringLiteral("protocolVersion")) >= MIN_VERSION_WITH_SSL_SUPPORT) { bool isDeviceTrusted = KdeConnectConfig::instance()->trustedDevices().contains(deviceId); configureSslSocket(socket, deviceId, isDeviceTrusted); qCDebug(KDECONNECT_CORE) << "Starting client ssl (but I'm the server TCP socket)"; connect(socket, &QSslSocket::encrypted, this, &LanLinkProvider::encrypted); if (isDeviceTrusted) { connect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(sslErrors(QList<QSslError>))); } socket->startClientEncryption(); } else { qWarning() << np->get<QString>(QStringLiteral("deviceName")) << "uses an old protocol version, this won't work"; //addLink(deviceId, socket, np, LanDeviceLink::Locally); delete receivedIdentityPackages.take(socket).np; } }
//I'm the existing device, a new device is kindly introducing itself. //I will create a TcpSocket and try to connect. This can result in either connected() or connectError(). void LanLinkProvider::newUdpConnection() //udpBroadcastReceived { while (mUdpSocket.hasPendingDatagrams()) { QByteArray datagram; datagram.resize(mUdpSocket.pendingDatagramSize()); QHostAddress sender; mUdpSocket.readDatagram(datagram.data(), datagram.size(), &sender); if (sender.isLoopback() && !mTestMode) continue; NetworkPackage* receivedPackage = new NetworkPackage(QLatin1String("")); bool success = NetworkPackage::unserialize(datagram, receivedPackage); //qCDebug(KDECONNECT_CORE) << "udp connection from " << receivedPackage->; //qCDebug(KDECONNECT_CORE) << "Datagram " << datagram.data() ; if (!success || receivedPackage->type() != PACKAGE_TYPE_IDENTITY) { delete receivedPackage; continue; } if (receivedPackage->get<QString>(QStringLiteral("deviceId")) == KdeConnectConfig::instance()->deviceId()) { //qCDebug(KDECONNECT_CORE) << "Ignoring my own broadcast"; delete receivedPackage; continue; } int tcpPort = receivedPackage->get<int>(QStringLiteral("tcpPort"), PORT); //qCDebug(KDECONNECT_CORE) << "Received Udp identity package from" << sender << " asking for a tcp connection on port " << tcpPort; QSslSocket* socket = new QSslSocket(this); receivedIdentityPackages[socket].np = receivedPackage; receivedIdentityPackages[socket].sender = sender; connect(socket, &QAbstractSocket::connected, this, &LanLinkProvider::connected); connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(connectError())); socket->connectToHost(sender, tcpPort); } }