File indexing completed on 2024-05-05 12:18:01

0001 /*
0002     This file is part of the KDE libraries
0003     SPDX-FileCopyrightText: 2003 Leo Savernik <l.savernik@aon.at>
0004     Derived from slave.cpp
0005 
0006     SPDX-License-Identifier: LGPL-2.0-only
0007 */
0008 
0009 #include "commands_p.h"
0010 #include "dataprotocol_p.h"
0011 #include "dataworker_p.h"
0012 #include "slavebase.h"
0013 
0014 #include <KLocalizedString>
0015 
0016 #include <QDataStream>
0017 #include <QTimer>
0018 
0019 using namespace KIO;
0020 
0021 static constexpr int s_kioDataPollInterval = 0;
0022 
0023 // don't forget to sync DISPATCH_DECL in dataworker_p.h
0024 /* clang-format off */
0025 #define DISPATCH_IMPL(type) \
0026     void DataWorker::dispatch_##type() \
0027     { \
0028         if (_suspended) { \
0029             QueueStruct q(Queue_##type); \
0030             q.size = -1; \
0031             dispatchQueue.push_back(q); \
0032             if (!timer->isActive()) { \
0033                 timer->start(s_kioDataPollInterval); \
0034             } \
0035         } else \
0036             Q_EMIT type(); \
0037     }
0038 
0039 // don't forget to sync DISPATCH_DECL1 in dataworker_p.h
0040 #define DISPATCH_IMPL1(type, paramtype, paramname) \
0041     void DataWorker::dispatch_##type(paramtype paramname) \
0042     { \
0043         if (_suspended) { \
0044             QueueStruct q(Queue_##type); \
0045             q.paramname = paramname; \
0046             dispatchQueue.push_back(q); \
0047             if (!timer->isActive()) { \
0048                 timer->start(s_kioDataPollInterval); \
0049             } \
0050         } else \
0051             Q_EMIT type(paramname); \
0052     }
0053 
0054 DataWorker::DataWorker()
0055     : Slave(QStringLiteral("data"))
0056 {
0057     // qDebug() << this;
0058     _suspended = false;
0059     timer = new QTimer(this);
0060     connect(timer, &QTimer::timeout, this, &DataWorker::dispatchNext);
0061 }
0062 
0063 DataWorker::~DataWorker()
0064 {
0065     // qDebug() << this;
0066 }
0067 
0068 void DataWorker::hold(const QUrl & /*url*/)
0069 {
0070     // ignored
0071 }
0072 
0073 void DataWorker::suspend()
0074 {
0075     _suspended = true;
0076     // qDebug() << this;
0077     timer->stop();
0078 }
0079 
0080 void DataWorker::resume()
0081 {
0082     _suspended = false;
0083     // qDebug() << this;
0084     // aarrrgh! This makes the once hyper fast and efficient data protocol
0085     // implementation slow as molasses. But it wouldn't work otherwise,
0086     // and I don't want to start messing around with threads
0087     timer->start(s_kioDataPollInterval);
0088 }
0089 
0090 // finished is a special case. If we emit it right away, then
0091 // TransferJob::start can delete the job even before the end of the method
0092 void DataWorker::dispatch_finished()
0093 {
0094     QueueStruct q(Queue_finished);
0095     q.size = -1;
0096     dispatchQueue.push_back(q);
0097     if (!timer->isActive()) {
0098         timer->start(s_kioDataPollInterval);
0099     }
0100 }
0101 
0102 void DataWorker::dispatchNext()
0103 {
0104     if (dispatchQueue.empty()) {
0105         timer->stop();
0106         return;
0107     }
0108 
0109     const QueueStruct &q = dispatchQueue.front();
0110     // qDebug() << this << "dispatching" << q.type << dispatchQueue.size() << "left";
0111     switch (q.type) {
0112     case Queue_mimeType:
0113         Q_EMIT mimeType(q.s);
0114         break;
0115     case Queue_totalSize:
0116         Q_EMIT totalSize(q.size);
0117         break;
0118     case Queue_sendMetaData:
0119         sendMetaData();
0120         break;
0121     case Queue_data:
0122         Q_EMIT data(q.ba);
0123         break;
0124     case Queue_finished:
0125         Q_EMIT finished();
0126         break;
0127     } /*end switch*/
0128 
0129     dispatchQueue.pop_front();
0130 }
0131 
0132 void DataWorker::send(int cmd, const QByteArray &arr)
0133 {
0134     QDataStream stream(arr);
0135 
0136     QUrl url;
0137 
0138     switch (cmd) {
0139     case CMD_GET: {
0140         stream >> url;
0141         get(url);
0142         break;
0143     }
0144     case CMD_MIMETYPE: {
0145         stream >> url;
0146         mimetype(url);
0147         break;
0148     }
0149     // ignore these (must not emit error, otherwise SIGSEGV occurs)
0150     case CMD_REPARSECONFIGURATION:
0151     case CMD_META_DATA:
0152     case CMD_SUBURL:
0153         break;
0154     default:
0155         Q_EMIT error(ERR_UNSUPPORTED_ACTION, unsupportedActionErrorString(QStringLiteral("data"), cmd));
0156     } /*end switch*/
0157 }
0158 
0159 bool DataWorker::suspended()
0160 {
0161     return _suspended;
0162 }
0163 
0164 void DataWorker::setHost(const QString & /*host*/, quint16 /*port*/, const QString & /*user*/, const QString & /*passwd*/)
0165 {
0166     // irrelevant -> will be ignored
0167 }
0168 
0169 void DataWorker::setConfig(const MetaData & /*config*/)
0170 {
0171     // FIXME: decide to handle this directly or not at all
0172 #if 0
0173     QByteArray data;
0174     QDataStream stream(data, QIODevice::WriteOnly);
0175     stream << config;
0176     slaveconn.send(CMD_CONFIG, data);
0177 #endif
0178 }
0179 
0180 void DataWorker::setAllMetaData(const MetaData &md)
0181 {
0182     meta_data = md;
0183 }
0184 
0185 void DataWorker::sendMetaData()
0186 {
0187     Q_EMIT metaData(meta_data);
0188 }
0189 
0190 DISPATCH_IMPL1(mimeType, const QString &, s)
0191 DISPATCH_IMPL1(totalSize, KIO::filesize_t, size)
0192 DISPATCH_IMPL(sendMetaData)
0193 DISPATCH_IMPL1(data, const QByteArray &, ba)
0194 
0195 #undef DISPATCH_IMPL
0196 #undef DISPATCH_IMPL1
0197 
0198 #include "moc_dataworker_p.cpp"