// // Created by grimmauld on 03.03.24. // #ifndef IPCSWAYTEST_SWAYMSG_H #define IPCSWAYTEST_SWAYMSG_H #include #include #include #include #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 = new char[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