Program Listing for File ChildProcess.hpp

Return to documentation for file (include/input/IPC/transmission/ChildProcess.hpp)

#pragma once

#include "Input_State.hpp"
#include "PDJE_Buffer.hpp"
#include "PDJE_Highres_Clock.hpp"
#include "PDJE_Input_DataLine.hpp"
#include "PDJE_Input_Device_Data.hpp"
#include "ipc_shared_memory.hpp"
#include <httplib.h>
#include <nlohmann/json.hpp>
#include <optional>
#include <string>
#include <unordered_map>
namespace PDJE_IPC {

using PDJE_DEV_PATH = std::string;
using PDJE_NAME     = std::string;
class ChildProcess {
  private:
#ifdef WIN32
    DWORD ThreadID;
#elif defined(__linux__)

#endif
    std::unordered_map<std::string, std::function<void()>> callables;
    httplib::Server                                        server;

    std::unordered_map<PDJE_ID, PDJE_NAME>           id_name;
    std::optional<PDJE_Buffer_Arena<PDJE_Input_Log>> input_buffer;
    std::optional<PDJE_IPC::SharedMem<int, PDJE_IPC::PDJE_IPC_RW>>
        spinlock_run; // 0 = stop, 1 = go, -1 = terminate

    void
    EndTransmission(const httplib::Request &, httplib::Response &res);

    bool
    RecvIPCSharedMem(const std::string &mem_path,
                     const std::string &dataType,
                     const uint64_t     data_count); // todo - impl

    std::vector<DeviceData>                      configed_devices;
    std::unordered_map<PDJE_DEV_PATH, PDJE_NAME> unlisted_targets;

    std::string
    ListDev();

  public:
    bool KillCheck = false;
    ChildProcess()
    {
        startlog();
        server.Get("/kill",
                   [&](const httplib::Request &req, httplib::Response &res) {
                       EndTransmission(req, res);
                       KillCheck = true;
                   });
        server.Get("/stop",
                   [&](const httplib::Request &req, httplib::Response &res) {
                       EndTransmission(req, res);
                   });
        server.Get("/health",
                   [&](const httplib::Request &, httplib::Response &res) {
                       res.set_content("serverOK", "text/plain");
                   });
        server.Get("/lsdev",
                   [&](const httplib::Request &req, httplib::Response &res) {
                       res.set_content(ListDev(), "application/json");
                   });
        server.Post("/config",
                    [&](const httplib::Request &req, httplib::Response &res) {
                        try {
                            configed_devices.clear();
                            auto nj = nlohmann::json::parse(req.body);
                            for (const auto &i : nj["body"]) {
                                DeviceData dd;
                                dd.device_specific_id =
                                    i.at("id").get<std::string>();
                                dd.Name = i.at("name").get<std::string>();
                                std::string tp =
                                    i.at("type").get<std::string>();
                                if (tp == "KEYBOARD") {
                                    dd.Type = PDJE_Dev_Type::KEYBOARD;
                                } else if (tp == "MOUSE") {
                                    dd.Type = PDJE_Dev_Type::MOUSE;
                                } else if (tp == "MIDI") {
                                    dd.Type = PDJE_Dev_Type::MIDI;
                                } else if (tp == "HID") {
                                    dd.Type = PDJE_Dev_Type::HID;
                                } else {
                                    continue;
                                }
                                configed_devices.push_back(dd);
                            }
                            res.status = 200;

                        } catch (const std::exception &e) {
                            res.status = 400;
                            std::string errlog =
                                "INVALID_JSON. why:" + std::string(e.what());
                            res.set_content(errlog, "text/plain");

                            critlog("failed to config device data. WHY: ");
                            critlog(e.what());
                            critlog("received json: ");
                            critlog(req.body);
                        }
                    });
        server.Post(
            "/shmem", [&](const httplib::Request &req, httplib::Response &res) {
                try {

                    auto nj = nlohmann::json::parse(req.body);

                    if (!RecvIPCSharedMem(nj.at("PATH").get<std::string>(),
                                          nj.at("DATATYPE").get<std::string>(),
                                          nj.at("COUNT").get<uint64_t>())) {
                        throw std::runtime_error(
                            "failed to receive ipc shared memory.");
                    }

                    res.status = 200;
                } catch (const std::exception &e) {
                    res.status = 400;
                    std::string errlog =
                        "INVALID_JSON. why:" + std::string(e.what());
                    res.set_content(errlog, "text/plain");

                    critlog("failed to config device data. WHY: ");
                    critlog(e.what());
                    critlog("received json: ");
                    critlog(req.body);
                }
            });
    }
    PDJE_HIGHRES_CLOCK::CLOCK timer;
    void
    RunServer(const int port);
    void *
    Init();
    void
    LoopTrig();
    void
    Run();

    ~ChildProcess() = default;
};
}; // namespace PDJE_IPC