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