First handshake with pica

This commit is contained in:
Blue 2023-11-24 20:48:01 -03:00
parent 4da9a275a9
commit f547170728
Signed by: blue
GPG key ID: 9B203B252A63EE38
12 changed files with 391 additions and 82 deletions

9
API/CMakeLists.txt Normal file
View file

@ -0,0 +1,9 @@
set(HEADERS
api.h
)
set(SOURCES
api.cpp
)
target_sources(megpie PRIVATE ${SOURCES})

93
API/api.cpp Normal file
View file

@ -0,0 +1,93 @@
#include "api.h"
#include <QDebug>
#include <QJsonDocument>
#include <QJsonObject>
constexpr const char* json = "application/json";
struct NetworkReplyDeleter {
void operator () (QNetworkReply* reply) {
reply->deleteLater();
}
};
API::API(const QUrl& address, QObject* parent):
QObject(parent),
address(address),
network()
{
}
void API::test(const QString& path, const QJSValue& finished) {
qDebug() << "Testing" << path;
QNetworkRequest request(path + "/info");
request.setHeader(QNetworkRequest::ContentTypeHeader, json);
QNetworkReply* reply = network.get(request);
connect(reply, &QNetworkReply::finished,
std::bind(&API::onTestSuccess, this, reply, finished)
);
}
void API::onTestSuccess(QNetworkReply* reply, const QJSValue& finished) const {
std::unique_ptr<QNetworkReply, NetworkReplyDeleter> rpl(reply);
QNetworkReply::NetworkError error = reply->error();
if (error != QNetworkReply::NoError) {
QString err = reply->errorString();
qDebug() << "Test for" << reply->url() << "failed:" << err;
callCallback(finished, err);
return;
}
QVariant contentType = reply->header(QNetworkRequest::ContentTypeHeader);
if (!
contentType.isValid() ||
!contentType.canConvert<QString>() ||
contentType.toString() != json
) {
QString err("wrong response content type");
qDebug() << "Test for" << reply->url() << "failed:" << err;
callCallback(finished, err);
return;
}
QByteArray data = reply->readAll();
QJsonDocument document = QJsonDocument::fromJson(data);
QJsonObject rootObj = document.object();
QJsonValue type = rootObj.value("type");
QJsonValue version = rootObj.value("version");
if (!type.isString() || !version.isString()) {
QString err("malformed json");
qDebug() << "Test for" << reply->url() << "failed:" << err;
callCallback(finished, err);
return;
}
if (type.toString() != "Pica") {
QString err("server of this type (" + type.toString() + ") is not supported");
qDebug() << "Test for" << reply->url() << "failed:" << err;
callCallback(finished, err);
return;
}
if (version.toString() != "0.0.1") {
QString err("server of this version (" + version.toString() + ") is not supported");
qDebug() << "Test for" << reply->url() << "failed:" << err;
callCallback(finished, err);
return;
}
callCallback(finished, QString(), {QJSValue(true)});
}
void API::callCallback(const QJSValue& callback, const QString& error, const QJSValueList& arguments) const {
if (callback.isCallable()) {
if (error.isEmpty())
callback.call(QJSValueList({QJSValue(QJSValue::NullValue)}) + arguments);
else
callback.call({QJSValue(error)});
}
}

28
API/api.h Normal file
View file

@ -0,0 +1,28 @@
#pragma once
#include <memory>
#include <QObject>
#include <QString>
#include <QUrl>
#include <QJSValue>
#include <QNetworkAccessManager>
#include <QNetworkReply>
class API : public QObject {
Q_OBJECT
public:
explicit API(const QUrl& path = QString(), QObject* parent = nullptr);
Q_INVOKABLE void test(const QString& path, const QJSValue& finished = QJSValue());
private slots:
void onTestSuccess(QNetworkReply* reply, const QJSValue& finished) const;
private:
void callCallback(const QJSValue& callback, const QString& error = QString(), const QJSValueList& arguments = QJSValueList()) const;
private:
QUrl address;
QNetworkAccessManager network;
};