void capture_packet_time_sorter(vector_t *vector, void *item) { capture_packet_t *prev, *cur; int count = vector_count(vector); int i; // Get current item cur = (capture_packet_t *) item; prev = vector_item(vector, count - 2); // Check if the item is already sorted if (prev && timeval_is_older(cur->header->ts, prev->header->ts)) { return; } for (i = count - 2 ; i >= 0; i--) { // Get previous packet prev = vector_item(vector, i); // Check if the item is already in a sorted position if (timeval_is_older(cur->header->ts, prev->header->ts)) { vector_insert(vector, item, i + 1); return; } } // Put this item at the begining of the vector vector_insert(vector, item, 0); }
void sip_list_sorter(vector_t *vector, void *item) { sip_call_t *prev, *cur = (sip_call_t *)item; int count = vector_count(vector); int i; // First item is alway sorted if (vector_count(vector) == 1) return; prev = vector_item(vector, vector_count(vector) - 2); // Check if the item is already sorted if (call_attr_compare(cur, prev, calls.sort.by) == 0) { return; } for (i = count - 2 ; i >= 0; i--) { // Get previous item prev = vector_item(vector, i); // Check if the item is already in a sorted position int cmp = call_attr_compare(cur, prev, calls.sort.by); if ((calls.sort.asc && cmp > 0) || (!calls.sort.asc && cmp < 0)) { vector_insert(vector, item, i + 1); return; } } // Put this item at the begining of the vector vector_insert(vector, item, 0); }
rtp_stream_t * call_group_get_next_stream(sip_call_group_t *group, rtp_stream_t *stream) { rtp_stream_t *next = NULL; rtp_stream_t *cand; sip_call_t *call; vector_iter_t streams; int i; for (i = 0; i < vector_count(group->calls); i++) { call = vector_item(group->calls, i); streams = vector_iterator(call->streams); while ( (cand = vector_iterator_next(&streams))) { if (!stream_get_count(cand)) continue; // candidate must be between msg and next if (stream_is_older(cand, stream) && (!next || stream_is_older(next, cand))) { next = cand; } } } return next; }
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); }
void capture_packet_time_sorter(vector_t *vector, void *item) { struct timeval curts, prevts; int count = vector_count(vector); int i; // TODO Implement multiframe packets curts = packet_time(item); prevts = packet_time(vector_last(vector)); // Check if the item is already sorted if (timeval_is_older(curts, prevts)) { return; } for (i = count - 2 ; i >= 0; i--) { // Get previous packet prevts = packet_time(vector_item(vector, i)); // Check if the item is already in a sorted position if (timeval_is_older(curts, prevts)) { vector_insert(vector, item, i + 1); return; } } // Put this item at the begining of the vector vector_insert(vector, item, 0); }
char* xyzsh_job_title(int n) { if(n < vector_count(gJobs) && n >= 0) { sObject* job = vector_item(gJobs, n); return SJOB(job).mName; } else { return NULL; } }
int call_group_msg_count(sip_call_group_t *group) { sip_call_t *call; vector_iter_t msgs; int msgcnt = 0, i; for (i = 0; i < vector_count(group->calls); i++) { call = vector_item(group->calls, i); msgs = vector_iterator(call->msgs); if (group->sdp_only) { vector_iterator_set_filter(&msgs, msg_has_sdp); } msgcnt += vector_iterator_count(&msgs); } return msgcnt; }
void * vector_iterator_prev(vector_iter_t *it) { void *item; if (it->current == -1) return NULL; while ((item = vector_item(it->vector, --it->current))) { if (it->filter) { if (it->filter(item)) { return item; } } else { return item; } } return NULL; }
void * vector_iterator_next(vector_iter_t *it) { void *item; if (!it || it->current >= vector_count(it->vector)) return NULL; while ((item = vector_item(it->vector, ++it->current))) { if (it->filter) { if (it->filter(item)) { return item; } } else { return item; } } return NULL; }
sip_call_t * call_group_get_next(sip_call_group_t *group, sip_call_t *call) { sip_msg_t *next, *first; sip_call_t *c; int i; if (!group) return NULL; // Get call of the first message in group if (!call) { if ((next = call_group_get_next_msg(group, NULL))) { return next->call; } return NULL; } // Initialize candidate next = NULL; // Get the call with the next chronological message for (i = 0; i < vector_count(group->calls); i++) { if ((c = vector_item(group->calls, i)) == call) continue; // Get first message first = vector_first(c->msgs); // Is first message of this call older? if (msg_is_older(first, vector_first(call->msgs)) && (!next || !msg_is_older(first, next))) { next = first; break; } } return (next) ? next->call : NULL; }
/** * @brief Main function logic * * Parse command line options and start running threads */ int main(int argc, char* argv[]) { int opt, idx, limit, only_calls, no_incomplete, i; const char *device, *outfile; char bpf[512]; const char *keyfile; const char *match_expr; int match_insensitive = 0, match_invert = 0; int no_interface = 0, quiet = 0, rtp_capture = 0; vector_t *infiles = vector_create(0, 1); // Program otptions static struct option long_options[] = { { "help", no_argument, 0, 'h' }, { "version", no_argument, 0, 'V' }, { "device", required_argument, 0, 'd' }, { "input", required_argument, 0, 'I' }, { "output", required_argument, 0, 'O' }, #if defined(WITH_GNUTLS) || defined(WITH_OPENSSL) { "keyfile", required_argument, 0, 'k' }, #endif { "calls", no_argument, 0, 'c' }, { "rtp", no_argument, 0, 'r' }, { "limit", no_argument, 0, 'l' }, { "icase", no_argument, 0, 'i' }, { "invert", no_argument, 0, 'v' }, { "no-interface", no_argument, 0, 'N' }, { "dump-config", no_argument, 0, 'D' }, #ifdef USE_EEP { "eep-listen", required_argument, 0, 'L' }, { "eep-send", required_argument, 0, 'H' }, #endif { "quiet", no_argument, 0, 'q' }, }; // Initialize configuration options init_options(); // Get initial values for configurable arguments device = setting_get_value(SETTING_CAPTURE_DEVICE); outfile = setting_get_value(SETTING_CAPTURE_OUTFILE); keyfile = setting_get_value(SETTING_CAPTURE_KEYFILE); limit = setting_get_intvalue(SETTING_CAPTURE_LIMIT); only_calls = setting_enabled(SETTING_SIP_CALLS); no_incomplete = setting_enabled(SETTING_SIP_NOINCOMPLETE); rtp_capture = setting_enabled(SETTING_CAPTURE_RTP); // Parse command line arguments opterr = 0; char *options = "hVd:I:O:pqtW:k:crl:ivNqDL:H:"; while ((opt = getopt_long(argc, argv, options, long_options, &idx)) != -1) { switch (opt) { case 'h': usage(); return 0; case 'V': version(); return 0; case 'd': device = optarg; break; case 'I': vector_append(infiles, optarg); break; case 'O': outfile = optarg; break; case 'l': if(!(limit = atoi(optarg))) { fprintf(stderr, "Invalid limit value.\n"); return 0; } break; #if defined(WITH_GNUTLS) || defined(WITH_OPENSSL) case 'k': keyfile = optarg; break; #endif case 'c': only_calls = 1; setting_set_value(SETTING_SIP_CALLS, SETTING_ON); break; case 'r': rtp_capture = 1; setting_set_value(SETTING_CAPTURE_RTP, SETTING_ON); break; case 'i': match_insensitive++; break; case 'v': match_invert++; break; case 'N': no_interface = 1; setting_set_value(SETTING_CAPTURE_STORAGE, "none"); break; case 'q': quiet = 1; break; case 'D': key_bindings_dump(); settings_dump(); return 0; // Dark options for dummy ones case 'p': case 't': case 'W': break; #ifdef USE_EEP case 'L': capture_eep_set_server_url(optarg); break; case 'H': capture_eep_set_client_url(optarg); break; #endif case '?': if (strchr(options, optopt)) { fprintf(stderr, "-%c option requires an argument.\n", optopt); } else if (isprint(optopt)) { fprintf(stderr, "Unknown option -%c.\n", optopt); } else { fprintf(stderr, "Unknown option character '\\x%x'.\n", optopt); } return 1; default: break; } } #if defined(WITH_GNUTLS) || defined(WITH_OPENSSL) // Set capture decrypt key file capture_set_keyfile(keyfile); // Check if we have a keyfile and is valid if (keyfile && !tls_check_keyfile(keyfile)) { fprintf(stderr, "%s does not contain a valid RSA private key.\n", keyfile); return 1; } #endif // Check if given argument is a file if (argc == 2 && (access(argv[1], F_OK) == 0)) { // Old legacy option to open pcaps without other arguments printf("%s seems to be a file: You forgot -I flag?\n", argv[1]); return 0; } // Initialize SIP Messages Storage sip_init(limit, only_calls, no_incomplete); // Set capture options capture_init(limit, rtp_capture); #ifdef USE_EEP // Initialize EEP if enabled capture_eep_init(); #endif // If we have an input file, load it if (vector_count(infiles)) { for (i = 0; i < vector_count(infiles); i++) { // Try to load file if (capture_offline(vector_item(infiles, i), outfile) != 0) return 1; } } else { // Check if all capture data is valid if (capture_online(device, outfile) != 0) return 1; } // Remove Input files vector vector_destroy(infiles); // More arguments pending! if (argv[optind]) { // Assume first pending argument is match expression match_expr = argv[optind++]; // Try to build the bpf filter string with the rest memset(bpf, 0, sizeof(bpf)); for (i = optind; i < argc; i++) sprintf(bpf + strlen(bpf), "%s ", argv[i]); // Check if this BPF filter is valid if (capture_set_bpf_filter(bpf) != 0) { // BPF Filter invalid, check incluiding match_expr match_expr = 0; // There is no need to parse all payload at this point // Build the bpf filter string memset(bpf, 0, sizeof(bpf)); for (i = optind - 1; i < argc; i++) sprintf(bpf + strlen(bpf), "%s ", argv[i]); // Check bpf filter is valid again if (capture_set_bpf_filter(bpf) != 0) { fprintf(stderr, "Couldn't install filter %s: %s\n", bpf, capture_last_error()); return 1; } } // Set the capture filter if (match_expr) if (sip_set_match_expression(match_expr, match_insensitive, match_invert)) { fprintf(stderr, "Unable to parse expression %s\n", match_expr); return 1; } } // Start a capture thread if (capture_launch_thread() != 0) { ncurses_deinit(); fprintf(stderr, "Failed to launch capture thread.\n"); return 1; } if (!no_interface) { // Initialize interface ncurses_init(); // This is a blocking call. // Create the first panel and wait for user input ui_create_panel(PANEL_CALL_LIST); wait_for_input(); } else { setbuf(stdout, NULL); while(capture_get_status() != CAPTURE_OFFLINE) { if (!quiet) printf("\rDialog count: %d", sip_calls_count()); usleep(500 * 1000); } if (!quiet) printf("\rDialog count: %d\n", sip_calls_count()); } // Capture deinit capture_deinit(); // Deinitialize interface ncurses_deinit(); // Deinitialize configuration options deinit_options(); // Deallocate sip stored messages sip_deinit(); // Leaving! return 0; }
sip_call_t * sip_find_by_index(int index) { return vector_item(calls.list, index); }
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 * vector_last(vector_t *vector) { return vector_item(vector, vector_count(vector) - 1); }
void * vector_first(vector_t *vector) { return vector_item(vector, 0); }