sip_msg_t * call_group_get_next_msg(sip_call_group_t *group, sip_msg_t *msg) { sip_msg_t *next = NULL; sip_msg_t *cand; vector_iter_t msgs; sip_call_t *call; int i; for (i = 0; i < vector_count(group->calls); i++) { call = vector_item(group->calls, i); msgs = vector_iterator(call->msgs); if (msg && call == msg_get_call(msg)) vector_iterator_set_current(&msgs, msg->index); if (group->sdp_only) vector_iterator_set_filter(&msgs, msg_has_sdp); cand = NULL; while ((cand = vector_iterator_next(&msgs))) { // candidate must be between msg and next if (msg_is_older(cand, msg) && (!next || !msg_is_older(cand, next))) { next = cand; break; } } } return sip_parse_msg(next); }
int call_msg_is_retrans(sip_msg_t *msg) { sip_msg_t *prev = NULL; vector_iter_t it; // Get previous message in call with same origin and destination it = vector_iterator(msg->call->msgs); vector_iterator_set_current(&it, vector_index(msg->call->msgs, msg)); while ((prev = vector_iterator_prev(&it))) { if (!strcmp(SRC(prev), SRC(msg)) && !strcmp(DST(prev), DST(msg))) break; } return (prev && !strcasecmp(msg_get_payload(msg), msg_get_payload(prev))); }
int call_msg_is_retrans(sip_msg_t *msg) { sip_msg_t *prev = NULL; vector_iter_t it; // Get previous message in call with same origin and destination it = vector_iterator(msg->call->msgs); vector_iterator_set_current(&it, vector_index(msg->call->msgs, msg)); while ((prev = vector_iterator_prev(&it))) { if (addressport_equals(prev->packet->src, msg->packet->src) && addressport_equals(prev->packet->dst, msg->packet->dst)) break; } return (prev && !strcasecmp(msg_get_payload(msg), msg_get_payload(prev))); }
int vector_iterator_count(vector_iter_t *it) { int count = 0; int pos = it->current; vector_iterator_reset(it); if (!it->filter) { count = vector_count(it->vector); } else { while (vector_iterator_next(it)) { count++; } } vector_iterator_set_current(it, pos); return count; }
int call_list_handle_key(PANEL *panel, int key) { int i, height, width, rnpag_steps = setting_get_intvalue(SETTING_CL_SCROLLSTEP); call_list_info_t *info; ui_t *next_panel; sip_call_group_t *group; int action = -1; sip_call_t *call; // Sanity check, this should not happen if (!(info = call_list_info(panel))) return -1; // Handle form key if (info->form_active) return call_list_handle_form_key(panel, key); // Get window of call list panel WINDOW *win = info->list_win; getmaxyx(win, height, width); // Reset iterator position to current call vector_iterator_set_current(&info->calls, info->cur_call); // Check actions for this key while ((action = key_find_action(key, action)) != ERR) { // Check if we handle this action switch (action) { case ACTION_DOWN: // Check if there is a call below us if (!vector_iterator_next(&info->calls)) break; info->cur_call = vector_iterator_current(&info->calls); info->cur_line++; // If we are out of the bottom of the displayed list // refresh it starting in the next call if (info->cur_line > height) { vector_iterator_set_current(&info->calls, info->first_call); vector_iterator_next(&info->calls); info->first_call = vector_iterator_current(&info->calls); info->first_line++; info->cur_line = height; } // Disable Autoscroll info->autoscroll = 0; break; case ACTION_UP: // Check if there is a call above us if (!vector_iterator_prev(&info->calls)) break; info->cur_call = vector_iterator_current(&info->calls); info->cur_line--; // If we are out of the top of the displayed list // refresh it starting in the previous (in fact current) call if (info->cur_line <= 0) { info->first_call = info->cur_call; info->first_line--; info->cur_line = 1; } // Disable Autoscroll info->autoscroll = 0; break; case ACTION_HNPAGE: rnpag_steps = rnpag_steps / 2; /* no break */ case ACTION_NPAGE: // Next page => N key down strokes for (i = 0; i < rnpag_steps; i++) call_list_handle_key(panel, KEY_DOWN); // Disable Autoscroll info->autoscroll = 0; break; case ACTION_HPPAGE: rnpag_steps = rnpag_steps / 2; /* no break */ case ACTION_PPAGE: // Prev page => N key up strokes for (i = 0; i < rnpag_steps; i++) call_list_handle_key(panel, KEY_UP); // Disable Autoscroll info->autoscroll = 0; break; case ACTION_BEGIN: // Initialize structures info->first_call = info->cur_call = -1; info->first_line = info->cur_line = 0; // Disable Autoscroll info->autoscroll = 0; break; case ACTION_END: // Check if there is a call below us while (vector_iterator_next(&info->calls)) { info->cur_call = vector_iterator_current(&info->calls); info->cur_line++; // If we are out of the bottom of the displayed list // refresh it starting in the next call if (info->cur_line > height) { vector_iterator_set_current(&info->calls, info->first_call); vector_iterator_next(&info->calls); info->first_call = vector_iterator_current(&info->calls); info->first_line++; info->cur_line = height; vector_iterator_set_current(&info->calls, info->cur_call); } } break; case ACTION_DISP_FILTER: // Activate Form call_list_form_activate(panel, 1); // Disable Autoscroll info->autoscroll = 0; break; case ACTION_SHOW_FLOW: case ACTION_SHOW_FLOW_EX: case ACTION_SHOW_RAW: // Check we have calls in the list if (info->cur_call == -1) break; // Create a new group of calls group = call_group_clone(info->group); // If not selected call, show current call flow if (call_group_count(info->group) == 0) call_group_add(group, sip_find_by_index(info->cur_call)); // Add xcall to the group if (action == ACTION_SHOW_FLOW_EX) call_group_add(group, call_get_xcall(sip_find_by_index(info->cur_call))); if (action == ACTION_SHOW_RAW) { // Create a Call Flow panel ui_create_panel(PANEL_CALL_RAW); call_raw_set_group(group); } else { // Display current call flow (normal or extended) ui_create_panel(PANEL_CALL_FLOW); call_flow_set_group(group); } break; case ACTION_SHOW_FILTERS: ui_create_panel(PANEL_FILTER); break; case ACTION_SHOW_COLUMNS: ui_create_panel(PANEL_COLUMN_SELECT); break; case ACTION_SHOW_STATS: ui_create_panel(PANEL_STATS); break; case ACTION_SAVE: next_panel = ui_create_panel(PANEL_SAVE); save_set_group(ui_get_panel(next_panel), info->group); break; case ACTION_CLEAR: // Clear group calls vector_clear(info->group->calls); break; case ACTION_CLEAR_CALLS: // Remove all stored calls sip_calls_clear(); // Clear List call_list_clear(panel); break; case ACTION_AUTOSCROLL: info->autoscroll = (info->autoscroll) ? 0 : 1; break; case ACTION_SHOW_SETTINGS: ui_create_panel(PANEL_SETTINGS); break; case ACTION_SELECT: call = vector_item(vector_iterator_vector(&info->calls), info->cur_call); if (call_group_exists(info->group, call)) { call_group_del(info->group, call); } else { call_group_add(info->group, call); } break; case ACTION_PREV_SCREEN: // Handle quit from this screen unless requested if (setting_enabled(SETTING_EXITPROMPT)) { if (dialog_confirm("Confirm exit", "Are you sure you want to quit?", "Yes,No") == 0) { return KEY_ESC; } else { return 0; } } else { return KEY_ESC; } break; default: // Parse next action continue; } // This panel has handled the key successfully break; } // Return if this panel has handled or not the key return (action == ERR) ? key : 0; }
void call_list_draw_list(PANEL *panel) { WINDOW *win; int height, width, cline = 0; struct sip_call *call; int i, collen; char coltext[256]; int colid; int colpos; int color; // Get panel info call_list_info_t *info = call_list_info(panel); // Get window of call list panel win = info->list_win; getmaxyx(win, height, width); // If autoscroll is enabled, select the last dialog if (info->autoscroll) { call_list_handle_key(panel, key_action_key(ACTION_END)); } // If no active call, use the fist one (if exists) if (info->first_call == -1 && vector_iterator_count(&info->calls)) { vector_iterator_reset(&info->calls); call = vector_iterator_next(&info->calls); info->cur_call = info->first_call = vector_index(vector_iterator_vector(&info->calls), call); info->cur_line = info->first_line = 1; } // Clear call list before redrawing werase(win); // Set the iterator position to the first call vector_iterator_set_current(&info->calls, info->first_call - 1 ); // Fill the call list while ((call = vector_iterator_next(&info->calls))) { // Stop if we have reached the bottom of the list if (cline == height) break; // We only print calls with messages (In fact, all call should have msgs) if (!call_msg_count(call)) continue; // Show bold selected rows if (call_group_exists(info->group, call)) wattron(win, A_BOLD | COLOR_PAIR(CP_DEFAULT)); // Highlight active call if (call->index == info->cur_call + 1) { wattron(win, COLOR_PAIR(CP_WHITE_ON_BLUE)); // Reverse colors on monochrome terminals if (!has_colors()) wattron(win, A_REVERSE); } // Set current line background clear_line(win, cline); // Set current line selection box mvwprintw(win, cline, 2, call_group_exists(info->group, call) ? "[*]" : "[ ]"); // Print requested columns colpos = 6; for (i = 0; i < info->columncnt; i++) { // Get current column id colid = info->columns[i].id; // Get current column width collen = info->columns[i].width; // Check if next column fits on window width if (colpos + collen >= width) break; // Initialize column text memset(coltext, 0, sizeof(coltext)); // Get call attribute for current column if (!call_get_attribute(call, colid, coltext)) { colpos += collen + 1; continue; } // Enable attribute color (if not current one) color = 0; if (call->index != info->cur_call + 1 && (color = sip_attr_get_color(colid, coltext)) > 0) wattron(win, color); // Add the column text to the existing columns mvwprintw(win, cline, colpos, "%.*s", collen, coltext); colpos += collen + 1; // Disable attribute color if (color > 0) wattroff(win, color); } cline++; wattroff(win, COLOR_PAIR(CP_DEFAULT)); wattroff(win, COLOR_PAIR(CP_DEF_ON_BLUE)); wattroff(win, A_BOLD | A_REVERSE); } // Draw scrollbar to the right draw_vscrollbar(win, info->first_line, info->dispcallcnt, 1); wnoutrefresh(info->list_win); }
void vector_iterator_reset(vector_iter_t *it) { vector_iterator_set_current(it, -1); }