From dd7d4737bfe0ef4ce543311798fede0a6a58540b Mon Sep 17 00:00:00 2001 From: Li Xi Date: Sun, 24 Apr 2022 14:52:13 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BD=BF=E7=94=A8QJson=E6=9B=BF?= =?UTF-8?q?=E6=8D=A2nlohmann?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 使用qt自带json库,替换掉nlohmann库 Log: Task: https://pms.uniontech.com/task-view-111975.html Influence: json解析 Change-Id: Ifef186afc84f7ebd92f9f1591df4b96eba0774c7 --- debian/control | 1 - src/CMakeLists.txt | 1 + src/loader/CMakeLists.txt | 1 + src/loader/main.cpp | 42 +- src/modules/methods/basic.h | 33 +- src/modules/methods/instance.hpp | 36 +- src/modules/methods/quit.hpp | 49 +- src/modules/methods/registe.hpp | 53 +- src/modules/methods/task.hpp | 92 ++- src/modules/socket/client.cpp | 26 +- src/modules/socket/client.h | 33 +- src/modules/util/json.h | 72 +- src/modules/util/oci_runtime.h | 950 +++++++++++++++++----- src/modules/util/util.h | 34 +- src/service/CMakeLists.txt | 2 - src/service/impl/application_instance.cpp | 10 +- src/service/impl/application_manager.cpp | 54 +- 17 files changed, 1072 insertions(+), 417 deletions(-) diff --git a/debian/control b/debian/control index 9c0953c..335fef0 100644 --- a/debian/control +++ b/debian/control @@ -6,7 +6,6 @@ Build-Depends: cmake, debhelper-compat (= 11), pkg-config, - nlohmann-json3-dev, libcap-dev, qt5-qmake, qtbase5-dev, diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 502633d..07d217f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,5 +1,6 @@ include(FindPkgConfig) find_package(PkgConfig REQUIRED) +find_package(Qt5 REQUIRED COMPONENTS Core DBus Concurrent) if(CMAKE_BUILD_TYPE STREQUAL "Debug") add_definitions(-DDEFINE_LOADER_PATH) diff --git a/src/loader/CMakeLists.txt b/src/loader/CMakeLists.txt index 3e5386f..0f75ace 100644 --- a/src/loader/CMakeLists.txt +++ b/src/loader/CMakeLists.txt @@ -35,5 +35,6 @@ target_link_libraries(deepin-application-loader pthread PkgConfig::LIBCAP stdc++fs + Qt5::Core ) install(TARGETS deepin-application-loader DESTINATION bin) diff --git a/src/loader/main.cpp b/src/loader/main.cpp index 3cd9a29..b8740d8 100644 --- a/src/loader/main.cpp +++ b/src/loader/main.cpp @@ -88,7 +88,7 @@ int child(void* _arg) prctl(PR_SET_PDEATHSIG, SIGTERM); prctl(PR_SET_PDEATHSIG, SIGHUP); - App app = parseApp(task->runId); + App app = parseApp(task->runId.toStdString()); std::string path{ "/usr/share/applications/" + app.id + ".desktop" }; if (app.type == "user") { struct passwd* user = getpwuid(getuid()); @@ -111,15 +111,17 @@ int child(void* _arg) mount.data = { "ro" }; runtime.hostname = "hostname"; runtime.process.cwd = "/"; - std::filesystem::path container_root_path(annotations.container_root_path); + std::filesystem::path container_root_path(annotations.container_root_path.toStdString()); if (!std::filesystem::exists(container_root_path)) { if (!std::filesystem::create_directories(container_root_path)) { std::cout << "[Loader] [Warning] cannot create container root path." << std::endl; return -1; } } - std::transform(task->environments.begin(), task->environments.end(), std::back_inserter(runtime.process.env), - [](const std::pair& pair) -> std::string { return pair.first + "=" + pair.second; }); + + for (auto it = task->environments.begin(); it != task->environments.end(); ++it) { + runtime.process.env.append(it.key() + "=" + it.value()); + } std::istringstream stream(dd.value("Exec")); std::string s; @@ -132,10 +134,12 @@ int child(void* _arg) if (s.length() == 2 && s[0] == '%') { continue; } - runtime.process.args.push_back(s); + runtime.process.args.push_back(QString::fromStdString(s)); } - std::cout << nlohmann::json(runtime).dump() << std::endl; + QByteArray runtimeArray; + toJson(runtimeArray, runtime); + qWarning() << "runtimeArray: " << runtimeArray; int pipeEnds[2]; if (pipe(pipeEnds) != 0) { @@ -161,8 +165,9 @@ int child(void* _arg) exit(ret); } else { - nlohmann::json json = runtime; - const std::string data = std::move(json.dump()); + QByteArray runtimeArray; + linglong::toJson(runtimeArray, runtime); + const std::string data = runtimeArray.data(); close(pipeEnds[0]); write(pipeEnds[1], data.c_str(), data.size()); close(pipeEnds[1]); @@ -192,15 +197,17 @@ int main(int argc, char* argv[]) Socket::Client client; client.connect(socketPath); + QByteArray registerArray; Methods::Registe registe; registe.id = dam_task_type; registe.hash = dam_task_hash; + Methods::toJson(registerArray, registe); Methods::Registe registe_result; registe_result.state = false; - auto result = client.get(registe); - if (!result.is_null()) { - registe_result = result; + auto result = client.get(registerArray); + if (!result.isEmpty()) { + Methods::fromJson(result, registe_result); } if (!registe_result.state) { return -3; @@ -209,9 +216,12 @@ int main(int argc, char* argv[]) Methods::Instance instance; instance.hash = registe_result.hash; std::cout << "get task" << std::endl; - result = client.get(instance); - Methods::Task task = result; - std::cout << "[result] " << result << std::endl; + QByteArray instanceArray; + Methods::toJson(instanceArray, instance); + result = client.get(instanceArray); + Methods::Task task; + Methods::toJson(result, task); + qWarning() << "[result] " << result; pthread_attr_t attr; size_t stack_size; @@ -246,7 +256,9 @@ int main(int argc, char* argv[]) Methods::Quit quit; quit.code = exitCode; quit.id = task.id; - client.send(quit); + QByteArray quitArray; + Methods::toJson(quitArray, quit); + client.send(quitArray); return exitCode; } diff --git a/src/modules/methods/basic.h b/src/modules/methods/basic.h index 78598a5..e663e76 100644 --- a/src/modules/methods/basic.h +++ b/src/modules/methods/basic.h @@ -1,17 +1,32 @@ #ifndef BASIC_H_ #define BASIC_H_ +#include +#include +#include -#include +namespace Methods +{ + struct Basic + { + QString type; + }; -namespace Methods { -struct Basic { - std::string type; -}; + inline void fromJson(const QByteArray &array, Basic &basic) + { + QJsonDocument doc = QJsonDocument::fromJson(array); + if (!doc.isObject()) { + qWarning() << "fromJson basic failed"; + return; + } -using json = nlohmann::json; -inline void from_json(const json &j, Basic &basic) { - j.at("type").get_to(basic.type); -} + QJsonObject obj = doc.object(); + if (!obj.contains("type")) { + qWarning() << "type not exist in basic array"; + return; + } + + basic.type = obj.value("type").toString(); + } } // namespace Methods diff --git a/src/modules/methods/instance.hpp b/src/modules/methods/instance.hpp index 8f12adc..4959df1 100644 --- a/src/modules/methods/instance.hpp +++ b/src/modules/methods/instance.hpp @@ -1,23 +1,39 @@ #ifndef C664E26D_6517_412B_950F_07E20963349E #define C664E26D_6517_412B_950F_07E20963349E -#include +#include +#include +#include namespace Methods { struct Instance { - std::string hash; - std::string type{ "instance" }; + QString hash; + QString type{ "instance" }; }; -using json = nlohmann::json; -inline void to_json(json &j, const Instance &instance) -{ - j = json{ { "type", instance.type }, { "hash", instance.hash } }; +inline void toJson(QByteArray &array, const Instance &instance) { + QJsonObject obj { + { "type", instance.type }, + { "hash", instance.hash } + }; + + array = QJsonDocument(obj).toJson(); } -inline void from_json(const json &j, Instance &instance) -{ - j.at("hash").get_to(instance.hash); +inline void fromJson(const QByteArray &array, Instance &instance) { + QJsonDocument doc = QJsonDocument::fromJson(array); + if (!doc.isObject()) { + qWarning() << "fromJson instance failed"; + return; + } + + QJsonObject obj = doc.object(); + if (!obj.contains("hash")) { + qWarning() << "hash not exist in instance array"; + return; + } + + instance.hash = obj.value("hash").toString(); } } // namespace Methods diff --git a/src/modules/methods/quit.hpp b/src/modules/methods/quit.hpp index 82d9dc4..6a59bab 100644 --- a/src/modules/methods/quit.hpp +++ b/src/modules/methods/quit.hpp @@ -1,27 +1,46 @@ #ifndef QUIT_H_ #define QUIT_H_ - -#include +#include +#include +#include namespace Methods { struct Quit { - std::string date; - std::string type{ "quit" }; - std::string id; - int code; + QString date; + QString type{ "quit" }; + QString id; + int code; }; -using json = nlohmann::json; -inline void to_json(json &j, const Quit &quit) -{ - j = json{ { "type", quit.type }, { "date", quit.date }, { "id", quit.id }, { "code", quit.code } }; + +inline void toJson(QByteArray &array, const Quit &quit) { + QJsonObject obj { + { "type", quit.type }, + { "date", quit.date }, + { "id", quit.id }, + { "code", quit.code } + }; + + array = QJsonDocument(obj).toJson(); } -inline void from_json(const json &j, Quit &quit) -{ - j.at("id").get_to(quit.id); - j.at("date").get_to(quit.date); - j.at("code").get_to(quit.code); +inline void fromJson(const QByteArray &array, Quit &quit) { + QJsonDocument doc = QJsonDocument::fromJson(array); + if (!doc.isObject()) { + qWarning() << "fromJson quit failed"; + return; + } + + QJsonObject obj = doc.object(); + if (!obj.contains("id") || !obj.contains("date") || !obj.contains("code")) { + qWarning() << "id date code not exist in quit array"; + return; + } + + quit.id = obj.value("id").toString(); + quit.date = obj.value("date").toString(); + quit.code = obj.value("code").toInt(); } + } // namespace Methods #endif // QUIT_H_ diff --git a/src/modules/methods/registe.hpp b/src/modules/methods/registe.hpp index 0696e39..f7490b7 100644 --- a/src/modules/methods/registe.hpp +++ b/src/modules/methods/registe.hpp @@ -1,29 +1,50 @@ #ifndef REGISTER_H_ #define REGISTER_H_ - -#include +#include +#include +#include namespace Methods { struct Registe { - std::string date; - std::string id; - std::string type{ "registe" }; - std::string hash; + QString date; + QString id; + QString type{ "registe" }; + QString hash; bool state; }; -using json = nlohmann::json; -inline void to_json(json &j, const Registe ®iste) -{ - j = json{ { "type", registe.type }, { "id", registe.id }, { "hash", registe.hash }, { "state", registe.state }, { "date", registe.date } }; +inline void toJson(QByteArray &array, const Registe ®iste) { + QJsonObject obj = { + { "type", registe.type }, + { "id", registe.id }, + { "hash", registe.hash }, + { "state", registe.state }, + { "date", registe.date } + }; + + array = QJsonDocument(obj).toJson(); } -inline void from_json(const json &j, Registe ®iste) -{ - j.at("id").get_to(registe.id); - j.at("date").get_to(registe.date); - j.at("hash").get_to(registe.hash); - j.at("state").get_to(registe.state); + +inline void fromJson(const QByteArray &array, Registe ®iste) { + QJsonDocument doc = QJsonDocument::fromJson(array); + if (!doc.isObject()) { + qWarning() << "fromJson registe failed"; + return; + } + + QJsonObject obj = doc.object(); + if (!obj.contains("id") || !obj.contains("date") || !obj.contains("hash")\ + || !obj.contains("state")) { + qWarning() << "id date code state not exist in registe array"; + return; + } + + registe.id = obj.value("id").toString(); + registe.date = obj.value("date").toString(); + registe.hash = obj.value("hash").toString(); + registe.state = obj.value("state").toBool(); } + } // namespace Methods #endif // REGISTER_H_ diff --git a/src/modules/methods/task.hpp b/src/modules/methods/task.hpp index a33b125..8ea08b6 100644 --- a/src/modules/methods/task.hpp +++ b/src/modules/methods/task.hpp @@ -1,36 +1,76 @@ #ifndef B0B88BD6_CF1E_4E87_926A_E6DBE6B9B19C #define B0B88BD6_CF1E_4E87_926A_E6DBE6B9B19C -#include -#include + #include -#include +#include +#include +#include +#include +#include +#include -namespace Methods { -struct Task { - std::string id; - std::string runId; - std::string type{ "task" }; - std::string date; - std::vector arguments; - std::multimap environments; -}; - -using json = nlohmann::json; -inline void to_json(json &j, const Task &task) +namespace Methods { - j = json{ { "type", task.type }, { "id", task.id }, { "run_id", task.runId }, { "date", task.date }, { "arguments", task.arguments }, { "environments", task.environments } }; -} + struct Task + { + QString id; + QString runId; + QString type{"task"}; + QString date; + QList arguments; + QMap environments; + }; -inline void from_json(const json &j, Task &task) -{ - j.at("id").get_to(task.id); - j.at("run_id").get_to(task.runId); - j.at("date").get_to(task.date); - j.at("arguments").get_to(task.arguments); - j.at("environments").get_to(task.environments); -} + inline void toJson(QByteArray &array, const Task &task) { + QJsonArray argArray; + for (auto arg : task.arguments) { + argArray.append(arg); + } -} // namespace Methods + QVariantMap envsMap; + for (auto it = task.environments.constBegin(); it != task.environments.constEnd(); ++it) { + envsMap.insert(it.key(), it.value()); + } + + QJsonObject obj = { + {"type", task.type}, + {"id", task.id}, + {"run_id", task.runId}, + {"date", task.date}, + {"arguments", argArray}, + {"environments", QJsonObject::fromVariantMap(envsMap)} + }; + + array = QJsonDocument(obj).toJson(); + } + + inline void fromJson(const QByteArray &array, Task &task) { + QJsonDocument doc = QJsonDocument::fromJson(array); + if (!doc.isObject()) { + qWarning() << "fromJson task failed"; + return; + } + + QJsonObject obj = doc.object(); + if (!obj.contains("id") || !obj.contains("runId") || !obj.contains("date") \ + || !obj.contains("arguments") || !obj.contains("environments")) { + qWarning() << "id runId date arguments environments not exist in task array"; + return; + } + + task.id = obj.value("id").toString(); + task.runId = obj.value("runId").toString(); + task.date = obj.value("date").toString(); + for (auto arg : obj.value("arguments").toArray()) { + task.arguments.append(arg.toString()); + } + + QVariantMap envsMap = obj.value("environments").toObject().toVariantMap(); + for (auto it = envsMap.constBegin(); it != envsMap.constEnd(); ++it) { + task.environments.insert(it.key(), it.value().toString()); + } + } +} // namespace Methods #endif /* B0B88BD6_CF1E_4E87_926A_E6DBE6B9B19C */ diff --git a/src/modules/socket/client.cpp b/src/modules/socket/client.cpp index b1fa1df..942779d 100644 --- a/src/modules/socket/client.cpp +++ b/src/modules/socket/client.cpp @@ -67,27 +67,29 @@ struct ClientPrivate { return true; } - nlohmann::json get(const nlohmann::json& call) - { + + QByteArray get(const QByteArray &call) { send(call); - char buf[512]; + char buf[512]; std::string result; - int bytesRead; + int bytesRead; while ((bytesRead = recv(socket_fd, buf, 512, 0)) > 0) { - for (int i = 0; i < bytesRead; i++) { + for (int i = 0; i < bytesRead; ++i) { result += buf[i]; } + if (buf[bytesRead - 1] == '\0') { break; } - }; - return nlohmann::json::parse(result); + } + + QJsonDocument doc = QJsonDocument::fromRawData(result.data(), result.size()); + return doc.toJson(); } - size_t send(const nlohmann::json& call) - { - std::string data = call.dump(); + size_t send(const QByteArray &call) { + std::string data = call.data(); data += '\0'; return write(socket_fd, data.c_str(), data.length()); } @@ -102,12 +104,12 @@ bool Client::connect(const std::string& host) return d_ptr->connect(host); } -nlohmann::json Client::get(const nlohmann::json& call) +QByteArray Client::get(const QByteArray &call) { return d_ptr->get(call); } -size_t Client::send(const nlohmann::json& call) +size_t Client::send(const QByteArray &call) { return d_ptr->send(call); } diff --git a/src/modules/socket/client.h b/src/modules/socket/client.h index 2cc3694..4f12fb7 100644 --- a/src/modules/socket/client.h +++ b/src/modules/socket/client.h @@ -3,23 +3,26 @@ #include #include -#include #include -namespace Socket { -class ClientPrivate; -class Client { - std::unique_ptr d_ptr; +#include -public: - Client(); - ~Client(); - bool connect(const std::string& host); - nlohmann::json get(const nlohmann::json& call); - size_t send(const nlohmann::json& call); - void onReadyRead(std::function&)> func); - void waitForFinished(); -}; -} // namespace Socket +namespace Socket +{ + class ClientPrivate; + class Client + { + std::unique_ptr d_ptr; + + public: + Client(); + ~Client(); + bool connect(const std::string &host); + QByteArray get(const QByteArray &call); + size_t send(const QByteArray &call); + void onReadyRead(std::function &)> func); + void waitForFinished(); + }; +} // namespace Socket #endif /* B1D5EB4F_7645_4BDA_87D6_6B80A4910014 */ diff --git a/src/modules/util/json.h b/src/modules/util/json.h index e2b6f54..6298024 100644 --- a/src/modules/util/json.h +++ b/src/modules/util/json.h @@ -13,46 +13,56 @@ #define JSON_USE_IMPLICIT_CONVERSIONS 0 -#include #include #define tl std -namespace nlohmann { +// namespace nlohmann { -template -inline void from_json(const J &j, tl::optional &v) -{ - if (j.is_null()) { - v = tl::nullopt; - } else { - v = j.template get(); - } -} +// template +// inline void from_json(const J &j, tl::optional &v) +// { +// if (j.is_null()) { +// v = tl::nullopt; +// } else { +// v = j.template get(); +// } +// } -template -inline void to_json(J &j, const tl::optional &o) -{ - if (o.has_value()) { - j = o.value(); - } -} +// template +// inline void to_json(J &j, const tl::optional &o) +// { +// if (o.has_value()) { +// j = o.value(); +// } +// } -} // namespace nlohmann +// } // namespace nlohmann -namespace linglong { +// namespace linglong { -template -tl::optional optional(const nlohmann::json &j, const char *key) -{ - tl::optional o; - auto iter = j.template find(key); - if (iter != j.end()) { - o = iter->template get>(); - } - return o; -} +// template +// tl::optional optional(const QJsonObject &j, const char *key) +// { +// tl::optional o; +// auto iter = j.template find(key); +// if (iter != j.end()) { +// o = iter->template get>(); +// } +// return o; +// } -} // namespace linglong +// template +// tl::optional optional(const nlohmann::json &j, const char *key) +// { +// tl::optional o; +// auto iter = j.template find(key); +// if (iter != j.end()) { +// o = iter->template get>(); +// } +// return o; +// } + +// } // namespace linglong #endif /* LINGLONG_BOX_SRC_UTIL_JSON_H_ */ diff --git a/src/modules/util/oci_runtime.h b/src/modules/util/oci_runtime.h index 33b5dc1..96bce0f 100644 --- a/src/modules/util/oci_runtime.h +++ b/src/modules/util/oci_runtime.h @@ -13,55 +13,105 @@ #include +#include +#include +#include +#include + +#include +#include +#include + #include "util.h" namespace linglong { -#define LLJS_FROM(KEY) (o.KEY = j.at(#KEY).get()) -#define LLJS_FROM_OPT(KEY) (o.KEY = optional(j, #KEY)) - -#define LLJS_TO(KEY) (j[#KEY] = o.KEY) - -#define LLJS_FROM_OBJ(TYPE) inline void from_json(const nlohmann::json &j, TYPE &o) -#define LLJS_TO_OBJ(TYPE) inline void to_json(nlohmann::json &j, const TYPE &o) - #undef linux struct Root { - std::string path; - tl::optional readonly; + QString path; + // 删除 std::optional 和 宏定义 + bool readonly; }; -LLJS_FROM_OBJ(Root) +inline void fromJson(const QByteArray &array, Root &o) { - LLJS_FROM(path); - LLJS_FROM_OPT(readonly); + QJsonDocument doc = QJsonDocument::fromJson(array); + if (!doc.isObject()) { + qWarning() << "fromJson root failed"; + return; + } + + QJsonObject obj = doc.object(); + // readonly 可以不存在 + if (!obj.contains("path")) { + return; + } + + o.path = obj.value("path").toString(); + if (obj.contains("readonly")) { + o.readonly = obj.value("readonly").toBool(); + } } -LLJS_TO_OBJ(Root) +inline void toJson(QByteArray &array, const Root &o) { - LLJS_TO(path); - LLJS_TO(readonly); + QJsonObject obj { + {"path", o.path}, + {"readonly", o.readonly} + }; + + array = QJsonDocument(obj).toJson(); } struct Process { - util::str_vec args; - util::str_vec env; - std::string cwd; + QList args; + QList env; + QString cwd; }; -inline void from_json(const nlohmann::json &j, Process &o) +inline void fromJson(const QByteArray &array, Process &o) { - o.args = j.at("args").get(); - o.env = j.at("env").get(); - o.cwd = j.at("cwd").get(); + QJsonDocument doc = QJsonDocument::fromJson(array); + if (!doc.isObject()) { + qWarning() << "fromJson process failed"; + return; + } + + QJsonObject obj = doc.object(); + if (!obj.contains("args") || !obj.contains("env") || !obj.contains("cwd")) { + std::cout << "process json invalid format" << std::endl; + return; + } + + for (auto arg : obj.value("args").toArray()) { + o.args.append(arg.toString()); + } + for (auto env : obj.value("env").toArray()) { + o.env.append(env.toString()); + } + o.cwd = obj.value("cwd").toString(); } -inline void to_json(nlohmann::json &j, const Process &o) + +inline void toJson(QByteArray &array, const Process &o) { - j["args"] = o.args; - j["env"] = o.env; - j["cwd"] = o.cwd; + QJsonArray argsArray; + for (auto arg : o.args) { + argsArray.append(arg); + } + QJsonArray envsArray; + for (auto env : o.env) { + envsArray.append(env); + } + + QJsonObject obj = { + {"args", argsArray}, + {"env", envsArray}, + {"cwd", o.cwd} + }; + + array = QJsonDocument(obj).toJson(); } struct Mount { @@ -76,18 +126,25 @@ struct Mount { Cgroup, Cgroup2, }; - std::string destination; - std::string type; - std::string source; - util::str_vec data; + QString destination; + QString type; + QString source; + QList data; Type fsType; uint32_t flags = 0u; }; -inline void from_json(const nlohmann::json &j, Mount &o) +inline void fromJson(const QByteArray &array, Mount &o) { - static std::map fsTypes = { + QJsonDocument doc = QJsonDocument::fromJson(array); + if (!doc.isObject()) { + qWarning() << "fromJson mount failed"; + return; + } + + QJsonObject obj = doc.object(); + static QMap fsTypes = { {"bind", Mount::Bind}, {"proc", Mount::Proc}, {"devpts", Mount::Devpts}, {"mqueue", Mount::Mqueue}, {"tmpfs", Mount::Tmpfs}, {"sysfs", Mount::Sysfs}, {"cgroup", Mount::Cgroup}, {"cgroup2", Mount::Cgroup2}, }; @@ -97,7 +154,7 @@ inline void from_json(const nlohmann::json &j, Mount &o) uint32_t flag; }; - static std::map optionFlags = { + static QMap optionFlags = { {"acl", {false, MS_POSIXACL}}, {"async", {true, MS_SYNCHRONOUS}}, {"atime", {true, MS_NOATIME}}, @@ -135,38 +192,53 @@ inline void from_json(const nlohmann::json &j, Mount &o) // {"symfollow",{true, MS_NOSYMFOLLOW}}, // since kernel 5.10 }; - o.destination = j.at("destination").get(); - o.type = j.at("type").get(); - o.fsType = fsTypes.find(o.type)->second; + if (!obj.contains("destination") || !obj.contains("type") || !obj.contains("source") \ + || !obj.contains("options")) { + std::cout << "mount json invalid format" << std::endl; + return; + } + + o.destination = obj.value("destination").toString(); + o.type = obj.value("type").toString(); + o.fsType = fsTypes.find(o.type).value(); if (o.fsType == Mount::Bind) { o.flags = MS_BIND; } - o.source = j.at("source").get(); + o.source = obj.value("source").toString(); o.data = {}; // Parse options to data and flags. // FIXME: support "propagation flags" and "recursive mount attrs" // https://github.com/opencontainers/runc/blob/c83abc503de7e8b3017276e92e7510064eee02a8/libcontainer/specconv/spec_linux.go#L958 - auto options = j.value("options", util::str_vec()); + auto options = obj.value("options").toArray().toVariantList(); for (auto const &opt : options) { auto it = optionFlags.find(opt); if (it != optionFlags.end()) { - if (it->second.clear) { - o.flags &= ~it->second.flag; + if (it.value().clear) { + o.flags &= ~it.value().flag; } else - o.flags |= it->second.flag; + o.flags |= it.value().flag; } else { - o.data.push_back(opt); + o.data.push_back(opt.toString()); } } } -inline void to_json(nlohmann::json &j, const Mount &o) +inline void toJson(QByteArray &array, const Mount &o) { - j["destination"] = o.destination; - j["source"] = o.source; - j["type"] = o.type; - j["options"] = o.data; // FIXME: this data is not original options, some of them have been prased to flags. + QJsonArray dataArray; + for (auto const &data : o.data) { + dataArray.append(data); + } + + QJsonObject obj = { + {"destination", o.destination}, + {"source", o.source}, + {"type", o.type}, + {"options", dataArray},// FIXME: this data is not original options, some of them have been prased to flags. + }; + + array = QJsonDocument(obj).toJson(); } struct Namespace { @@ -178,16 +250,33 @@ static std::map namespaceType = { {"network", CLONE_NEWNET}, {"ipc", CLONE_NEWIPC}, {"user", CLONE_NEWUSER}, }; -inline void from_json(const nlohmann::json &j, Namespace &o) +inline void fromJson(const QByteArray &array, Namespace &o) { - o.type = namespaceType.find(j.at("type").get())->second; + QJsonDocument doc = QJsonDocument::fromJson(array); + if (!doc.isObject()) { + qWarning() << "fromJson namespace failed"; + return; + } + + QJsonObject obj = doc.object(); + if (!obj.contains("type")) { + std::cout << "namespace json invalid format" << std::endl; + return; + } + + o.type = namespaceType.find(obj.value("type").toString().toStdString())->second; } -inline void to_json(nlohmann::json &j, const Namespace &o) +inline void toJson(QByteArray &array, const Namespace &o) { auto matchPair = std::find_if(std::begin(namespaceType), std::end(namespaceType), [&](const std::pair &pair) { return pair.second == o.type; }); - j["type"] = matchPair->first; + + QJsonObject obj = { + {"type", matchPair->second}, + }; + + array = QJsonDocument(obj).toJson(); } struct IDMap { @@ -196,84 +285,190 @@ struct IDMap { uint64_t size = 0u; }; -inline void from_json(const nlohmann::json &j, IDMap &o) +inline void fromJson(const QByteArray &array, IDMap &o) { - o.hostID = j.value("hostID", 0); - o.containerID = j.value("containerID", 0); - o.size = j.value("size", 0); + QJsonDocument doc = QJsonDocument::fromJson(array); + if (!doc.isObject()) { + qWarning() << "fromJson idmap failed"; + return; + } + + QJsonObject obj = doc.object(); + if (!obj.contains("hostID") || !obj.contains("containerID") || !obj.contains("size")) { + std::cout << "idmap json invalid format" << std::endl; + return; + } + + o.hostID = obj.value("hostID").toVariant().ULongLong; + o.containerID = obj.value("containerID").toVariant().ULongLong; + o.size = obj.value("size").toVariant().ULongLong; } -inline void to_json(nlohmann::json &j, const IDMap &o) +inline void toJson(QByteArray &array, const IDMap &o) { - j["hostID"] = o.hostID; - j["containerID"] = o.containerID; - j["size"] = o.size; + QJsonObject obj = { + {"hostID", QString::number(o.hostID, 10)}, + {"containerID", QString::number(o.containerID, 10)}, + {"size", QString::number(o.size, 10)}, + }; + + array = QJsonDocument(obj).toJson(); } -typedef std::string SeccompAction; -typedef std::string SeccompArch; +typedef QString SeccompAction; +typedef QString SeccompArch; struct SyscallArg { u_int index; // require u_int64_t value; // require u_int64_t valueTwo; // optional - std::string op; // require + QString op; // require }; -inline void from_json(const nlohmann::json &j, SyscallArg &o) +inline void fromJson(const QByteArray &array, SyscallArg &o) { - o.index = j.at("index").get(); - o.value = j.at("value").get(); - o.valueTwo = j.value("valueTwo", u_int64_t()); - o.op = j.at("op").get(); + QJsonDocument doc = QJsonDocument::fromJson(array); + if (!doc.isObject()) { + qWarning() << "fromJson SyscallArg failed"; + return; + } + + QJsonObject obj = doc.object(); + if (!obj.contains("index") || !obj.contains("value") \ + || !obj.contains("valueTwo") || !obj.contains("op")) { + qWarning() << "syscallarg json invalid format"; + return; + } + + o.index = obj.value("index").toVariant().UInt; + o.value = obj.value("value").toVariant().ULongLong; + o.valueTwo = obj.value("valueTwo").toVariant().ULongLong; + o.op = obj.value("op").toString(); } -inline void to_json(nlohmann::json &j, const SyscallArg &o) +inline void toJson(QByteArray &array, const SyscallArg &o) { - j["index"] = o.index; - j["value"] = o.value; - j["valueTwo"] = o.valueTwo; - j["op"] = o.op; + QJsonObject obj = { + {"index", QString::number(o.index, 10)}, + {"value", QString::number(o.value, 10)}, + {"valueTwo", QString::number(o.valueTwo, 10)}, + {"op", o.op}, + }; + + array = QJsonDocument(obj).toJson(); } struct Syscall { - util::str_vec names; + QList names; SeccompAction action; - std::vector args; + QList args; }; -inline void from_json(const nlohmann::json &j, Syscall &o) +inline void fromJson(const QByteArray &array, Syscall &o) { - o.names = j.at("names").get(); - o.action = j.at("action").get(); - o.args = j.value("args", std::vector()); + QJsonDocument doc = QJsonDocument::fromJson(array); + if (!doc.isObject()) { + qWarning() << "fromJson Syscall failed"; + return; + } + + QJsonObject obj = doc.object(); + if (!obj.contains("names") || !obj.contains("action") || !obj.contains("args")) { + std::cout << "syscall json invalid format" << std::endl; + return; + } + + o.action = obj.value("action").toString(); + for (auto const &name : obj.value("names").toArray()) { + o.names.append(name.toString()); + } + + QJsonValue argsValue = obj.take("args"); + SyscallArg tmpArgs; + for (const auto &arg : argsValue.toArray()) { + fromJson(QJsonDocument(arg.toObject()).toJson(), tmpArgs); + o.args.append(tmpArgs); + } } -inline void to_json(nlohmann::json &j, const Syscall &o) +inline void toJson(QByteArray &array, const Syscall &o) { - j["names"] = o.names; - j["action"] = o.action; - j["args"] = o.args; + QByteArray argsArray; + QJsonArray argsJsonArray; + for (const auto &arg : o.args) { + toJson(argsArray, arg); + argsJsonArray.append(QJsonDocument::fromJson(argsArray).array()); + } + + QByteArray namesArray; + QJsonArray namesJsonArray; + for (const auto &name : o.names) { + namesJsonArray.append(name); + } + + QJsonObject obj = { + { "names", namesJsonArray }, + { "action", o.action }, + { "args", argsJsonArray }, + }; + + array = QJsonDocument(obj).toJson(); } struct Seccomp { SeccompAction defaultAction = "INVALID_ACTION"; - std::vector architectures; - std::vector syscalls; + QList architectures; + QList syscalls; }; -inline void from_json(const nlohmann::json &j, Seccomp &o) +inline void fromJson(const QByteArray &array, Seccomp &o) { - o.defaultAction = j.at("defaultAction").get(); - o.architectures = j.value("architectures", std::vector {}); - o.syscalls = j.value("syscalls", std::vector {}); + QJsonDocument doc = QJsonDocument::fromJson(array); + if (!doc.isObject()) { + qWarning() << "fromJson Seccomp failed"; + return; + } + + QJsonObject obj = doc.object(); + if (!obj.contains("defaultAction") || !obj.contains("architectures") \ + || !obj.contains("syscalls")) { + qWarning() << "seccomp json invalid format"; + return; + } + + o.defaultAction = obj.value("defaultAction").toString(); + for (auto const &arch : obj.value("architectures").toArray()) { + o.architectures.append(arch.toString()); + } + + Syscall syscallsArray; + for (auto const &syscall : obj.value("syscalls").toArray()) { + fromJson(QJsonDocument(syscall.toObject()).toJson(), syscallsArray); + o.syscalls.append(syscallsArray); + } } -inline void to_json(nlohmann::json &j, const Seccomp &o) +inline void toJson(QByteArray &array, const Seccomp &o) { - j["defaultAction"] = o.defaultAction; - j["architectures"] = o.architectures; - j["syscalls"] = o.syscalls; + QJsonArray syscallsJsonArray; + QByteArray syscallsByteArray; + for (auto const &syscall : o.syscalls) { + toJson(syscallsByteArray, syscall); + syscallsJsonArray.append(QJsonDocument::fromJson(syscallsByteArray).array()); + } + + QJsonArray archArray; + for (auto const &arch : o.architectures) { + archArray.append(arch); + } + + QJsonObject obj = { + { "defaultAction", o.defaultAction }, + { "architectures", archArray }, + { "syscalls", syscallsJsonArray }, + }; + + array = QJsonDocument(obj).toJson(); } // https://github.com/containers/crun/blob/main/crun.1.md#memory-controller @@ -283,18 +478,34 @@ struct ResourceMemory { int64_t swap = -1; }; -inline void from_json(const nlohmann::json &j, ResourceMemory &o) +inline void fromJson(const QByteArray &array, ResourceMemory &o) { - o.limit = j.value("limit", -1); - o.reservation = j.value("reservation", -1); - o.swap = j.value("swap", -1); + QJsonDocument doc = QJsonDocument::fromJson(array); + if (!doc.isObject()) { + qWarning() << "fromJson ResourceMemory failed"; + return; + } + + QJsonObject obj = doc.object(); + if (!obj.contains("limit") || !obj.contains("reservation") || !obj.contains("swap")) { + qWarning() << "resourceMemory json invalid format"; + return; + } + + o.limit = obj.value("limit").toVariant().toLongLong(); + o.reservation = obj.value("reservation").toVariant().toLongLong(); + o.swap = obj.value("swap").toVariant().toLongLong(); } -inline void to_json(nlohmann::json &j, const ResourceMemory &o) +inline void toJson(QByteArray &array, const ResourceMemory &o) { - j["limit"] = o.limit; - j["reservation"] = o.reservation; - j["swap"] = o.swap; + QJsonObject obj = { + {"limit", static_cast(o.limit)}, + {"reservation", static_cast(o.reservation)}, + {"swap", static_cast(o.swap)}, + }; + + array = QJsonDocument(obj).toJson(); } // https://github.com/containers/crun/blob/main/crun.1.md#cpu-controller @@ -309,18 +520,34 @@ struct ResourceCPU { // std::string mems; }; -inline void from_json(const nlohmann::json &j, ResourceCPU &o) +inline void fromJson(const QByteArray &array, ResourceCPU &o) { - o.shares = j.value("shares", 1024); - o.quota = j.value("quota", 100000); - o.period = j.value("period", 100000); + QJsonDocument doc = QJsonDocument::fromJson(array); + if (!doc.isObject()) { + qWarning() << "fromJson ResourceCPU failed"; + return; + } + + QJsonObject obj = doc.object(); + if (!obj.contains("shares") || !obj.contains("quota") || !obj.contains("period")) { + qWarning() << "resourcecpu json invalid format"; + return; + } + + o.shares = obj.value("shares").toVariant().toULongLong(); + o.quota = obj.value("quota").toVariant().toLongLong(); + o.period = obj.value("period").toVariant().toULongLong(); } -inline void to_json(nlohmann::json &j, const ResourceCPU &o) +inline void toJson(QByteArray &array, const ResourceCPU &o) { - j["shares"] = o.shares; - j["quota"] = o.quota; - j["period"] = o.period; + QJsonObject obj = { + {"shares", QString::number(o.shares, 10)}, + {"quota", static_cast(o.quota)}, + {"period", QString::number(o.period, 10)}, + }; + + array = QJsonDocument(obj).toJson(); } struct Resources { @@ -328,45 +555,131 @@ struct Resources { ResourceCPU cpu; }; -inline void from_json(const nlohmann::json &j, Resources &o) +inline void fromJson(const QByteArray &array, Resources &o) { - o.cpu = j.value("cpu", ResourceCPU()); - o.memory = j.value("memory", ResourceMemory()); + QJsonDocument doc = QJsonDocument::fromJson(array); + if (!doc.isObject()) { + qWarning() << "fromJson Resources failed"; + return; + } + + QJsonObject obj = doc.object(); + if (!obj.contains("cpu") || !obj.contains("memory")) { + qWarning() << "resources json invalid format"; + return; + } + + fromJson(QJsonDocument(obj.value("cpu").toObject()).toJson(), o.cpu); + fromJson(QJsonDocument(obj.value("memory").toObject()).toJson(), o.cpu); } -inline void to_json(nlohmann::json &j, const Resources &o) +inline void toJson(QByteArray &array, const Resources &o) { - j["cpu"] = o.cpu; - j["memory"] = o.memory; + QByteArray cpuArray; + toJson(cpuArray, o.cpu); + QByteArray memoryArray; + toJson(memoryArray, o.memory); + QJsonObject obj = { + {"cpu", QJsonDocument::fromJson(cpuArray).array()}, + {"memory", QJsonDocument::fromJson(memoryArray).array()}, + }; + + array = QJsonDocument(obj).toJson(); } struct Linux { - std::vector namespaces; - std::vector uidMappings; - std::vector gidMappings; - tl::optional seccomp; - std::string cgroupsPath; + QList namespaces; + QList uidMappings; + QList gidMappings; + Seccomp seccomp; + QString cgroupsPath; Resources resources; }; -inline void from_json(const nlohmann::json &j, Linux &o) +inline void fromJson(const QByteArray &array, Linux &o) { - o.namespaces = j.at("namespaces").get>(); - o.uidMappings = j.value("uidMappings", std::vector {}); - o.gidMappings = j.value("gidMappings", std::vector {}); - o.seccomp = optional(j, "seccomp"); - o.cgroupsPath = j.value("cgroupsPath", ""); - o.resources = j.value("resources", Resources()); + QJsonDocument doc = QJsonDocument::fromJson(array); + if (!doc.isObject()) { + qWarning() << "fromJson Linux failed"; + return; + } + + QJsonObject obj = doc.object(); + if (!obj.contains("namespaces") || !obj.contains("uidMappings") || !obj.contains("gidMappings") \ + || !obj.contains("cgroupsPath") || !obj.contains("resources")) { + qWarning() << "linux json invalid format"; + return; + } + + Namespace nameArray; + for (auto name : obj.take("namespaces").toArray()) { + fromJson(QJsonDocument(name.toObject()).toJson(), nameArray); + o.namespaces.append(nameArray); + } + + { + IDMap uidMap; + for (auto uid : obj.take("uidMappings").toArray()) { + fromJson(QJsonDocument(uid.toObject()).toJson(), uidMap); + o.uidMappings.append(uidMap); + } + } + + { + IDMap gidMap; + for (auto gid : obj.take("gidMappings").toArray()) { + fromJson(QJsonDocument(gid.toObject()).toJson(), gidMap); + o.gidMappings.append(gidMap); + } + } + + o.cgroupsPath = obj.value("cgroupsPath").toString(); + fromJson(QJsonDocument(obj.value("resources").toObject()).toJson(), o.resources); + + if (obj.contains("seccomp")) { + fromJson(QJsonDocument(obj.value("seccomp").toObject()).toJson(), o.seccomp); + } } -inline void to_json(nlohmann::json &j, const Linux &o) +inline void toJson(QByteArray &array, const Linux &o) { - j["namespaces"] = o.namespaces; - j["uidMappings"] = o.uidMappings; - j["gidMappings"] = o.gidMappings; - j["seccomp"] = o.seccomp; - j["cgroupsPath"] = o.cgroupsPath; - j["resources"] = o.resources; + QJsonArray nameSpacesJsonArray; + QByteArray nameSpacesByteArray; + for (auto const &nameSpace : o.namespaces) { + toJson(nameSpacesByteArray, nameSpace); + nameSpacesJsonArray.append(QJsonDocument::fromJson(nameSpacesByteArray).array()); + } + + QJsonArray uidMapsJsonArray; + QByteArray uidMapsByteArray; + for (auto const &uid : o.uidMappings) { + toJson(uidMapsByteArray, uid); + uidMapsJsonArray.append(QJsonDocument::fromJson(uidMapsByteArray).array()); + } + + QJsonArray gidMapsJsonArray; + QByteArray gidMapsByteArray; + for (auto const &gid : o.gidMappings) { + toJson(gidMapsByteArray, gid); + gidMapsJsonArray.append(QJsonDocument::fromJson(gidMapsByteArray).array()); + } + + QByteArray seccompArray; + toJson(seccompArray, o.seccomp); + + QByteArray resourcesArray; + toJson(resourcesArray, o.resources); + + QJsonObject obj = { + {"namespaces", nameSpacesJsonArray}, + {"uidMappings", uidMapsJsonArray}, + {"gidMappings", gidMapsJsonArray}, + {"seccomp", QJsonDocument::fromJson(seccompArray).array()}, + {"cgroupsPath", o.cgroupsPath}, + {"resources", QJsonDocument::fromJson(resourcesArray).array()}, + }; + + array = QJsonDocument(obj).toJson(); } /* @@ -397,146 +710,347 @@ inline void to_json(nlohmann::json &j, const Linux &o) */ struct Hook { - std::string path; - tl::optional args; - tl::optional> env; + QString path; + QList args; + QList env; }; -inline void from_json(const nlohmann::json &j, Hook &o) +inline void fromJson(const QByteArray &array, Hook &o) { - LLJS_FROM(path); - LLJS_FROM_OPT(args); - LLJS_FROM_OPT(env); + QJsonDocument doc = QJsonDocument::fromJson(array); + if (!doc.isObject()) { + qWarning() << "fromJson Hook failed"; + return; + } + + QJsonObject obj = doc.object(); + if (!obj.contains("path")) { + qWarning() << "hook json invalid format"; + return; + } + + o.path = obj.value("path").toString(); + + if (obj.contains("args")) { + for (auto const &arg : obj.value("args").toArray()) { + o.args.append(arg.toString()); + } + } + + if (obj.contains("env")) { + for (auto const &env : obj.value("env").toArray()) { + o.env.append(env.toString()); + } + } } -inline void to_json(nlohmann::json &j, const Hook &o) +inline void toJson(QByteArray &array, const Hook &o) { - j["path"] = o.path; - j["args"] = o.args; - j["env"] = o.env; + QJsonArray argsArray; + for (auto const &arg : o.args) { + argsArray.append(arg); + } + + QJsonArray envArray; + for (auto const &env : o.env) { + envArray.append(env); + } + + QJsonObject obj = { + {"path", o.path}, + {"args", argsArray}, + {"env", envArray}, + }; + + array = QJsonDocument(obj).toJson(); } struct Hooks { - tl::optional> prestart; - tl::optional> poststart; - tl::optional> poststop; + QList prestart; + QList poststart; + QList poststop; }; -inline void from_json(const nlohmann::json &j, Hooks &o) +inline void fromJson(const QByteArray &array, Hooks &o) { - LLJS_FROM_OPT(prestart); - LLJS_FROM_OPT(poststart); - LLJS_FROM_OPT(poststop); + QJsonDocument doc = QJsonDocument::fromJson(array); + if (!doc.isObject()) { + qWarning() << "fromJson Hooks failed"; + return; + } + + QJsonObject obj = doc.object(); + Hook hook; + if (obj.contains("prestart")) { + for (auto prestart : obj.take("prestart").toArray()) { + fromJson(QJsonDocument(prestart.toObject()).toJson(), hook); + o.prestart.append(hook); + } + } + + if (obj.contains("poststart")) { + for (auto poststart : obj.take("poststart").toArray()) { + fromJson(QJsonDocument(poststart.toObject()).toJson(), hook); + o.poststart.append(hook); + } + } + + if (obj.contains("poststop")) { + for (auto poststop : obj.take("poststop").toArray()) { + fromJson(QJsonDocument(poststop.toObject()).toJson(), hook); + o.poststop.append(hook); + } + } } -inline void to_json(nlohmann::json &j, const Hooks &o) +inline void toJson(QByteArray &array, const Hooks &o) { - j["poststop"] = o.poststop; - j["poststart"] = o.poststart; - j["prestart"] = o.prestart; + QJsonArray poststartJsonArray; + QByteArray poststartByteArray; + for (auto const &poststart : o.poststart) { + toJson(poststartByteArray, poststart); + poststartJsonArray.append(QJsonDocument::fromJson(poststartByteArray).array()); + } + + QJsonArray poststopJsonArray; + QByteArray poststopByteArray; + for (auto const &poststop : o.poststop) { + toJson(poststopByteArray, poststop); + poststopJsonArray.append(QJsonDocument::fromJson(poststopByteArray).array()); + } + + QJsonArray prestartJsonArray; + QByteArray prestartByteArray; + for (auto const &prestart : o.prestart) { + toJson(prestartByteArray, prestart); + prestartJsonArray.append(QJsonDocument::fromJson(prestartByteArray).array()); + } + + QJsonObject obj = { + {"prestart", prestartJsonArray}, + {"poststart", poststartJsonArray}, + {"poststop", poststopJsonArray}, + }; + + array = QJsonDocument(obj).toJson(); } struct AnnotationsOverlayfs { - std::string lower_parent; - std::string upper; - std::string workdir; - std::vector mounts; + QString lower_parent; + QString upper; + QString workdir; + QList mounts; }; -LLJS_FROM_OBJ(AnnotationsOverlayfs) +inline void fromJson(const QByteArray &array, AnnotationsOverlayfs &o) { - LLJS_FROM(lower_parent); - LLJS_FROM(upper); - LLJS_FROM(workdir); - LLJS_FROM(mounts); + QJsonDocument doc = QJsonDocument::fromJson(array); + if (!doc.isObject()) { + qWarning() << "fromJson AnnotationsOverlayfs failed"; + return; + } + + QJsonObject obj = doc.object(); + if (!obj.contains("lower_parent") || !obj.contains("upper") \ + || !obj.contains("workdir") || !obj.contains("mounts")) { + qWarning() << "annotationsOverlayfs json invalid format"; + return; + } + + o.lower_parent = obj.value("lower_parent").toString(); + o.upper = obj.value("upper").toString(); + o.workdir = obj.value("workdir").toString(); + + Mount mount; + for (auto mountArray : obj.take("mounts").toArray()) { + fromJson(QJsonDocument(mountArray.toObject()).toJson(), mount); + o.mounts.append(mount); + } } -LLJS_TO_OBJ(AnnotationsOverlayfs) + +inline void toJson(QByteArray &array, const AnnotationsOverlayfs &o) { - LLJS_TO(lower_parent); - LLJS_TO(upper); - LLJS_TO(workdir); - LLJS_TO(mounts); + QJsonArray MountsJsonArray; + QByteArray MountsByteArray; + for (auto const &mount : o.mounts) { + toJson(MountsByteArray, mount); + MountsJsonArray.append(QJsonDocument::fromJson(MountsByteArray).array()); + } + + QJsonObject obj = { + {"lower_parent", o.lower_parent}, + {"upper", o.upper}, + {"workdir", o.workdir}, + {"mounts", MountsJsonArray}, + }; + + array = QJsonDocument(obj).toJson(); } struct AnnotationsNativeRootfs { - std::vector mounts; + QList mounts; }; -LLJS_FROM_OBJ(AnnotationsNativeRootfs) +inline void fromJson(const QByteArray &array, AnnotationsNativeRootfs &o) { - LLJS_FROM(mounts); + QJsonDocument doc = QJsonDocument::fromJson(array); + if (!doc.isObject()) { + qWarning() << "fromJson AnnotationsNativeRootfs failed"; + return; + } + + QJsonObject obj = doc.object(); + if (!obj.contains("mounts")) { + qWarning() << "annotationsNativeRootfs json invalid format"; + return; + } + + Mount mount; + for (auto uid : obj.take("mounts").toArray()) { + fromJson(QJsonDocument(uid.toObject()).toJson(), mount); + o.mounts.append(mount); + } } -LLJS_TO_OBJ(AnnotationsNativeRootfs) +inline void toJson(QByteArray &array, const AnnotationsNativeRootfs &o) { - LLJS_TO(mounts); + QJsonArray mountsJsonArray; + QByteArray mountsByteArray; + for (auto const &mount : o.mounts) { + toJson(mountsByteArray, mount); + mountsJsonArray.append(QJsonDocument::fromJson(mountsByteArray).array()); + } + + QJsonObject obj = { + {"mounts", mountsJsonArray}, + }; + + array = QJsonDocument(obj).toJson(); } struct Annotations { - std::string container_root_path; - tl::optional overlayfs; - tl::optional native; + QString container_root_path; + AnnotationsOverlayfs overlayfs; + AnnotationsNativeRootfs native; }; -LLJS_FROM_OBJ(Annotations) +inline void fromJson(const QByteArray &array, Annotations &o) { - LLJS_FROM(container_root_path); - LLJS_FROM_OPT(overlayfs); - LLJS_FROM_OPT(native); + QJsonDocument doc = QJsonDocument::fromJson(array); + if (!doc.isObject()) { + qWarning() << "fromJson Linux failed"; + return; + } + + QJsonObject obj = doc.object(); + if (!obj.contains("container_root_path")) { + qWarning() << "annotations json invalid format"; + return; + } + + o.container_root_path = obj.value("container_root_path").toString(); + if (obj.contains("overlayfs")) { + fromJson(QJsonDocument(obj.value("overlayfs").toObject()).toJson(), o.overlayfs); + } + if (obj.contains("native")) { + fromJson(QJsonDocument(obj.value("native").toObject()).toJson(), o.native); + } } -LLJS_TO_OBJ(Annotations) +inline void toJson(QByteArray &array, const Annotations &o) { - LLJS_TO(container_root_path); - LLJS_TO(overlayfs); - LLJS_TO(native); + QByteArray overlayfsArray; + toJson(overlayfsArray, o.overlayfs); + QByteArray nativeArray; + toJson(nativeArray, o.native); + + QJsonObject obj = { + {"overlayfs", QJsonDocument::fromJson(overlayfsArray).array()}, + {"native", QJsonDocument::fromJson(nativeArray).array()}, + {"container_root_path", o.container_root_path} + }; + + array = QJsonDocument(obj).toJson(); } struct Runtime { - std::string version; + QString version; Root root; Process process; - std::string hostname; + QString hostname; Linux linux; - tl::optional> mounts; - tl::optional hooks; - tl::optional annotations; + QList mounts; + Hooks hooks; + Annotations annotations; }; -inline void from_json(const nlohmann::json &j, Runtime &o) +inline void fromJson(const QByteArray &array, Runtime &o) { - o.version = j.at("ociVersion").get(); - o.hostname = j.at("hostname").get(); - LLJS_FROM(process); - o.mounts = optional(j, "mounts"); - LLJS_FROM(linux); - // maybe optional - LLJS_FROM(root); - o.hooks = optional(j, "hooks"); - LLJS_FROM_OPT(annotations); + QJsonDocument doc = QJsonDocument::fromJson(array); + if (!doc.isObject()) { + qWarning() << "fromJson Runtime failed"; + return; + } + + QJsonObject obj = doc.object(); + if (!obj.contains("version") || !obj.contains("root") || !obj.contains("process") \ + || !obj.contains("hostname") || !obj.contains("linux")) { + qWarning() << "runtime json invalid format"; + return; + } + + o.version = obj.value("version").toString(); + o.hostname = obj.value("hostname").toString(); + fromJson(QJsonDocument(obj.value("root").toObject()).toJson(), o.root); + fromJson(QJsonDocument(obj.value("process").toObject()).toJson(), o.process); + fromJson(QJsonDocument(obj.value("linux").toObject()).toJson(), o.linux); + + // mounts hooks annotations 可不存在 + if (!obj.contains("mounts") || !obj.contains("hooks") || !obj.contains("annotations")) { + return; + } + fromJson(QJsonDocument(obj.value("hooks").toObject()).toJson(), o.hooks); + fromJson(QJsonDocument(obj.value("annotations").toObject()).toJson(), o.annotations); + Mount mount; + for (auto uid : obj.take("mounts").toArray()) { + fromJson(QJsonDocument(uid.toObject()).toJson(), mount); + o.mounts.append(mount); + } } -inline void to_json(nlohmann::json &j, const Runtime &o) +inline void toJson(QByteArray &array, const Runtime &o) { - j["ociVersion"] = o.version; - j["hostname"] = o.hostname; - j["process"] = o.process; - j["mounts"] = o.mounts; - j["linux"] = o.linux; - j["root"] = o.root; - j["hooks"] = o.hooks; - LLJS_TO(annotations); -} + QByteArray rootArray; + QByteArray processArray; + QByteArray linuxArray; + QByteArray hooksArray; + QByteArray annotationsArray; + toJson(rootArray, o.root); + toJson(processArray, o.process); + toJson(linuxArray, o.linux); + toJson(hooksArray, o.hooks); + toJson(annotationsArray, o.annotations); -inline static Runtime fromFile(const std::string &filepath) -{ - return util::json::fromFile(filepath).get(); -} + QJsonArray MountsJsonArray; + QByteArray MountsByteArray; + for (auto const &mount : o.mounts) { + toJson(MountsByteArray, mount); + MountsJsonArray.append(QJsonDocument::fromJson(MountsByteArray).array()); + } -inline static Runtime fromString(const std::string &content) -{ - return util::json::fromByteArray(content).get(); + QJsonObject obj = { + {"version", o.version}, + {"root", QJsonDocument::fromJson(rootArray).array()}, + {"process", QJsonDocument::fromJson(processArray).array()}, + {"hostname", o.hostname}, + {"linux", QJsonDocument::fromJson(linuxArray).array()}, + {"hooks", QJsonDocument::fromJson(hooksArray).array()}, + {"annotations", QJsonDocument::fromJson(annotationsArray).array()}, + {"mounts", MountsJsonArray}, + }; + + array = QJsonDocument(obj).toJson(); } } // namespace linglong diff --git a/src/modules/util/util.h b/src/modules/util/util.h index ed0a604..c98f6c9 100644 --- a/src/modules/util/util.h +++ b/src/modules/util/util.h @@ -20,25 +20,25 @@ #include -namespace linglong { -namespace util { -namespace json { +// namespace linglong { +// namespace util { +// namespace json { -inline nlohmann::json fromByteArray(const std::string &content) -{ - return nlohmann::json::parse(content); -} +// inline nlohmann::json fromByteArray(const std::string &content) +// { +// return nlohmann::json::parse(content); +// } -inline nlohmann::json fromFile(const std::string &filepath) -{ - std::ifstream f(filepath); - std::string str((std::istreambuf_iterator(f)), std::istreambuf_iterator()); - auto j = fromByteArray(str); - return j; -} +// inline nlohmann::json fromFile(const std::string &filepath) +// { +// std::ifstream f(filepath); +// std::string str((std::istreambuf_iterator(f)), std::istreambuf_iterator()); +// auto j = fromByteArray(str); +// return j; +// } -} // namespace json -} // namespace util -} // namespace linglong +// } // namespace json +// } // namespace util +// } // namespace linglong #endif /* LINGLONG_BOX_SRC_UTIL_UTIL_H_ */ diff --git a/src/service/CMakeLists.txt b/src/service/CMakeLists.txt index 201e392..bc40932 100644 --- a/src/service/CMakeLists.txt +++ b/src/service/CMakeLists.txt @@ -2,8 +2,6 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) -find_package(Qt5 REQUIRED COMPONENTS Core DBus Concurrent) - qt5_add_dbus_adaptor(ADAPTER_SOURCES ../../DBus/org.desktopspec.ApplicationManager.xml impl/application_manager.h diff --git a/src/service/impl/application_instance.cpp b/src/service/impl/application_instance.cpp index 44980cd..2f5a727 100644 --- a/src/service/impl/application_instance.cpp +++ b/src/service/impl/application_instance.cpp @@ -140,15 +140,15 @@ Methods::Task ApplicationInstance::taskInfo() const Q_D(const ApplicationInstance); Methods::Task task; - task.id = d->m_id.toStdString(); - task.runId = d->application->id().toStdString(); - task.date = QString::number(startuptime()).toStdString(); + task.id = d->m_id; + task.runId = d->application->id(); + task.date = QString::number(startuptime()); // TODO: debug to display environment - task.environments.insert({ "DISPLAY", ":0" }); + task.environments.insert( "DISPLAY", ":0" ); auto sysEnv = QProcessEnvironment::systemEnvironment(); for (const auto& key : sysEnv.keys()) { - task.environments.insert({ key.toStdString(), sysEnv.value(key).toStdString() }); + task.environments.insert( key, sysEnv.value(key) ); } return task; diff --git a/src/service/impl/application_manager.cpp b/src/service/impl/application_manager.cpp index 83eb2b8..2ead968 100644 --- a/src/service/impl/application_manager.cpp +++ b/src/service/impl/application_manager.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include "../../modules/methods/basic.h" @@ -18,19 +17,20 @@ #include "application_instance.h" #include "applicationinstanceadaptor.h" -class ApplicationManagerPrivate : public QObject { +class ApplicationManagerPrivate : public QObject +{ Q_OBJECT ApplicationManager *q_ptr = nullptr; Q_DECLARE_PUBLIC(ApplicationManager); - QList> applications; - Socket::Server server; + QList> applications; + Socket::Server server; std::multimap> tasks; public: ApplicationManagerPrivate(ApplicationManager *parent) : QObject(parent), q_ptr(parent) { - const QString socketPath{ QString("/run/user/%1/deepin-application-manager.socket").arg(getuid()) }; + const QString socketPath{QString("/run/user/%1/deepin-application-manager.socket").arg(getuid())}; connect(&server, &Socket::Server::onReadyRead, this, &ApplicationManagerPrivate::recvClientData, Qt::QueuedConnection); server.listen(socketPath.toStdString()); } @@ -43,43 +43,47 @@ private: for (char c : data) { tmp += c; } - using namespace nlohmann; - if (json::parse(tmp).is_null()) { - server.close(socket); - return; - } - Methods::Basic basic = json::parse(tmp); + + QByteArray jsonArray = data.data(); + Methods::Basic basic; + Methods::fromJson(jsonArray, basic); + QByteArray tmpArray; do { if (basic.type == "instance") { - Methods::Instance instance = nlohmann::json::parse(tmp); - auto find = tasks.find(instance.hash); - if (find != tasks.end()) { - nlohmann::json result = find->second->taskInfo(); - write(socket, result.dump()); + Methods::Instance instance; + Methods::fromJson(jsonArray, instance); + auto find = tasks.find(instance.hash.toStdString()); + if (find != tasks.end()) + { + Methods::Task task = find->second->taskInfo(); + Methods::toJson(tmpArray, task); + write(socket, tmpArray.toStdString()); tasks.erase(find); break; } } if (basic.type == "quit") { - Methods::Quit quit = json::parse(tmp); + Methods::Quit quit; + Methods::fromJson(jsonArray, quit); server.close(socket); std::cout << "client quit" << std::endl; break; } if (basic.type == "registe") { - Methods::Registe registe = nlohmann::json::parse(tmp); + Methods::Registe registe; + Methods::fromJson(jsonArray, registe); Methods::Registe result; result.state = false; - //std::lock_guard lock(task_mutex); + // std::lock_guard lock(task_mutex); for (auto it = tasks.begin(); it != tasks.end(); ++it) { result.state = true; - result.hash = it->first; + result.hash = QString::fromStdString(it->first); } - write(socket, json(result).dump()); - std::cout << "registe a new client" << std::endl; + Methods::toJson(tmpArray, result); + write(socket, tmpArray.toStdString()); break; } - write(socket, json().dump()); + write(socket, jsonArray.toStdString()); } while (false); } @@ -150,8 +154,8 @@ QDBusObjectPath ApplicationManager::Run(const QString &id) for (const QSharedPointer &app : d->applications) { if (app->id() == id) { // 创建任务所需的数据,并记录到任务队列,等待 loader 消耗 - QSharedPointer instance{ app->createInstance() }; - const std::string hash{ instance->hash().toStdString() }; + QSharedPointer instance{app->createInstance()}; + const std::string hash{instance->hash().toStdString()}; connect(instance.get(), &ApplicationInstance::taskFinished, this, [=] { for (auto it = d->tasks.begin(); it != d->tasks.end(); ++it) { if (it->first == hash) {