New panel to change CallList displayed columns

This commit is contained in:
Kaian 2015-02-03 15:11:46 +01:00
parent 667a8cdb1a
commit 7311392e2c
8 changed files with 479 additions and 33 deletions

View File

@ -29,11 +29,6 @@ AC_LANG(C)
#######################################################################
# Check for other REQUIRED libraries
AC_CHECK_LIB([m],[ceil],[],[
AC_MSG_ERROR([ Your glibc version does not support math functions.])
])
AC_CHECK_HEADER([ncurses.h], [], [
AC_MSG_ERROR([ You need to have ncurses development files installed to compile sngrep.])
])
@ -50,6 +45,10 @@ AC_CHECK_LIB([form], [new_form], [], [
AC_MSG_ERROR([ You need to have ncurses forms library installed to compile sngrep.])
])
AC_CHECK_LIB([menu], [new_item], [], [
AC_MSG_ERROR([ You need to have ncurses menu library installed to compile sngrep.])
])
AC_CHECK_LIB([pthread], [pthread_create], [], [
AC_MSG_ERROR([ You need to have libpthread installed to compile sngrep.])
])

View File

@ -1,6 +1,7 @@
bin_PROGRAMS=sngrep
sngrep_SOURCES=capture.c sip.c sip_attr.c main.c option.c group.c
sngrep_SOURCES+=ui_manager.c ui_call_list.c ui_call_flow.c ui_call_raw.c ui_filter.c ui_save_pcap.c ui_save_raw.c ui_msg_diff.c
sngrep_SOURCES+=ui_manager.c ui_call_list.c ui_call_flow.c ui_call_raw.c
sngrep_SOURCES+=ui_filter.c ui_save_pcap.c ui_save_raw.c ui_msg_diff.c ui_column_select.c
if WITH_OPENSSL
sngrep_SOURCES+=capture_tls.c

View File

@ -52,7 +52,7 @@ static sip_attr_hdr_t attrs[] =
{
.id = SIP_ATTR_SRC_HOST,
.name = "srchost",
.desc = "Source",
.desc = "Source Host",
.dwidth = 16, },
{
.id = SIP_ATTR_DST,
@ -62,7 +62,7 @@ static sip_attr_hdr_t attrs[] =
{
.id = SIP_ATTR_DST_HOST,
.name = "dsthost",
.desc = "Destiny",
.desc = "Destiny Host",
.dwidth = 16, },
{
.id = SIP_ATTR_CALLID,
@ -132,7 +132,7 @@ static sip_attr_hdr_t attrs[] =
{
.id = SIP_ATTR_CALLSTATE,
.name = "state",
.desc = "State",
.desc = "Call State",
.dwidth = 10 } };
sip_attr_hdr_t *

View File

@ -42,7 +42,7 @@ call_list_create()
{
PANEL *panel;
WINDOW *win;
int height, width, i, colpos, collen, attrid;
int height, width, i, attrid, collen;
call_list_info_t *info;
char option[80];
const char *field, *title;
@ -104,19 +104,6 @@ call_list_create()
// Draw panel title
mvwprintw(win, 0, 0, "%*s", width, "");
mvwprintw(win, 0, (width - 45) / 2, "sngrep - SIP messages flow viewer");
// Draw columns titles
mvwprintw(win, 3, 0, "%*s", width, "");
for (colpos = 6, i = 0; i < info->columncnt; i++) {
// Get current column width
collen = info->columns[i].width;
// Check if the column will fit in the remaining space of the screen
if (colpos + collen >= width)
break;
mvwprintw(win, 3, colpos, "%.*s", collen, sip_attr_get_description(info->columns[i].id));
colpos += collen + 1;
}
wattroff(win, COLOR_PAIR(CP_DEF_ON_CYAN));
// Set defualt filter text if configured
@ -181,9 +168,11 @@ call_list_draw_footer(PANEL *panel)
"F6",
"Raw",
"F7",
"Filter" };
"Filter",
"F10",
"Columns" };
draw_keybindings(panel, keybindings, 20);
draw_keybindings(panel, keybindings, 22);
}
int
@ -196,10 +185,11 @@ call_list_redraw_required(PANEL *panel, sip_msg_t *msg)
int
call_list_draw(PANEL *panel)
{
int height, width, cline = 0;
int height, width, cline = 0, i, colpos, collen;
struct sip_call *call;
int callcnt;
const char *ouraddr;
const char *coldesc;
char linetext[256];
// Get panel info
@ -207,14 +197,35 @@ call_list_draw(PANEL *panel)
if (!info)
return -1;
// Get window of call list panel
WINDOW *win = panel_window(panel);
getmaxyx(win, height, width);
// Update current mode information
if (!info->form_active) {
mvwprintw(panel_window(panel), 1, 2, "Current Mode: %s %9s", get_option_value("sngrep.mode"),
mvwprintw(win, 1, 2, "Current Mode: %s %9s", get_option_value("sngrep.mode"),
(is_option_enabled("sip.capture") ? "" : "(Stopped)"));
}
// Draw columns titles
wattron(win, COLOR_PAIR(CP_DEF_ON_CYAN));
mvwprintw(win, 3, 0, "%*s", width, "");
for (colpos = 6, i = 0; i < info->columncnt; i++) {
// Get current column width
collen = info->columns[i].width;
// Get current column title
coldesc = sip_attr_get_description(info->columns[i].id);
// Check if the column will fit in the remaining space of the screen
if (colpos + strlen(coldesc) >= width)
break;
mvwprintw(win, 3, colpos, "%.*s", collen, coldesc);
colpos += collen + 1;
}
wattroff(win, COLOR_PAIR(CP_DEF_ON_CYAN));
// Get window of call list panel
WINDOW *win = info->list_win;
win = info->list_win;
getmaxyx(win, height, width);
// Get available calls counter (we'll use it here a couple of times)
@ -346,13 +357,20 @@ call_list_line_text(PANEL *panel, sip_call_t *call, char *text)
// Check if next column fits on window width
if (strlen(text) + collen >= width)
collen -= width - strlen(text);
// If no space left on the screen stop processing columns
if (collen <= 0)
break;
// Initialize column text
memset(coltext, 0, sizeof(coltext));
// Get call attribute for current column
if ((call_attr = call_get_attribute(call, colid))) {
sprintf(coltext, "%.*s", collen, call_attr);
sprintf(text + strlen(text), "%-*s ", collen, coltext);
}
// Add the column text to the existing columns
sprintf(text + strlen(text), "%-*s ", collen, coltext);
}
return text;
@ -479,6 +497,14 @@ call_list_handle_key(PANEL *panel, int key)
wait_for_input(next_panel);
call_list_filter_update(panel);
break;
case 't':
case 'T':
case KEY_F(10):
// Display column selection panel
next_panel = ui_create(ui_find_by_type(COLUMN_SELECT_PANEL));
wait_for_input(next_panel);
call_list_filter_update(panel);
break;
case 's':
case 'S':
case KEY_F(2):
@ -588,7 +614,7 @@ call_list_help(PANEL *panel)
int height, width;
// Create a new panel and show centered
height = 26;
height = 27;
width = 65;
help_win = newwin(height, width, (LINES - height) / 2, (COLS - width) / 2);
help_panel = new_panel(help_win);
@ -634,7 +660,8 @@ call_list_help(PANEL *panel)
mvwprintw(help_win, 19, 2, "F7/F Show filter options");
mvwprintw(help_win, 20, 2, "F8/c Turn on/off window colours");
mvwprintw(help_win, 21, 2, "F9/l Turn on/off resolved addresses");
mvwprintw(help_win, 22, 2, "i/I Set display filter to invite");
mvwprintw(help_win, 22, 2, "F10/t Select displayed columns");
mvwprintw(help_win, 23, 2, "i/I Set display filter to invite");
// Press any key to close
wgetch(help_win);

271
src/ui_column_select.c Normal file
View File

@ -0,0 +1,271 @@
/**************************************************************************
**
** sngrep - SIP Messages flow viewer
**
** Copyright (C) 2014,2015 Ivan Alonso (Kaian)
** Copyright (C) 2014,2015 Irontec SL. All rights reserved.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
**
****************************************************************************/
/**
* @file ui_column_select.c
* @author Ivan Alonso [aka Kaian] <kaian@irontec.com>
*
* @brief Source of functions defined in ui_column_select.h
*
*/
#include <string.h>
#include <stdlib.h>
#include "ui_manager.h"
#include "ui_call_list.h"
#include "ui_column_select.h"
PANEL *
column_select_create()
{
int attr_id, column;
PANEL *panel;
WINDOW *win;
MENU *menu;
int height, width;
column_select_info_t *info;
// Calculate window dimensions
height = 20;
width = 60;
// Cerate a new indow for the panel and form
win = newwin(height, width, (LINES - height) / 2, (COLS - width) / 2);
// Create a new panel
panel = new_panel(win);
// Initialize Filter panel specific data
info = malloc(sizeof(column_select_info_t));
memset(info, 0, sizeof(column_select_info_t));
// Store it into panel userptr
set_panel_userptr(panel, (void*) info);
// Create a subwin for the menu area
info->menu_win = derwin(win, 10, width - 2, 7, 0);
// Initialize one field for each attribute
for (attr_id = 0; attr_id < SIP_ATTR_SENTINEL; attr_id++) {
// Create a new field for this column
info->items[attr_id] = new_item("[ ]", sip_attr_get_description(attr_id));
set_item_userptr(info->items[attr_id], (void*) sip_attr_get_name(attr_id));
}
info->items[SIP_ATTR_SENTINEL] = NULL;
// Create the columns menu and post it
info->menu = menu = new_menu(info->items);
// Set current enabled fields
call_list_info_t *list_info = (call_list_info_t*) panel_userptr(
ui_get_panel(ui_find_by_type(MAIN_PANEL)));
// Enable current enabled fields and move them to the top
for (column = 0; column < list_info->columncnt; column++) {
const char *desc = list_info->columns[column].title;
for (attr_id = 0; attr_id < item_count(menu); attr_id++) {
if (!strcmp(item_description(info->items[attr_id]), desc)) {
column_select_toggle_item(panel, info->items[attr_id]);
column_select_move_item(panel, info->items[attr_id], column);
break;
}
}
}
// Set main window and sub window
set_menu_win(menu, win);
set_menu_sub(menu, derwin(win, 10, width - 5, 7, 2));
set_menu_format(menu, 10, 1);
set_menu_mark(menu, "");
set_menu_fore(menu, COLOR_PAIR(CP_DEF_ON_BLUE));
menu_opts_off(menu, O_ONEVALUE);
post_menu(menu);
// Draw a scrollbar to the right
draw_vscrollbar(info->menu_win, top_row(menu), item_count(menu) - 1, 0);
// Set the window title and boxes
mvwprintw(win, 1, width / 2 - 14, "Call List columns selection");
wattron(win, COLOR_PAIR(CP_BLUE_ON_DEF));
title_foot_box(panel_window(panel));
mvwhline(win, 6, 1, ACS_HLINE, width - 1);
mvwaddch(win, 6, 0, ACS_LTEE);
mvwaddch(win, 6, width - 1, ACS_RTEE);
wattroff(win, COLOR_PAIR(CP_BLUE_ON_DEF));
// Some brief explanation abotu what window shows
wattron(win, COLOR_PAIR(CP_CYAN_ON_DEF));
mvwprintw(win, 3, 2, "This windows show the list of columns displayed on Call");
mvwprintw(win, 4, 2, "List. You can enable/disable using Space Bar and reorder");
mvwprintw(win, 5, 2, "them using + and - keys.");
mvwprintw(win, height - 2, 12, "Press Enter when done. Esc to exit.");
wattroff(win, COLOR_PAIR(CP_CYAN_ON_DEF));
return panel;
}
void
column_select_destroy(PANEL *panel)
{
int i, itemcnt;
column_select_info_t *info = (column_select_info_t*) panel_userptr(panel);
// Get item count
itemcnt = item_count(info->menu);
// Unpost the menu
unpost_menu(info->menu);
// Free items
for (i = 0; i < itemcnt; i++) {
free_item(info->items[i]);
}
}
int
column_select_handle_key(PANEL *panel, int key)
{
MENU *menu;
ITEM *current;
int current_idx;
// Get panel information
column_select_info_t *info = (column_select_info_t*) panel_userptr(panel);
menu = info->menu;
current = current_item(menu);
current_idx = item_index(current);
switch (key) {
case KEY_DOWN:
menu_driver(menu, REQ_DOWN_ITEM);
break;
case KEY_UP:
menu_driver(menu, REQ_UP_ITEM);
break;
case KEY_NPAGE:
menu_driver(menu, REQ_SCR_DPAGE);
break;
case KEY_PPAGE:
menu_driver(menu, REQ_SCR_UPAGE);
break;
case ' ':
column_select_toggle_item(panel, current);
column_select_update_menu(panel);
break;
case '+':
column_select_move_item(panel, current, current_idx + 1);
column_select_update_menu(panel);
break;
case '-':
column_select_move_item(panel, current, current_idx - 1);
column_select_update_menu(panel);
break;
case 10:
column_select_update_columns(panel);
return 27;
default:
return key;
}
// Draw a scrollbar to the right
draw_vscrollbar(info->menu_win, top_row(menu), item_count(menu) - 1, 0);
wnoutrefresh(info->menu_win);
return 0;
}
void
column_select_update_columns(PANEL *panel)
{
int column, attr_id;
// Get panel information
column_select_info_t *info = (column_select_info_t*) panel_userptr(panel);
// Set enabled fields
PANEL *list_panel = ui_get_panel(ui_find_by_type(MAIN_PANEL));
call_list_info_t *list_info = (call_list_info_t*) panel_userptr(list_panel);
// Reset column count
list_info->columncnt = 0;
// Add all selected columns
for (column = 0; column < item_count(info->menu); column++) {
// If column is active
if (!strncmp(item_name(info->items[column]), "[ ]", 3))
continue;
// Get column attribute
attr_id = sip_attr_from_name(item_userptr(info->items[column]));
// Add a new column to the list
call_list_add_column(list_panel, attr_id, sip_attr_get_name(attr_id),
sip_attr_get_description(attr_id), sip_attr_get_width(attr_id));
}
}
void
column_select_move_item(PANEL *panel, ITEM *item, int pos)
{
// Get panel information
column_select_info_t *info = (column_select_info_t*) panel_userptr(panel);
// Check we have a valid position
if (pos == item_count(info->menu) || pos < 0)
return;
// Swap position with destiny
int item_pos = item_index(item);
info->items[item_pos] = info->items[pos];
info->items[item_pos]->index = item_pos;
info->items[pos] = item;
info->items[pos]->index = pos;
}
void
column_select_toggle_item(PANEL *panel, ITEM *item)
{
// Change item name
if (!strncmp(item_name(item), "[ ]", 3)) {
item->name.str = "[*]";
} else {
item->name.str = "[ ]";
}
}
void
column_select_update_menu(PANEL *panel)
{
// Get panel information
column_select_info_t *info = (column_select_info_t*) panel_userptr(panel);
ITEM *current = current_item(info->menu);
int top_idx = top_row(info->menu);
// Remove the menu from the subwindow
unpost_menu(info->menu);
// Set menu items
set_menu_items(info->menu, info->items);
// Put the menu agin into its subwindow
post_menu(info->menu);
// Move until the current position is set
set_top_row(info->menu, top_idx);
set_current_item(info->menu, current);
}

137
src/ui_column_select.h Normal file
View File

@ -0,0 +1,137 @@
/**************************************************************************
**
** sngrep - SIP Messages flow viewer
**
** Copyright (C) 2014,2015 Ivan Alonso (Kaian)
** Copyright (C) 2014,2015 Irontec SL. All rights reserved.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
**
****************************************************************************/
/**
* @file ui_column_select.h
* @author Ivan Alonso [aka Kaian] <kaian@irontec.com>
*
* @brief Functions to manage columns select panel
*/
#ifndef __UI_COLUMN_SELECT_H
#define __UI_COLUMN_SELECT_H
#include <menu.h>
#include "ui_manager.h"
#include "sip_attr.h"
//! Sorter declaration of struct columns_select_info
typedef struct column_select_info column_select_info_t;
/**
* @brief Column selector panel private information
*
* This structure contains the durable data of column selection panel.
*/
struct column_select_info
{
// Section of panel where menu is being displayed
WINDOW *menu_win;
// Columns menu
MENU *menu;
// Columns Items
ITEM *items[SIP_ATTR_SENTINEL + 1];
};
/**
* @brief Creates a new column selection panel
*
* This function allocates all required memory for
* displaying the column selection panel. It also draws all the
* static information of the panel that will never be
* redrawn.
*
* @return a panel pointer
*/
PANEL *
column_select_create();
/**
* @brief Destroy column selection panel
*
* This function do the final cleanups for this panel
*/
void
column_select_destroy();
/**
* @brief Manage pressed keys for column selection panel
*
* This function is called by UI manager every time a
* key is pressed. This allow the filter panel to manage
* its own keys.
* If this function return 0, the key will not be handled
* by ui manager. Otherwise the return will be considered
* a key code.
*
* @param panel Column selection panel pointer
* @param key key code
* @return 0 if the key is handled, keycode otherwise
*/
int
column_select_handle_key(PANEL *panel, int key);
/**
* @brief Update Call List columns
*
* This function will update the columns of Call List
*
* @param panel Column selection panel pointer
*/
void
column_select_update_columns(PANEL *panel);
/**
* @brief Move a item to a new position
*
* This function can be used to reorder the column list
*
* @param panel Column selection panel pointer
* @param item Menu item to be moved
* @param post New position in the menu
*/
void
column_select_move_item(PANEL *panel, ITEM *item, int pos);
/**
* @brief Select/Deselect a menu item
*
* This function can be used to toggle selection status of
* the menu item
*
* @param panel Column selection panel pointer
* @param item Menu item to be (de)selected
*/
void
column_select_toggle_item(PANEL *panel, ITEM *item);
/**
* @brief Update menu after a change
*
* After moving an item or updating its selection status
* menu must be redrawn.
*
* @param panel Column selection panel pointer
*/
void
column_select_update_menu(PANEL *panel);
#endif /* __UI_COLUMN_SELECT_H */

View File

@ -38,6 +38,7 @@
#include "ui_save_pcap.h"
#include "ui_save_raw.h"
#include "ui_msg_diff.h"
#include "ui_column_select.h"
/**
* @brief Warranty thread-safe ui refresh
@ -109,7 +110,13 @@ static ui_t panel_pool[] =
.handle_key = msg_diff_handle_key,
.destroy = msg_diff_destroy,
.draw = msg_diff_draw,
.help = msg_diff_help } };
.help = msg_diff_help },
{
.type = COLUMN_SELECT_PANEL,
.panel = NULL,
.create = column_select_create,
.handle_key = column_select_handle_key,
.destroy = column_select_destroy } };
int
init_interface()
@ -470,7 +477,7 @@ draw_vscrollbar(WINDOW *win, int value, int max, bool left)
mvwvline(win, 0, scrollxpos, ACS_VLINE, height);
// How long the scroll will be
scrollen = ceil(height * 1.0f / max * height);
scrollen = (height * 1.0f / max * height) + 0.5;
// Where will the scroll start
scrollypos = height * (value * 1.0f / max);
@ -478,6 +485,8 @@ draw_vscrollbar(WINDOW *win, int value, int max, bool left)
// Draw the N blocks of the scrollbar
for (cline = 0; cline < scrollen; cline++)
mvwaddch(win, cline + scrollypos, scrollxpos, ACS_CKBOARD);
mvwprintw(win, 0, 0, "%d/%d [%d] %d/%d", scrollypos, height, scrollen, value, max);
}
int

View File

@ -124,6 +124,8 @@ enum panel_types
SAVE_RAW_PANEL,
//! Message comprare
MSG_DIFF_PANEL,
//! Column selector panel
COLUMN_SELECT_PANEL,
};
/**