Program Listing for File Common_Features.hpp

Return to documentation for file (include/input/linux/common/Common_Features.hpp)

#pragma once

#include <arpa/inet.h>
#include <cerrno>
#include <cstddef>
#include <cstdint>
#include <limits>
#include <netinet/in.h>
#include <nlohmann/json.hpp>
#include <string>
#include <sys/socket.h>
#include <vector>
using nj = nlohmann::json;
enum PDJE_RT_ERROR {
    FAILED_TO_PARSE_JSON                     = -1,
    FAILED_TO_PARSE_JSON_HEAD_BODY           = -2,
    INVALID_JSON_FORMAT                      = -3,
    FAILED_TO_SCHED_GETAFFINITY              = -4,
    FAILED_TO_SET_CPU_NUMBER                 = -5,
    FAILED_TO_SEND_RECV__DATA_LENGTH_IS_ZERO = -6,
    FAILED_TO_SET_DEV__INVALID_DATA          = -7
};

namespace Common_Features {

static int
SendByte(int dest_fd, const void *data, size_t len)
{
    const char *p = reinterpret_cast<const char *>(data);
    while (len > 0) {
        auto sended_bytes = send(dest_fd, p, len, MSG_NOSIGNAL);

        if (sended_bytes < 0) {
            if (errno == EINTR)
                continue; // ignore signal
            if (errno == EAGAIN)
                continue; // nonblock
            return -errno;
        } else if (sended_bytes == 0) {
            return -EPIPE;
        }
        p += static_cast<size_t>(sended_bytes);
        len -= static_cast<size_t>(sended_bytes);
    }
    return len;
}

static int
RecvByte(int dest_fd, void *data, size_t len)
{
    char *p = reinterpret_cast<char *>(data);
    while (len > 0) {
        auto readed_bytes = recv(dest_fd, p, len, 0);

        if (readed_bytes < 0) {
            if (errno == EINTR)
                continue; // ignore signal
            if (errno == EAGAIN)
                continue; // nonblock
            return -errno;
        } else if (readed_bytes == 0) {
            return -EPIPE;
        }
        p += static_cast<size_t>(readed_bytes);
        len -= static_cast<size_t>(readed_bytes);
    }
    return len;
}

static int
LPSend(int dest_fd, const std::string &data)
{
    auto len = data.size();
    if (len > std::numeric_limits<uint32_t>::max()) {
        return -EMSGSIZE;
    }
    if (len == 0) {
        return PDJE_RT_ERROR::FAILED_TO_SEND_RECV__DATA_LENGTH_IS_ZERO;
    }
    auto net_len = htonl(static_cast<uint32_t>(len));
    if (SendByte(dest_fd, &net_len, sizeof(uint32_t)) < 0) {
        return errno;
    }
    if (SendByte(dest_fd, data.data(), len) < 0) {
        return errno;
    }
    return 0;
}

static int
LPRecv(int dest_fd, std::string &data)
{
    uint32_t net_len;
    if (RecvByte(dest_fd, &net_len, sizeof(uint32_t)) < 0) {
        return errno;
    }
    auto len = ntohl(net_len);
    if (len == 0) {
        return PDJE_RT_ERROR::FAILED_TO_SEND_RECV__DATA_LENGTH_IS_ZERO;
    }
    data.resize(len);

    if (RecvByte(dest_fd, data.data(), len) < 0) {
        return errno;
    }
    return 0;
}

static std::string
MakeMSG(const std::string &head, const std::vector<std::string> &datas)
{
    nj j_obj;
    j_obj["HEAD"] = head;
    j_obj["BODY"] = datas;
    return j_obj.dump();
}

static std::string
MakeMSG(const std::string &head, const std::string &msg)
{
    std::vector<std::string> tempVec;
    tempVec.push_back(msg);
    nj j_obj;
    j_obj["HEAD"] = head;
    j_obj["BODY"] = tempVec;
    return j_obj.dump();
}

static std::vector<std::string>
ReadMSG(const std::string &head, const std::string &raw_json_msg)
{
    nj parsed;
    try {
        parsed = nj::parse(raw_json_msg);

    } catch (const std::exception &e) {
        return std::vector<std::string>();
    }
    if (parsed.contains("HEAD") && parsed.contains("BODY")) {
        if (parsed["HEAD"].is_string() && parsed["BODY"].is_array()) {
            if (parsed["HEAD"].get<std::string>() == head) {
                return parsed["BODY"].get<std::vector<std::string>>();
            } else {
                return std::vector<std::string>();
            }

        } else {

            return std::vector<std::string>();
        }
    } else {
        return std::vector<std::string>();
    }
}
}; // namespace Common_Features