int default_handle_key(ui_t *ui, int key) { int action = -1; // Check actions for this key while ((action = key_find_action(key, action)) != ERR) { // Check if we handle this action switch (action) { case ACTION_RESIZE_SCREEN: ui_resize_panel(ui); break; case ACTION_TOGGLE_SYNTAX: setting_toggle(SETTING_SYNTAX); break; case ACTION_TOGGLE_HINT: setting_toggle(SETTING_ALTKEY_HINT); break; case ACTION_CYCLE_COLOR: setting_toggle(SETTING_COLORMODE); break; case ACTION_SHOW_HOSTNAMES: setting_toggle(SETTING_DISPLAY_HOST); break; case ACTION_SHOW_ALIAS: setting_toggle(SETTING_DISPLAY_ALIAS); break; case ACTION_SHOW_SETTINGS: ui_create_panel(PANEL_SETTINGS); break; case ACTION_TOGGLE_PAUSE: // Pause/Resume capture capture_set_paused(!capture_is_paused()); break; case ACTION_SHOW_HELP: ui_help(ui); break; case ACTION_PREV_SCREEN: ui_destroy(ui); break; default: // Parse next action continue; } // Default handler has handled the key break; } // Return this is a valid handled key return (action == ERR) ? key : 0; }
/** * @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; }
int call_raw_handle_key(PANEL *panel, int key) { call_raw_info_t *info; ui_t *next_panel; int rnpag_steps = setting_get_intvalue(SETTING_CR_SCROLLSTEP); int action = -1; // Sanity check, this should not happen if (!(info = call_raw_info(panel))) return -1; // Check actions for this key while ((action = key_find_action(key, action)) != ERR) { // Check if we handle this action switch (action) { case ACTION_DOWN: info->scroll++; break; case ACTION_UP: info->scroll--; break; case ACTION_HNPAGE: rnpag_steps = rnpag_steps / 2; /* no break */ case ACTION_NPAGE: // Next page => N key down strokes info->scroll += rnpag_steps; break; case ACTION_HPPAGE: rnpag_steps = rnpag_steps / 2; /* no break */ case ACTION_PPAGE: // Prev page => N key up strokes info->scroll -= rnpag_steps; break; case ACTION_SHOW_HOSTNAMES: // Tooggle Host/Address display setting_toggle(SETTING_DISPLAY_HOST); // Force refresh panel if (info->group) { call_raw_set_group(info->group); } else { call_raw_set_msg(info->msg); } break; case ACTION_SAVE: if (info->group) { // KEY_S, Display save panel next_panel = ui_create_panel(PANEL_SAVE); save_set_group(ui_get_panel(next_panel), info->group); } break; case ACTION_TOGGLE_SYNTAX: case ACTION_CYCLE_COLOR: // Handle colors using default handler default_handle_key(ui_find_by_panel(panel), key); // Create a new pad (forces messages draw) delwin(info->pad); info->pad = newpad(500, COLS); info->last = NULL; // Force refresh panel if (info->group) { call_raw_set_group(info->group); } else { call_raw_set_msg(info->msg); } break; default: // Parse next action continue; } // This panel has handled the key successfully break; } if (info->scroll < 0 || info->padline < LINES) { info->scroll = 0; // Disable scrolling if there's nothing to scroll } else { if (info->scroll + LINES / 2 > info->padline) info->scroll = info->padline - LINES / 2; } // Return if this panel has handled or not the key return (action == ERR) ? key : 0; }
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; }