From 88b327cff57b24c1a64248fcb8e10c63e5969232 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Thu, 6 Aug 2009 15:50:10 -0500 Subject: [PATCH] Cleanup the debug support patch --- gatchat/gatchat.c | 97 +++++++++++++++++++++++++++++++++++------------ gatchat/gatchat.h | 8 +++- 2 files changed, 78 insertions(+), 27 deletions(-) diff --git a/gatchat/gatchat.c b/gatchat/gatchat.c index 9f69c8a2..1347f183 100644 --- a/gatchat/gatchat.c +++ b/gatchat/gatchat.c @@ -29,6 +29,7 @@ #include #include #include +#include #include @@ -78,7 +79,7 @@ struct _GAtChat { guint read_so_far; /* Number of bytes processed */ gboolean disconnecting; /* Whether we're disconnecting */ GAtDebugFunc debugf; /* debugging output function */ - gpointer debug_func_user_data; + gpointer debug_data; /* Data to pass to debug func */ char *pdu_notify; /* Unsolicited Resp w/ PDU */ GSList *response_lines; /* char * lines of the response */ char *wakeup; /* command sent to wakeup modem */ @@ -592,33 +593,79 @@ static void new_bytes(GAtChat *p) g_at_chat_shutdown(p); } -static void g_at_chat_debug_log(GAtChat *chat, gboolean is_read, - const char *str, gsize len) +static void debug_chat(GAtChat *chat, gboolean in, const char *str, gsize len) { - char type = is_read ? '<' : '>'; - char *t1, *t2; + char type = in ? '<' : '>'; + gsize escaped = 2; /* Enough for '<', ' ' */ + char *escaped_str; + const char *esc = ""; + gsize esc_size = strlen(esc); + const char *ctrlz = ""; + gsize ctrlz_size = strlen(ctrlz); + gsize i; if (!chat->debugf || !len) return; - if (len > 2048) { - /* 27.007 specifies a max command result length of 2048 */ - t1 = g_strdup_printf("%c (ignoring string of length %d)", type, len); - chat->debugf(t1, chat->debug_func_user_data); - g_free(t1); - return; + for (i = 0; i < len; i++) { + char c = str[i]; + + if (isprint(c)) + escaped += 1; + else if (c == '\r' || c == '\t' || c == '\n') + escaped += 2; + else if (c == 26) + escaped += ctrlz_size; + else if (c == 25) + escaped += esc_size; + else + escaped += 4; } - /* prefix with "> " or "< ", and ensure null-termination */ - t1 = g_malloc(len + 3); - g_sprintf(t1, "%c ", type); - g_memmove(t1 + 2, str, len); - t1[len + 2] = '\0'; + escaped_str = g_malloc(escaped + 1); + escaped_str[0] = type; + escaped_str[1] = ' '; + escaped_str[2] = '\0'; + escaped_str[escaped] = '\0'; - t2 = g_strescape(t1, "\""); - chat->debugf(t2, chat->debug_func_user_data); - g_free(t1); - g_free(t2); + for (escaped = 2, i = 0; i < len; i++) { + char c = str[i]; + + switch (c) { + case '\r': + escaped_str[escaped++] = '\\'; + escaped_str[escaped++] = 'r'; + break; + case '\t': + escaped_str[escaped++] = '\\'; + escaped_str[escaped++] = 't'; + break; + case '\n': + escaped_str[escaped++] = '\\'; + escaped_str[escaped++] = 'n'; + break; + case 26: + strncpy(&escaped_str[escaped], ctrlz, ctrlz_size); + escaped += ctrlz_size; + break; + case 25: + strncpy(&escaped_str[escaped], esc, esc_size); + escaped += esc_size; + break; + default: + if (isprint(c)) + escaped_str[escaped++] = c; + else { + escaped_str[escaped++] = '\\'; + escaped_str[escaped++] = '0' + ((c >> 6) & 07); + escaped_str[escaped++] = '0' + ((c >> 3) & 07); + escaped_str[escaped++] = '0' + (c & 07); + } + } + } + + chat->debugf(escaped_str, chat->debug_data); + g_free(escaped_str); } static gboolean received_data(GIOChannel *channel, GIOCondition cond, @@ -646,7 +693,7 @@ static gboolean received_data(GIOChannel *channel, GIOCondition cond, buf = ring_buffer_write_ptr(chat->buf); err = g_io_channel_read(channel, (char *) buf, toread, &rbytes); - g_at_chat_debug_log(chat, TRUE, buf, rbytes); + debug_chat(chat, TRUE, (char *)buf, rbytes); total_read += rbytes; @@ -773,7 +820,7 @@ static gboolean can_write_data(GIOChannel *channel, GIOCondition cond, return FALSE; } - g_at_chat_debug_log(chat, FALSE, cmd->cmd + chat->cmd_bytes_written, + debug_chat(chat, FALSE, cmd->cmd + chat->cmd_bytes_written, bytes_written); chat->cmd_bytes_written += bytes_written; @@ -964,14 +1011,14 @@ gboolean g_at_chat_set_disconnect_function(GAtChat *chat, return TRUE; } -gboolean g_at_chat_set_debugging(GAtChat *chat, GAtDebugFunc func, - gpointer user_data) +gboolean g_at_chat_set_debug(GAtChat *chat, GAtDebugFunc func, gpointer user) { if (chat == NULL) return FALSE; chat->debugf = func; - chat->debug_func_user_data = user_data; + chat->debug_data = user; + return TRUE; } diff --git a/gatchat/gatchat.h b/gatchat/gatchat.h index 9bfcab1d..5822f1b2 100644 --- a/gatchat/gatchat.h +++ b/gatchat/gatchat.h @@ -57,8 +57,12 @@ gboolean g_at_chat_shutdown(GAtChat *chat); gboolean g_at_chat_set_disconnect_function(GAtChat *chat, GAtDisconnectFunc disconnect, gpointer user_data); -gboolean g_at_chat_set_debugging(GAtChat *chat, GAtDebugFunc func, - gpointer user_data); +/*! + * If the function is not NULL, then on every read/write from the GIOChannel + * provided to GAtChat the logging function will be called with the + * input/output string and user data + */ +gboolean g_at_chat_set_debug(GAtChat *chat, GAtDebugFunc func, gpointer user); /*! * Queue an AT command for execution. The command contents are given