File indexing completed on 2024-05-12 04:58:51

0001 /**
0002  * SPDX-FileCopyrightText: 2013 Albert Vaca <albertvaka@gmail.com>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  */
0006 
0007 #include "landevicelink.h"
0008 
0009 #include <KLocalizedString>
0010 
0011 #include "backends/linkprovider.h"
0012 #include "core_debug.h"
0013 #include "kdeconnectconfig.h"
0014 #include "lanlinkprovider.h"
0015 #include "plugins/share/shareplugin.h"
0016 
0017 LanDeviceLink::LanDeviceLink(const DeviceInfo &deviceInfo, LanLinkProvider *parent, QSslSocket *socket)
0018     : DeviceLink(deviceInfo.id, parent)
0019     , m_socket(nullptr)
0020     , m_deviceInfo(deviceInfo)
0021 {
0022     reset(socket);
0023 }
0024 
0025 void LanDeviceLink::reset(QSslSocket *socket)
0026 {
0027     if (m_socket) {
0028         disconnect(m_socket, &QAbstractSocket::disconnected, this, &QObject::deleteLater);
0029         delete m_socket;
0030     }
0031 
0032     m_socket = socket;
0033     socket->setParent(this);
0034 
0035     connect(socket, &QAbstractSocket::disconnected, this, &QObject::deleteLater);
0036     connect(socket, &QAbstractSocket::readyRead, this, &LanDeviceLink::dataReceived);
0037 }
0038 
0039 QHostAddress LanDeviceLink::hostAddress() const
0040 {
0041     if (!m_socket) {
0042         return QHostAddress::Null;
0043     }
0044     QHostAddress addr = m_socket->peerAddress();
0045     if (addr.protocol() == QAbstractSocket::IPv6Protocol) {
0046         bool success;
0047         QHostAddress convertedAddr = QHostAddress(addr.toIPv4Address(&success));
0048         if (success) {
0049             qCDebug(KDECONNECT_CORE) << "Converting IPv6" << addr << "to IPv4" << convertedAddr;
0050             addr = convertedAddr;
0051         }
0052     }
0053     return addr;
0054 }
0055 
0056 bool LanDeviceLink::sendPacket(NetworkPacket &np)
0057 {
0058     if (np.payload()) {
0059         if (np.type() == PACKET_TYPE_SHARE_REQUEST && np.payloadSize() >= 0) {
0060             if (!m_compositeUploadJob || !m_compositeUploadJob->isRunning()) {
0061                 m_compositeUploadJob = new CompositeUploadJob(deviceId(), true);
0062             }
0063 
0064             m_compositeUploadJob->addSubjob(new UploadJob(np));
0065 
0066             if (!m_compositeUploadJob->isRunning()) {
0067                 m_compositeUploadJob->start();
0068             }
0069         } else { // Infinite stream
0070             CompositeUploadJob *fireAndForgetJob = new CompositeUploadJob(deviceId(), false);
0071             fireAndForgetJob->addSubjob(new UploadJob(np));
0072             fireAndForgetJob->start();
0073         }
0074 
0075         return true;
0076     } else {
0077         int written = m_socket->write(np.serialize());
0078 
0079         // Actually we can't detect if a packet is received or not. We keep TCP
0080         //"ESTABLISHED" connections that look legit (return true when we use them),
0081         // but that are actually broken (until keepalive detects that they are down).
0082         return (written != -1);
0083     }
0084 }
0085 
0086 void LanDeviceLink::dataReceived()
0087 {
0088     while (m_socket->canReadLine()) {
0089         const QByteArray serializedPacket = m_socket->readLine();
0090         NetworkPacket packet;
0091         NetworkPacket::unserialize(serializedPacket, &packet);
0092 
0093         // qCDebug(KDECONNECT_CORE) << "LanDeviceLink dataReceived" << serializedPacket;
0094 
0095         if (packet.hasPayloadTransferInfo()) {
0096             // qCDebug(KDECONNECT_CORE) << "HasPayloadTransferInfo";
0097             const QVariantMap transferInfo = packet.payloadTransferInfo();
0098 
0099             QSharedPointer<QSslSocket> socket(new QSslSocket);
0100 
0101             LanLinkProvider::configureSslSocket(socket.data(), deviceId(), true);
0102 
0103             // emit readChannelFinished when the socket gets disconnected. This seems to be a bug in upstream QSslSocket.
0104             // Needs investigation and upstreaming of the fix. QTBUG-62257
0105             connect(socket.data(), &QAbstractSocket::disconnected, socket.data(), &QAbstractSocket::readChannelFinished);
0106 
0107             const QString address = m_socket->peerAddress().toString();
0108             const quint16 port = transferInfo[QStringLiteral("port")].toInt();
0109             socket->connectToHostEncrypted(address, port, QIODevice::ReadWrite);
0110             packet.setPayload(socket, packet.payloadSize());
0111         }
0112 
0113         Q_EMIT receivedPacket(packet);
0114     }
0115 }
0116 
0117 #include "moc_landevicelink.cpp"