diff --git a/src/sip.c b/src/sip.c index cf40cf9..a5aea31 100644 --- a/src/sip.c +++ b/src/sip.c @@ -127,6 +127,29 @@ sip_msg_create(const char *header, const char *payload) return msg; } +void +sip_msg_destroy(sip_msg_t *msg) +{ + sip_msg_t *prev = NULL; + + if (!msg) return; + + // If the message belongs to a call, remove it from + // its message list + if (msg->call) { + if ((prev = call_get_prev_msg(msg->call, msg))) { + prev->next = msg->next; + } else { + msg->call->msgs = msg->next; + } + } + + // Free all memory + free(msg->headerptr); + free(msg->payload); + free(msg); +} + sip_call_t * sip_call_create(char *callid) { @@ -162,6 +185,24 @@ sip_call_create(char *callid) return call; } +void +sip_call_destroy(sip_call_t *call) +{ + sip_call_t *prev = NULL; + sip_msg_t *msg = NULL; + + // No call to destroy + if (!call) return; + + // Get previous message + //for (msg = call->msgs; msg; msg = msg->next) + // sip_msg_destroy(msg); + + // Free it! + free(call); +} + + char * sip_get_callid(const char* payload) { @@ -216,14 +257,16 @@ sip_load_message(const char *header, const char *payload) && strncasecmp(method, "REGISTER", 8) && strncasecmp(method, "SUBSCRIBE", 9) && strncasecmp(method, "OPTIONS", 7) && strncasecmp(method, "PUBLISH", 7) && strncasecmp(method, "MESSAGE", 7) && strncasecmp(method, "NOTIFY", 6)){ - //@todo sip_msg_destroy(); + // Deallocate message memory + sip_msg_destroy(msg); return NULL; } } // Create the call if not found if (!(call = sip_call_create(callid))) { - //@todo sip_msg_destroy(); + // Deallocate message memory + sip_msg_destroy(msg); return NULL; } } @@ -242,11 +285,13 @@ int sip_calls_count() { int callcnt = 0; + pthread_mutex_lock(&calls_lock); sip_call_t *call = calls; while (call) { if (!sip_check_call_ignore(call)) callcnt++; call = call->next; } + pthread_mutex_unlock(&calls_lock); return callcnt; } @@ -256,6 +301,7 @@ sip_check_call_ignore(sip_call_t *call) int i; char filter_option[80]; const char *filter; + // Check if an ignore option exists for (i = 0; i < sizeof(attrs) / sizeof(*attrs); i++) { if (is_ignored_value(attrs[i].name, call_get_attribute(call, attrs[i].id))) { @@ -312,7 +358,6 @@ const char * sip_attr_get_description(enum sip_attr_id id) { sip_attr_hdr_t *header; - if ((header = sip_attr_get_header(id))) { return header->desc; } @@ -323,7 +368,6 @@ const char * sip_attr_get_name(enum sip_attr_id id) { sip_attr_hdr_t *header; - if ((header = sip_attr_get_header(id))) { return header->name; } @@ -383,6 +427,7 @@ call_add_message(sip_call_t *call, sip_msg_t *msg) pthread_mutex_lock(&call->lock); // Set the message owner msg->call = call; + // XXX Put this msg at the end of the msg list // Order is important!!! if (!call->msgs) { @@ -399,16 +444,18 @@ sip_call_t * call_find_by_callid(const char *callid) { const char *cur_callid; + pthread_mutex_lock(&calls_lock); sip_call_t *cur = calls; - // XXX LOCKING while (cur) { cur_callid = call_get_attribute(cur, SIP_ATTR_CALLID); if (cur_callid && !strcmp(cur_callid, callid)) { + pthread_mutex_unlock(&calls_lock); return cur; } cur = cur->next; } + pthread_mutex_unlock(&calls_lock); return NULL; } @@ -416,15 +463,19 @@ sip_call_t * call_find_by_xcallid(const char *xcallid) { const char *cur_xcallid; + + pthread_mutex_lock(&calls_lock); sip_call_t *cur = calls; while (cur) { cur_xcallid = call_get_attribute(cur, SIP_ATTR_XCALLID); if (cur_xcallid && !strcmp(cur_xcallid, xcallid)) { + pthread_mutex_unlock(&calls_lock); return cur; } cur = cur->next; } + pthread_mutex_unlock(&calls_lock); return NULL; } @@ -609,7 +660,6 @@ msg_parse_payload(sip_msg_t *msg, const char *payload) char * pch; char value[256]; char rest[256]; - int irest; // Sanity check if (!msg || !payload) return 1; @@ -704,3 +754,19 @@ msg_is_retrans(sip_msg_t *msg) { // All check passed, this package is equal to its previous return 1; } + +void +sip_calls_clear() +{ + sip_call_t *call = NULL; + pthread_mutex_lock(&calls_lock); + + // Remove first call until no first call exists + for (call = calls; call; call = call->next) + sip_call_destroy(call); + + // Initialize calls list header + calls = NULL; + + pthread_mutex_unlock(&calls_lock); +} diff --git a/src/sip.h b/src/sip.h index 9e09f00..642fef6 100644 --- a/src/sip.h +++ b/src/sip.h @@ -189,6 +189,18 @@ struct sip_call extern sip_msg_t * sip_msg_create(const char *header, const char *payload); +/** + * @brief Destroy a SIP message and free its memory + * + * Deallocate memory of an existing SIP Message. + * This function will remove the message from the call and the + * passed pointer will be NULL. + * + * @param msg SIP message to be deleted + */ +extern void +sip_msg_destroy(sip_msg_t *msg); + /** * @brief Create a new call with the given callid (Minimum required data) * @@ -201,6 +213,18 @@ sip_msg_create(const char *header, const char *payload); extern sip_call_t * sip_call_create(char *callid); +/** + * @brief Free all related memory from a call and remove from call list + * + * Deallocate memory of an existing SIP Call. + * This will also remove all messages, calling sip_msg_destroy for each + * one. + * + * @param call Call to be destroyed + */ +extern void +sip_call_destroy(sip_call_t *call); + /** * @brief Parses Call-ID header of a SIP message payload * @@ -529,4 +553,14 @@ msg_get_attribute(sip_msg_t *msg, enum sip_attr_id id); extern int msg_is_retrans(sip_msg_t *msg); +/** + * @brief Remove al calls + * + * This funtion will clear the call list invoking the destroy + * function for each one. + */ +void +sip_calls_clear(); + + #endif diff --git a/src/ui_call_flow.c b/src/ui_call_flow.c index 82759f9..aaf7813 100644 --- a/src/ui_call_flow.c +++ b/src/ui_call_flow.c @@ -327,7 +327,8 @@ call_flow_draw_message(PANEL *panel, sip_msg_t *msg, int cline) if ((prev = call_get_prev_msg(msg->call, msg))) { if (strcmp(msg_get_attribute(msg, SIP_ATTR_CSEQ), msg_get_attribute(prev, SIP_ATTR_CSEQ))) { - info->group->color = msg->call->color = (info->group->color++ % 7) + 1; + int color = info->group->color + 1; + info->group->color = msg->call->color = (color % 7) + 1; } } msg->color = msg->call->color; diff --git a/src/ui_call_flow.h b/src/ui_call_flow.h index 7b01da9..e761403 100644 --- a/src/ui_call_flow.h +++ b/src/ui_call_flow.h @@ -32,6 +32,7 @@ #ifndef __UI_CALL_FLOW_EX_H #define __UI_CALL_FLOW_EX_H #include "ui_manager.h" +#include "group.h" //! Sorter declaration of struct call_flow_info typedef struct call_flow_info call_flow_info_t; diff --git a/src/ui_call_list.c b/src/ui_call_list.c index 21e02a6..74b98d8 100644 --- a/src/ui_call_list.c +++ b/src/ui_call_list.c @@ -335,6 +335,12 @@ call_list_handle_key(PANEL *panel, int key) wait_for_input(next_panel); } break; + case KEY_F(5): + // Remove all stored calls + sip_calls_clear(); + // Clear List + call_list_clear(panel); + break; case ' ': if (!info->cur_call) return -1; if (call_group_exists(info->group, info->cur_call)) { @@ -469,7 +475,7 @@ call_list_exit_confirm(PANEL *panel) case KEY_LEFT: exit = 1; break; - case 9: + case 9: exit = (exit)?0:1; break; case 10: @@ -502,8 +508,26 @@ call_list_filter_update(PANEL *panel) { WINDOW *win = panel_window(panel); - int height, width, i, startline = 8; + // Clear list + call_list_clear(panel); + + // Get Window dimensions + int height, width; + getmaxyx(win, height, width); + + // Print filter info + mvwprintw(win, 4, 2, "%*s", width - 4, ""); + if (is_option_enabled("filter.enable")) + mvwprintw(win, 4, 2, "%s", "Display filter: TODO"); +} + +void +call_list_clear(PANEL *panel) +{ + WINDOW *win = panel_window(panel); + + int height, width, i, startline = 8; // Get panel info call_list_info_t *info = (call_list_info_t*) panel_userptr(panel); if (!info) return; @@ -520,9 +544,5 @@ call_list_filter_update(PANEL *panel) for (i=0; i < info->linescnt; i++) { mvwprintw(win, startline++, 5, "%*s", width - 6, ""); } - - // Print filter info - mvwprintw(win, 4, 2, "%*s", width - 4, ""); - if (is_option_enabled("filter.enable")) - mvwprintw(win, 4, 2, "%s", "Display filter: TODO"); } + diff --git a/src/ui_call_list.h b/src/ui_call_list.h index 1bd8d6c..509650f 100644 --- a/src/ui_call_list.h +++ b/src/ui_call_list.h @@ -196,4 +196,14 @@ call_list_add_column(PANEL *panel, enum sip_attr_id id, const char* attr, const extern void call_list_filter_update(PANEL *panel); + +/** + * @brief Remove all calls from the list and calls storage + * + * This funtion will clear all call lines in the list + * @param panel Call list panel pointer + */ +extern void +call_list_clear(PANEL *panel); + #endif diff --git a/src/ui_call_raw.c b/src/ui_call_raw.c index 18acd2d..bea0e50 100644 --- a/src/ui_call_raw.c +++ b/src/ui_call_raw.c @@ -40,9 +40,7 @@ PANEL * call_raw_create() { PANEL *panel; - WINDOW *win; call_raw_info_t *info; - int height, width; // Create a new panel to fill all the screen panel = new_panel(newwin(LINES, COLS, 0, 0)); @@ -137,7 +135,8 @@ call_raw_print_msg(PANEL *panel, sip_msg_t *msg) if ((prev = call_get_prev_msg(msg->call, msg))) { if (strcmp(msg_get_attribute(msg, SIP_ATTR_CSEQ), msg_get_attribute(prev, SIP_ATTR_CSEQ))) { - info->group->color = msg->call->color = (info->group->color++ % 7) + 1; + int color = info->group->color + 1; + info->group->color = msg->call->color = (color % 7) + 1; } } msg->color = msg->call->color; @@ -177,7 +176,6 @@ call_raw_print_msg(PANEL *panel, sip_msg_t *msg) int call_raw_handle_key(PANEL *panel, int key) { - int i, rnpag_steps = 10; call_raw_info_t *info = (call_raw_info_t*) panel_userptr(panel); ui_t *next_panel;