kdirshare: thread the server again

the initial testing was done with a small buffer (QT_BUFFSIZE) which
did not block long while reading file chunks but to reach the disk I/O
limit a larger buffer may be used by KHTTP in the future

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2022-12-26 17:57:11 +02:00
parent 417d9065fb
commit 9cd4a781ff
2 changed files with 154 additions and 73 deletions

View file

@ -19,6 +19,7 @@
#include "kdirshareimpl.h"
#include "kdirshare.h"
#include <QCoreApplication>
#include <QDir>
#include <QBuffer>
#include <QPixmap>
@ -144,84 +145,25 @@ static QByteArray contentForDirectory(const QString &path, const QString &basedi
return data;
}
KDirShareImpl::KDirShareImpl(QObject *parent)
: KHTTP(parent),
m_directory(QDir::currentPath()),
m_portmin(s_kdirshareportmin),
m_portmax(s_kdirshareportmax)
KDirServer::KDirServer(QObject *parent)
: KHTTP(parent)
{
setServerID(QString::fromLatin1("KDirShare"));
}
KDirShareImpl::~KDirShareImpl()
bool KDirServer::setDirectory(const QString &directory)
{
m_kdnssd.unpublishService();
stop();
}
QString KDirShareImpl::serve(const QString &dirpath,
const quint16 portmin, const quint16 portmax,
const QString &username, const QString &password)
{
// qDebug() << Q_FUNC_INFO << dirpath << portmin << portmax << username << password;
const quint16 port = getPort(portmin, portmax);
m_directory = dirpath;
m_portmin = portmin;
m_portmax = portmax;
m_user = username;
m_password = password;
m_error.clear();
if (!QDir(m_directory).exists()) {
m_error = i18n("Directory does not exist: %1", m_directory);
return m_error;
return false;
}
if (!m_user.isEmpty() && !m_password.isEmpty()) {
if (!setAuthenticate(m_user.toUtf8(), m_password.toUtf8())) {
m_error = i18n("Could not set authentication: %1", errorString());
return m_error;
}
}
if (!start(QHostAddress(QHostAddress::Any), port)) {
m_error = i18n("Could not serve: %1", errorString());
return m_error;
}
if (!m_kdnssd.publishService("_http._tcp", port, getTitle(m_directory))) {
stop();
m_error = i18n("Could not publish service: %1", m_kdnssd.errorString());
return m_error;
}
return m_error;
}
QString KDirShareImpl::directory() const
{
return m_directory;
}
quint16 KDirShareImpl::portMin() const
{
return m_portmin;
}
quint16 KDirShareImpl::portMax() const
{
return m_portmax;
}
QString KDirShareImpl::user() const
{
return m_user;
}
QString KDirShareImpl::password() const
{
return m_password;
m_directory = directory;
return true;
}
// for reference:
// https://en.wikipedia.org/wiki/List_of_HTTP_status_codes
void KDirShareImpl::respond(const QByteArray &url, QByteArray *outdata,
ushort *outhttpstatus, KHTTPHeaders *outheaders,
QString *outfilepath)
void KDirServer::respond(const QByteArray &url, QByteArray *outdata,
ushort *outhttpstatus, KHTTPHeaders *outheaders,
QString *outfilepath)
{
// qDebug() << Q_FUNC_INFO << url;
const QString normalizedpath = QUrl::fromPercentEncoding(url);
@ -257,4 +199,117 @@ void KDirShareImpl::respond(const QByteArray &url, QByteArray *outdata,
}
}
KDirShareImpl::KDirShareImpl(QObject *parent)
: QThread(parent),
m_directory(QDir::currentPath()),
m_portmin(s_kdirshareportmin),
m_portmax(s_kdirshareportmax),
m_starting(false),
m_kdirserver(nullptr)
{
connect(
this, SIGNAL(unblock()),
this, SLOT(slotUnblock())
);
connect(
this, SIGNAL(serveError(QString)),
this, SLOT(slotServeError(QString))
);
}
KDirShareImpl::~KDirShareImpl()
{
m_kdnssd.unpublishService();
delete m_kdirserver;
}
QString KDirShareImpl::serve(const QString &dirpath,
const quint16 portmin, const quint16 portmax,
const QString &username, const QString &password)
{
// qDebug() << Q_FUNC_INFO << dirpath << portmin << portmax << username << password;
m_directory = dirpath;
m_portmin = portmin;
m_portmax = portmax;
m_user = username;
m_password = password;
m_error.clear();
m_starting = true;
m_error.clear();
start();
while (m_starting) {
QCoreApplication::processEvents();
}
return m_error;
}
QString KDirShareImpl::directory() const
{
return m_directory;
}
quint16 KDirShareImpl::portMin() const
{
return m_portmin;
}
quint16 KDirShareImpl::portMax() const
{
return m_portmax;
}
QString KDirShareImpl::user() const
{
return m_user;
}
QString KDirShareImpl::password() const
{
return m_password;
}
void KDirShareImpl::run()
{
m_kdirserver = new KDirServer();
m_kdirserver->setServerID(QString::fromLatin1("KDirShare"));
if (!m_kdirserver->setDirectory(m_directory)) {
emit serveError(i18n("Directory does not exist: %1", m_directory));
emit unblock();
return;
}
if (!m_user.isEmpty() && !m_password.isEmpty()) {
if (!m_kdirserver->setAuthenticate(m_user.toUtf8(), m_password.toUtf8())) {
emit serveError(i18n("Could not set authentication: %1", m_kdirserver->errorString()));
emit unblock();
return;
}
}
const quint16 port = getPort(m_portmin, m_portmax);
if (!m_kdirserver->start(QHostAddress(QHostAddress::Any), port)) {
emit serveError(i18n("Could not serve: %1", m_kdirserver->errorString()));
emit unblock();
return;
}
if (!m_kdnssd.publishService("_http._tcp", port, getTitle(m_directory))) {
m_kdirserver->stop();
emit serveError(i18n("Could not publish service: %1", m_kdnssd.errorString()));
emit unblock();
return;
}
emit unblock();
exec();
}
void KDirShareImpl::slotUnblock()
{
m_starting = false;
}
void KDirShareImpl::slotServeError(const QString &error)
{
m_error = error;
}
#include "moc_kdirshareimpl.cpp"

View file

@ -19,10 +19,29 @@
#ifndef KDIRSHAREIMPL_H
#define KDIRSHAREIMPL_H
#include <QThread>
#include <khttp.h>
#include <kdnssd.h>
class KDirShareImpl : public KHTTP
class KDirServer : public KHTTP
{
public:
KDirServer(QObject *parent = nullptr);
bool setDirectory(const QString &directory);
protected:
void respond(
const QByteArray &url,
QByteArray *outdata, ushort *outhttpstatus, KHTTPHeaders *outheaders, QString *outfilepath
) final;
private:
QString m_directory;
};
class KDirShareImpl : public QThread
{
Q_OBJECT
public:
@ -39,10 +58,15 @@ public:
QString password() const;
protected:
void respond(
const QByteArray &url,
QByteArray *outdata, ushort *outhttpstatus, KHTTPHeaders *outheaders, QString *outfilepath
) final;
void run() final;
Q_SIGNALS:
void unblock();
void serveError(const QString &error);
private Q_SLOTS:
void slotUnblock();
void slotServeError(const QString &error);
private:
QString m_directory;
@ -51,6 +75,8 @@ private:
QString m_user;
QString m_password;
QString m_error;
bool m_starting;
KDirServer* m_kdirserver;
KDNSSD m_kdnssd;
};