1 #pragma once 2 3 #include <cstdint> 4 #include <string> 5 #include <memory> 6 #include <stdexcept> 7 8 // extern "C" { 9 // #include <i3/ipc.h> 10 // } 11 12 namespace i3ipc { 13 14 /** @defgroup i3ipc_util i3 IPC internal utilities 15 * Stuff for internal usage in I3Connection 16 * @{ 17 */ 18 19 // extern "C" { 20 21 /** 22 * i3 IPC header 23 */ 24 struct header_t { 25 /* 6 = strlen(I3_IPC_MAGIC) */ 26 char magic[6]; ///< Magic string @see I3_IPC_MAGIC 27 uint32_t size; ///< Size of payload 28 uint32_t type; ///< Message type 29 } __attribute__ ((packed)); 30 31 32 /** 33 * @brief Base class of i3 IPC errors 34 */ 35 class ipc_error : public std::runtime_error { using std::runtime_error::runtime_error; }; 36 37 /** 38 * @brief Something wrong in message header (wrong magic number, message type etc.) 39 */ 40 class invalid_header_error : public ipc_error { using ipc_error::ipc_error; }; 41 42 /** 43 * @brief Socket return EOF, but expected a data 44 */ 45 class eof_error : public ipc_error { using ipc_error::ipc_error; }; 46 47 /** 48 * @brief If something wrong in a payload of i3's reply 49 */ 50 class invalid_reply_payload_error : public ipc_error { using ipc_error::ipc_error; }; 51 52 /** 53 * @brief If any error occured, while using C-functions 54 */ 55 class errno_error : public ipc_error { 56 public: 57 errno_error(); 58 errno_error(const std::string& msg); 59 }; 60 61 62 /** 63 * @brief Messages (requests), that can be sended from the client 64 */ 65 enum class ClientMessageType : uint32_t { 66 COMMAND = 0, 67 GET_WORKSPACES = 1, 68 SUBSCRIBE = 2, 69 GET_OUTPUTS = 3, 70 GET_TREE = 4, 71 GET_MARKS = 5, 72 GET_BAR_CONFIG = 6, 73 GET_VERSION = 7, 74 }; 75 76 77 /** 78 * @brief Replies, that can be sended from the i3 to the client 79 */ 80 enum class ReplyType : uint32_t { 81 COMMAND = 0, 82 WORKSPACES = 1, 83 SUBSCRIBE = 2, 84 OUTPUTS = 3, 85 TREE = 4, 86 MARKS = 5, 87 BAR_CONFIG = 6, 88 VERSION = 7, 89 }; 90 91 92 /** 93 * @brief i3 IPC message buffer 94 */ 95 struct buf_t { 96 uint32_t size; ///< @brief Size of whole buffer 97 uint8_t* data; ///< @brief Pointer to the message 98 99 /** 100 * @brief i3 IPC message header 101 * 102 * Pointing on the begining 103 */ 104 header_t* header; 105 106 /** 107 * @brief Message payload 108 * 109 * Pointing on the byte after the header 110 */ 111 char* payload; 112 113 buf_t(uint32_t payload_size); 114 ~buf_t(); 115 116 /** 117 * @brief Resize payload to the payload_size in the header 118 */ 119 void realloc_payload_to_header(); 120 }; 121 122 /** 123 * Connect to the i3 socket 124 * @param socket_path a socket path 125 * @return socket id 126 */ 127 int32_t i3_connect(const std::string& socket_path); 128 129 /** 130 * @brief Close the connection 131 * @param sockfd socket 132 */ 133 void i3_disconnect(const int32_t sockfd); 134 135 /** 136 * @brief Send message to the socket 137 * @param sockfd a socket 138 * @param buff a message 139 */ 140 void i3_send(const int32_t sockfd, const buf_t& buff); 141 142 /** 143 * @brief Recive a message from i3 144 * @param sockfd a socket 145 * @return a buffer of the message 146 */ 147 std::shared_ptr<buf_t> i3_recv(const int32_t sockfd); 148 149 /** 150 * @brief Pack a buffer of message 151 */ 152 std::shared_ptr<buf_t> i3_pack(const ClientMessageType type, const std::string& payload); 153 154 /** 155 * @brief Pack, send a message and receiv a reply 156 * 157 * Almost same to: 158 * @code{.cpp} 159 * i3_send(sockfd, i3_pack(type, payload)); 160 * auto reply = i3_recv(sockfd); 161 * @endcode 162 */ 163 std::shared_ptr<buf_t> i3_msg(const int32_t sockfd, const ClientMessageType type, const std::string& payload = std::string()); 164 165 /** 166 * @} 167 */ 168 169 } 170