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