1 /* EINA - EFL data type library
2  * Copyright (C) 2015 Carsten Haitzler
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library;
16  * if not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #ifndef EINA_DEBUG_H_
20 # define EINA_DEBUG_H_
21 
22 # include "eina_config.h"
23 # include "eina_list.h"
24 
25 #ifdef EFL_BETA_API_SUPPORT
26 
27 /**
28  * @page eina_debug_main Eina Debug
29  *
30  * @date 2015 (created)
31  */
32 
33 /**
34  * @addtogroup Eina_Debug
35  * @{
36  */
37 
38 enum
39 {
40    EINA_DEBUG_OPCODE_INVALID = -1, /**< Invalid opcode value */
41    EINA_DEBUG_OPCODE_REGISTER = 0, /**< Opcode used to register other opcodes */
42    EINA_DEBUG_OPCODE_HELLO = 1 /**< Opcode used to send greetings to the daemon */
43 };
44 
45 /**
46  * @typedef Eina_Debug_Session
47  *
48  * A handle used to interact with the debug daemon.
49  * It contains all the information related to this connection and needed
50  * to send/receive/dispatch/...
51  */
52 typedef struct _Eina_Debug_Session Eina_Debug_Session;
53 
54 /**
55  * @typedef Eina_Debug_Cb
56  *
57  * A callback invoked when a specific packet is received.
58  *
59  * @param[in,out] session the session
60  * @param[in] srcid the source id
61  * @param[in] buffer the packet payload data. It doesn't contain any transport information.
62  * @param[in] size the packet payload size
63  *
64  * @return True on success, false if the connection seems compromised.
65  */
66 typedef Eina_Bool (*Eina_Debug_Cb)(Eina_Debug_Session *session, int srcid, void *buffer, int size);
67 
68 /**
69  * @typedef Eina_Debug_Opcode_Status_Cb
70  *
71  * When the opcodes ids are retrieved, this callback is invoked with a true
72  * status.
73  * When a disconnection to the daemon is happening, the opcodes ids are set
74  * as invalid and this callback is invoked with a false status. The upper
75  * layer should not try to send more requests until a new connection is
76  * established.
77  *
78  * @param[in,out] data data pointer given when registering opcodes
79  * @param[in] status EINA_TRUE if opcodes have been received from the daemon, EINA_FALSE otherwise.
80  */
81 typedef void (*Eina_Debug_Opcode_Status_Cb)(void *data, Eina_Bool status);
82 
83 /**
84  * @typedef Eina_Debug_Dispatch_Cb
85  *
86  * Dispatcher callback prototype used to override the default dispatcher of a
87  * session.
88  *
89  * @param[in,out] session the session
90  * @param[in] buffer the packet received
91  *
92  * The given packet is the entire data received, including the header.
93  *
94  * @return The return result of the invoked callback.
95  */
96 typedef Eina_Bool (*Eina_Debug_Dispatch_Cb)(Eina_Debug_Session *session, void *buffer);
97 
98 /**
99  * @typedef Eina_Debug_Timer_Cb
100  *
101  * A callback for a timer
102  */
103 typedef Eina_Bool (*Eina_Debug_Timer_Cb)(void *);
104 
105 /**
106  * @typedef Eina_Debug_Timer
107  */
108 typedef struct _Eina_Debug_Timer Eina_Debug_Timer;
109 
110 /**
111  * @struct Eina_Debug_Packet_Header
112  *
113  * Header of Eina Debug packet
114  */
115 typedef struct
116 {
117    unsigned int size; /**< Packet size including this element */
118    /**<
119     * During sending, it corresponds to the id of the destination. During reception, it is the id of the source
120     * The daemon is in charge of swapping the id before forwarding the packet to the destination.
121     */
122    int cid;
123    int opcode; /**< Opcode of the packet */
124 } Eina_Debug_Packet_Header;
125 
126 /**
127  * Helper for creating global opcodes arrays.
128  * The problem is on windows where you can't declare a static array with
129  * external symbols in it, because the addresses are only known at runtime.
130  */
131 #define EINA_DEBUG_OPCODES_ARRAY_DEFINE(Name, ...)                           \
132   static Eina_Debug_Opcode *                                      \
133   Name(void)                                                            \
134   {                                                                     \
135      Eina_Debug_Opcode tmp[] = { __VA_ARGS__ }; \
136      static Eina_Debug_Opcode internal[EINA_C_ARRAY_LENGTH(tmp) + 1] = \
137        { { 0, 0, 0 } };         \
138      if (internal[0].opcode_name == NULL)                                      \
139        {                                                                \
140           memcpy(internal, tmp, sizeof(tmp)); \
141        }                                                                \
142      return internal;                                                   \
143   }
144 
145 /**
146  * @struct Eina_Debug_Opcode
147  *
148  * Structure to describe information for an opcode. It is used to register new
149  * opcodes.
150  */
151 typedef struct
152 {
153    char *opcode_name; /**< Opcode string. On registration, the daemon uses it to calculate an opcode id */
154    int *opcode_id; /**< A pointer to store the opcode id received from the daemon */
155    Eina_Debug_Cb cb; /**< Callback to call when a packet corresponding to the opcode is received */
156 } Eina_Debug_Opcode;
157 
158 /**
159  * @brief Disable debugging
160  *
161  * Useful for applications that don't want debugging. The debug daemon is one
162  * of them.
163  * Need to be invoked before eina_init. Otherwise it won't have any effect.
164  */
165 EAPI void eina_debug_disable(void);
166 
167 /**
168  * @brief Connect to the local daemon
169  *
170  * @param[in] is_master true if the application is a debugger. EINA_FALSE otherwise.
171  *
172  * @return The session on success or NULL otherwise.
173  */
174 EAPI Eina_Debug_Session *eina_debug_local_connect(Eina_Bool is_master);
175 
176 /**
177  * @brief Connect to remote daemon
178  *
179  * This function connects to localhost:port.
180  *
181  * @param[in] port the port to connect to
182  *
183  * @return The session on success or NULL otherwise.
184  */
185 EAPI Eina_Debug_Session *eina_debug_remote_connect(int port);
186 
187 /**
188  * @brief Terminate the session
189  *
190  * @param[in,out] session the session to terminate
191  */
192 EAPI void eina_debug_session_terminate(Eina_Debug_Session *session);
193 
194 /**
195  * @brief Override the dispatcher of a specific session
196  *
197  * For example, it can be used to forward a packet to the main thread and to
198  * use the default dispatcher there.
199  * All the packets received in this session will use this dispatcher.
200  *
201  * @param[in,out] session the session
202  * @param[in] disp_cb the new dispatcher for the given session
203  */
204 EAPI void eina_debug_session_dispatch_override(Eina_Debug_Session *session, Eina_Debug_Dispatch_Cb disp_cb);
205 
206 /**
207  * @brief Get the dispatcher of a specific session
208  *
209  * @param[in,out] session the session
210  *
211  * @return The session dispatcher.
212  */
213 EAPI Eina_Debug_Dispatch_Cb eina_debug_session_dispatch_get(Eina_Debug_Session *session);
214 
215 /**
216  * @brief Dispatch a given packet according to its header.
217  *
218  * This function checks the header contained in the packet and invokes
219  * the correct callback according to the opcode.
220  * This is the default dispatcher.
221  *
222  * @param[in,out] session the session
223  * @param[in] buffer the packet
224  *
225  * @return True on success, false if the connection seems compromised.
226  */
227 EAPI Eina_Bool eina_debug_dispatch(Eina_Debug_Session *session, void *buffer);
228 
229 /**
230  * @brief Set data to a session
231  *
232  * @param[in,out] session the session
233  * @param[in] data the data to set
234  */
235 EAPI void eina_debug_session_data_set(Eina_Debug_Session *session, void *data);
236 
237 /**
238  * @brief Get the data attached to a session
239  *
240  * @param[in,out] session the session
241  *
242  * @return The data of the session.
243  */
244 EAPI void *eina_debug_session_data_get(Eina_Debug_Session *session);
245 
246 /**
247  * @brief Register opcodes to a session
248  *
249  * This function registers opcodes for the given session. If the session is not
250  * connected, the request is not sent to the daemon. Otherwise, the request for
251  * the opcodes ids is sent.
252  * On the reception from the daemon, status_cb function is invoked to inform
253  * the requester that the opcodes can now be used.
254  *
255  * @param[in,out] session the session
256  * @param[in] ops the operations to register
257  * @param[in] status_cb a function to call when the opcodes are received
258  * @param[in] status_data the data to give to status_cb
259  */
260 EAPI void eina_debug_opcodes_register(Eina_Debug_Session *session,
261       const Eina_Debug_Opcode ops[],
262       Eina_Debug_Opcode_Status_Cb status_cb, void *status_data);
263 
264 /**
265  * @brief Send a packet to the given destination
266  *
267  * The packet will be treated by the debug thread itself.
268  *
269  * @param[in,out] session the session to use to send the packet
270  * @param[in] dest_id the destination id to send the packet to
271  * @param[in] op the opcode for this packet
272  * @param[in] data payload to send
273  * @param[in] size payload size
274  *
275  * @return The number of sent bytes.
276  */
277 EAPI int eina_debug_session_send(Eina_Debug_Session *session, int dest_id, int op, void *data, int size);
278 
279 /**
280  * @brief Add a timer
281  *
282  * @param[in] timeout_ms timeout in ms
283  * @param[in] cb callback to call when the timeout is reached
284  * @param[in] data user data
285  *
286  * @return The timer handle, NULL on error.
287  */
288 EAPI Eina_Debug_Timer *eina_debug_timer_add(unsigned int timeout_ms, Eina_Debug_Timer_Cb cb, void *data);
289 
290 /**
291  * @brief Delete a timer
292  *
293  * @param[in,out] timer the timer to delete
294  *
295  * If the timer reaches the end and has not be renewed, trying to delete it will lead to a crash, as
296  * it has already been deleted internally.
297  */
298 EAPI void eina_debug_timer_del(Eina_Debug_Timer *timer);
299 
300 /**
301  * @brief Reset the eina debug system after forking
302  *
303  * Call this any time the application forks
304  * @since 1.21
305  * */
306 EAPI void eina_debug_fork_reset(void);
307 /**
308  * @}
309  */
310 
311 #endif
312 
313 #endif
314