File indexing completed on 2024-04-28 04:57:01

0001 /**
0002  * SPDX-FileCopyrightText: 2015 Albert Vaca Cintora <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 "pairinghandler.h"
0008 
0009 #include "core_debug.h"
0010 
0011 #include <KLocalizedString>
0012 
0013 PairingHandler::PairingHandler(Device *parent, PairState initialState)
0014     : QObject(parent)
0015     , m_device(parent)
0016     , m_pairState(initialState)
0017 {
0018     m_pairingTimeout.setSingleShot(true);
0019     m_pairingTimeout.setInterval(pairingTimeoutMsec);
0020     connect(&m_pairingTimeout, &QTimer::timeout, this, &PairingHandler::pairingTimeout);
0021 }
0022 
0023 void PairingHandler::packetReceived(const NetworkPacket &np)
0024 {
0025     m_pairingTimeout.stop();
0026     bool wantsPair = np.get<bool>(QStringLiteral("pair"));
0027     if (wantsPair) {
0028         switch (m_pairState) {
0029         case PairState::Requested:
0030             pairingDone();
0031             break;
0032         case PairState::RequestedByPeer:
0033             qCDebug(KDECONNECT_CORE) << "Ignoring second pairing request before the first one timed out";
0034             break;
0035         case PairState::Paired:
0036         case PairState::NotPaired:
0037             if (m_pairState == PairState::Paired) {
0038                 qWarning() << "Received pairing request from a device we already trusted.";
0039                 // It would be nice to auto-accept the pairing request here, but since the pairing accept and pairing request
0040                 // messages are identical, this could create an infinite loop if both devices are "accepting" each other pairs.
0041                 // Instead, unpair and handle as if "NotPaired".
0042                 m_pairState = PairState::NotPaired;
0043                 Q_EMIT unpaired();
0044             }
0045             m_pairState = PairState::RequestedByPeer;
0046             m_pairingTimeout.start();
0047             Q_EMIT incomingPairRequest();
0048             break;
0049         }
0050     } else { // wantsPair == false
0051         qCDebug(KDECONNECT_CORE) << "Unpair request received";
0052         switch (m_pairState) {
0053         case PairState::NotPaired:
0054             qCDebug(KDECONNECT_CORE) << "Ignoring unpair request for already unpaired device";
0055             break;
0056         case PairState::Requested: // We started pairing and got rejected
0057         case PairState::RequestedByPeer: // They stared pairing, then cancelled
0058             m_pairState = PairState::NotPaired;
0059             Q_EMIT pairingFailed(i18n("Canceled by other peer"));
0060             break;
0061         case PairState::Paired:
0062             m_pairState = PairState::NotPaired;
0063             Q_EMIT unpaired();
0064             break;
0065         }
0066     }
0067 }
0068 
0069 bool PairingHandler::requestPairing()
0070 {
0071     m_pairingTimeout.stop();
0072 
0073     if (m_pairState == PairState::Paired) {
0074         qWarning() << m_device->name() << ": requestPairing was called on an already paired device.";
0075         Q_EMIT pairingFailed(i18n("%1: Already paired", m_device->name()));
0076         return false;
0077     }
0078     if (m_pairState == PairState::RequestedByPeer) {
0079         qWarning() << m_device->name() << ": Pairing already started by the other end, accepting their request.";
0080         return acceptPairing();
0081     }
0082 
0083     if (!m_device->isReachable()) {
0084         Q_EMIT pairingFailed(i18n("%1: Device not reachable", m_device->name()));
0085         return false;
0086     }
0087 
0088     m_pairState = PairState::Requested;
0089 
0090     m_pairingTimeout.start();
0091 
0092     NetworkPacket np(PACKET_TYPE_PAIR, {{QStringLiteral("pair"), true}});
0093     const bool success = m_device->sendPacket(np);
0094     if (!success) {
0095         m_pairingTimeout.stop();
0096         qWarning() << m_device->name() << ": Failed to send pair request packet.";
0097         m_pairState = PairState::NotPaired;
0098         Q_EMIT pairingFailed(i18n("%1: Device not reachable", m_device->name()));
0099     }
0100     return success;
0101 }
0102 
0103 bool PairingHandler::acceptPairing()
0104 {
0105     m_pairingTimeout.stop();
0106     NetworkPacket np(PACKET_TYPE_PAIR, {{QStringLiteral("pair"), true}});
0107     const bool success = m_device->sendPacket(np);
0108     if (success) {
0109         pairingDone();
0110     } else {
0111         qWarning() << "Failed to send packet accepting pairing";
0112         m_pairState = PairState::NotPaired;
0113         Q_EMIT pairingFailed(i18n("Device not reachable"));
0114     }
0115     return success;
0116 }
0117 
0118 void PairingHandler::cancelPairing()
0119 {
0120     m_pairingTimeout.stop();
0121     m_pairState = PairState::NotPaired;
0122     NetworkPacket np(PACKET_TYPE_PAIR, {{QStringLiteral("pair"), false}});
0123     m_device->sendPacket(np);
0124     Q_EMIT pairingFailed(i18n("Cancelled by user"));
0125 }
0126 
0127 void PairingHandler::unpair()
0128 {
0129     m_pairState = PairState::NotPaired;
0130     NetworkPacket np(PACKET_TYPE_PAIR, {{QStringLiteral("pair"), false}});
0131     m_device->sendPacket(np);
0132     Q_EMIT unpaired();
0133 }
0134 
0135 void PairingHandler::pairingTimeout()
0136 {
0137     NetworkPacket np(PACKET_TYPE_PAIR, {{QStringLiteral("pair"), false}});
0138     m_device->sendPacket(np);
0139     m_pairState = PairState::NotPaired;
0140     Q_EMIT pairingFailed(i18n("Timed out"));
0141 }
0142 
0143 void PairingHandler::pairingDone()
0144 {
0145     qCDebug(KDECONNECT_CORE) << "Pairing done";
0146     m_pairState = PairState::Paired;
0147     Q_EMIT pairingSuccessful();
0148 }
0149 
0150 #include "moc_pairinghandler.cpp"