swaymux/sway_bindings/swaymsg.h

106 lines
4.0 KiB
C++

//
// Created by grimmauld on 03.03.24.
//
#ifndef IPCSWAYTEST_SWAYMSG_H
#define IPCSWAYTEST_SWAYMSG_H
#include <sys/socket.h>
#include <sys/un.h>
#include <cstring>
#include <cstdlib>
#include "Formatter.h"
struct swaymsg {
explicit swaymsg(const unsigned int payloadType, const char *msg) : swaymsg(payloadType, msg,
msg == nullptr ? 0 : strlen(msg)) {};
explicit swaymsg(const unsigned int payloadType, const std::string& msg) : swaymsg(payloadType, msg.c_str(), msg.length()) {};
explicit swaymsg(const unsigned int payloadType, const char *msg, const unsigned int payload_len)
: payload_len(payload_len), payload_type(payloadType) {
this->msg = static_cast<char *>(std::malloc(payload_len));
std::memcpy(this->msg, msg, payload_len);
buff = new unsigned char [size()];
std::memcpy(buff, magic, strlen(magic));
std::memcpy(buff + (unsigned int) strlen(magic), &payload_len, sizeof(payload_len));
std::memcpy(buff + (unsigned int) strlen(magic) + sizeof(payload_len), &payload_type, sizeof(payload_type));
std::memcpy(buff + (unsigned int) strlen(magic) + sizeof(payload_len) + sizeof(payload_type), msg, payload_len);
}
explicit swaymsg(const unsigned int payloadType) : swaymsg(payloadType, nullptr) {}
[[nodiscard]] static swaymsg fromSock(const int sockfd) {
char buff[6];
size_t dlen;
if ((dlen = recv(sockfd, buff, 6, 0)) != 6) {
throw std::runtime_error(
Formatter() << "Swaysock: Unexpected length on recv() call for magic: " << dlen
>> Formatter::to_str);
}
if (strncmp(buff, magic, 6) != 0) {
throw std::runtime_error("Swaysock: magic did not match");
}
unsigned int payloadType;
unsigned int payloadLen;
static_assert(sizeof(payloadType) == 4);
static_assert(sizeof(payloadLen) == 4);
if ((dlen = recv(sockfd, &payloadLen, sizeof(payloadLen), 0)) != sizeof(payloadLen)) {
throw std::runtime_error(
Formatter() << "Swaysock: Unexpected length on recv() call for len: " << dlen >> Formatter::to_str);
}
if ((dlen = recv(sockfd, &payloadType, sizeof(payloadType), 0)) != sizeof(payloadType)) {
throw std::runtime_error(
Formatter() << "Swaysock: Unexpected length on recv() call for type: " << dlen
>> Formatter::to_str);
}
char msgBuff[payloadLen + 1];
if ((dlen = recv(sockfd, msgBuff, payloadLen, 0)) != payloadLen) {
throw std::runtime_error(
Formatter() << "Swaysock: Unexpected length on recv() call for message: " << dlen
>> Formatter::to_str);
}
msgBuff[payloadLen] = '\00'; // make sure we have a c-style string that is properly terminated or json parsing gets all weird...
return swaymsg(payloadType, msgBuff, payloadLen + 1);
};
constexpr const static char *magic = "i3-ipc";
const unsigned int payload_len;
const unsigned int payload_type;
char *msg;
unsigned char *buff = nullptr;
static_assert(sizeof(payload_len) == 4);
static_assert(sizeof(payload_type) == 4);
[[nodiscard]] size_t size() const {
return (int) strlen(magic) + sizeof(payload_len) + sizeof(payload_type) + payload_len;
}
[[nodiscard]] void *asBuffer() const {
return buff;
}
~swaymsg() {
delete buff;
delete msg;
}
};
static const swaymsg SWAY_EXIT = swaymsg(0, "exit");
static const swaymsg SWAY_GET_WORKSPACES = swaymsg(1);
static const swaymsg SWAY_GET_OUTPUTS = swaymsg(3);
static const swaymsg SWAY_GET_TREE = swaymsg(4);
static const swaymsg SWAY_GET_VERSION = swaymsg(7);
static const swaymsg SWAY_GET_CONFIG = swaymsg(9);
static const swaymsg SWAY_GET_INPUTS = swaymsg(100);
#endif //IPCSWAYTEST_SWAYMSG_H