nextcloud-desktop/src/gui/socketapi/socketapi_p.h
2021-08-23 09:44:34 +02:00

169 lines
4.3 KiB
C++

/*
* Copyright (C) by Dominik Schmidt <dev@dominik-schmidt.de>
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
* Copyright (C) by Roeland Jago Douma <roeland@famdouma.nl>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef SOCKETAPI_P_H
#define SOCKETAPI_P_H
#include <functional>
#include <QBitArray>
#include <QPointer>
#include <QJsonDocument>
#include <QJsonObject>
#include <memory>
#include <QTimer>
namespace OCC {
class BloomFilter
{
// Initialize with m=1024 bits and k=2 (high and low 16 bits of a qHash).
// For a client navigating in less than 100 directories, this gives us a probability less than
// (1-e^(-2*100/1024))^2 = 0.03147872136 false positives.
const static int NumBits = 1024;
public:
BloomFilter()
: hashBits(NumBits)
{
}
void storeHash(uint hash)
{
hashBits.setBit((hash & 0xFFFF) % NumBits); // NOLINT it's uint all the way and the modulo puts us back in the 0..1023 range
hashBits.setBit((hash >> 16) % NumBits); // NOLINT
}
bool isHashMaybeStored(uint hash) const
{
return hashBits.testBit((hash & 0xFFFF) % NumBits) // NOLINT
&& hashBits.testBit((hash >> 16) % NumBits); // NOLINT
}
private:
QBitArray hashBits;
};
class SocketListener
{
public:
QPointer<QIODevice> socket;
explicit SocketListener(QIODevice *_socket)
: socket(_socket)
{
}
void sendMessage(const QString &message, bool doWait = false) const;
void sendWarning(const QString &message, bool doWait = false) const
{
sendMessage(QStringLiteral("WARNING:") + message, doWait);
}
void sendError(const QString &message, bool doWait = false) const
{
sendMessage(QStringLiteral("ERROR:") + message, doWait);
}
void sendMessageIfDirectoryMonitored(const QString &message, uint systemDirectoryHash) const
{
if (_monitoredDirectoriesBloomFilter.isHashMaybeStored(systemDirectoryHash))
sendMessage(message, false);
}
void registerMonitoredDirectory(uint systemDirectoryHash)
{
_monitoredDirectoriesBloomFilter.storeHash(systemDirectoryHash);
}
private:
BloomFilter _monitoredDirectoriesBloomFilter;
};
class ListenerClosure : public QObject
{
Q_OBJECT
public:
using CallbackFunction = std::function<void()>;
ListenerClosure(CallbackFunction callback)
: callback_(callback)
{
}
public slots:
void closureSlot()
{
callback_();
deleteLater();
}
private:
CallbackFunction callback_;
};
class SocketApiJob : public QObject
{
Q_OBJECT
public:
explicit SocketApiJob(const QString &jobId, const QSharedPointer<SocketListener> &socketListener, const QJsonObject &arguments)
: _jobId(jobId)
, _socketListener(socketListener)
, _arguments(arguments)
{
}
void resolve(const QString &response = QString());
void resolve(const QJsonObject &response);
const QJsonObject &arguments() { return _arguments; }
void reject(const QString &response);
protected:
QString _jobId;
QSharedPointer<SocketListener> _socketListener;
QJsonObject _arguments;
};
class SocketApiJobV2 : public QObject
{
Q_OBJECT
public:
explicit SocketApiJobV2(const QSharedPointer<SocketListener> &socketListener, const QByteArray &command, const QJsonObject &arguments);
void success(const QJsonObject &response) const;
void failure(const QString &error) const;
const QJsonObject &arguments() const { return _arguments; }
QByteArray command() const { return _command; }
Q_SIGNALS:
void finished() const;
private:
void doFinish(const QJsonObject &obj) const;
QSharedPointer<SocketListener> _socketListener;
const QByteArray _command;
QString _jobId;
QJsonObject _arguments;
};
}
Q_DECLARE_METATYPE(OCC::SocketListener *)
#endif // SOCKETAPI_P_H