File indexing completed on 2024-04-28 15:39:42

0001 // SPDX-FileCopyrightText: 2014-2022 Jesper K. Pedersen <blackie@kde.org>
0002 //
0003 // SPDX-License-Identifier: GPL-2.0-or-later
0004 
0005 #include "RemoteConnection.h"
0006 
0007 #include "RemoteCommand.h"
0008 
0009 #include <QApplication>
0010 #include <QBuffer>
0011 #include <QTcpSocket>
0012 #include <QThread>
0013 #include <QTime>
0014 
0015 #if 0
0016 #define protocolDebug qDebug
0017 #else
0018 #define protocolDebug \
0019     if (false)        \
0020     qDebug
0021 #endif
0022 
0023 using namespace RemoteControl;
0024 
0025 RemoteConnection::RemoteConnection(QObject *parent)
0026     : QObject(parent)
0027 {
0028 }
0029 
0030 void RemoteConnection::sendCommand(const RemoteCommand &command)
0031 {
0032     protocolDebug() << qPrintable(QTime::currentTime().toString(QString::fromUtf8("hh:mm:ss.zzz")))
0033                     << ": Sending " << QString::number((int)command.commandType());
0034     Q_ASSERT(QThread::currentThread() == qApp->thread());
0035 
0036     if (!isConnected())
0037         return;
0038 
0039     // Stream into a buffer so we can send length of buffer over
0040     // this is to ensure the remote side gets all data before it
0041     // starts to demarshal the data.
0042     QBuffer buffer;
0043     buffer.open(QIODevice::WriteOnly);
0044     QDataStream stream(&buffer);
0045 
0046     // stream a placeholder for the length
0047     stream << (qint32)0;
0048 
0049     // Steam the id and the data
0050     stream << (qint32)command.commandType();
0051     command.encode(stream);
0052 
0053     // Wind back and stream the length
0054     stream.device()->seek(0);
0055     stream << (qint32)buffer.size();
0056 
0057     // Send the data.
0058     socket()->write(buffer.data());
0059     socket()->flush();
0060 }
0061 
0062 void RemoteConnection::dataReceived()
0063 {
0064     QTcpSocket *socket = this->socket();
0065     if (!socket)
0066         return;
0067 
0068     QDataStream stream(socket);
0069 
0070     while (socket->bytesAvailable()) {
0071         if (m_state == WaitingForLength) {
0072             if (socket->bytesAvailable() < (qint64)sizeof(qint32))
0073                 return;
0074 
0075             stream >> m_length;
0076             m_length -= sizeof(qint32);
0077             m_state = WaitingForData;
0078         }
0079 
0080         if (m_state == WaitingForData) {
0081             if (socket->bytesAvailable() < m_length)
0082                 return;
0083 
0084             m_state = WaitingForLength;
0085             QByteArray data = socket->read(m_length);
0086             Q_ASSERT(data.length() == m_length);
0087 
0088             QBuffer buffer(&data);
0089             buffer.open(QIODevice::ReadOnly);
0090             QDataStream stream(&buffer);
0091             qint32 id;
0092             stream >> id;
0093 
0094             std::unique_ptr<RemoteCommand> command = RemoteCommand::create(static_cast<CommandType>(id));
0095             command->decode(stream);
0096             protocolDebug() << qPrintable(QTime::currentTime().toString(QString::fromUtf8("hh:mm:ss.zzz")))
0097                             << ": Received " << id;
0098 
0099             Q_EMIT gotCommand(*command);
0100         }
0101     }
0102 }
0103 
0104 #include "moc_RemoteConnection.cpp"