| 1 /* |
|
| 2 * (C) Copyright 2001-2006 Wojtek Kaniewski <wojtekka@irc.pl> |
|
| 3 * Robert J. Woźny <speedy@ziew.org> |
|
| 4 * Arkadiusz Miśkiewicz <arekm@pld-linux.org> |
|
| 5 * Tomasz Chiliński <chilek@chilan.com> |
|
| 6 * Adam Wysocki <gophi@ekg.chmurka.net> |
|
| 7 * |
|
| 8 * This program is free software; you can redistribute it and/or modify |
|
| 9 * it under the terms of the GNU Lesser General Public License Version |
|
| 10 * 2.1 as published by the Free Software Foundation. |
|
| 11 * |
|
| 12 * This program is distributed in the hope that it will be useful, |
|
| 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 15 * GNU Lesser General Public License for more details. |
|
| 16 * |
|
| 17 * You should have received a copy of the GNU Lesser General Public |
|
| 18 * License along with this program; if not, write to the Free Software |
|
| 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, |
|
| 20 * USA. |
|
| 21 */ |
|
| 22 |
|
| 23 /** |
|
| 24 * \file debug.c |
|
| 25 * |
|
| 26 * \brief Funkcje odpluskwiania |
|
| 27 */ |
|
| 28 #include <sys/types.h> |
|
| 29 #include <errno.h> |
|
| 30 #include <stdarg.h> |
|
| 31 #include <stdio.h> |
|
| 32 #include <string.h> |
|
| 33 |
|
| 34 #include "libgadu.h" |
|
| 35 #include "debug.h" |
|
| 36 |
|
| 37 /** |
|
| 38 * Poziom rejestracji informacji odpluskwiających. Zmienna jest maską bitową |
|
| 39 * składającą się ze stałych \c GG_DEBUG_... |
|
| 40 * |
|
| 41 * \ingroup debug |
|
| 42 */ |
|
| 43 int gg_debug_level = 0; |
|
| 44 |
|
| 45 /** |
|
| 46 * Funkcja, do której są przekazywane informacje odpluskwiające. Jeśli zarówno |
|
| 47 * ten \c gg_debug_handler, jak i \c gg_debug_handler_session, są równe |
|
| 48 * \c NULL, informacje są wysyłane do standardowego wyjścia błędu (\c stderr). |
|
| 49 * |
|
| 50 * \param level Poziom rejestracji |
|
| 51 * \param format Format wiadomości (zgodny z \c printf) |
|
| 52 * \param ap Lista argumentów (zgodna z \c printf) |
|
| 53 * |
|
| 54 * \note Funkcja jest przesłaniana przez \c gg_debug_handler_session. |
|
| 55 * |
|
| 56 * \ingroup debug |
|
| 57 */ |
|
| 58 void (*gg_debug_handler)(int level, const char *format, va_list ap) = NULL; |
|
| 59 |
|
| 60 /** |
|
| 61 * Funkcja, do której są przekazywane informacje odpluskwiające. Jeśli zarówno |
|
| 62 * ten \c gg_debug_handler, jak i \c gg_debug_handler_session, są równe |
|
| 63 * \c NULL, informacje są wysyłane do standardowego wyjścia błędu. |
|
| 64 * |
|
| 65 * \param sess Sesja której dotyczy informacja lub \c NULL |
|
| 66 * \param level Poziom rejestracji |
|
| 67 * \param format Format wiadomości (zgodny z \c printf) |
|
| 68 * \param ap Lista argumentów (zgodna z \c printf) |
|
| 69 * |
|
| 70 * \note Funkcja przesłania przez \c gg_debug_handler_session. |
|
| 71 * |
|
| 72 * \ingroup debug |
|
| 73 */ |
|
| 74 void (*gg_debug_handler_session)(struct gg_session *sess, int level, const char *format, va_list ap) = NULL; |
|
| 75 |
|
| 76 /** |
|
| 77 * Plik, do którego będą przekazywane informacje odpluskwiania. |
|
| 78 * |
|
| 79 * Funkcja \c gg_debug() i pochodne mogą być przechwytywane przez aplikację |
|
| 80 * korzystającą z biblioteki, by wyświetlić je na żądanie użytkownika lub |
|
| 81 * zapisać do późniejszej analizy. Jeśli nie określono pliku, wybrane |
|
| 82 * informacje będą wysyłane do standardowego wyjścia błędu (\c stderr). |
|
| 83 * |
|
| 84 * \ingroup debug |
|
| 85 */ |
|
| 86 FILE *gg_debug_file = NULL; |
|
| 87 |
|
| 88 #ifndef GG_DEBUG_DISABLE |
|
| 89 |
|
| 90 /** |
|
| 91 * \internal Przekazuje informacje odpluskwiania do odpowiedniej funkcji. |
|
| 92 * |
|
| 93 * Jeśli aplikacja ustawiła odpowiednią funkcję obsługi w |
|
| 94 * \c gg_debug_handler_session lub \c gg_debug_handler, jest ona wywoływana. |
|
| 95 * W przeciwnym wypadku wynik jest wysyłany do standardowego wyjścia błędu. |
|
| 96 * |
|
| 97 * \param sess Struktura sesji (może być \c NULL) |
|
| 98 * \param level Poziom informacji |
|
| 99 * \param format Format wiadomości (zgodny z \c printf) |
|
| 100 * \param ap Lista argumentów (zgodna z \c printf) |
|
| 101 */ |
|
| 102 void gg_debug_common(struct gg_session *sess, int level, const char *format, va_list ap) |
|
| 103 { |
|
| 104 if (gg_debug_handler_session != NULL) |
|
| 105 (*gg_debug_handler_session)(sess, level, format, ap); |
|
| 106 else if (gg_debug_handler != NULL) |
|
| 107 (*gg_debug_handler)(level, format, ap); |
|
| 108 else if ((gg_debug_level & level) != 0) |
|
| 109 vfprintf((gg_debug_file) ? gg_debug_file : stderr, format, ap); |
|
| 110 } |
|
| 111 |
|
| 112 |
|
| 113 /** |
|
| 114 * \internal Przekazuje informację odpluskawiania. |
|
| 115 * |
|
| 116 * \param level Poziom wiadomości |
|
| 117 * \param format Format wiadomości (zgodny z \c printf) |
|
| 118 * |
|
| 119 * \ingroup debug |
|
| 120 */ |
|
| 121 void gg_debug(int level, const char *format, ...) |
|
| 122 { |
|
| 123 va_list ap; |
|
| 124 int old_errno = errno; |
|
| 125 |
|
| 126 va_start(ap, format); |
|
| 127 gg_debug_common(NULL, level, format, ap); |
|
| 128 va_end(ap); |
|
| 129 errno = old_errno; |
|
| 130 } |
|
| 131 |
|
| 132 /** |
|
| 133 * \internal Przekazuje informację odpluskwiania związaną z sesją. |
|
| 134 * |
|
| 135 * \param gs Struktura sesji |
|
| 136 * \param level Poziom wiadomości |
|
| 137 * \param format Format wiadomości (zgodny z \c printf) |
|
| 138 * |
|
| 139 * \ingroup debug |
|
| 140 */ |
|
| 141 void gg_debug_session(struct gg_session *gs, int level, const char *format, ...) |
|
| 142 { |
|
| 143 va_list ap; |
|
| 144 int old_errno = errno; |
|
| 145 |
|
| 146 va_start(ap, format); |
|
| 147 gg_debug_common(gs, level, format, ap); |
|
| 148 va_end(ap); |
|
| 149 errno = old_errno; |
|
| 150 } |
|
| 151 |
|
| 152 /** |
|
| 153 * \internal Przekazuje zrzut bufora do odpluskwiania. |
|
| 154 * |
|
| 155 * \param gs Struktura sesji |
|
| 156 * \param level Poziom wiadomości |
|
| 157 * \param buf Bufor danych |
|
| 158 * \param len Długość bufora danych |
|
| 159 * |
|
| 160 * \ingroup debug |
|
| 161 */ |
|
| 162 void gg_debug_dump(struct gg_session *gs, int level, const char *buf, size_t len) |
|
| 163 { |
|
| 164 char line[80]; |
|
| 165 unsigned int i, j; |
|
| 166 |
|
| 167 for (i = 0; i < len; i += 16) { |
|
| 168 int ofs; |
|
| 169 |
|
| 170 sprintf(line, "%.4x: ", i); |
|
| 171 ofs = 6; |
|
| 172 |
|
| 173 for (j = 0; j < 16; j++) { |
|
| 174 if (i + j < len) |
|
| 175 sprintf(line + ofs, " %02x", (unsigned char) buf[i + j]); |
|
| 176 else |
|
| 177 sprintf(line + ofs, " "); |
|
| 178 |
|
| 179 ofs += 3; |
|
| 180 } |
|
| 181 |
|
| 182 sprintf(line + ofs, " "); |
|
| 183 ofs += 2; |
|
| 184 |
|
| 185 for (j = 0; j < 16; j++) { |
|
| 186 unsigned char ch; |
|
| 187 |
|
| 188 if (i + j < len) { |
|
| 189 ch = buf[i + j]; |
|
| 190 |
|
| 191 if (ch < 32 || ch > 126) |
|
| 192 ch = '.'; |
|
| 193 } else { |
|
| 194 ch = ' '; |
|
| 195 } |
|
| 196 |
|
| 197 line[ofs++] = ch; |
|
| 198 } |
|
| 199 |
|
| 200 line[ofs++] = '\n'; |
|
| 201 line[ofs++] = 0; |
|
| 202 |
|
| 203 gg_debug_session(gs, level, "%s", line); |
|
| 204 } |
|
| 205 } |
|
| 206 |
|
| 207 /** |
|
| 208 * \internal Zwraca ciąg z nazwą podanego stanu sesji. |
|
| 209 * |
|
| 210 * \param state Stan sesji. |
|
| 211 * |
|
| 212 * \return Ciąg z nazwą stanu |
|
| 213 * |
|
| 214 * \ingroup debug |
|
| 215 */ |
|
| 216 const char *gg_debug_state(enum gg_state_t state) |
|
| 217 { |
|
| 218 switch (state) { |
|
| 219 #define GG_DEBUG_STATE(x) case x: return #x; |
|
| 220 GG_DEBUG_STATE(GG_STATE_IDLE) |
|
| 221 GG_DEBUG_STATE(GG_STATE_RESOLVING) |
|
| 222 GG_DEBUG_STATE(GG_STATE_CONNECTING) |
|
| 223 GG_DEBUG_STATE(GG_STATE_READING_DATA) |
|
| 224 GG_DEBUG_STATE(GG_STATE_ERROR) |
|
| 225 GG_DEBUG_STATE(GG_STATE_CONNECTING_HUB) |
|
| 226 GG_DEBUG_STATE(GG_STATE_CONNECTING_GG) |
|
| 227 GG_DEBUG_STATE(GG_STATE_READING_KEY) |
|
| 228 GG_DEBUG_STATE(GG_STATE_READING_REPLY) |
|
| 229 GG_DEBUG_STATE(GG_STATE_CONNECTED) |
|
| 230 GG_DEBUG_STATE(GG_STATE_SENDING_QUERY) |
|
| 231 GG_DEBUG_STATE(GG_STATE_READING_HEADER) |
|
| 232 GG_DEBUG_STATE(GG_STATE_PARSING) |
|
| 233 GG_DEBUG_STATE(GG_STATE_DONE) |
|
| 234 GG_DEBUG_STATE(GG_STATE_LISTENING) |
|
| 235 GG_DEBUG_STATE(GG_STATE_READING_UIN_1) |
|
| 236 GG_DEBUG_STATE(GG_STATE_READING_UIN_2) |
|
| 237 GG_DEBUG_STATE(GG_STATE_SENDING_ACK) |
|
| 238 GG_DEBUG_STATE(GG_STATE_READING_ACK) |
|
| 239 GG_DEBUG_STATE(GG_STATE_READING_REQUEST) |
|
| 240 GG_DEBUG_STATE(GG_STATE_SENDING_REQUEST) |
|
| 241 GG_DEBUG_STATE(GG_STATE_SENDING_FILE_INFO) |
|
| 242 GG_DEBUG_STATE(GG_STATE_READING_PRE_FILE_INFO) |
|
| 243 GG_DEBUG_STATE(GG_STATE_READING_FILE_INFO) |
|
| 244 GG_DEBUG_STATE(GG_STATE_SENDING_FILE_ACK) |
|
| 245 GG_DEBUG_STATE(GG_STATE_READING_FILE_ACK) |
|
| 246 GG_DEBUG_STATE(GG_STATE_SENDING_FILE_HEADER) |
|
| 247 GG_DEBUG_STATE(GG_STATE_READING_FILE_HEADER) |
|
| 248 GG_DEBUG_STATE(GG_STATE_GETTING_FILE) |
|
| 249 GG_DEBUG_STATE(GG_STATE_SENDING_FILE) |
|
| 250 GG_DEBUG_STATE(GG_STATE_READING_VOICE_ACK) |
|
| 251 GG_DEBUG_STATE(GG_STATE_READING_VOICE_HEADER) |
|
| 252 GG_DEBUG_STATE(GG_STATE_READING_VOICE_SIZE) |
|
| 253 GG_DEBUG_STATE(GG_STATE_READING_VOICE_DATA) |
|
| 254 GG_DEBUG_STATE(GG_STATE_SENDING_VOICE_ACK) |
|
| 255 GG_DEBUG_STATE(GG_STATE_SENDING_VOICE_REQUEST) |
|
| 256 GG_DEBUG_STATE(GG_STATE_READING_TYPE) |
|
| 257 GG_DEBUG_STATE(GG_STATE_TLS_NEGOTIATION) |
|
| 258 GG_DEBUG_STATE(GG_STATE_REQUESTING_ID) |
|
| 259 GG_DEBUG_STATE(GG_STATE_WAITING_FOR_ACCEPT) |
|
| 260 GG_DEBUG_STATE(GG_STATE_WAITING_FOR_INFO) |
|
| 261 GG_DEBUG_STATE(GG_STATE_READING_ID) |
|
| 262 GG_DEBUG_STATE(GG_STATE_SENDING_ID) |
|
| 263 GG_DEBUG_STATE(GG_STATE_RESOLVING_GG) |
|
| 264 GG_DEBUG_STATE(GG_STATE_RESOLVING_RELAY) |
|
| 265 GG_DEBUG_STATE(GG_STATE_CONNECTING_RELAY) |
|
| 266 GG_DEBUG_STATE(GG_STATE_READING_RELAY) |
|
| 267 GG_DEBUG_STATE(GG_STATE_DISCONNECTING) |
|
| 268 GG_DEBUG_STATE(GG_STATE_CONNECT_HUB) |
|
| 269 GG_DEBUG_STATE(GG_STATE_CONNECT_PROXY_HUB) |
|
| 270 GG_DEBUG_STATE(GG_STATE_CONNECT_GG) |
|
| 271 GG_DEBUG_STATE(GG_STATE_CONNECT_PROXY_GG) |
|
| 272 GG_DEBUG_STATE(GG_STATE_CONNECTING_PROXY_HUB) |
|
| 273 GG_DEBUG_STATE(GG_STATE_CONNECTING_PROXY_GG) |
|
| 274 GG_DEBUG_STATE(GG_STATE_RESOLVE_HUB_SYNC) |
|
| 275 GG_DEBUG_STATE(GG_STATE_RESOLVE_HUB_ASYNC) |
|
| 276 GG_DEBUG_STATE(GG_STATE_RESOLVE_PROXY_HUB_SYNC) |
|
| 277 GG_DEBUG_STATE(GG_STATE_RESOLVE_PROXY_HUB_ASYNC) |
|
| 278 GG_DEBUG_STATE(GG_STATE_RESOLVE_PROXY_GG_SYNC) |
|
| 279 GG_DEBUG_STATE(GG_STATE_RESOLVE_PROXY_GG_ASYNC) |
|
| 280 GG_DEBUG_STATE(GG_STATE_RESOLVE_GG_SYNC) |
|
| 281 GG_DEBUG_STATE(GG_STATE_RESOLVE_GG_ASYNC) |
|
| 282 GG_DEBUG_STATE(GG_STATE_RESOLVING_HUB) |
|
| 283 GG_DEBUG_STATE(GG_STATE_RESOLVING_PROXY_HUB) |
|
| 284 GG_DEBUG_STATE(GG_STATE_RESOLVING_PROXY_GG) |
|
| 285 GG_DEBUG_STATE(GG_STATE_SEND_HUB) |
|
| 286 GG_DEBUG_STATE(GG_STATE_SEND_PROXY_HUB) |
|
| 287 GG_DEBUG_STATE(GG_STATE_SEND_PROXY_GG) |
|
| 288 GG_DEBUG_STATE(GG_STATE_SENDING_HUB) |
|
| 289 GG_DEBUG_STATE(GG_STATE_SENDING_PROXY_HUB) |
|
| 290 GG_DEBUG_STATE(GG_STATE_SENDING_PROXY_GG) |
|
| 291 GG_DEBUG_STATE(GG_STATE_READING_HUB) |
|
| 292 GG_DEBUG_STATE(GG_STATE_READING_PROXY_HUB) |
|
| 293 GG_DEBUG_STATE(GG_STATE_READING_PROXY_GG) |
|
| 294 #undef GG_DEBUG_STATE |
|
| 295 |
|
| 296 /* Celowo nie ma default, żeby kompilator wyłapał brakujące stany */ |
|
| 297 } |
|
| 298 |
|
| 299 return NULL; |
|
| 300 } |
|
| 301 |
|
| 302 /** |
|
| 303 * \internal Zwraca ciąg z nazwą podanego zdarzenia. |
|
| 304 * |
|
| 305 * \param event Zdarzenie. |
|
| 306 * |
|
| 307 * \return Ciąg z nazwą zdarzenia |
|
| 308 * |
|
| 309 * \ingroup debug |
|
| 310 */ |
|
| 311 const char *gg_debug_event(enum gg_event_t event) |
|
| 312 { |
|
| 313 switch (event) { |
|
| 314 #define GG_DEBUG_EVENT(x) case x: return #x; |
|
| 315 GG_DEBUG_EVENT(GG_EVENT_NONE) |
|
| 316 GG_DEBUG_EVENT(GG_EVENT_MSG) |
|
| 317 GG_DEBUG_EVENT(GG_EVENT_NOTIFY) |
|
| 318 GG_DEBUG_EVENT(GG_EVENT_NOTIFY_DESCR) |
|
| 319 GG_DEBUG_EVENT(GG_EVENT_STATUS) |
|
| 320 GG_DEBUG_EVENT(GG_EVENT_ACK) |
|
| 321 GG_DEBUG_EVENT(GG_EVENT_PONG) |
|
| 322 GG_DEBUG_EVENT(GG_EVENT_CONN_FAILED) |
|
| 323 GG_DEBUG_EVENT(GG_EVENT_CONN_SUCCESS) |
|
| 324 GG_DEBUG_EVENT(GG_EVENT_DISCONNECT) |
|
| 325 GG_DEBUG_EVENT(GG_EVENT_DCC_NEW) |
|
| 326 GG_DEBUG_EVENT(GG_EVENT_DCC_ERROR) |
|
| 327 GG_DEBUG_EVENT(GG_EVENT_DCC_DONE) |
|
| 328 GG_DEBUG_EVENT(GG_EVENT_DCC_CLIENT_ACCEPT) |
|
| 329 GG_DEBUG_EVENT(GG_EVENT_DCC_CALLBACK) |
|
| 330 GG_DEBUG_EVENT(GG_EVENT_DCC_NEED_FILE_INFO) |
|
| 331 GG_DEBUG_EVENT(GG_EVENT_DCC_NEED_FILE_ACK) |
|
| 332 GG_DEBUG_EVENT(GG_EVENT_DCC_NEED_VOICE_ACK) |
|
| 333 GG_DEBUG_EVENT(GG_EVENT_DCC_VOICE_DATA) |
|
| 334 GG_DEBUG_EVENT(GG_EVENT_PUBDIR50_SEARCH_REPLY) |
|
| 335 GG_DEBUG_EVENT(GG_EVENT_PUBDIR50_READ) |
|
| 336 GG_DEBUG_EVENT(GG_EVENT_PUBDIR50_WRITE) |
|
| 337 GG_DEBUG_EVENT(GG_EVENT_STATUS60) |
|
| 338 GG_DEBUG_EVENT(GG_EVENT_NOTIFY60) |
|
| 339 GG_DEBUG_EVENT(GG_EVENT_USERLIST) |
|
| 340 GG_DEBUG_EVENT(GG_EVENT_IMAGE_REQUEST) |
|
| 341 GG_DEBUG_EVENT(GG_EVENT_IMAGE_REPLY) |
|
| 342 GG_DEBUG_EVENT(GG_EVENT_DCC_ACK) |
|
| 343 GG_DEBUG_EVENT(GG_EVENT_DCC7_NEW) |
|
| 344 GG_DEBUG_EVENT(GG_EVENT_DCC7_ACCEPT) |
|
| 345 GG_DEBUG_EVENT(GG_EVENT_DCC7_REJECT) |
|
| 346 GG_DEBUG_EVENT(GG_EVENT_DCC7_CONNECTED) |
|
| 347 GG_DEBUG_EVENT(GG_EVENT_DCC7_ERROR) |
|
| 348 GG_DEBUG_EVENT(GG_EVENT_DCC7_DONE) |
|
| 349 GG_DEBUG_EVENT(GG_EVENT_DCC7_PENDING) |
|
| 350 GG_DEBUG_EVENT(GG_EVENT_XML_EVENT) |
|
| 351 GG_DEBUG_EVENT(GG_EVENT_JSON_EVENT) |
|
| 352 GG_DEBUG_EVENT(GG_EVENT_ACK110) |
|
| 353 GG_DEBUG_EVENT(GG_EVENT_DISCONNECT_ACK) |
|
| 354 GG_DEBUG_EVENT(GG_EVENT_TYPING_NOTIFICATION) |
|
| 355 GG_DEBUG_EVENT(GG_EVENT_USER_DATA) |
|
| 356 GG_DEBUG_EVENT(GG_EVENT_MULTILOGON_MSG) |
|
| 357 GG_DEBUG_EVENT(GG_EVENT_MULTILOGON_INFO) |
|
| 358 GG_DEBUG_EVENT(GG_EVENT_USERLIST100_VERSION) |
|
| 359 GG_DEBUG_EVENT(GG_EVENT_USERLIST100_REPLY) |
|
| 360 GG_DEBUG_EVENT(GG_EVENT_IMTOKEN) |
|
| 361 GG_DEBUG_EVENT(GG_EVENT_PONG110) |
|
| 362 GG_DEBUG_EVENT(GG_EVENT_CHAT_INFO) |
|
| 363 GG_DEBUG_EVENT(GG_EVENT_CHAT_INFO_GOT_ALL) |
|
| 364 GG_DEBUG_EVENT(GG_EVENT_CHAT_INFO_UPDATE) |
|
| 365 GG_DEBUG_EVENT(GG_EVENT_CHAT_CREATED) |
|
| 366 GG_DEBUG_EVENT(GG_EVENT_CHAT_INVITE_ACK) |
|
| 367 #undef GG_DEBUG_EVENT |
|
| 368 |
|
| 369 /* Celowo nie ma default, żeby kompilator wyłapał brakujące zdarzenia */ |
|
| 370 } |
|
| 371 |
|
| 372 return NULL; |
|
| 373 } |
|
| 374 |
|
| 375 #else |
|
| 376 |
|
| 377 #undef gg_debug_common |
|
| 378 void gg_debug_common(struct gg_session *sess, int level, const char *format, va_list ap) |
|
| 379 { |
|
| 380 } |
|
| 381 |
|
| 382 #undef gg_debug |
|
| 383 void gg_debug(int level, const char *format, ...) |
|
| 384 { |
|
| 385 } |
|
| 386 |
|
| 387 #undef gg_debug_session |
|
| 388 void gg_debug_session(struct gg_session *gs, int level, const char *format, ...) |
|
| 389 { |
|
| 390 } |
|
| 391 |
|
| 392 #undef gg_debug_dump |
|
| 393 void gg_debug_dump(struct gg_session *gs, int level, const char *buf, size_t len) |
|
| 394 { |
|
| 395 } |
|
| 396 |
|
| 397 #endif |
|