Initial and woefully incomplete flow graph support.
Copy common code from ui/gtk/flow_graph.c and ui/gtk/graph_analysis.[ch] to ui/tap-sequence-analysis.[ch]. Start using the name "sequence" in places. svn path=/trunk/; revision=52824
This commit is contained in:
parent
39fd5f29af
commit
1a4033b63b
|
@ -39,6 +39,7 @@ set(COMMON_UI_SRC
|
||||||
software_update.c
|
software_update.c
|
||||||
tap-megaco-common.c
|
tap-megaco-common.c
|
||||||
tap-rtp-common.c
|
tap-rtp-common.c
|
||||||
|
tap-sequence-analysis.c
|
||||||
tap-tcp-stream.c
|
tap-tcp-stream.c
|
||||||
text_import.c
|
text_import.c
|
||||||
time_shift.c
|
time_shift.c
|
||||||
|
|
|
@ -60,6 +60,7 @@ WIRESHARK_UI_SRC = \
|
||||||
ssl_key_export.c \
|
ssl_key_export.c \
|
||||||
tap-megaco-common.c \
|
tap-megaco-common.c \
|
||||||
tap-rtp-common.c \
|
tap-rtp-common.c \
|
||||||
|
tap-sequence-analysis.c \
|
||||||
tap-tcp-stream.c \
|
tap-tcp-stream.c \
|
||||||
text_import.c \
|
text_import.c \
|
||||||
time_shift.c \
|
time_shift.c \
|
||||||
|
@ -86,6 +87,7 @@ noinst_HEADERS = \
|
||||||
ssl_key_export.h \
|
ssl_key_export.h \
|
||||||
tap-megaco-common.h \
|
tap-megaco-common.h \
|
||||||
tap-rtp-common.h \
|
tap-rtp-common.h \
|
||||||
|
tap-sequence-analysis.h \
|
||||||
tap-tcp-stream.h \
|
tap-tcp-stream.h \
|
||||||
text_import.h \
|
text_import.h \
|
||||||
text_import_scanner.h \
|
text_import_scanner.h \
|
||||||
|
|
|
@ -34,8 +34,6 @@
|
||||||
#include <epan/filesystem.h>
|
#include <epan/filesystem.h>
|
||||||
#include <epan/stat_cmd_args.h>
|
#include <epan/stat_cmd_args.h>
|
||||||
#include <epan/to_str.h>
|
#include <epan/to_str.h>
|
||||||
#include <epan/tap.h>
|
|
||||||
#include <epan/dissectors/packet-tcp.h>
|
|
||||||
#include <epan/strutil.h>
|
#include <epan/strutil.h>
|
||||||
|
|
||||||
#include "../stat_menu.h"
|
#include "../stat_menu.h"
|
||||||
|
@ -49,26 +47,7 @@
|
||||||
#include "ui/gtk/main.h"
|
#include "ui/gtk/main.h"
|
||||||
#include "ui/gtk/old-gtk-compat.h"
|
#include "ui/gtk/old-gtk-compat.h"
|
||||||
|
|
||||||
|
static seq_analysis_info_t *graph_analysis = NULL;
|
||||||
#define TYPE_OF_PACKETS_DISPLAYED 0
|
|
||||||
#define TYPE_OF_PACKETS_ALL 1
|
|
||||||
|
|
||||||
#define TYPE_OF_FLOW_GENERAL 0
|
|
||||||
#define TYPE_OF_FLOW_TCP 1
|
|
||||||
|
|
||||||
#define NODE_ADDR_TYPE_SRCDST 0
|
|
||||||
#define NODE_ADDR_TYPE_NET_SRCDST 1
|
|
||||||
|
|
||||||
static int type_of_packets = TYPE_OF_PACKETS_DISPLAYED;
|
|
||||||
static int type_of_flow = TYPE_OF_FLOW_GENERAL;
|
|
||||||
static int node_addr_type = NODE_ADDR_TYPE_SRCDST;
|
|
||||||
|
|
||||||
static int tap_identifier;
|
|
||||||
|
|
||||||
static gboolean have_frame_tap_listener = FALSE;
|
|
||||||
static gboolean have_tcp_tap_listener = FALSE;
|
|
||||||
|
|
||||||
static graph_analysis_info_t *graph_analysis = NULL;
|
|
||||||
static graph_analysis_data_t *graph_analysis_data = NULL;
|
static graph_analysis_data_t *graph_analysis_data = NULL;
|
||||||
|
|
||||||
static GtkWidget *flow_graph_dlg = NULL;
|
static GtkWidget *flow_graph_dlg = NULL;
|
||||||
|
@ -80,51 +59,13 @@ static GtkWidget *select_tcp_rb;
|
||||||
static GtkWidget *src_dst_rb;
|
static GtkWidget *src_dst_rb;
|
||||||
static GtkWidget *net_src_dst_rb;
|
static GtkWidget *net_src_dst_rb;
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
/* free up memory and initialize the pointers */
|
|
||||||
|
|
||||||
static void
|
|
||||||
flow_graph_reset(void *ptr _U_)
|
|
||||||
{
|
|
||||||
graph_analysis_item_t *graph_item;
|
|
||||||
|
|
||||||
GList *list;
|
|
||||||
|
|
||||||
if (graph_analysis !=NULL){
|
|
||||||
|
|
||||||
/* free the graph data items */
|
|
||||||
list = g_list_first(graph_analysis->list);
|
|
||||||
while (list)
|
|
||||||
{
|
|
||||||
graph_item = (graph_analysis_item_t *)list->data;
|
|
||||||
g_free(graph_item->frame_label);
|
|
||||||
g_free(graph_item->comment);
|
|
||||||
g_free(list->data);
|
|
||||||
list = g_list_next(list);
|
|
||||||
}
|
|
||||||
g_list_free(graph_analysis->list);
|
|
||||||
graph_analysis->nconv = 0;
|
|
||||||
graph_analysis->list = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
static void
|
static void
|
||||||
flow_graph_data_init(void) {
|
flow_graph_data_init(void) {
|
||||||
graph_analysis = (graph_analysis_info_t *)g_malloc(sizeof(graph_analysis_info_t));
|
graph_analysis = (seq_analysis_info_t *)g_malloc0(sizeof(seq_analysis_info_t));
|
||||||
graph_analysis->nconv = 0;
|
graph_analysis->type = SEQ_ANALYSIS_ANY;
|
||||||
graph_analysis->list = NULL;
|
graph_analysis->all_packets = TRUE;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
static void
|
|
||||||
remove_tap_listener_flow_graph(void)
|
|
||||||
{
|
|
||||||
remove_tap_listener(&(tap_identifier));
|
|
||||||
|
|
||||||
have_frame_tap_listener=FALSE;
|
|
||||||
have_tcp_tap_listener=FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -134,11 +75,8 @@ remove_tap_listener_flow_graph(void)
|
||||||
static void
|
static void
|
||||||
flow_graph_on_destroy(GObject *object _U_, gpointer user_data _U_)
|
flow_graph_on_destroy(GObject *object _U_, gpointer user_data _U_)
|
||||||
{
|
{
|
||||||
/* remove_tap_listeners */
|
|
||||||
remove_tap_listener_flow_graph();
|
|
||||||
|
|
||||||
/* Clean up memory used by tap */
|
/* Clean up memory used by tap */
|
||||||
flow_graph_reset(NULL);
|
sequence_analysis_list_free(graph_analysis);
|
||||||
|
|
||||||
g_assert(graph_analysis != NULL);
|
g_assert(graph_analysis != NULL);
|
||||||
g_assert(graph_analysis_data != NULL);
|
g_assert(graph_analysis_data != NULL);
|
||||||
|
@ -160,7 +98,7 @@ toggle_select_all(GtkWidget *widget _U_, gpointer user_data _U_)
|
||||||
{
|
{
|
||||||
/* is the button now active? */
|
/* is the button now active? */
|
||||||
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(select_all_rb))) {
|
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(select_all_rb))) {
|
||||||
type_of_packets = TYPE_OF_PACKETS_ALL;
|
graph_analysis->all_packets = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,7 +108,7 @@ toggle_select_displayed(GtkWidget *widget _U_, gpointer user_data _U_)
|
||||||
{
|
{
|
||||||
/* is the button now active? */
|
/* is the button now active? */
|
||||||
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(select_displayed_rb))) {
|
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(select_displayed_rb))) {
|
||||||
type_of_packets = TYPE_OF_PACKETS_DISPLAYED;
|
graph_analysis->all_packets = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,7 +118,7 @@ toggle_select_general(GtkWidget *widget _U_, gpointer user_data _U_)
|
||||||
{
|
{
|
||||||
/* is the button now active? */
|
/* is the button now active? */
|
||||||
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(select_general_rb))) {
|
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(select_general_rb))) {
|
||||||
type_of_flow = TYPE_OF_FLOW_GENERAL;
|
graph_analysis->type = SEQ_ANALYSIS_ANY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,7 +128,7 @@ toggle_select_tcp(GtkWidget *widget _U_, gpointer user_data _U_)
|
||||||
{
|
{
|
||||||
/* is the button now active? */
|
/* is the button now active? */
|
||||||
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(select_tcp_rb))) {
|
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(select_tcp_rb))) {
|
||||||
type_of_flow = TYPE_OF_FLOW_TCP;
|
graph_analysis->type = SEQ_ANALYSIS_TCP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,7 +138,7 @@ toggle_select_srcdst(GtkWidget *widget _U_, gpointer user_data _U_)
|
||||||
{
|
{
|
||||||
/* is the button now active? */
|
/* is the button now active? */
|
||||||
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(src_dst_rb))) {
|
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(src_dst_rb))) {
|
||||||
node_addr_type = NODE_ADDR_TYPE_SRCDST;
|
graph_analysis->any_addr = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,245 +148,18 @@ toggle_select_netsrcdst(GtkWidget *widget _U_, gpointer user_data _U_)
|
||||||
{
|
{
|
||||||
/* is the button now active? */
|
/* is the button now active? */
|
||||||
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(net_src_dst_rb))) {
|
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(net_src_dst_rb))) {
|
||||||
node_addr_type = NODE_ADDR_TYPE_NET_SRCDST;
|
graph_analysis->any_addr = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
/* Add a new frame into the graph */
|
|
||||||
static int
|
|
||||||
flow_graph_frame_add_to_graph(packet_info *pinfo)
|
|
||||||
{
|
|
||||||
graph_analysis_item_t *gai;
|
|
||||||
int i;
|
|
||||||
gchar *protocol;
|
|
||||||
gchar *colinfo;
|
|
||||||
|
|
||||||
protocol=NULL;
|
|
||||||
colinfo=NULL;
|
|
||||||
|
|
||||||
if (node_addr_type == NODE_ADDR_TYPE_NET_SRCDST) {
|
|
||||||
if (pinfo->net_src.type!=AT_NONE && pinfo->net_dst.type!=AT_NONE) {
|
|
||||||
gai = (graph_analysis_item_t *)g_malloc(sizeof(graph_analysis_item_t));
|
|
||||||
COPY_ADDRESS(&(gai->src_addr),&(pinfo->net_src));
|
|
||||||
COPY_ADDRESS(&(gai->dst_addr),&(pinfo->net_dst));
|
|
||||||
}
|
|
||||||
else return 0;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (pinfo->src.type!=AT_NONE && pinfo->dst.type!=AT_NONE) {
|
|
||||||
gai = (graph_analysis_item_t *)g_malloc(sizeof(graph_analysis_item_t));
|
|
||||||
COPY_ADDRESS(&(gai->src_addr),&(pinfo->src));
|
|
||||||
COPY_ADDRESS(&(gai->dst_addr),&(pinfo->dst));
|
|
||||||
}
|
|
||||||
else return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
gai->fd = pinfo->fd;
|
|
||||||
|
|
||||||
gai->port_src=pinfo->srcport;
|
|
||||||
gai->port_dst=pinfo->destport;
|
|
||||||
gai->comment=NULL;
|
|
||||||
gai->frame_label=NULL;
|
|
||||||
|
|
||||||
#if 0 /* this code doesn't make sense. */
|
|
||||||
g_free(gai->comment);
|
|
||||||
g_free(gai->frame_label);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(pinfo->cinfo) {
|
|
||||||
if (pinfo->cinfo->col_first[COL_INFO]>=0){
|
|
||||||
|
|
||||||
for (i = pinfo->cinfo->col_first[COL_INFO]; i <= pinfo->cinfo->col_last[COL_INFO]; i++) {
|
|
||||||
if (pinfo->cinfo->fmt_matx[i][COL_INFO]) {
|
|
||||||
colinfo = g_strdup(pinfo->cinfo->col_data[i]);
|
|
||||||
/* break; ? or g_free(colinfo); before g_strdup() */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pinfo->cinfo->col_first[COL_PROTOCOL]>=0){
|
|
||||||
|
|
||||||
for (i = pinfo->cinfo->col_first[COL_PROTOCOL]; i <= pinfo->cinfo->col_last[COL_PROTOCOL]; i++) {
|
|
||||||
if (pinfo->cinfo->fmt_matx[i][COL_PROTOCOL]) {
|
|
||||||
protocol = g_strdup(pinfo->cinfo->col_data[i]);
|
|
||||||
/* break; ? or g_free(protocol); before g_strdup() */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (colinfo != NULL) {
|
|
||||||
if (protocol != NULL) {
|
|
||||||
gai->frame_label = g_strdup_printf("%.19s", colinfo);
|
|
||||||
gai->comment = g_strdup_printf("%s: %s", protocol, colinfo);
|
|
||||||
} else {
|
|
||||||
gai->frame_label = g_strdup_printf("%.19s", colinfo);
|
|
||||||
gai->comment = g_strdup_printf("%s", colinfo);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* This will probably never happen...*/
|
|
||||||
if (protocol != NULL) {
|
|
||||||
gai->frame_label = g_strdup_printf("%.19s", protocol);
|
|
||||||
gai->comment = g_strdup_printf("%s", protocol);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g_free(protocol);
|
|
||||||
g_free(colinfo);
|
|
||||||
|
|
||||||
gai->line_style=1;
|
|
||||||
gai->conv_num=0;
|
|
||||||
gai->display=TRUE;
|
|
||||||
|
|
||||||
graph_analysis->list = g_list_append(graph_analysis->list, gai);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
/* Add a new tcp frame into the graph */
|
|
||||||
static int
|
|
||||||
flow_graph_tcp_add_to_graph(packet_info *pinfo, const struct tcpheader *tcph)
|
|
||||||
{
|
|
||||||
graph_analysis_item_t *gai;
|
|
||||||
/* copied from packet-tcp */
|
|
||||||
static const gchar *fstr[] = {"FIN", "SYN", "RST", "PSH", "ACK", "URG", "ECN", "CWR" };
|
|
||||||
guint i, bpos;
|
|
||||||
gboolean flags_found = FALSE;
|
|
||||||
gchar flags[64];
|
|
||||||
|
|
||||||
gai = (graph_analysis_item_t *)g_malloc(sizeof(graph_analysis_item_t));
|
|
||||||
gai->fd = pinfo->fd;
|
|
||||||
if (node_addr_type == NODE_ADDR_TYPE_NET_SRCDST) {
|
|
||||||
COPY_ADDRESS(&(gai->src_addr),&(pinfo->net_src));
|
|
||||||
COPY_ADDRESS(&(gai->dst_addr),&(pinfo->net_dst));
|
|
||||||
} else {
|
|
||||||
COPY_ADDRESS(&(gai->src_addr),&(pinfo->src));
|
|
||||||
COPY_ADDRESS(&(gai->dst_addr),&(pinfo->dst));
|
|
||||||
}
|
|
||||||
gai->port_src=pinfo->srcport;
|
|
||||||
gai->port_dst=pinfo->destport;
|
|
||||||
|
|
||||||
flags[0] = '\0';
|
|
||||||
for (i = 0; i < 8; i++) {
|
|
||||||
bpos = 1 << i;
|
|
||||||
if (tcph->th_flags & bpos) {
|
|
||||||
if (flags_found) {
|
|
||||||
g_strlcat(flags, ", ", sizeof(flags));
|
|
||||||
}
|
|
||||||
g_strlcat(flags, fstr[i], sizeof(flags));
|
|
||||||
flags_found = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (flags[0] == '\0') {
|
|
||||||
g_snprintf (flags, sizeof(flags), "<None>");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((tcph->th_have_seglen)&&(tcph->th_seglen!=0)){
|
|
||||||
gai->frame_label = g_strdup_printf("%s - Len: %u",flags, tcph->th_seglen);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
gai->frame_label = g_strdup(flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tcph->th_flags & TH_ACK)
|
|
||||||
gai->comment = g_strdup_printf("Seq = %u Ack = %u",tcph->th_seq, tcph->th_ack);
|
|
||||||
else
|
|
||||||
gai->comment = g_strdup_printf("Seq = %u",tcph->th_seq);
|
|
||||||
|
|
||||||
gai->line_style=1;
|
|
||||||
gai->conv_num=0;
|
|
||||||
gai->display=TRUE;
|
|
||||||
|
|
||||||
graph_analysis->list = g_list_append(graph_analysis->list, gai);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
/* whenever a frame packet is seen by the tap listener */
|
|
||||||
static gboolean
|
|
||||||
flow_graph_frame_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *dummy _U_)
|
|
||||||
{
|
|
||||||
if ((type_of_packets == TYPE_OF_PACKETS_ALL)||(pinfo->fd->flags.passed_dfilter==1)){
|
|
||||||
flow_graph_frame_add_to_graph(pinfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
/* whenever a TCP packet is seen by the tap listener */
|
|
||||||
static gboolean
|
|
||||||
flow_graph_tcp_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *tcp_info)
|
|
||||||
{
|
|
||||||
const struct tcpheader *tcph = (struct tcpheader *)tcp_info;
|
|
||||||
|
|
||||||
if ((type_of_packets == TYPE_OF_PACKETS_ALL)||(pinfo->fd->flags.passed_dfilter==1)){
|
|
||||||
flow_graph_tcp_add_to_graph(pinfo,tcph);
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
flow_graph_packet_draw(void *prs _U_)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
static void
|
static void
|
||||||
flow_graph_on_ok(GtkButton *button _U_,
|
flow_graph_on_ok(GtkButton *button _U_,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
if ((have_frame_tap_listener==TRUE)
|
|
||||||
||(have_tcp_tap_listener==TRUE))
|
|
||||||
{
|
|
||||||
/* remove_tap_listeners */
|
|
||||||
remove_tap_listener_flow_graph();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Scan for displayed packets (retap all packets) */
|
/* Scan for displayed packets (retap all packets) */
|
||||||
|
sequence_analysis_list_free(graph_analysis);
|
||||||
if (type_of_flow == TYPE_OF_FLOW_GENERAL){
|
sequence_analysis_list_get(&cfile, graph_analysis);
|
||||||
/* Register the tap listener */
|
|
||||||
|
|
||||||
if(have_frame_tap_listener==FALSE)
|
|
||||||
{
|
|
||||||
/* don't register tap listener, if we have it already */
|
|
||||||
register_tap_listener("frame", &tap_identifier, NULL,
|
|
||||||
TL_REQUIRES_COLUMNS,
|
|
||||||
flow_graph_reset,
|
|
||||||
flow_graph_frame_packet,
|
|
||||||
flow_graph_packet_draw
|
|
||||||
);
|
|
||||||
have_frame_tap_listener=TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
cf_retap_packets(&cfile);
|
|
||||||
}
|
|
||||||
else if (type_of_flow == TYPE_OF_FLOW_TCP){
|
|
||||||
/* Register the tap listener */
|
|
||||||
|
|
||||||
if(have_tcp_tap_listener==FALSE)
|
|
||||||
{
|
|
||||||
/* don't register tap listener, if we have it already */
|
|
||||||
register_tap_listener("tcp", &tap_identifier, NULL,
|
|
||||||
0,
|
|
||||||
flow_graph_reset,
|
|
||||||
flow_graph_tcp_packet,
|
|
||||||
flow_graph_packet_draw
|
|
||||||
);
|
|
||||||
have_tcp_tap_listener=TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
cf_retap_packets(&cfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (graph_analysis_data->dlg.window != NULL){ /* if we still have a window */
|
if (graph_analysis_data->dlg.window != NULL){ /* if we still have a window */
|
||||||
graph_analysis_update(graph_analysis_data); /* refresh it xxx */
|
graph_analysis_update(graph_analysis_data); /* refresh it xxx */
|
||||||
|
@ -524,7 +235,7 @@ flow_graph_dlg_create(void)
|
||||||
gtk_widget_set_tooltip_text (select_all_rb, ("Process all packets"));
|
gtk_widget_set_tooltip_text (select_all_rb, ("Process all packets"));
|
||||||
g_signal_connect(select_all_rb, "toggled", G_CALLBACK(toggle_select_all), NULL);
|
g_signal_connect(select_all_rb, "toggled", G_CALLBACK(toggle_select_all), NULL);
|
||||||
ws_gtk_grid_attach(GTK_GRID(range_grid), select_all_rb, 0, 0, 1, 1);
|
ws_gtk_grid_attach(GTK_GRID(range_grid), select_all_rb, 0, 0, 1, 1);
|
||||||
if (type_of_packets == TYPE_OF_PACKETS_ALL) {
|
if (graph_analysis->all_packets) {
|
||||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(select_all_rb),TRUE);
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(select_all_rb),TRUE);
|
||||||
}
|
}
|
||||||
gtk_widget_show(select_all_rb);
|
gtk_widget_show(select_all_rb);
|
||||||
|
@ -535,7 +246,7 @@ flow_graph_dlg_create(void)
|
||||||
gtk_widget_set_tooltip_text (select_displayed_rb, ("Process displayed packets"));
|
gtk_widget_set_tooltip_text (select_displayed_rb, ("Process displayed packets"));
|
||||||
g_signal_connect(select_displayed_rb, "toggled", G_CALLBACK(toggle_select_displayed), NULL);
|
g_signal_connect(select_displayed_rb, "toggled", G_CALLBACK(toggle_select_displayed), NULL);
|
||||||
ws_gtk_grid_attach(GTK_GRID(range_grid), select_displayed_rb, 0, 1, 1, 1);
|
ws_gtk_grid_attach(GTK_GRID(range_grid), select_displayed_rb, 0, 1, 1, 1);
|
||||||
if (type_of_packets == TYPE_OF_PACKETS_DISPLAYED) {
|
if (!graph_analysis->all_packets) {
|
||||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(select_displayed_rb),TRUE);
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(select_displayed_rb),TRUE);
|
||||||
}
|
}
|
||||||
gtk_widget_show(select_displayed_rb);
|
gtk_widget_show(select_displayed_rb);
|
||||||
|
@ -556,7 +267,7 @@ flow_graph_dlg_create(void)
|
||||||
gtk_widget_set_tooltip_text (select_general_rb, ("Show all packets, with general information"));
|
gtk_widget_set_tooltip_text (select_general_rb, ("Show all packets, with general information"));
|
||||||
g_signal_connect(select_general_rb, "toggled", G_CALLBACK(toggle_select_general), NULL);
|
g_signal_connect(select_general_rb, "toggled", G_CALLBACK(toggle_select_general), NULL);
|
||||||
ws_gtk_grid_attach(GTK_GRID(flow_type_grid), select_general_rb, 0, 0, 1, 1);
|
ws_gtk_grid_attach(GTK_GRID(flow_type_grid), select_general_rb, 0, 0, 1, 1);
|
||||||
if (type_of_flow == TYPE_OF_FLOW_GENERAL) {
|
if (graph_analysis->type == SEQ_ANALYSIS_ANY) {
|
||||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(select_general_rb),TRUE);
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(select_general_rb),TRUE);
|
||||||
}
|
}
|
||||||
gtk_widget_show(select_general_rb);
|
gtk_widget_show(select_general_rb);
|
||||||
|
@ -567,7 +278,7 @@ flow_graph_dlg_create(void)
|
||||||
gtk_widget_set_tooltip_text (select_tcp_rb, ("Show only TCP packets, with TCP specific information"));
|
gtk_widget_set_tooltip_text (select_tcp_rb, ("Show only TCP packets, with TCP specific information"));
|
||||||
g_signal_connect(select_tcp_rb, "toggled", G_CALLBACK(toggle_select_tcp), NULL);
|
g_signal_connect(select_tcp_rb, "toggled", G_CALLBACK(toggle_select_tcp), NULL);
|
||||||
ws_gtk_grid_attach(GTK_GRID(flow_type_grid), select_tcp_rb, 0, 1, 1, 1);
|
ws_gtk_grid_attach(GTK_GRID(flow_type_grid), select_tcp_rb, 0, 1, 1, 1);
|
||||||
if (type_of_flow == TYPE_OF_FLOW_TCP) {
|
if (graph_analysis->type == SEQ_ANALYSIS_TCP) {
|
||||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(select_tcp_rb),TRUE);
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(select_tcp_rb),TRUE);
|
||||||
}
|
}
|
||||||
gtk_widget_show(select_tcp_rb);
|
gtk_widget_show(select_tcp_rb);
|
||||||
|
@ -589,7 +300,7 @@ flow_graph_dlg_create(void)
|
||||||
("Nodes in the diagram are identified with source and destination addresses"));
|
("Nodes in the diagram are identified with source and destination addresses"));
|
||||||
g_signal_connect(src_dst_rb, "toggled", G_CALLBACK(toggle_select_srcdst), NULL);
|
g_signal_connect(src_dst_rb, "toggled", G_CALLBACK(toggle_select_srcdst), NULL);
|
||||||
ws_gtk_grid_attach(GTK_GRID(node_addr_grid), src_dst_rb, 0, 0, 1, 1);
|
ws_gtk_grid_attach(GTK_GRID(node_addr_grid), src_dst_rb, 0, 0, 1, 1);
|
||||||
if (node_addr_type == NODE_ADDR_TYPE_SRCDST) {
|
if (!graph_analysis->any_addr) {
|
||||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(src_dst_rb),TRUE);
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(src_dst_rb),TRUE);
|
||||||
}
|
}
|
||||||
gtk_widget_show(src_dst_rb);
|
gtk_widget_show(src_dst_rb);
|
||||||
|
@ -601,7 +312,7 @@ flow_graph_dlg_create(void)
|
||||||
("Nodes in the diagram are identified with network source and destination addresses"));
|
("Nodes in the diagram are identified with network source and destination addresses"));
|
||||||
g_signal_connect(net_src_dst_rb, "toggled", G_CALLBACK(toggle_select_netsrcdst), NULL);
|
g_signal_connect(net_src_dst_rb, "toggled", G_CALLBACK(toggle_select_netsrcdst), NULL);
|
||||||
ws_gtk_grid_attach(GTK_GRID(node_addr_grid), net_src_dst_rb, 0, 1, 1, 1);
|
ws_gtk_grid_attach(GTK_GRID(node_addr_grid), net_src_dst_rb, 0, 1, 1, 1);
|
||||||
if (node_addr_type == NODE_ADDR_TYPE_NET_SRCDST) {
|
if (graph_analysis->any_addr) {
|
||||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(net_src_dst_rb),TRUE);
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(net_src_dst_rb),TRUE);
|
||||||
}
|
}
|
||||||
gtk_widget_show(net_src_dst_rb);
|
gtk_widget_show(net_src_dst_rb);
|
||||||
|
@ -660,8 +371,7 @@ flow_graph_init_tap(const char *dummy _U_, void *userdata _U_)
|
||||||
flow_graph_data_init();
|
flow_graph_data_init();
|
||||||
|
|
||||||
/* init the Graph Analysis */
|
/* init the Graph Analysis */
|
||||||
graph_analysis_data = graph_analysis_init();
|
graph_analysis_data = graph_analysis_init(graph_analysis);
|
||||||
graph_analysis_data->graph_info = graph_analysis;
|
|
||||||
|
|
||||||
flow_graph_dlg_create();
|
flow_graph_dlg_create();
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,13 +52,10 @@
|
||||||
|
|
||||||
#include "ui/util.h"
|
#include "ui/util.h"
|
||||||
|
|
||||||
#include "ui/alert_box.h"
|
|
||||||
#include "ui/last_open_dir.h"
|
#include "ui/last_open_dir.h"
|
||||||
#include "ui/recent.h"
|
#include "ui/recent.h"
|
||||||
#include "ui/simple_dialog.h"
|
#include "ui/simple_dialog.h"
|
||||||
|
|
||||||
#include <wsutil/file_util.h>
|
|
||||||
|
|
||||||
#include "ui/gtk/gtkglobals.h"
|
#include "ui/gtk/gtkglobals.h"
|
||||||
#include "ui/gtk/file_dlg.h"
|
#include "ui/gtk/file_dlg.h"
|
||||||
#include "ui/gtk/gui_utils.h"
|
#include "ui/gtk/gui_utils.h"
|
||||||
|
@ -81,27 +78,19 @@
|
||||||
#define COMMENT_WIDTH 400
|
#define COMMENT_WIDTH 400
|
||||||
#define TIME_WIDTH 150
|
#define TIME_WIDTH 150
|
||||||
|
|
||||||
#define NODE_CHARS_WIDTH 20
|
|
||||||
#define CONV_TIME_HEADER "Conv.| Time "
|
|
||||||
#define TIME_HEADER "|Time "
|
|
||||||
#define CONV_TIME_EMPTY_HEADER " | "
|
|
||||||
#define TIME_EMPTY_HEADER "| "
|
|
||||||
#define CONV_TIME_HEADER_LENGTH 16
|
|
||||||
#define TIME_HEADER_LENGTH 10
|
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
/* Reset the user_data structure */
|
/* Reset the user_data structure */
|
||||||
static void graph_analysis_reset(graph_analysis_data_t *user_data)
|
static void graph_analysis_reset(graph_analysis_data_t *user_data)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
user_data->num_nodes = 0;
|
user_data->graph_info->num_nodes = 0;
|
||||||
user_data->num_items = 0;
|
user_data->num_items = 0;
|
||||||
for (i=0; i<MAX_NUM_NODES; i++) {
|
for (i=0; i<MAX_NUM_NODES; i++) {
|
||||||
user_data->nodes[i].type = AT_NONE;
|
user_data->graph_info->nodes[i].type = AT_NONE;
|
||||||
user_data->nodes[i].len = 0;
|
user_data->graph_info->nodes[i].len = 0;
|
||||||
g_free((void *)user_data->nodes[i].data);
|
g_free((void *)user_data->graph_info->nodes[i].data);
|
||||||
user_data->nodes[i].data = NULL;
|
user_data->graph_info->nodes[i].data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
user_data->dlg.first_node = 0;
|
user_data->dlg.first_node = 0;
|
||||||
|
@ -116,14 +105,14 @@ static void graph_analysis_init_dlg(graph_analysis_data_t *user_data)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
user_data->num_nodes = 0;
|
user_data->graph_info->num_nodes = 0;
|
||||||
user_data->num_items = 0;
|
user_data->num_items = 0;
|
||||||
user_data->on_destroy_user_data = NULL;
|
user_data->on_destroy_user_data = NULL;
|
||||||
user_data->data = NULL;
|
user_data->data = NULL;
|
||||||
for (i=0; i<MAX_NUM_NODES; i++) {
|
for (i=0; i<MAX_NUM_NODES; i++) {
|
||||||
user_data->nodes[i].type = AT_NONE;
|
user_data->graph_info->nodes[i].type = AT_NONE;
|
||||||
user_data->nodes[i].len = 0;
|
user_data->graph_info->nodes[i].len = 0;
|
||||||
user_data->nodes[i].data = NULL;
|
user_data->graph_info->nodes[i].data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
user_data->dlg.first_node = 0;
|
user_data->dlg.first_node = 0;
|
||||||
|
@ -169,10 +158,10 @@ static void on_destroy(GtkWidget *win _U_, graph_analysis_data_t *user_data)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i=0; i<MAX_NUM_NODES; i++) {
|
for (i=0; i<MAX_NUM_NODES; i++) {
|
||||||
user_data->nodes[i].type = AT_NONE;
|
user_data->graph_info->nodes[i].type = AT_NONE;
|
||||||
user_data->nodes[i].len = 0;
|
user_data->graph_info->nodes[i].len = 0;
|
||||||
g_free((void *)user_data->nodes[i].data);
|
g_free((void *)user_data->graph_info->nodes[i].data);
|
||||||
user_data->nodes[i].data = NULL;
|
user_data->graph_info->nodes[i].data = NULL;
|
||||||
}
|
}
|
||||||
user_data->dlg.window = NULL;
|
user_data->dlg.window = NULL;
|
||||||
g_free(user_data->dlg.title);
|
g_free(user_data->dlg.title);
|
||||||
|
@ -241,281 +230,6 @@ static void draw_arrow(GdkDrawable *pixmap, GdkRGBA *color, gint x, gint y, gboo
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
/* Adds trailing characters to complete the requested length. */
|
|
||||||
/****************************************************************************/
|
|
||||||
|
|
||||||
static void enlarge_string(GString *gstr, guint32 length, char pad) {
|
|
||||||
|
|
||||||
gsize i;
|
|
||||||
|
|
||||||
for (i = gstr->len; i < length; i++) {
|
|
||||||
g_string_append_c(gstr, pad);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
/* overwrites the characters in a string, between positions p1 and p2, with */
|
|
||||||
/* the characters of text_to_insert */
|
|
||||||
/* NB: it does not check that p1 and p2 fit into string */
|
|
||||||
/****************************************************************************/
|
|
||||||
|
|
||||||
static void overwrite (GString *gstr, char *text_to_insert, guint32 p1, guint32 p2) {
|
|
||||||
|
|
||||||
gsize len;
|
|
||||||
gsize pos;
|
|
||||||
|
|
||||||
if (p1 == p2)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (p1 > p2) {
|
|
||||||
pos = p2;
|
|
||||||
len = p1 - p2;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
pos = p1;
|
|
||||||
len = p2 - p1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len > strlen(text_to_insert)) {
|
|
||||||
len = strlen(text_to_insert);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pos > gstr->len)
|
|
||||||
pos = gstr->len;
|
|
||||||
|
|
||||||
/* ouch this is ugly but gtk1 needs it */
|
|
||||||
if ((pos + len) > gstr->len)
|
|
||||||
g_string_truncate(gstr, pos);
|
|
||||||
else
|
|
||||||
g_string_erase(gstr, pos, len);
|
|
||||||
|
|
||||||
g_string_insert(gstr, pos, text_to_insert);
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
static gboolean
|
|
||||||
dialog_graph_dump_to_file(char *pathname, graph_analysis_data_t *user_data)
|
|
||||||
{
|
|
||||||
guint32 i, first_node, display_items, display_nodes;
|
|
||||||
guint32 start_position, end_position, item_width, header_length;
|
|
||||||
graph_analysis_item_t *gai;
|
|
||||||
guint16 first_conv_num = 0;
|
|
||||||
gboolean several_convs = FALSE;
|
|
||||||
gboolean first_packet = TRUE;
|
|
||||||
|
|
||||||
GString *label_string, *empty_line, *separator_line, *tmp_str, *tmp_str2;
|
|
||||||
const char *empty_header;
|
|
||||||
char src_port[8], dst_port[8];
|
|
||||||
gchar *time_str;
|
|
||||||
GList *list;
|
|
||||||
|
|
||||||
FILE *of;
|
|
||||||
|
|
||||||
of = ws_fopen(pathname, "w");
|
|
||||||
if (of==NULL) {
|
|
||||||
open_failure_alert_box(pathname, errno, TRUE);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
time_str = (gchar *)g_malloc(COL_MAX_LEN);
|
|
||||||
label_string = g_string_new("");
|
|
||||||
empty_line = g_string_new("");
|
|
||||||
separator_line = g_string_new("");
|
|
||||||
tmp_str = g_string_new("");
|
|
||||||
tmp_str2 = g_string_new("");
|
|
||||||
|
|
||||||
display_items = 0;
|
|
||||||
list = g_list_first(user_data->graph_info->list);
|
|
||||||
while (list)
|
|
||||||
{
|
|
||||||
gai = (graph_analysis_item_t *)list->data;
|
|
||||||
list = g_list_next(list);
|
|
||||||
|
|
||||||
if (!gai->display)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
display_items += 1;
|
|
||||||
if (first_packet) {
|
|
||||||
first_conv_num = gai->conv_num;
|
|
||||||
first_packet = FALSE;
|
|
||||||
}
|
|
||||||
else if (gai->conv_num != first_conv_num) {
|
|
||||||
several_convs = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if not items to display */
|
|
||||||
if (display_items == 0)
|
|
||||||
goto exit;
|
|
||||||
|
|
||||||
display_nodes = user_data->num_nodes;
|
|
||||||
|
|
||||||
first_node = user_data->dlg.first_node;
|
|
||||||
|
|
||||||
/* Write the conv. and time headers */
|
|
||||||
if (several_convs) {
|
|
||||||
fprintf(of, CONV_TIME_HEADER);
|
|
||||||
empty_header = CONV_TIME_EMPTY_HEADER;
|
|
||||||
header_length = CONV_TIME_HEADER_LENGTH;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
fprintf(of, TIME_HEADER);
|
|
||||||
empty_header = TIME_EMPTY_HEADER;
|
|
||||||
header_length = TIME_HEADER_LENGTH;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write the node names on top */
|
|
||||||
for (i=0; i<display_nodes; i+=2) {
|
|
||||||
/* print the node identifiers */
|
|
||||||
g_string_printf(label_string, "| %s",
|
|
||||||
get_addr_name(&(user_data->nodes[i+first_node])));
|
|
||||||
enlarge_string(label_string, NODE_CHARS_WIDTH*2, ' ');
|
|
||||||
fprintf(of, "%s", label_string->str);
|
|
||||||
g_string_printf(label_string, "| ");
|
|
||||||
enlarge_string(label_string, NODE_CHARS_WIDTH, ' ');
|
|
||||||
g_string_append(empty_line, label_string->str);
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(of, "|\n%s", empty_header);
|
|
||||||
g_string_printf(label_string, "| ");
|
|
||||||
enlarge_string(label_string, NODE_CHARS_WIDTH, ' ');
|
|
||||||
fprintf(of, "%s", label_string->str);
|
|
||||||
|
|
||||||
/* Write the node names on top */
|
|
||||||
for (i=1; i<display_nodes; i+=2) {
|
|
||||||
/* print the node identifiers */
|
|
||||||
g_string_printf(label_string, "| %s",
|
|
||||||
get_addr_name(&(user_data->nodes[i+first_node])));
|
|
||||||
if (label_string->len < NODE_CHARS_WIDTH)
|
|
||||||
{
|
|
||||||
enlarge_string(label_string, NODE_CHARS_WIDTH, ' ');
|
|
||||||
g_string_append(label_string, "| ");
|
|
||||||
}
|
|
||||||
enlarge_string(label_string, NODE_CHARS_WIDTH*2, ' ');
|
|
||||||
fprintf(of, "%s", label_string->str);
|
|
||||||
g_string_printf(label_string, "| ");
|
|
||||||
enlarge_string(label_string, NODE_CHARS_WIDTH, ' ');
|
|
||||||
g_string_append(empty_line, label_string->str);
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(of, "\n");
|
|
||||||
|
|
||||||
g_string_append_c(empty_line, '|');
|
|
||||||
|
|
||||||
enlarge_string(separator_line, (guint32) empty_line->len + header_length, '-');
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Draw the items
|
|
||||||
*/
|
|
||||||
|
|
||||||
list = g_list_first(user_data->graph_info->list);
|
|
||||||
while (list)
|
|
||||||
{
|
|
||||||
gai = (graph_analysis_item_t *)list->data;
|
|
||||||
list = g_list_next(list);
|
|
||||||
|
|
||||||
if (!gai->display)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
start_position = (gai->src_node-first_node)*NODE_CHARS_WIDTH+NODE_CHARS_WIDTH/2;
|
|
||||||
|
|
||||||
end_position = (gai->dst_node-first_node)*NODE_CHARS_WIDTH+NODE_CHARS_WIDTH/2;
|
|
||||||
|
|
||||||
if (start_position > end_position) {
|
|
||||||
item_width = start_position-end_position;
|
|
||||||
}
|
|
||||||
else if (start_position < end_position) {
|
|
||||||
item_width = end_position-start_position;
|
|
||||||
}
|
|
||||||
else{ /* same origin and destination address */
|
|
||||||
end_position = start_position+NODE_CHARS_WIDTH;
|
|
||||||
item_width = NODE_CHARS_WIDTH;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* separator between conversations */
|
|
||||||
if (gai->conv_num != first_conv_num) {
|
|
||||||
fprintf(of, "%s\n", separator_line->str);
|
|
||||||
first_conv_num = gai->conv_num;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* write the conversation number */
|
|
||||||
if (several_convs) {
|
|
||||||
g_string_printf(label_string, "%i", gai->conv_num);
|
|
||||||
enlarge_string(label_string, 5, ' ');
|
|
||||||
fprintf(of, "%s", label_string->str);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* write the time */
|
|
||||||
g_string_printf(label_string, "|%.3f", nstime_to_sec(&gai->fd->rel_ts));
|
|
||||||
#endif
|
|
||||||
/* Write the time, using the same format as in the time col */
|
|
||||||
set_fd_time(cfile.epan, gai->fd, time_str);
|
|
||||||
g_string_printf(label_string, "|%s", time_str);
|
|
||||||
enlarge_string(label_string, 10, ' ');
|
|
||||||
fprintf(of, "%s", label_string->str);
|
|
||||||
|
|
||||||
/* write the frame label */
|
|
||||||
|
|
||||||
g_string_printf(tmp_str, "%s", empty_line->str);
|
|
||||||
overwrite(tmp_str, gai->frame_label,
|
|
||||||
start_position,
|
|
||||||
end_position
|
|
||||||
);
|
|
||||||
fprintf(of, "%s", tmp_str->str);
|
|
||||||
|
|
||||||
/* write the comments */
|
|
||||||
fprintf(of, "%s\n", gai->comment);
|
|
||||||
|
|
||||||
/* write the arrow and frame label*/
|
|
||||||
fprintf(of, "%s", empty_header);
|
|
||||||
|
|
||||||
g_string_printf(tmp_str, "%s", empty_line->str);
|
|
||||||
|
|
||||||
g_string_truncate(tmp_str2, 0);
|
|
||||||
|
|
||||||
if (start_position<end_position) {
|
|
||||||
enlarge_string(tmp_str2, item_width-2, '-');
|
|
||||||
g_string_append_c(tmp_str2, '>');
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
g_string_printf(tmp_str2, "<");
|
|
||||||
enlarge_string(tmp_str2, item_width-1, '-');
|
|
||||||
}
|
|
||||||
|
|
||||||
overwrite(tmp_str, tmp_str2->str,
|
|
||||||
start_position,
|
|
||||||
end_position
|
|
||||||
);
|
|
||||||
|
|
||||||
g_snprintf(src_port, sizeof(src_port), "(%i)", gai->port_src);
|
|
||||||
g_snprintf(dst_port, sizeof(dst_port), "(%i)", gai->port_dst);
|
|
||||||
|
|
||||||
if (start_position<end_position) {
|
|
||||||
overwrite(tmp_str, src_port, start_position-9, start_position-1);
|
|
||||||
overwrite(tmp_str, dst_port, end_position+1, end_position+9);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
overwrite(tmp_str, src_port, start_position+1, start_position+9);
|
|
||||||
overwrite(tmp_str, dst_port, end_position-9, end_position+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(of, "%s\n", tmp_str->str);
|
|
||||||
}
|
|
||||||
|
|
||||||
exit:
|
|
||||||
g_string_free(label_string, TRUE);
|
|
||||||
g_string_free(empty_line, TRUE);
|
|
||||||
g_string_free(separator_line, TRUE);
|
|
||||||
g_string_free(tmp_str, TRUE);
|
|
||||||
g_string_free(tmp_str2, TRUE);
|
|
||||||
g_free(time_str);
|
|
||||||
fclose (of);
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
/* save in a file */
|
/* save in a file */
|
||||||
|
|
||||||
|
@ -559,7 +273,7 @@ on_save_bt_clicked (GtkWidget *button _U_,
|
||||||
/* User gave up. */
|
/* User gave up. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (dialog_graph_dump_to_file(pathname, user_data)) {
|
if (sequence_analysis_dump_to_file(pathname, user_data->graph_info, &cfile, user_data->dlg.first_node)) {
|
||||||
/* We succeeded. */
|
/* We succeeded. */
|
||||||
g_free(pathname);
|
g_free(pathname);
|
||||||
break;
|
break;
|
||||||
|
@ -580,7 +294,7 @@ static void dialog_graph_draw(graph_analysis_data_t *user_data)
|
||||||
guint32 right_x_border;
|
guint32 right_x_border;
|
||||||
guint32 top_y_border;
|
guint32 top_y_border;
|
||||||
guint32 bottom_y_border;
|
guint32 bottom_y_border;
|
||||||
graph_analysis_item_t *gai;
|
seq_analysis_item_t *gai;
|
||||||
|
|
||||||
PangoLayout *layout;
|
PangoLayout *layout;
|
||||||
PangoLayout *middle_layout;
|
PangoLayout *middle_layout;
|
||||||
|
@ -595,7 +309,6 @@ static void dialog_graph_draw(graph_analysis_data_t *user_data)
|
||||||
char label_string[MAX_COMMENT];
|
char label_string[MAX_COMMENT];
|
||||||
GList *list;
|
GList *list;
|
||||||
cairo_t *cr;
|
cairo_t *cr;
|
||||||
gchar *time_str;
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
GdkColor *color_p, *bg_color_p;
|
GdkColor *color_p, *bg_color_p;
|
||||||
|
@ -657,7 +370,6 @@ static void dialog_graph_draw(graph_analysis_data_t *user_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
bg_pixbuf = gdk_pixbuf_new_from_xpm_data(voip_bg_xpm);
|
bg_pixbuf = gdk_pixbuf_new_from_xpm_data(voip_bg_xpm);
|
||||||
time_str = (gchar *)g_malloc(COL_MAX_LEN);
|
|
||||||
user_data->dlg.needs_redraw = FALSE;
|
user_data->dlg.needs_redraw = FALSE;
|
||||||
|
|
||||||
gtk_widget_get_allocation(user_data->dlg.draw_area_time, &draw_area_time_alloc);
|
gtk_widget_get_allocation(user_data->dlg.draw_area_time, &draw_area_time_alloc);
|
||||||
|
@ -724,7 +436,7 @@ static void dialog_graph_draw(graph_analysis_data_t *user_data)
|
||||||
i = 0;
|
i = 0;
|
||||||
while (list)
|
while (list)
|
||||||
{
|
{
|
||||||
gai = (graph_analysis_item_t *)list->data;
|
gai = (seq_analysis_item_t *)list->data;
|
||||||
if (gai->display) {
|
if (gai->display) {
|
||||||
if (current_item>=display_items) break; /* the item is outside the display */
|
if (current_item>=display_items) break; /* the item is outside the display */
|
||||||
if (i>=first_item) {
|
if (i>=first_item) {
|
||||||
|
@ -738,6 +450,7 @@ static void dialog_graph_draw(graph_analysis_data_t *user_data)
|
||||||
gai->frame_label[46] = '.';
|
gai->frame_label[46] = '.';
|
||||||
}
|
}
|
||||||
user_data->dlg.items[current_item].frame_label = gai->frame_label;
|
user_data->dlg.items[current_item].frame_label = gai->frame_label;
|
||||||
|
user_data->dlg.items[current_item].time_str = gai->time_str;
|
||||||
user_data->dlg.items[current_item].comment = gai->comment;
|
user_data->dlg.items[current_item].comment = gai->comment;
|
||||||
user_data->dlg.items[current_item].conv_num = gai->conv_num;
|
user_data->dlg.items[current_item].conv_num = gai->conv_num;
|
||||||
|
|
||||||
|
@ -764,21 +477,12 @@ static void dialog_graph_draw(graph_analysis_data_t *user_data)
|
||||||
last_item = first_item+display_items-1;
|
last_item = first_item+display_items-1;
|
||||||
user_data->dlg.last_item = last_item;
|
user_data->dlg.last_item = last_item;
|
||||||
|
|
||||||
/* if no items to display */
|
|
||||||
if (display_items == 0) {
|
|
||||||
g_free(time_str);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Calculate the x borders */
|
/* Calculate the x borders */
|
||||||
/* We use time from the last display item to calcultate the x left border */
|
/* We use time from the last display item to calcultate the x left border */
|
||||||
#if 0
|
#if 0
|
||||||
g_snprintf(label_string, MAX_LABEL, "%.3f", nstime_to_sec(&user_data->dlg.items[display_items-1].fd->rel_ts));
|
g_snprintf(label_string, MAX_LABEL, "%.3f", nstime_to_sec(&user_data->dlg.items[display_items-1].fd->rel_ts));
|
||||||
#endif
|
#endif
|
||||||
/* Write the time, using the same format as in th etime col */
|
g_snprintf(label_string, MAX_LABEL, "%s", user_data->dlg.items[display_items-1].time_str);
|
||||||
set_fd_time(cfile.epan, user_data->dlg.items[display_items-1].fd, time_str);
|
|
||||||
g_snprintf(label_string, MAX_LABEL, "%s", time_str);
|
|
||||||
layout = gtk_widget_create_pango_layout(user_data->dlg.draw_area_time, label_string);
|
layout = gtk_widget_create_pango_layout(user_data->dlg.draw_area_time, label_string);
|
||||||
middle_layout = gtk_widget_create_pango_layout(user_data->dlg.draw_area_time, label_string);
|
middle_layout = gtk_widget_create_pango_layout(user_data->dlg.draw_area_time, label_string);
|
||||||
small_layout = gtk_widget_create_pango_layout(user_data->dlg.draw_area_time, label_string);
|
small_layout = gtk_widget_create_pango_layout(user_data->dlg.draw_area_time, label_string);
|
||||||
|
@ -923,10 +627,10 @@ static void dialog_graph_draw(graph_analysis_data_t *user_data)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
/* Draw the node names on top and the division lines */
|
/* Draw the node names on top and the division lines */
|
||||||
for (i=0; i<user_data->num_nodes; i++) {
|
for (i=0; i<user_data->graph_info->num_nodes; i++) {
|
||||||
/* print the node identifiers */
|
/* print the node identifiers */
|
||||||
/* XXX we assign 5 pixels per character in the node identity */
|
/* XXX we assign 5 pixels per character in the node identity */
|
||||||
g_strlcpy(label_string, get_addr_name(&(user_data->nodes[i])), NODE_WIDTH/5);
|
g_strlcpy(label_string, get_addr_name(&(user_data->graph_info->nodes[i])), NODE_WIDTH/5);
|
||||||
pango_layout_set_text(layout, label_string, -1);
|
pango_layout_set_text(layout, label_string, -1);
|
||||||
pango_layout_get_pixel_size(layout, &label_width, &label_height);
|
pango_layout_get_pixel_size(layout, &label_width, &label_height);
|
||||||
#if GTK_CHECK_VERSION(2,22,0)
|
#if GTK_CHECK_VERSION(2,22,0)
|
||||||
|
@ -978,8 +682,7 @@ static void dialog_graph_draw(graph_analysis_data_t *user_data)
|
||||||
g_snprintf(label_string, MAX_LABEL, "%.3f", nstime_to_sec(&user_data->dlg.items[current_item].fd->rel_ts));
|
g_snprintf(label_string, MAX_LABEL, "%.3f", nstime_to_sec(&user_data->dlg.items[current_item].fd->rel_ts));
|
||||||
#endif
|
#endif
|
||||||
/* Draw the time */
|
/* Draw the time */
|
||||||
set_fd_time(cfile.epan, user_data->dlg.items[current_item].fd, time_str);
|
g_snprintf(label_string, MAX_LABEL, "%s", user_data->dlg.items[current_item].time_str);
|
||||||
g_snprintf(label_string, MAX_LABEL, "%s", time_str);
|
|
||||||
pango_layout_set_text(layout, label_string, -1);
|
pango_layout_set_text(layout, label_string, -1);
|
||||||
pango_layout_get_pixel_size(layout, &label_width, &label_height);
|
pango_layout_get_pixel_size(layout, &label_width, &label_height);
|
||||||
#if GTK_CHECK_VERSION(2,22,0)
|
#if GTK_CHECK_VERSION(2,22,0)
|
||||||
|
@ -1186,7 +889,7 @@ static void dialog_graph_draw(graph_analysis_data_t *user_data)
|
||||||
#endif
|
#endif
|
||||||
/* draw the div line of the selected item with soft gray*/
|
/* draw the div line of the selected item with soft gray*/
|
||||||
if ( current_item+first_item == user_data->dlg.selected_item )
|
if ( current_item+first_item == user_data->dlg.selected_item )
|
||||||
for (i=0; i<user_data->num_nodes; i++) {
|
for (i=0; i<user_data->graph_info->num_nodes; i++) {
|
||||||
#if GTK_CHECK_VERSION(2,22,0)
|
#if GTK_CHECK_VERSION(2,22,0)
|
||||||
cr = cairo_create (user_data->dlg.surface_main);
|
cr = cairo_create (user_data->dlg.surface_main);
|
||||||
gdk_cairo_set_source_rgba (cr, &grey_color1);
|
gdk_cairo_set_source_rgba (cr, &grey_color1);
|
||||||
|
@ -1214,7 +917,6 @@ static void dialog_graph_draw(graph_analysis_data_t *user_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
g_object_unref(G_OBJECT(layout));
|
g_object_unref(G_OBJECT(layout));
|
||||||
g_free(time_str);
|
|
||||||
|
|
||||||
/* refresh the draw areas */
|
/* refresh the draw areas */
|
||||||
if (gtk_widget_is_drawable(user_data->dlg.draw_area_time) ) {
|
if (gtk_widget_is_drawable(user_data->dlg.draw_area_time) ) {
|
||||||
|
@ -1851,11 +1553,11 @@ static void create_draw_area(graph_analysis_data_t *user_data, GtkWidget *box)
|
||||||
/* create main Graph draw area */
|
/* create main Graph draw area */
|
||||||
user_data->dlg.draw_area = gtk_drawing_area_new();
|
user_data->dlg.draw_area = gtk_drawing_area_new();
|
||||||
/* allow a little extra space (2*NODE_WIDTH) for wide labels */
|
/* allow a little extra space (2*NODE_WIDTH) for wide labels */
|
||||||
user_data->dlg.surface_width = user_data->num_nodes * NODE_WIDTH + 2*NODE_WIDTH;
|
user_data->dlg.surface_width = user_data->graph_info->num_nodes * NODE_WIDTH + 2*NODE_WIDTH;
|
||||||
gtk_widget_set_size_request(user_data->dlg.draw_area, user_data->dlg.surface_width, user_data->dlg.surface_height);
|
gtk_widget_set_size_request(user_data->dlg.draw_area, user_data->dlg.surface_width, user_data->dlg.surface_height);
|
||||||
user_data->dlg.scroll_window = gtk_scrolled_window_new(NULL, NULL);
|
user_data->dlg.scroll_window = gtk_scrolled_window_new(NULL, NULL);
|
||||||
if ( user_data->num_nodes < 6)
|
if ( user_data->graph_info->num_nodes < 6)
|
||||||
gtk_widget_set_size_request(user_data->dlg.scroll_window, NODE_WIDTH*user_data->num_nodes, user_data->dlg.surface_height);
|
gtk_widget_set_size_request(user_data->dlg.scroll_window, NODE_WIDTH*user_data->graph_info->num_nodes, user_data->dlg.surface_height);
|
||||||
else
|
else
|
||||||
gtk_widget_set_size_request(user_data->dlg.scroll_window, NODE_WIDTH*5, user_data->dlg.surface_height);
|
gtk_widget_set_size_request(user_data->dlg.scroll_window, NODE_WIDTH*5, user_data->dlg.surface_height);
|
||||||
|
|
||||||
|
@ -2036,60 +1738,13 @@ static void dialog_graph_create_window(graph_analysis_data_t *user_data)
|
||||||
g_free(win_name);
|
g_free(win_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the index array if the node is in the array. Return -1 if there is room in the array
|
|
||||||
* and Return -2 if the array is full
|
|
||||||
*/
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
static gint add_or_get_node(graph_analysis_data_t *user_data, address *node) {
|
graph_analysis_data_t *graph_analysis_init(seq_analysis_info_t *sainfo)
|
||||||
guint i;
|
|
||||||
|
|
||||||
if (node->type == AT_NONE) return NODE_OVERFLOW;
|
|
||||||
|
|
||||||
for (i=0; i<MAX_NUM_NODES && i < user_data->num_nodes ; i++) {
|
|
||||||
if ( CMP_ADDRESS(&(user_data->nodes[i]), node) == 0 ) return i; /* it is in the array */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == MAX_NUM_NODES) {
|
|
||||||
return NODE_OVERFLOW;
|
|
||||||
} else {
|
|
||||||
user_data->num_nodes++;
|
|
||||||
COPY_ADDRESS(&(user_data->nodes[i]), node);
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the nodes from the list */
|
|
||||||
/****************************************************************************/
|
|
||||||
static void get_nodes(graph_analysis_data_t *user_data)
|
|
||||||
{
|
|
||||||
GList *list;
|
|
||||||
graph_analysis_item_t *gai;
|
|
||||||
|
|
||||||
/* fill the node array */
|
|
||||||
list = g_list_first(user_data->graph_info->list);
|
|
||||||
while (list)
|
|
||||||
{
|
|
||||||
gai = (graph_analysis_item_t *)list->data;
|
|
||||||
if (gai->display) {
|
|
||||||
user_data->num_items++;
|
|
||||||
if (!user_data->dlg.inverse) {
|
|
||||||
gai->src_node = (guint16)add_or_get_node(user_data, &(gai->src_addr));
|
|
||||||
gai->dst_node = (guint16)add_or_get_node(user_data, &(gai->dst_addr));
|
|
||||||
} else {
|
|
||||||
gai->dst_node = (guint16)add_or_get_node(user_data, &(gai->src_addr));
|
|
||||||
gai->src_node = (guint16)add_or_get_node(user_data, &(gai->dst_addr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
list = g_list_next(list);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
graph_analysis_data_t *graph_analysis_init(void)
|
|
||||||
{
|
{
|
||||||
graph_analysis_data_t *user_data;
|
graph_analysis_data_t *user_data;
|
||||||
/* init */
|
/* init */
|
||||||
user_data = g_new(graph_analysis_data_t,1);
|
user_data = g_new(graph_analysis_data_t,1);
|
||||||
|
user_data->graph_info = sainfo;
|
||||||
|
|
||||||
/* init user_data */
|
/* init user_data */
|
||||||
graph_analysis_init_dlg(user_data);
|
graph_analysis_init_dlg(user_data);
|
||||||
|
@ -2107,7 +1762,7 @@ void graph_analysis_create(graph_analysis_data_t *user_data)
|
||||||
graph_analysis_reset(user_data);
|
graph_analysis_reset(user_data);
|
||||||
|
|
||||||
/* get nodes (each node is an address) */
|
/* get nodes (each node is an address) */
|
||||||
get_nodes(user_data);
|
user_data->num_items = sequence_analysis_get_nodes(user_data->graph_info);
|
||||||
|
|
||||||
/* create the graph windows */
|
/* create the graph windows */
|
||||||
dialog_graph_create_window(user_data);
|
dialog_graph_create_window(user_data);
|
||||||
|
@ -2125,12 +1780,12 @@ void graph_analysis_update(graph_analysis_data_t *user_data)
|
||||||
graph_analysis_reset(user_data);
|
graph_analysis_reset(user_data);
|
||||||
|
|
||||||
/* get nodes (each node is an address) */
|
/* get nodes (each node is an address) */
|
||||||
get_nodes(user_data);
|
user_data->num_items = sequence_analysis_get_nodes(user_data->graph_info);
|
||||||
|
|
||||||
user_data->dlg.surface_width = user_data->num_nodes * NODE_WIDTH;
|
user_data->dlg.surface_width = user_data->graph_info->num_nodes * NODE_WIDTH;
|
||||||
gtk_widget_set_size_request(user_data->dlg.draw_area, user_data->dlg.surface_width, user_data->dlg.surface_height);
|
gtk_widget_set_size_request(user_data->dlg.draw_area, user_data->dlg.surface_width, user_data->dlg.surface_height);
|
||||||
if (user_data->num_nodes < 6)
|
if (user_data->graph_info->num_nodes < 6)
|
||||||
gtk_widget_set_size_request(user_data->dlg.scroll_window, NODE_WIDTH*user_data->num_nodes, user_data->dlg.surface_height);
|
gtk_widget_set_size_request(user_data->dlg.scroll_window, NODE_WIDTH*user_data->graph_info->num_nodes, user_data->dlg.surface_height);
|
||||||
else
|
else
|
||||||
gtk_widget_set_size_request(user_data->dlg.scroll_window, NODE_WIDTH*5, user_data->dlg.surface_height);
|
gtk_widget_set_size_request(user_data->dlg.scroll_window, NODE_WIDTH*5, user_data->dlg.surface_height);
|
||||||
|
|
||||||
|
@ -2146,12 +1801,12 @@ void graph_analysis_update(graph_analysis_data_t *user_data)
|
||||||
void graph_analysis_redraw(graph_analysis_data_t *user_data)
|
void graph_analysis_redraw(graph_analysis_data_t *user_data)
|
||||||
{
|
{
|
||||||
/* get nodes (each node is an address) */
|
/* get nodes (each node is an address) */
|
||||||
get_nodes(user_data);
|
user_data->num_items = sequence_analysis_get_nodes(user_data->graph_info);
|
||||||
|
|
||||||
user_data->dlg.surface_width = user_data->num_nodes * NODE_WIDTH;
|
user_data->dlg.surface_width = user_data->graph_info->num_nodes * NODE_WIDTH;
|
||||||
gtk_widget_set_size_request(user_data->dlg.draw_area, user_data->dlg.surface_width, user_data->dlg.surface_height);
|
gtk_widget_set_size_request(user_data->dlg.draw_area, user_data->dlg.surface_width, user_data->dlg.surface_height);
|
||||||
if (user_data->num_nodes < 6)
|
if (user_data->graph_info->num_nodes < 6)
|
||||||
gtk_widget_set_size_request(user_data->dlg.scroll_window, NODE_WIDTH*user_data->num_nodes, user_data->dlg.surface_height);
|
gtk_widget_set_size_request(user_data->dlg.scroll_window, NODE_WIDTH*user_data->graph_info->num_nodes, user_data->dlg.surface_height);
|
||||||
else
|
else
|
||||||
gtk_widget_set_size_request(user_data->dlg.scroll_window, NODE_WIDTH*5, user_data->dlg.surface_height);
|
gtk_widget_set_size_request(user_data->dlg.scroll_window, NODE_WIDTH*5, user_data->dlg.surface_height);
|
||||||
|
|
||||||
|
|
|
@ -34,35 +34,10 @@
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
#include <epan/address.h>
|
#include <epan/address.h>
|
||||||
|
#include <ui/tap-sequence-analysis.h>
|
||||||
#define MAX_NUM_NODES 40
|
|
||||||
|
|
||||||
/** defines an entry for the graph analysis */
|
|
||||||
typedef struct _graph_analysis_item {
|
|
||||||
frame_data *fd; /**< Holds the frame number and time information */
|
|
||||||
address src_addr;
|
|
||||||
guint16 port_src;
|
|
||||||
address dst_addr;
|
|
||||||
guint16 port_dst;
|
|
||||||
gchar *frame_label; /**< the label on top of the arrow */
|
|
||||||
gchar *comment; /**< a comment that appears at the left of the graph */
|
|
||||||
guint16 conv_num; /**< the conversation number, each conversation will be colored */
|
|
||||||
gboolean display; /**< indicate if the packet is displayed or not in the graph */
|
|
||||||
guint16 src_node; /**< this is used by graph_analysis.c to identify the node */
|
|
||||||
guint16 dst_node; /**< a node is an IP address that will be displayed in columns */
|
|
||||||
guint16 line_style; /**< the arrow line width in pixels*/
|
|
||||||
} graph_analysis_item_t;
|
|
||||||
|
|
||||||
/** defines the graph analysis structure */
|
|
||||||
typedef struct _graph_analysis_info {
|
|
||||||
int nconv; /**< number of conversations in the list */
|
|
||||||
GList* list; /**< list with the graph analysis items */
|
|
||||||
GHashTable *ht; /**< hash table for retrieving graph analysis items */
|
|
||||||
} graph_analysis_info_t;
|
|
||||||
|
|
||||||
/** max number of nodes to display, each node will be an IP address */
|
/** max number of nodes to display, each node will be an IP address */
|
||||||
#define MAX_NUM_COL_CONV 10
|
#define MAX_NUM_COL_CONV 10
|
||||||
#define NODE_OVERFLOW MAX_NUM_NODES+1
|
|
||||||
#define NUM_DISPLAY_ITEMS 1000
|
#define NUM_DISPLAY_ITEMS 1000
|
||||||
|
|
||||||
typedef struct _display_items {
|
typedef struct _display_items {
|
||||||
|
@ -70,6 +45,7 @@ typedef struct _display_items {
|
||||||
guint16 port_src;
|
guint16 port_src;
|
||||||
guint16 port_dst;
|
guint16 port_dst;
|
||||||
gchar *frame_label; /**< the label on top of the arrow */
|
gchar *frame_label; /**< the label on top of the arrow */
|
||||||
|
gchar *time_str; /**< timestamp */
|
||||||
gchar *comment; /**< a comment that appears at the left of the graph */
|
gchar *comment; /**< a comment that appears at the left of the graph */
|
||||||
guint16 conv_num; /**< the conversation number, each conversation will be colored */
|
guint16 conv_num; /**< the conversation number, each conversation will be colored */
|
||||||
guint16 src_node; /**< this is used by graph_analysis.c to identify the node */
|
guint16 src_node; /**< this is used by graph_analysis.c to identify the node */
|
||||||
|
@ -119,18 +95,16 @@ typedef void (*destroy_user_data_cb)(void *data);
|
||||||
/** structure that holds general information and the dialog */
|
/** structure that holds general information and the dialog */
|
||||||
typedef struct _graph_analysis_data_t {
|
typedef struct _graph_analysis_data_t {
|
||||||
/**> graphic data */
|
/**> graphic data */
|
||||||
graph_analysis_info_t *graph_info;
|
seq_analysis_info_t *graph_info;
|
||||||
|
|
||||||
/**> dialog associated data */
|
/**> dialog associated data */
|
||||||
graph_analysis_dialog_data_t dlg;
|
graph_analysis_dialog_data_t dlg;
|
||||||
address nodes[MAX_NUM_NODES];
|
|
||||||
guint32 num_nodes;
|
|
||||||
guint32 num_items;
|
guint32 num_items;
|
||||||
destroy_user_data_cb on_destroy_user_data; /**< callback info for destroy */
|
destroy_user_data_cb on_destroy_user_data; /**< callback info for destroy */
|
||||||
void *data; /**< data to be passes when on destroy */
|
void *data; /**< data to be passes when on destroy */
|
||||||
} graph_analysis_data_t;
|
} graph_analysis_data_t;
|
||||||
|
|
||||||
graph_analysis_data_t* graph_analysis_init(void);
|
graph_analysis_data_t* graph_analysis_init(seq_analysis_info_t *sainfo);
|
||||||
void graph_analysis_create(graph_analysis_data_t* user_data);
|
void graph_analysis_create(graph_analysis_data_t* user_data);
|
||||||
void graph_analysis_update(graph_analysis_data_t* user_data);
|
void graph_analysis_update(graph_analysis_data_t* user_data);
|
||||||
void graph_analysis_redraw(graph_analysis_data_t* user_data);
|
void graph_analysis_redraw(graph_analysis_data_t* user_data);
|
||||||
|
|
|
@ -427,7 +427,7 @@ static void
|
||||||
mark_rtp_stream_to_play(gchar *key _U_ , rtp_stream_info_t *rsi, gpointer ptr _U_)
|
mark_rtp_stream_to_play(gchar *key _U_ , rtp_stream_info_t *rsi, gpointer ptr _U_)
|
||||||
{
|
{
|
||||||
GList* graph_list;
|
GList* graph_list;
|
||||||
graph_analysis_item_t *graph_item;
|
seq_analysis_item_t *graph_item;
|
||||||
GList* voip_calls_list;
|
GList* voip_calls_list;
|
||||||
voip_calls_info_t *tmp_voip_call;
|
voip_calls_info_t *tmp_voip_call;
|
||||||
|
|
||||||
|
@ -440,7 +440,7 @@ mark_rtp_stream_to_play(gchar *key _U_ , rtp_stream_info_t *rsi, gpointer ptr _U
|
||||||
graph_list = g_list_first(voip_calls->graph_analysis->list);
|
graph_list = g_list_first(voip_calls->graph_analysis->list);
|
||||||
while (graph_list)
|
while (graph_list)
|
||||||
{
|
{
|
||||||
graph_item = (graph_analysis_item_t *)graph_list->data;
|
graph_item = (seq_analysis_item_t *)graph_list->data;
|
||||||
if (rsi->first_frame_number == graph_item->fd->num) {
|
if (rsi->first_frame_number == graph_item->fd->num) {
|
||||||
rsi->call_num = graph_item->conv_num;
|
rsi->call_num = graph_item->conv_num;
|
||||||
/* if it is in the graph list, then check if the voip_call is selected */
|
/* if it is in the graph list, then check if the voip_call is selected */
|
||||||
|
|
|
@ -160,7 +160,7 @@ void voip_calls_reset(voip_calls_tapinfo_t *tapinfo)
|
||||||
voip_calls_info_t *callsinfo;
|
voip_calls_info_t *callsinfo;
|
||||||
voip_rtp_tapinfo_t *rtp_tapinfo = &the_tapinfo_rtp_struct;
|
voip_rtp_tapinfo_t *rtp_tapinfo = &the_tapinfo_rtp_struct;
|
||||||
voip_rtp_stream_info_t *strinfo;
|
voip_rtp_stream_info_t *strinfo;
|
||||||
graph_analysis_item_t *graph_item;
|
seq_analysis_item_t *graph_item;
|
||||||
GList *list;
|
GList *list;
|
||||||
|
|
||||||
#ifdef HAVE_LIBPORTAUDIO
|
#ifdef HAVE_LIBPORTAUDIO
|
||||||
|
@ -204,7 +204,7 @@ void voip_calls_reset(voip_calls_tapinfo_t *tapinfo)
|
||||||
list = g_list_first(tapinfo->graph_analysis->list);
|
list = g_list_first(tapinfo->graph_analysis->list);
|
||||||
while (list)
|
while (list)
|
||||||
{
|
{
|
||||||
graph_item = (graph_analysis_item_t *)list->data;
|
graph_item = (seq_analysis_item_t *)list->data;
|
||||||
g_free(graph_item->frame_label);
|
g_free(graph_item->frame_label);
|
||||||
g_free(graph_item->comment);
|
g_free(graph_item->comment);
|
||||||
g_free((void *)graph_item->src_addr.data);
|
g_free((void *)graph_item->src_addr.data);
|
||||||
|
@ -234,7 +234,7 @@ void voip_calls_reset(voip_calls_tapinfo_t *tapinfo)
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
void graph_analysis_data_init(void) {
|
void graph_analysis_data_init(void) {
|
||||||
the_tapinfo_struct.graph_analysis = (graph_analysis_info_t *)g_malloc(sizeof(graph_analysis_info_t));
|
the_tapinfo_struct.graph_analysis = (seq_analysis_info_t *)g_malloc(sizeof(seq_analysis_info_t));
|
||||||
the_tapinfo_struct.graph_analysis->nconv = 0;
|
the_tapinfo_struct.graph_analysis->nconv = 0;
|
||||||
the_tapinfo_struct.graph_analysis->list = NULL;
|
the_tapinfo_struct.graph_analysis->list = NULL;
|
||||||
the_tapinfo_struct.graph_analysis->ht= g_hash_table_new(g_int_hash, g_int_equal);
|
the_tapinfo_struct.graph_analysis->ht= g_hash_table_new(g_int_hash, g_int_equal);
|
||||||
|
@ -244,9 +244,9 @@ void graph_analysis_data_init(void) {
|
||||||
/* Add a new item into the graph */
|
/* Add a new item into the graph */
|
||||||
static void add_to_graph(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, const gchar *frame_label, const gchar *comment, guint16 call_num, address *src_addr, address *dst_addr, guint16 line_style)
|
static void add_to_graph(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, const gchar *frame_label, const gchar *comment, guint16 call_num, address *src_addr, address *dst_addr, guint16 line_style)
|
||||||
{
|
{
|
||||||
graph_analysis_item_t *gai;
|
seq_analysis_item_t *gai;
|
||||||
|
|
||||||
gai = (graph_analysis_item_t *)g_malloc(sizeof(graph_analysis_item_t));
|
gai = (seq_analysis_item_t *)g_malloc(sizeof(seq_analysis_item_t));
|
||||||
gai->fd = pinfo->fd;
|
gai->fd = pinfo->fd;
|
||||||
COPY_ADDRESS(&(gai->src_addr),src_addr);
|
COPY_ADDRESS(&(gai->src_addr),src_addr);
|
||||||
COPY_ADDRESS(&(gai->dst_addr),dst_addr);
|
COPY_ADDRESS(&(gai->dst_addr),dst_addr);
|
||||||
|
@ -276,12 +276,12 @@ static void add_to_graph(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo,
|
||||||
/* return 0 if the frame_num is not in the graph list */
|
/* return 0 if the frame_num is not in the graph list */
|
||||||
static int append_to_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num, const gchar *new_frame_label, const gchar *new_comment)
|
static int append_to_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num, const gchar *new_frame_label, const gchar *new_comment)
|
||||||
{
|
{
|
||||||
graph_analysis_item_t *gai=NULL;
|
seq_analysis_item_t *gai=NULL;
|
||||||
gchar *frame_label = NULL;
|
gchar *frame_label = NULL;
|
||||||
gchar *comment = NULL;
|
gchar *comment = NULL;
|
||||||
|
|
||||||
if(NULL!=tapinfo->graph_analysis->ht)
|
if(NULL!=tapinfo->graph_analysis->ht)
|
||||||
gai=(graph_analysis_item_t *)g_hash_table_lookup(tapinfo->graph_analysis->ht, &frame_num);
|
gai=(seq_analysis_item_t *)g_hash_table_lookup(tapinfo->graph_analysis->ht, &frame_num);
|
||||||
if(gai) {
|
if(gai) {
|
||||||
frame_label = gai->frame_label;
|
frame_label = gai->frame_label;
|
||||||
comment = gai->comment;
|
comment = gai->comment;
|
||||||
|
@ -305,12 +305,12 @@ static int append_to_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 fram
|
||||||
/* return 0 if the frame_num is not in the graph list */
|
/* return 0 if the frame_num is not in the graph list */
|
||||||
static int change_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num, const gchar *new_frame_label, const gchar *new_comment)
|
static int change_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_num, const gchar *new_frame_label, const gchar *new_comment)
|
||||||
{
|
{
|
||||||
graph_analysis_item_t *gai=NULL;
|
seq_analysis_item_t *gai=NULL;
|
||||||
gchar *frame_label = NULL;
|
gchar *frame_label = NULL;
|
||||||
gchar *comment = NULL;
|
gchar *comment = NULL;
|
||||||
|
|
||||||
if(NULL!=tapinfo->graph_analysis->ht)
|
if(NULL!=tapinfo->graph_analysis->ht)
|
||||||
gai=(graph_analysis_item_t *)g_hash_table_lookup(tapinfo->graph_analysis->ht, &frame_num);
|
gai=(seq_analysis_item_t *)g_hash_table_lookup(tapinfo->graph_analysis->ht, &frame_num);
|
||||||
if(gai) {
|
if(gai) {
|
||||||
frame_label = gai->frame_label;
|
frame_label = gai->frame_label;
|
||||||
comment = gai->comment;
|
comment = gai->comment;
|
||||||
|
@ -333,7 +333,7 @@ static int change_frame_graph(voip_calls_tapinfo_t *tapinfo _U_, guint32 frame_n
|
||||||
/* Change all the graph items with call_num to new_call_num */
|
/* Change all the graph items with call_num to new_call_num */
|
||||||
static guint change_call_num_graph(voip_calls_tapinfo_t *tapinfo _U_, guint16 call_num, guint16 new_call_num)
|
static guint change_call_num_graph(voip_calls_tapinfo_t *tapinfo _U_, guint16 call_num, guint16 new_call_num)
|
||||||
{
|
{
|
||||||
graph_analysis_item_t *gai;
|
seq_analysis_item_t *gai;
|
||||||
GList *list;
|
GList *list;
|
||||||
guint items_changed;
|
guint items_changed;
|
||||||
|
|
||||||
|
@ -341,7 +341,7 @@ static guint change_call_num_graph(voip_calls_tapinfo_t *tapinfo _U_, guint16 ca
|
||||||
list = g_list_first(tapinfo->graph_analysis->list);
|
list = g_list_first(tapinfo->graph_analysis->list);
|
||||||
while (list)
|
while (list)
|
||||||
{
|
{
|
||||||
gai = (graph_analysis_item_t *)list->data;
|
gai = (seq_analysis_item_t *)list->data;
|
||||||
if (gai->conv_num == call_num) {
|
if (gai->conv_num == call_num) {
|
||||||
gai->conv_num = new_call_num;
|
gai->conv_num = new_call_num;
|
||||||
items_changed++;
|
items_changed++;
|
||||||
|
@ -355,12 +355,12 @@ static guint change_call_num_graph(voip_calls_tapinfo_t *tapinfo _U_, guint16 ca
|
||||||
/* Insert the item in the graph list */
|
/* Insert the item in the graph list */
|
||||||
static void insert_to_graph_t38(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, const gchar *frame_label, const gchar *comment, guint16 call_num, address *src_addr, address *dst_addr, guint16 line_style, guint32 frame_num)
|
static void insert_to_graph_t38(voip_calls_tapinfo_t *tapinfo _U_, packet_info *pinfo, const gchar *frame_label, const gchar *comment, guint16 call_num, address *src_addr, address *dst_addr, guint16 line_style, guint32 frame_num)
|
||||||
{
|
{
|
||||||
graph_analysis_item_t *gai, *new_gai;
|
seq_analysis_item_t *gai, *new_gai;
|
||||||
GList *list;
|
GList *list;
|
||||||
guint item_num;
|
guint item_num;
|
||||||
gboolean inserted;
|
gboolean inserted;
|
||||||
|
|
||||||
new_gai = (graph_analysis_item_t *)g_malloc(sizeof(graph_analysis_item_t));
|
new_gai = (seq_analysis_item_t *)g_malloc(sizeof(seq_analysis_item_t));
|
||||||
new_gai->fd = packet_list_get_row_data(frame_num);
|
new_gai->fd = packet_list_get_row_data(frame_num);
|
||||||
COPY_ADDRESS(&(new_gai->src_addr),src_addr);
|
COPY_ADDRESS(&(new_gai->src_addr),src_addr);
|
||||||
COPY_ADDRESS(&(new_gai->dst_addr),dst_addr);
|
COPY_ADDRESS(&(new_gai->dst_addr),dst_addr);
|
||||||
|
@ -385,7 +385,7 @@ static void insert_to_graph_t38(voip_calls_tapinfo_t *tapinfo _U_, packet_info *
|
||||||
list = g_list_first(tapinfo->graph_analysis->list);
|
list = g_list_first(tapinfo->graph_analysis->list);
|
||||||
while (list)
|
while (list)
|
||||||
{
|
{
|
||||||
gai = (graph_analysis_item_t *)list->data;
|
gai = (seq_analysis_item_t *)list->data;
|
||||||
if (gai->fd->num > frame_num) {
|
if (gai->fd->num > frame_num) {
|
||||||
the_tapinfo_struct.graph_analysis->list = g_list_insert(the_tapinfo_struct.graph_analysis->list, new_gai, item_num);
|
the_tapinfo_struct.graph_analysis->list = g_list_insert(the_tapinfo_struct.graph_analysis->list, new_gai, item_num);
|
||||||
g_hash_table_insert(tapinfo->graph_analysis->ht, &new_gai->fd->num, new_gai);
|
g_hash_table_insert(tapinfo->graph_analysis->ht, &new_gai->fd->num, new_gai);
|
||||||
|
@ -598,8 +598,8 @@ static void RTP_packet_draw(void *prs _U_)
|
||||||
GList *rtp_streams_list;
|
GList *rtp_streams_list;
|
||||||
voip_rtp_stream_info_t *rtp_listinfo;
|
voip_rtp_stream_info_t *rtp_listinfo;
|
||||||
/* GList *voip_calls_graph_list; */
|
/* GList *voip_calls_graph_list; */
|
||||||
graph_analysis_item_t *gai;
|
seq_analysis_item_t *gai;
|
||||||
graph_analysis_item_t *new_gai;
|
seq_analysis_item_t *new_gai;
|
||||||
guint16 conv_num;
|
guint16 conv_num;
|
||||||
guint32 duration;
|
guint32 duration;
|
||||||
|
|
||||||
|
@ -612,12 +612,12 @@ static void RTP_packet_draw(void *prs _U_)
|
||||||
/* using the setup frame number of the RTP stream, we get the call number that it belongs to*/
|
/* using the setup frame number of the RTP stream, we get the call number that it belongs to*/
|
||||||
/* voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list); */
|
/* voip_calls_graph_list = g_list_first(the_tapinfo_struct.graph_analysis->list); */
|
||||||
|
|
||||||
gai = (graph_analysis_item_t *)g_hash_table_lookup(the_tapinfo_struct.graph_analysis->ht, &rtp_listinfo->setup_frame_number);
|
gai = (seq_analysis_item_t *)g_hash_table_lookup(the_tapinfo_struct.graph_analysis->ht, &rtp_listinfo->setup_frame_number);
|
||||||
if(gai != NULL) {
|
if(gai != NULL) {
|
||||||
/* Found the setup frame*/
|
/* Found the setup frame*/
|
||||||
conv_num = gai->conv_num;
|
conv_num = gai->conv_num;
|
||||||
/* if RTP was already in the Graph, just update the comment information */
|
/* if RTP was already in the Graph, just update the comment information */
|
||||||
gai = (graph_analysis_item_t *)g_hash_table_lookup(the_tapinfo_struct.graph_analysis->ht, &rtp_listinfo->start_fd->num);
|
gai = (seq_analysis_item_t *)g_hash_table_lookup(the_tapinfo_struct.graph_analysis->ht, &rtp_listinfo->start_fd->num);
|
||||||
if(gai != NULL) {
|
if(gai != NULL) {
|
||||||
duration = (guint32)(nstime_to_msec(&rtp_listinfo->stop_rel_ts) - nstime_to_msec(&rtp_listinfo->start_rel_ts));
|
duration = (guint32)(nstime_to_msec(&rtp_listinfo->stop_rel_ts) - nstime_to_msec(&rtp_listinfo->start_rel_ts));
|
||||||
g_free(gai->comment);
|
g_free(gai->comment);
|
||||||
|
@ -625,7 +625,7 @@ static void RTP_packet_draw(void *prs _U_)
|
||||||
(rtp_listinfo->is_srtp)?"SRTP":"RTP", rtp_listinfo->npackets,
|
(rtp_listinfo->is_srtp)?"SRTP":"RTP", rtp_listinfo->npackets,
|
||||||
duration/1000,(duration%1000), rtp_listinfo->ssrc);
|
duration/1000,(duration%1000), rtp_listinfo->ssrc);
|
||||||
}else {
|
}else {
|
||||||
new_gai = (graph_analysis_item_t *)g_malloc(sizeof(graph_analysis_item_t));
|
new_gai = (seq_analysis_item_t *)g_malloc(sizeof(seq_analysis_item_t));
|
||||||
new_gai->fd = rtp_listinfo->start_fd;
|
new_gai->fd = rtp_listinfo->start_fd;
|
||||||
COPY_ADDRESS(&(new_gai->src_addr),&(rtp_listinfo->src_addr));
|
COPY_ADDRESS(&(new_gai->src_addr),&(rtp_listinfo->src_addr));
|
||||||
COPY_ADDRESS(&(new_gai->dst_addr),&(rtp_listinfo->dest_addr));
|
COPY_ADDRESS(&(new_gai->dst_addr),&(rtp_listinfo->dest_addr));
|
||||||
|
@ -658,8 +658,8 @@ static void RTP_packet_draw(void *prs _U_)
|
||||||
voip_rtp_stream_info_t *rtp_listinfo;
|
voip_rtp_stream_info_t *rtp_listinfo;
|
||||||
GList *voip_calls_graph_list;
|
GList *voip_calls_graph_list;
|
||||||
guint item;
|
guint item;
|
||||||
graph_analysis_item_t *gai;
|
seq_analysis_item_t *gai;
|
||||||
graph_analysis_item_t *new_gai;
|
seq_analysis_item_t *new_gai;
|
||||||
guint16 conv_num;
|
guint16 conv_num;
|
||||||
guint32 duration;
|
guint32 duration;
|
||||||
|
|
||||||
|
@ -698,7 +698,7 @@ static void RTP_packet_draw(void *prs _U_)
|
||||||
|
|
||||||
/* add the RTP item to the graph if was not there*/
|
/* add the RTP item to the graph if was not there*/
|
||||||
if (rtp_listinfo->start_fd->num<gai->fd->num || !voip_calls_graph_list) {
|
if (rtp_listinfo->start_fd->num<gai->fd->num || !voip_calls_graph_list) {
|
||||||
new_gai = g_malloc(sizeof(graph_analysis_item_t));
|
new_gai = g_malloc(sizeof(seq_analysis_item_t));
|
||||||
new_gai->fd = rtp_listinfo->start_fd;
|
new_gai->fd = rtp_listinfo->start_fd;
|
||||||
COPY_ADDRESS(&(new_gai->src_addr),&(rtp_listinfo->src_addr));
|
COPY_ADDRESS(&(new_gai->src_addr),&(rtp_listinfo->src_addr));
|
||||||
COPY_ADDRESS(&(new_gai->dst_addr),&(rtp_listinfo->dest_addr));
|
COPY_ADDRESS(&(new_gai->dst_addr),&(rtp_listinfo->dest_addr));
|
||||||
|
@ -781,7 +781,7 @@ T38_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const vo
|
||||||
GList *list;
|
GList *list;
|
||||||
gchar *frame_label = NULL;
|
gchar *frame_label = NULL;
|
||||||
gchar *comment = NULL;
|
gchar *comment = NULL;
|
||||||
graph_analysis_item_t *tmp_gai, *gai = NULL;
|
seq_analysis_item_t *tmp_gai, *gai = NULL;
|
||||||
guint16 line_style = 2;
|
guint16 line_style = 2;
|
||||||
double duration;
|
double duration;
|
||||||
int conv_num = -1;
|
int conv_num = -1;
|
||||||
|
@ -793,7 +793,7 @@ T38_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const vo
|
||||||
voip_calls_graph_list = g_list_first(tapinfo->graph_analysis->list);
|
voip_calls_graph_list = g_list_first(tapinfo->graph_analysis->list);
|
||||||
while (voip_calls_graph_list)
|
while (voip_calls_graph_list)
|
||||||
{
|
{
|
||||||
tmp_gai = (graph_analysis_item_t *)voip_calls_graph_list->data;
|
tmp_gai = (seq_analysis_item_t *)voip_calls_graph_list->data;
|
||||||
if (pi->setup_frame_number == tmp_gai->fd->num) {
|
if (pi->setup_frame_number == tmp_gai->fd->num) {
|
||||||
gai = tmp_gai;
|
gai = tmp_gai;
|
||||||
break;
|
break;
|
||||||
|
@ -2389,7 +2389,7 @@ MGCPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, co
|
||||||
GList *listGraph;
|
GList *listGraph;
|
||||||
gchar *frame_label = NULL;
|
gchar *frame_label = NULL;
|
||||||
gchar *comment = NULL;
|
gchar *comment = NULL;
|
||||||
graph_analysis_item_t *gai;
|
seq_analysis_item_t *gai;
|
||||||
gboolean newcall = FALSE;
|
gboolean newcall = FALSE;
|
||||||
gboolean fromEndpoint = FALSE; /* true for calls originated in Endpoints, false for calls from MGC */
|
gboolean fromEndpoint = FALSE; /* true for calls originated in Endpoints, false for calls from MGC */
|
||||||
gdouble diff_time;
|
gdouble diff_time;
|
||||||
|
@ -2448,7 +2448,7 @@ MGCPcalls_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, co
|
||||||
listGraph = g_list_first(tapinfo->graph_analysis->list);
|
listGraph = g_list_first(tapinfo->graph_analysis->list);
|
||||||
while (listGraph)
|
while (listGraph)
|
||||||
{
|
{
|
||||||
gai = (graph_analysis_item_t *)listGraph->data;
|
gai = (seq_analysis_item_t *)listGraph->data;
|
||||||
if (gai->fd->num == pi->req_num) {
|
if (gai->fd->num == pi->req_num) {
|
||||||
/* there is a request that match, so look the associated call with this call_num */
|
/* there is a request that match, so look the associated call with this call_num */
|
||||||
list = g_list_first(tapinfo->callsinfo_list);
|
list = g_list_first(tapinfo->callsinfo_list);
|
||||||
|
|
|
@ -171,7 +171,7 @@ typedef struct _voip_calls_tapinfo {
|
||||||
int start_packets;
|
int start_packets;
|
||||||
int completed_calls;
|
int completed_calls;
|
||||||
int rejected_calls;
|
int rejected_calls;
|
||||||
graph_analysis_info_t* graph_analysis;
|
seq_analysis_info_t* graph_analysis;
|
||||||
gboolean reversed;
|
gboolean reversed;
|
||||||
gboolean redraw;
|
gboolean redraw;
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -181,7 +181,7 @@ voip_calls_on_filter(GtkButton *button _U_, gpointer user_data _U_)
|
||||||
GList* lista;
|
GList* lista;
|
||||||
GList* listb;
|
GList* listb;
|
||||||
voip_calls_info_t *listinfo;
|
voip_calls_info_t *listinfo;
|
||||||
graph_analysis_item_t *gai;
|
seq_analysis_item_t *gai;
|
||||||
size_t filter_length;
|
size_t filter_length;
|
||||||
size_t max_filter_length = 2048; /* What's this based on ? */
|
size_t max_filter_length = 2048; /* What's this based on ? */
|
||||||
int pos;
|
int pos;
|
||||||
|
@ -215,7 +215,7 @@ voip_calls_on_filter(GtkButton *button _U_, gpointer user_data _U_)
|
||||||
if (listinfo->selected) {
|
if (listinfo->selected) {
|
||||||
listb = g_list_first(voip_calls_get_info()->graph_analysis->list);
|
listb = g_list_first(voip_calls_get_info()->graph_analysis->list);
|
||||||
while (listb) {
|
while (listb) {
|
||||||
gai = (graph_analysis_item_t *)listb->data;
|
gai = (seq_analysis_item_t *)listb->data;
|
||||||
if (gai->conv_num == listinfo->call_num) {
|
if (gai->conv_num == listinfo->call_num) {
|
||||||
g_string_append_printf(filter_string_fwd, "%sframe.number == %u", is_first?"":" or ", gai->fd->num);
|
g_string_append_printf(filter_string_fwd, "%sframe.number == %u", is_first?"":" or ", gai->fd->num);
|
||||||
is_first = FALSE;
|
is_first = FALSE;
|
||||||
|
@ -318,8 +318,8 @@ voip_calls_on_select_all(GtkButton *button _U_, gpointer user_data _U_)
|
||||||
static gint
|
static gint
|
||||||
graph_analysis_sort_compare(gconstpointer a, gconstpointer b)
|
graph_analysis_sort_compare(gconstpointer a, gconstpointer b)
|
||||||
{
|
{
|
||||||
const graph_analysis_item_t *entry_a = (const graph_analysis_item_t *)a;
|
const seq_analysis_item_t *entry_a = (const seq_analysis_item_t *)a;
|
||||||
const graph_analysis_item_t *entry_b = (const graph_analysis_item_t *)b;
|
const seq_analysis_item_t *entry_b = (const seq_analysis_item_t *)b;
|
||||||
|
|
||||||
if(entry_a->fd->num < entry_b->fd->num)
|
if(entry_a->fd->num < entry_b->fd->num)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -334,7 +334,7 @@ graph_analysis_sort_compare(gconstpointer a, gconstpointer b)
|
||||||
static void
|
static void
|
||||||
on_graph_bt_clicked(GtkButton *button _U_, gpointer user_data _U_)
|
on_graph_bt_clicked(GtkButton *button _U_, gpointer user_data _U_)
|
||||||
{
|
{
|
||||||
graph_analysis_item_t *gai;
|
seq_analysis_item_t *gai;
|
||||||
GList* lista;
|
GList* lista;
|
||||||
GList* listb;
|
GList* listb;
|
||||||
voip_calls_info_t *listinfo;
|
voip_calls_info_t *listinfo;
|
||||||
|
@ -349,7 +349,7 @@ on_graph_bt_clicked(GtkButton *button _U_, gpointer user_data _U_)
|
||||||
/* reset the "display" parameter in graph analysis */
|
/* reset the "display" parameter in graph analysis */
|
||||||
listb = g_list_first(voip_calls_get_info()->graph_analysis->list);
|
listb = g_list_first(voip_calls_get_info()->graph_analysis->list);
|
||||||
while (listb) {
|
while (listb) {
|
||||||
gai = (graph_analysis_item_t *)listb->data;
|
gai = (seq_analysis_item_t *)listb->data;
|
||||||
gai->display = FALSE;
|
gai->display = FALSE;
|
||||||
listb = g_list_next(listb);
|
listb = g_list_next(listb);
|
||||||
}
|
}
|
||||||
|
@ -361,7 +361,7 @@ on_graph_bt_clicked(GtkButton *button _U_, gpointer user_data _U_)
|
||||||
if (listinfo->selected) {
|
if (listinfo->selected) {
|
||||||
listb = g_list_first(voip_calls_get_info()->graph_analysis->list);
|
listb = g_list_first(voip_calls_get_info()->graph_analysis->list);
|
||||||
while (listb) {
|
while (listb) {
|
||||||
gai = (graph_analysis_item_t *)listb->data;
|
gai = (seq_analysis_item_t *)listb->data;
|
||||||
if (gai->conv_num == listinfo->call_num) {
|
if (gai->conv_num == listinfo->call_num) {
|
||||||
gai->display = TRUE;
|
gai->display = TRUE;
|
||||||
}
|
}
|
||||||
|
@ -851,8 +851,7 @@ voip_calls_init_tap(const char *dummy _U_, void* userdata _U_)
|
||||||
if (graph_analysis_data == NULL) {
|
if (graph_analysis_data == NULL) {
|
||||||
graph_analysis_data_init();
|
graph_analysis_data_init();
|
||||||
/* init the Graph Analysys */
|
/* init the Graph Analysys */
|
||||||
graph_analysis_data = graph_analysis_init();
|
graph_analysis_data = graph_analysis_init(voip_calls_get_info()->graph_analysis);
|
||||||
graph_analysis_data->graph_info = voip_calls_get_info()->graph_analysis;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clean up memory used by calls tap */
|
/* Clean up memory used by calls tap */
|
||||||
|
|
|
@ -68,6 +68,8 @@ set(QTSHARK_H_SRC
|
||||||
qcustomplot.h
|
qcustomplot.h
|
||||||
recent_file_status.h
|
recent_file_status.h
|
||||||
search_frame.h
|
search_frame.h
|
||||||
|
sequence_diagram.h
|
||||||
|
sequence_dialog.h
|
||||||
simple_dialog_qt.h
|
simple_dialog_qt.h
|
||||||
splash_overlay.h
|
splash_overlay.h
|
||||||
summary_dialog.h
|
summary_dialog.h
|
||||||
|
@ -133,6 +135,8 @@ set(CLEAN_FILES
|
||||||
recent_file_status.cpp
|
recent_file_status.cpp
|
||||||
related_packet_delegate.cpp
|
related_packet_delegate.cpp
|
||||||
search_frame.cpp
|
search_frame.cpp
|
||||||
|
sequence_diagram.cpp
|
||||||
|
sequence_dialog.cpp
|
||||||
simple_dialog_qt.cpp
|
simple_dialog_qt.cpp
|
||||||
splash_overlay.cpp
|
splash_overlay.cpp
|
||||||
sparkline_delegate.cpp
|
sparkline_delegate.cpp
|
||||||
|
@ -169,6 +173,7 @@ set(QTSHARK_UI
|
||||||
print_dialog.ui
|
print_dialog.ui
|
||||||
profile_dialog.ui
|
profile_dialog.ui
|
||||||
search_frame.ui
|
search_frame.ui
|
||||||
|
sequence_dialog.ui
|
||||||
splash_overlay.ui
|
splash_overlay.ui
|
||||||
summary_dialog.ui
|
summary_dialog.ui
|
||||||
tcp_stream_dialog.ui
|
tcp_stream_dialog.ui
|
||||||
|
|
|
@ -51,6 +51,7 @@ NODIST_GENERATED_HEADER_FILES = \
|
||||||
ui_print_dialog.h \
|
ui_print_dialog.h \
|
||||||
ui_profile_dialog.h \
|
ui_profile_dialog.h \
|
||||||
ui_search_frame.h \
|
ui_search_frame.h \
|
||||||
|
ui_sequence_dialog.h \
|
||||||
ui_splash_overlay.h \
|
ui_splash_overlay.h \
|
||||||
ui_summary_dialog.h \
|
ui_summary_dialog.h \
|
||||||
ui_tcp_stream_dialog.h \
|
ui_tcp_stream_dialog.h \
|
||||||
|
@ -135,6 +136,8 @@ MOC_HDRS = \
|
||||||
recent_file_status.h \
|
recent_file_status.h \
|
||||||
related_packet_delegate.h \
|
related_packet_delegate.h \
|
||||||
search_frame.h \
|
search_frame.h \
|
||||||
|
sequence_diagram.h \
|
||||||
|
sequence_dialog.h \
|
||||||
simple_dialog_qt.h \
|
simple_dialog_qt.h \
|
||||||
sparkline_delegate.h \
|
sparkline_delegate.h \
|
||||||
splash_overlay.h \
|
splash_overlay.h \
|
||||||
|
@ -170,6 +173,7 @@ UI_FILES = \
|
||||||
print_dialog.ui \
|
print_dialog.ui \
|
||||||
profile_dialog.ui \
|
profile_dialog.ui \
|
||||||
search_frame.ui \
|
search_frame.ui \
|
||||||
|
sequence_dialog.ui \
|
||||||
splash_overlay.ui \
|
splash_overlay.ui \
|
||||||
summary_dialog.ui \
|
summary_dialog.ui \
|
||||||
tcp_stream_dialog.ui \
|
tcp_stream_dialog.ui \
|
||||||
|
@ -271,6 +275,8 @@ WIRESHARK_QT_SRC = \
|
||||||
recent_file_status.cpp \
|
recent_file_status.cpp \
|
||||||
related_packet_delegate.cpp \
|
related_packet_delegate.cpp \
|
||||||
search_frame.cpp \
|
search_frame.cpp \
|
||||||
|
sequence_diagram.cpp \
|
||||||
|
sequence_dialog.cpp \
|
||||||
simple_dialog_qt.cpp \
|
simple_dialog_qt.cpp \
|
||||||
sparkline_delegate.cpp \
|
sparkline_delegate.cpp \
|
||||||
summary_dialog.cpp \
|
summary_dialog.cpp \
|
||||||
|
|
|
@ -500,6 +500,8 @@ HEADERS += \
|
||||||
qcustomplot.h \
|
qcustomplot.h \
|
||||||
recent_file_status.h \
|
recent_file_status.h \
|
||||||
related_packet_delegate.h \
|
related_packet_delegate.h \
|
||||||
|
sequence_diagram.h \
|
||||||
|
sequence_dialog.h \
|
||||||
simple_dialog_qt.h \
|
simple_dialog_qt.h \
|
||||||
sparkline_delegate.h \
|
sparkline_delegate.h \
|
||||||
syntax_line_edit.h \
|
syntax_line_edit.h \
|
||||||
|
@ -557,6 +559,8 @@ SOURCES += \
|
||||||
recent_file_status.cpp \
|
recent_file_status.cpp \
|
||||||
related_packet_delegate.cpp \
|
related_packet_delegate.cpp \
|
||||||
search_frame.cpp \
|
search_frame.cpp \
|
||||||
|
sequence_diagram.cpp \
|
||||||
|
sequence_dialog.cpp \
|
||||||
simple_dialog_qt.cpp \
|
simple_dialog_qt.cpp \
|
||||||
sparkline_delegate.cpp \
|
sparkline_delegate.cpp \
|
||||||
splash_overlay.cpp \
|
splash_overlay.cpp \
|
||||||
|
|
|
@ -307,6 +307,7 @@ private slots:
|
||||||
void on_actionStopCapture_triggered();
|
void on_actionStopCapture_triggered();
|
||||||
|
|
||||||
void on_actionSummary_triggered();
|
void on_actionSummary_triggered();
|
||||||
|
void on_actionStatisticsFlowGraph_triggered();
|
||||||
void openTcpStreamDialog(int graph_type);
|
void openTcpStreamDialog(int graph_type);
|
||||||
void on_actionStatisticsTcpStreamStevens_triggered();
|
void on_actionStatisticsTcpStreamStevens_triggered();
|
||||||
void on_actionStatisticsTcpStreamTcptrace_triggered();
|
void on_actionStatisticsTcpStreamTcptrace_triggered();
|
||||||
|
|
|
@ -332,6 +332,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
<addaction name="actionSummary"/>
|
<addaction name="actionSummary"/>
|
||||||
<addaction name="actionProtocol_Hierarchy"/>
|
<addaction name="actionProtocol_Hierarchy"/>
|
||||||
|
<addaction name="actionStatisticsFlowGraph"/>
|
||||||
<addaction name="menuTcpStreamGraphs"/>
|
<addaction name="menuTcpStreamGraphs"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menuTelephony">
|
<widget class="QMenu" name="menuTelephony">
|
||||||
|
@ -1321,6 +1322,14 @@
|
||||||
<string>TCP time sequence graph (tcptrace)</string>
|
<string>TCP time sequence graph (tcptrace)</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionStatisticsFlowGraph">
|
||||||
|
<property name="text">
|
||||||
|
<string>Flow Graph...</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Flow sequence diagram</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
|
|
|
@ -77,6 +77,7 @@
|
||||||
#include "print_dialog.h"
|
#include "print_dialog.h"
|
||||||
#include "profile_dialog.h"
|
#include "profile_dialog.h"
|
||||||
#include "qt_ui_utils.h"
|
#include "qt_ui_utils.h"
|
||||||
|
#include "sequence_dialog.h"
|
||||||
#include "tcp_stream_dialog.h"
|
#include "tcp_stream_dialog.h"
|
||||||
#include "time_shift_dialog.h"
|
#include "time_shift_dialog.h"
|
||||||
#include "wireshark_application.h"
|
#include "wireshark_application.h"
|
||||||
|
@ -1759,6 +1760,15 @@ void MainWindow::on_actionAnalyzeFollowSSLStream_triggered()
|
||||||
|
|
||||||
// Statistics Menu
|
// Statistics Menu
|
||||||
|
|
||||||
|
void MainWindow::on_actionStatisticsFlowGraph_triggered()
|
||||||
|
{
|
||||||
|
SequenceDialog *sequence_dialog = new SequenceDialog(this, cap_file_);
|
||||||
|
connect(sequence_dialog, SIGNAL(goToPacket(int)),
|
||||||
|
packet_list_, SLOT(goToPacket(int)));
|
||||||
|
connect(this, SIGNAL(setCaptureFile(capture_file*)),
|
||||||
|
sequence_dialog, SLOT(setCaptureFile(capture_file*)));
|
||||||
|
sequence_dialog->show();
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::openTcpStreamDialog(int graph_type)
|
void MainWindow::openTcpStreamDialog(int graph_type)
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,227 @@
|
||||||
|
/* sequence_diagram.cpp
|
||||||
|
*
|
||||||
|
* $Id: tcp_stream_dialog.h 52102 2013-09-16 17:28:42Z gerald $
|
||||||
|
*
|
||||||
|
* Wireshark - Network traffic analyzer
|
||||||
|
* By Gerald Combs <gerald@wireshark.org>
|
||||||
|
* Copyright 1998 Gerald Combs
|
||||||
|
*
|
||||||
|
* 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 2
|
||||||
|
* 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, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "sequence_diagram.h"
|
||||||
|
|
||||||
|
#include <epan/addr_resolv.h>
|
||||||
|
|
||||||
|
#include <QFont>
|
||||||
|
#include <QFontMetrics>
|
||||||
|
#include <QPen>
|
||||||
|
#include <QPointF>
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
const int max_comment_em_width_ = 20;
|
||||||
|
|
||||||
|
// UML-like network node sequence diagrams.
|
||||||
|
// http://www.ibm.com/developerworks/rational/library/3101.html
|
||||||
|
|
||||||
|
WSCPSeqData::WSCPSeqData() :
|
||||||
|
key(0),
|
||||||
|
value(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
WSCPSeqData::WSCPSeqData(double key, seq_analysis_item_t *value) :
|
||||||
|
key(key),
|
||||||
|
value(value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SequenceDiagram::SequenceDiagram(QCPAxis *keyAxis, QCPAxis *valueAxis, QCPAxis *commentAxis) :
|
||||||
|
QCPAbstractPlottable(keyAxis, valueAxis),
|
||||||
|
key_axis_(keyAxis),
|
||||||
|
value_axis_(valueAxis),
|
||||||
|
comment_axis_(commentAxis),
|
||||||
|
sainfo_(NULL)
|
||||||
|
{
|
||||||
|
data_ = new WSCPSeqDataMap();
|
||||||
|
// xaxis (value): Address
|
||||||
|
// yaxis (key): Time
|
||||||
|
// yaxis2 (comment): Extra info ("Comment" in GTK+)
|
||||||
|
|
||||||
|
// valueAxis->setAutoTickStep(false);
|
||||||
|
QList<QCPAxis *> axes;
|
||||||
|
axes << value_axis_ << key_axis_ << comment_axis_;
|
||||||
|
foreach (QCPAxis *axis, axes) {
|
||||||
|
axis->setAutoTicks(false);
|
||||||
|
axis->setTickStep(1.0);
|
||||||
|
axis->setAutoTickLabels(false);
|
||||||
|
axis->setTicks(false);
|
||||||
|
axis->setBasePen(QPen(Qt::NoPen));
|
||||||
|
}
|
||||||
|
|
||||||
|
value_axis_->grid()->setVisible(true);
|
||||||
|
|
||||||
|
key_axis_->setRangeReversed(true);
|
||||||
|
key_axis_->grid()->setVisible(false);
|
||||||
|
|
||||||
|
comment_axis_->setRangeReversed(true);
|
||||||
|
comment_axis_->grid()->setVisible(false);
|
||||||
|
|
||||||
|
QFont comment_font = comment_axis_->tickLabelFont();
|
||||||
|
comment_axis_->setTickLabelFont(comment_font);
|
||||||
|
comment_axis_->setSelectedTickLabelFont(QFont(comment_font.family(), comment_font.pointSize(), QFont::Bold));
|
||||||
|
// frame_label
|
||||||
|
// port_src -----------------> port_dst
|
||||||
|
|
||||||
|
// setTickVectorLabels
|
||||||
|
// valueAxis->setTickLabelRotation(30);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SequenceDiagram::setData(seq_analysis_info_t *sainfo)
|
||||||
|
{
|
||||||
|
data_->clear();
|
||||||
|
WSCPSeqData new_data;
|
||||||
|
double cur_key = 0.0;
|
||||||
|
QVector<double> key_ticks, val_ticks;
|
||||||
|
QVector<QString> key_labels, val_labels, com_labels;
|
||||||
|
QFontMetrics com_fm(comment_axis_->tickLabelFont());
|
||||||
|
int elide_w = com_fm.height() * max_comment_em_width_;
|
||||||
|
|
||||||
|
for (GList *cur = g_list_first(sainfo->list); cur; cur = g_list_next(cur)) {
|
||||||
|
seq_analysis_item_t *sai = (seq_analysis_item_t *) cur->data;
|
||||||
|
|
||||||
|
new_data.key = cur_key;
|
||||||
|
new_data.value = sai;
|
||||||
|
data_->insertMulti(new_data.key, new_data);
|
||||||
|
|
||||||
|
key_ticks.append(cur_key);
|
||||||
|
key_labels.append(sai->time_str);
|
||||||
|
com_labels.append(com_fm.elidedText(sai->comment, Qt::ElideRight, elide_w));
|
||||||
|
|
||||||
|
cur_key++;
|
||||||
|
}
|
||||||
|
sainfo_ = sainfo;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < sainfo_->num_nodes; i++) {
|
||||||
|
val_ticks.append(i);
|
||||||
|
val_labels.append(get_addr_name(&(sainfo_->nodes[i])));
|
||||||
|
}
|
||||||
|
keyAxis()->setTickVector(key_ticks);
|
||||||
|
keyAxis()->setTickVectorLabels(key_labels);
|
||||||
|
valueAxis()->setTickVector(val_ticks);
|
||||||
|
valueAxis()->setTickVectorLabels(val_labels);
|
||||||
|
comment_axis_->setTickVector(key_ticks);
|
||||||
|
comment_axis_->setTickVectorLabels(com_labels);
|
||||||
|
}
|
||||||
|
|
||||||
|
double SequenceDiagram::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(pos);
|
||||||
|
Q_UNUSED(onlySelectable);
|
||||||
|
Q_UNUSED(details);
|
||||||
|
return -1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SequenceDiagram::draw(QCPPainter *painter)
|
||||||
|
{
|
||||||
|
WSCPSeqDataMap::const_iterator it;
|
||||||
|
for (it = data_->constBegin(); it != data_->constEnd(); ++it) {
|
||||||
|
double cur_key = it.key();
|
||||||
|
seq_analysis_item_t *sai = (seq_analysis_item_t *) it.value().value;
|
||||||
|
|
||||||
|
if (cur_key < key_axis_->range().lower || cur_key > key_axis_->range().upper) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (sai->dst_node > sai->src_node && (sai->dst_node < value_axis_->range().lower || sai->src_node > value_axis_->range().upper)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (sai->src_node > sai->dst_node && (sai->src_node < value_axis_->range().lower || sai->dst_node > value_axis_->range().upper)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
double ah_size = (QFontMetrics(comment_axis_->tickLabelFont()).height() / 5)
|
||||||
|
* ((sai->src_node < sai->dst_node) ? 1 : -1);
|
||||||
|
QPointF arrow_end(coordsToPixels(cur_key, sai->dst_node));
|
||||||
|
QLineF arrow_line(coordsToPixels(cur_key, sai->src_node), arrow_end);
|
||||||
|
QPolygonF arrow_head;
|
||||||
|
arrow_head
|
||||||
|
<< QPointF(arrow_end.x() - (ah_size*3), arrow_end.y() - ah_size)
|
||||||
|
<< arrow_end
|
||||||
|
<< QPointF(arrow_end.x() - (ah_size*3), arrow_end.y() + ah_size);
|
||||||
|
if (mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0) {
|
||||||
|
painter->setBrush(mainPen().color());
|
||||||
|
painter->setPen(mainPen());
|
||||||
|
painter->drawLine(arrow_line);
|
||||||
|
painter->drawPolygon(arrow_head);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SequenceDiagram::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(painter);
|
||||||
|
Q_UNUSED(rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
QCPRange SequenceDiagram::getKeyRange(bool &validRange, QCPAbstractPlottable::SignDomain inSignDomain) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(inSignDomain);
|
||||||
|
QCPRange range;
|
||||||
|
bool valid = false;
|
||||||
|
|
||||||
|
WSCPSeqDataMap::const_iterator it = data_->constBegin();
|
||||||
|
while (it != data_->constEnd()) {
|
||||||
|
double cur_key = it.key();
|
||||||
|
if (!valid) {
|
||||||
|
range.lower = range.upper = cur_key;
|
||||||
|
valid = true;
|
||||||
|
} else if (cur_key < range.lower) {
|
||||||
|
range.lower = cur_key;
|
||||||
|
} else if (cur_key > range.upper) {
|
||||||
|
range.upper = cur_key;
|
||||||
|
}
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
validRange = valid;
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
|
||||||
|
QCPRange SequenceDiagram::getValueRange(bool &validRange, QCPAbstractPlottable::SignDomain inSignDomain) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(inSignDomain);
|
||||||
|
QCPRange range;
|
||||||
|
bool valid = false;
|
||||||
|
|
||||||
|
if (sainfo_) {
|
||||||
|
range.lower = 0;
|
||||||
|
range.upper = sainfo_->num_nodes;
|
||||||
|
valid = true;
|
||||||
|
}
|
||||||
|
validRange = valid;
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Editor modelines
|
||||||
|
*
|
||||||
|
* Local Variables:
|
||||||
|
* c-basic-offset: 4
|
||||||
|
* tab-width: 8
|
||||||
|
* indent-tabs-mode: nil
|
||||||
|
* End:
|
||||||
|
*
|
||||||
|
* ex: set shiftwidth=4 tabstop=8 expandtab:
|
||||||
|
* :indentSize=4:tabSize=8:noTabs=true:
|
||||||
|
*/
|
|
@ -0,0 +1,107 @@
|
||||||
|
/* sequence_diagram.h
|
||||||
|
*
|
||||||
|
* $Id: tcp_stream_dialog.h 52102 2013-09-16 17:28:42Z gerald $
|
||||||
|
*
|
||||||
|
* Wireshark - Network traffic analyzer
|
||||||
|
* By Gerald Combs <gerald@wireshark.org>
|
||||||
|
* Copyright 1998 Gerald Combs
|
||||||
|
*
|
||||||
|
* 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 2
|
||||||
|
* 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, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SEQUENCE_DIAGRAM_H
|
||||||
|
#define SEQUENCE_DIAGRAM_H
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include <epan/address.h>
|
||||||
|
|
||||||
|
#include "ui/tap-sequence-analysis.h"
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QMultiMap>
|
||||||
|
#include "qcustomplot.h"
|
||||||
|
|
||||||
|
// Most of this is probably unnecessary
|
||||||
|
class WSCPSeqData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WSCPSeqData();
|
||||||
|
WSCPSeqData(double key, seq_analysis_item_t *value);
|
||||||
|
double key;
|
||||||
|
seq_analysis_item_t *value;
|
||||||
|
};
|
||||||
|
Q_DECLARE_TYPEINFO(WSCPSeqData, Q_MOVABLE_TYPE);
|
||||||
|
|
||||||
|
typedef QMap<double, WSCPSeqData> WSCPSeqDataMap;
|
||||||
|
typedef QMapIterator<double, WSCPSeqData> WSCPSeqDataMapIterator;
|
||||||
|
typedef QMutableMapIterator<double, WSCPSeqData> WSCPSeqDataMutableMapIterator;
|
||||||
|
|
||||||
|
// XXX Should we dispense with this class and simply add items to a graph instead?
|
||||||
|
class SequenceDiagram : public QCPAbstractPlottable
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit SequenceDiagram(QCPAxis *keyAxis, QCPAxis *valueAxis, QCPAxis *commentAxis);
|
||||||
|
|
||||||
|
// getters:
|
||||||
|
// double width() const { return mWidth; }
|
||||||
|
// WSCPSeqDataMap *data() const { return mData; }
|
||||||
|
|
||||||
|
// setters:
|
||||||
|
// void setWidth(double width);
|
||||||
|
void setData(seq_analysis_info_t *sainfo);
|
||||||
|
// void setData(const QVector<double> &key, const QVector<double> &value);
|
||||||
|
|
||||||
|
// non-property methods:
|
||||||
|
// void addData(const WSCPSeqDataMap &dataMap);
|
||||||
|
// void addData(const WSCPSeqData &data);
|
||||||
|
// void addData(double key, double value);
|
||||||
|
// void addData(const QVector<double> &keys, const QVector<double> &values);
|
||||||
|
|
||||||
|
// reimplemented virtual methods:
|
||||||
|
virtual void clearData() {}
|
||||||
|
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void draw(QCPPainter *painter);
|
||||||
|
virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const;
|
||||||
|
virtual QCPRange getKeyRange(bool &validRange, SignDomain inSignDomain=sdBoth) const;
|
||||||
|
virtual QCPRange getValueRange(bool &validRange, SignDomain inSignDomain=sdBoth) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QCPAxis *key_axis_;
|
||||||
|
QCPAxis *value_axis_;
|
||||||
|
QCPAxis *comment_axis_;
|
||||||
|
WSCPSeqDataMap *data_;
|
||||||
|
seq_analysis_info_t *sainfo_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SEQUENCE_DIAGRAM_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Editor modelines
|
||||||
|
*
|
||||||
|
* Local Variables:
|
||||||
|
* c-basic-offset: 4
|
||||||
|
* tab-width: 8
|
||||||
|
* indent-tabs-mode: nil
|
||||||
|
* End:
|
||||||
|
*
|
||||||
|
* ex: set shiftwidth=4 tabstop=8 expandtab:
|
||||||
|
* :indentSize=4:tabSize=8:noTabs=true:
|
||||||
|
*/
|
|
@ -0,0 +1,147 @@
|
||||||
|
/* sequence_dialog.cpp
|
||||||
|
*
|
||||||
|
* $Id: tcp_stream_dialog.cpp 52108 2013-09-16 21:33:26Z gerald $
|
||||||
|
*
|
||||||
|
* Wireshark - Network traffic analyzer
|
||||||
|
* By Gerald Combs <gerald@wireshark.org>
|
||||||
|
* Copyright 1998 Gerald Combs
|
||||||
|
*
|
||||||
|
* 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 2
|
||||||
|
* 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, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "sequence_dialog.h"
|
||||||
|
#include "ui_sequence_dialog.h"
|
||||||
|
|
||||||
|
#include "wsutil/nstime.h"
|
||||||
|
|
||||||
|
#include <QFontMetrics>
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
// To do:
|
||||||
|
// - Fix horizontal scrolling
|
||||||
|
// - Save as
|
||||||
|
// - Sequence item labels
|
||||||
|
// - Scroll bars
|
||||||
|
// - Selection
|
||||||
|
// - Keyboard shortcuts
|
||||||
|
// - ...
|
||||||
|
|
||||||
|
SequenceDialog::SequenceDialog(QWidget *parent, capture_file *cf, SequenceType type) :
|
||||||
|
QDialog(parent),
|
||||||
|
ui(new Ui::SequenceDialog),
|
||||||
|
cap_file_(cf)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
QCustomPlot *sp = ui->sequencePlot;
|
||||||
|
|
||||||
|
seq_diagram_ = new SequenceDiagram(ui->sequencePlot->yAxis, ui->sequencePlot->xAxis2,
|
||||||
|
ui->sequencePlot->yAxis2);
|
||||||
|
sp->addPlottable(seq_diagram_);
|
||||||
|
|
||||||
|
sp->xAxis->setVisible(false);
|
||||||
|
sp->xAxis2->setVisible(true);
|
||||||
|
sp->yAxis2->setVisible(true);
|
||||||
|
|
||||||
|
one_em_ = QFontMetrics(sp->yAxis->labelFont()).height();
|
||||||
|
|
||||||
|
sp->setInteractions(QCP::iRangeDrag);
|
||||||
|
|
||||||
|
connect(sp->yAxis, SIGNAL(rangeChanged(QCPRange)), sp->yAxis2, SLOT(setRange(QCPRange)));
|
||||||
|
|
||||||
|
memset (&seq_analysis_, 0, sizeof(seq_analysis_));
|
||||||
|
switch (type) {
|
||||||
|
case any:
|
||||||
|
seq_analysis_.type = SEQ_ANALYSIS_ANY;
|
||||||
|
break;
|
||||||
|
case tcp:
|
||||||
|
seq_analysis_.type = SEQ_ANALYSIS_TCP;
|
||||||
|
break;
|
||||||
|
case voip:
|
||||||
|
seq_analysis_.type = SEQ_ANALYSIS_VOIP;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
seq_analysis_.all_packets = TRUE;
|
||||||
|
|
||||||
|
if (parent) {
|
||||||
|
resize(parent->width(), parent->height() * 4 / 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
fillDiagram();
|
||||||
|
}
|
||||||
|
|
||||||
|
SequenceDialog::~SequenceDialog()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SequenceDialog::setCaptureFile(capture_file *cf)
|
||||||
|
{
|
||||||
|
if (!cf) { // We only want to know when the file closes.
|
||||||
|
cap_file_ = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SequenceDialog::showEvent(QShowEvent *event)
|
||||||
|
{
|
||||||
|
Q_UNUSED(event);
|
||||||
|
resetAxes();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SequenceDialog::resizeEvent(QResizeEvent *event)
|
||||||
|
{
|
||||||
|
Q_UNUSED(event);
|
||||||
|
resetAxes(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SequenceDialog::fillDiagram()
|
||||||
|
{
|
||||||
|
QCustomPlot *sp = ui->sequencePlot;
|
||||||
|
|
||||||
|
sequence_analysis_list_free(&seq_analysis_);
|
||||||
|
sequence_analysis_list_get(cap_file_, &seq_analysis_);
|
||||||
|
sequence_analysis_get_nodes(&seq_analysis_);
|
||||||
|
|
||||||
|
seq_diagram_->setData(&seq_analysis_);
|
||||||
|
// ui->sequencePlot->rescaleAxes();
|
||||||
|
sp->replot();
|
||||||
|
|
||||||
|
resetAxes();
|
||||||
|
// tracer_->setGraph(base_graph_);
|
||||||
|
|
||||||
|
// XXX QCustomPlot doesn't seem to draw any sort of focus indicator.
|
||||||
|
sp->setFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SequenceDialog::resetAxes(bool keep_lower)
|
||||||
|
{
|
||||||
|
QCustomPlot *sp = ui->sequencePlot;
|
||||||
|
double top_pos = -1.0;
|
||||||
|
if (keep_lower) {
|
||||||
|
top_pos = sp->yAxis->range().lower;
|
||||||
|
}
|
||||||
|
|
||||||
|
sp->xAxis->moveRange(sp->xAxis->range().lower * -1);
|
||||||
|
|
||||||
|
double range_ratio = sp->yAxis->axisRect()->height() / one_em_;
|
||||||
|
sp->yAxis->setRange(top_pos, range_ratio + top_pos);
|
||||||
|
|
||||||
|
sp->replot();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SequenceDialog::on_resetButton_clicked()
|
||||||
|
{
|
||||||
|
resetAxes();
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
/* sequence_dialog.h
|
||||||
|
*
|
||||||
|
* $Id: tcp_stream_dialog.cpp 52108 2013-09-16 21:33:26Z gerald $
|
||||||
|
*
|
||||||
|
* Wireshark - Network traffic analyzer
|
||||||
|
* By Gerald Combs <gerald@wireshark.org>
|
||||||
|
* Copyright 1998 Gerald Combs
|
||||||
|
*
|
||||||
|
* 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 2
|
||||||
|
* 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, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SEQUENCE_DIALOG_H
|
||||||
|
#define SEQUENCE_DIALOG_H
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include "cfile.h"
|
||||||
|
|
||||||
|
#include "epan/packet.h"
|
||||||
|
|
||||||
|
#include "sequence_diagram.h"
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class SequenceDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class SequenceDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum SequenceType { any, tcp, voip };
|
||||||
|
|
||||||
|
explicit SequenceDialog(QWidget *parent = 0, capture_file *cf = NULL, SequenceType type = any);
|
||||||
|
~SequenceDialog();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void goToPacket(int packet_num);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void setCaptureFile(capture_file *cf);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void showEvent(QShowEvent *event);
|
||||||
|
void resizeEvent(QResizeEvent *event);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_resetButton_clicked();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::SequenceDialog *ui;
|
||||||
|
SequenceDiagram *seq_diagram_;
|
||||||
|
capture_file *cap_file_;
|
||||||
|
seq_analysis_info_t seq_analysis_;
|
||||||
|
double one_em_;
|
||||||
|
|
||||||
|
void fillDiagram();
|
||||||
|
void resetAxes(bool keep_lower = false);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SEQUENCE_DIALOG_H
|
|
@ -0,0 +1,206 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>SequenceDialog</class>
|
||||||
|
<widget class="QDialog" name="SequenceDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>679</width>
|
||||||
|
<height>568</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Flow</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QCustomPlot" name="sequencePlot" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>1</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="hintLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string><small><i>A hint</i></small></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="controlHorizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Show:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="packetComboBox">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>All packets</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Displayed packets</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>13</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Flow type:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="flowComboBox">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>General</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>TCP</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>13</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>Addresses:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="addressComboBox">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Any</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Network</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="resetButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Reset</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::Ok|QDialogButtonBox::Save</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>QCustomPlot</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>qcustomplot.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>SequenceDialog</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>248</x>
|
||||||
|
<y>254</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>157</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>SequenceDialog</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>316</x>
|
||||||
|
<y>260</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>286</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
|
@ -226,7 +226,7 @@ TCPStreamDialog::~TCPStreamDialog()
|
||||||
|
|
||||||
void TCPStreamDialog::showEvent(QShowEvent *event)
|
void TCPStreamDialog::showEvent(QShowEvent *event)
|
||||||
{
|
{
|
||||||
Q_UNUSED(event)
|
Q_UNUSED(event);
|
||||||
resetAxes();
|
resetAxes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -374,7 +374,6 @@ void TCPStreamDialog::fillGraph()
|
||||||
int pkts_fwd = 0;
|
int pkts_fwd = 0;
|
||||||
int pkts_rev = 0;
|
int pkts_rev = 0;
|
||||||
|
|
||||||
|
|
||||||
time_stamp_map_.clear();
|
time_stamp_map_.clear();
|
||||||
for (struct segment *seg = graph_.segments; seg != NULL; seg = seg->next) {
|
for (struct segment *seg = graph_.segments; seg != NULL; seg = seg->next) {
|
||||||
if (!compareHeaders(seg)) {
|
if (!compareHeaders(seg)) {
|
||||||
|
|
|
@ -0,0 +1,620 @@
|
||||||
|
/* tap-sequence-analysis.c
|
||||||
|
* Flow sequence analysis
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Some code from from gtk/flow_graph.c
|
||||||
|
*
|
||||||
|
* Wireshark - Network traffic analyzer
|
||||||
|
* By Gerald Combs <gerald@wireshark.org>
|
||||||
|
* Copyright 1998 Gerald Combs
|
||||||
|
*
|
||||||
|
* 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 2
|
||||||
|
* 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, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "file.h"
|
||||||
|
|
||||||
|
#include "tap-sequence-analysis.h"
|
||||||
|
|
||||||
|
#include "epan/addr_resolv.h"
|
||||||
|
#include "epan/column-utils.h"
|
||||||
|
#include "epan/packet.h"
|
||||||
|
#include "epan/tap.h"
|
||||||
|
#include "epan/dissectors/packet-tcp.h"
|
||||||
|
|
||||||
|
#include "ui/alert_box.h"
|
||||||
|
|
||||||
|
#include <wsutil/file_util.h>
|
||||||
|
|
||||||
|
#define NODE_OVERFLOW MAX_NUM_NODES+1
|
||||||
|
|
||||||
|
#define NODE_CHARS_WIDTH 20
|
||||||
|
#define CONV_TIME_HEADER "Conv.| Time "
|
||||||
|
#define TIME_HEADER "|Time "
|
||||||
|
#define CONV_TIME_EMPTY_HEADER " | "
|
||||||
|
#define TIME_EMPTY_HEADER "| "
|
||||||
|
#define CONV_TIME_HEADER_LENGTH 16
|
||||||
|
#define TIME_HEADER_LENGTH 10
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/* whenever a frame packet is seen by the tap listener */
|
||||||
|
/* Add a new frame into the graph */
|
||||||
|
static gboolean
|
||||||
|
seq_analysis_frame_packet( void *ptr, packet_info *pinfo, epan_dissect_t *edt _U_, const void *dummy _U_)
|
||||||
|
{
|
||||||
|
seq_analysis_info_t *sainfo = (seq_analysis_info_t *) ptr;
|
||||||
|
|
||||||
|
if ((sainfo->all_packets)||(pinfo->fd->flags.passed_dfilter==1)){
|
||||||
|
int i;
|
||||||
|
gchar *protocol;
|
||||||
|
gchar *colinfo;
|
||||||
|
seq_analysis_item_t *sai;
|
||||||
|
|
||||||
|
protocol = NULL;
|
||||||
|
colinfo = NULL;
|
||||||
|
|
||||||
|
if (sainfo->any_addr) {
|
||||||
|
if (pinfo->net_src.type!=AT_NONE && pinfo->net_dst.type!=AT_NONE) {
|
||||||
|
sai = (seq_analysis_item_t *)g_malloc(sizeof(seq_analysis_item_t));
|
||||||
|
COPY_ADDRESS(&(sai->src_addr),&(pinfo->net_src));
|
||||||
|
COPY_ADDRESS(&(sai->dst_addr),&(pinfo->net_dst));
|
||||||
|
}
|
||||||
|
else return FALSE;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (pinfo->src.type!=AT_NONE && pinfo->dst.type!=AT_NONE) {
|
||||||
|
sai = (seq_analysis_item_t *)g_malloc(sizeof(seq_analysis_item_t));
|
||||||
|
COPY_ADDRESS(&(sai->src_addr),&(pinfo->src));
|
||||||
|
COPY_ADDRESS(&(sai->dst_addr),&(pinfo->dst));
|
||||||
|
}
|
||||||
|
else return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
sai->fd = pinfo->fd;
|
||||||
|
|
||||||
|
sai->port_src=pinfo->srcport;
|
||||||
|
sai->port_dst=pinfo->destport;
|
||||||
|
sai->comment=NULL;
|
||||||
|
sai->frame_label=NULL;
|
||||||
|
|
||||||
|
if(pinfo->cinfo) {
|
||||||
|
if (pinfo->cinfo->col_first[COL_INFO]>=0){
|
||||||
|
|
||||||
|
for (i = pinfo->cinfo->col_first[COL_INFO]; i <= pinfo->cinfo->col_last[COL_INFO]; i++) {
|
||||||
|
if (pinfo->cinfo->fmt_matx[i][COL_INFO]) {
|
||||||
|
colinfo = g_strdup(pinfo->cinfo->col_data[i]);
|
||||||
|
/* break; ? or g_free(colinfo); before g_strdup() */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pinfo->cinfo->col_first[COL_PROTOCOL]>=0){
|
||||||
|
|
||||||
|
for (i = pinfo->cinfo->col_first[COL_PROTOCOL]; i <= pinfo->cinfo->col_last[COL_PROTOCOL]; i++) {
|
||||||
|
if (pinfo->cinfo->fmt_matx[i][COL_PROTOCOL]) {
|
||||||
|
protocol = g_strdup(pinfo->cinfo->col_data[i]);
|
||||||
|
/* break; ? or g_free(protocol); before g_strdup() */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (colinfo != NULL) {
|
||||||
|
if (protocol != NULL) {
|
||||||
|
sai->frame_label = g_strdup_printf("%.19s", colinfo);
|
||||||
|
sai->comment = g_strdup_printf("%s: %s", protocol, colinfo);
|
||||||
|
} else {
|
||||||
|
sai->frame_label = g_strdup_printf("%.19s", colinfo);
|
||||||
|
sai->comment = g_strdup_printf("%s", colinfo);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* This will probably never happen...*/
|
||||||
|
if (protocol != NULL) {
|
||||||
|
sai->frame_label = g_strdup_printf("%.19s", protocol);
|
||||||
|
sai->comment = g_strdup_printf("%s", protocol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(protocol);
|
||||||
|
g_free(colinfo);
|
||||||
|
|
||||||
|
sai->line_style=1;
|
||||||
|
sai->conv_num=0;
|
||||||
|
sai->display=TRUE;
|
||||||
|
|
||||||
|
sainfo->list = g_list_prepend(sainfo->list, sai);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/* whenever a TCP packet is seen by the tap listener */
|
||||||
|
/* Add a new tcp frame into the graph */
|
||||||
|
static gboolean
|
||||||
|
seq_analysis_tcp_packet( void *ptr _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *tcp_info)
|
||||||
|
{
|
||||||
|
seq_analysis_info_t *sainfo = (seq_analysis_info_t *) ptr;
|
||||||
|
const struct tcpheader *tcph = (struct tcpheader *)tcp_info;
|
||||||
|
|
||||||
|
if ((sainfo->all_packets)||(pinfo->fd->flags.passed_dfilter==1)){
|
||||||
|
/* copied from packet-tcp */
|
||||||
|
static const gchar *fstr[] = {"FIN", "SYN", "RST", "PSH", "ACK", "URG", "ECN", "CWR" };
|
||||||
|
guint i, bpos;
|
||||||
|
gboolean flags_found = FALSE;
|
||||||
|
gchar flags[64];
|
||||||
|
seq_analysis_item_t *sai;
|
||||||
|
|
||||||
|
sai = (seq_analysis_item_t *)g_malloc(sizeof(seq_analysis_item_t));
|
||||||
|
sai->fd = pinfo->fd;
|
||||||
|
if (sainfo->any_addr) {
|
||||||
|
COPY_ADDRESS(&(sai->src_addr),&(pinfo->net_src));
|
||||||
|
COPY_ADDRESS(&(sai->dst_addr),&(pinfo->net_dst));
|
||||||
|
} else {
|
||||||
|
COPY_ADDRESS(&(sai->src_addr),&(pinfo->src));
|
||||||
|
COPY_ADDRESS(&(sai->dst_addr),&(pinfo->dst));
|
||||||
|
}
|
||||||
|
sai->port_src=pinfo->srcport;
|
||||||
|
sai->port_dst=pinfo->destport;
|
||||||
|
|
||||||
|
flags[0] = '\0';
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
bpos = 1 << i;
|
||||||
|
if (tcph->th_flags & bpos) {
|
||||||
|
if (flags_found) {
|
||||||
|
g_strlcat(flags, ", ", sizeof(flags));
|
||||||
|
}
|
||||||
|
g_strlcat(flags, fstr[i], sizeof(flags));
|
||||||
|
flags_found = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (flags[0] == '\0') {
|
||||||
|
g_snprintf (flags, sizeof(flags), "<None>");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((tcph->th_have_seglen)&&(tcph->th_seglen!=0)){
|
||||||
|
sai->frame_label = g_strdup_printf("%s - Len: %u",flags, tcph->th_seglen);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
sai->frame_label = g_strdup(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tcph->th_flags & TH_ACK)
|
||||||
|
sai->comment = g_strdup_printf("Seq = %u Ack = %u",tcph->th_seq, tcph->th_ack);
|
||||||
|
else
|
||||||
|
sai->comment = g_strdup_printf("Seq = %u",tcph->th_seq);
|
||||||
|
|
||||||
|
sai->line_style = 1;
|
||||||
|
sai->conv_num = 0;
|
||||||
|
sai->display = TRUE;
|
||||||
|
|
||||||
|
sainfo->list = g_list_prepend(sainfo->list, sai);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sequence_analysis_list_get(capture_file *cf, seq_analysis_info_t *sainfo)
|
||||||
|
{
|
||||||
|
GList *list;
|
||||||
|
gchar time_str[COL_MAX_LEN];
|
||||||
|
|
||||||
|
if (!cf || !sainfo) return;
|
||||||
|
|
||||||
|
switch (sainfo->type) {
|
||||||
|
case SEQ_ANALYSIS_ANY:
|
||||||
|
register_tap_listener("frame", sainfo, NULL,
|
||||||
|
TL_REQUIRES_COLUMNS,
|
||||||
|
NULL,
|
||||||
|
seq_analysis_frame_packet,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case SEQ_ANALYSIS_TCP:
|
||||||
|
register_tap_listener("tcp", sainfo, NULL,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
seq_analysis_tcp_packet,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case SEQ_ANALYSIS_VOIP:
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
cf_retap_packets(cf);
|
||||||
|
sainfo->list = g_list_reverse(sainfo->list);
|
||||||
|
remove_tap_listener(sainfo);
|
||||||
|
|
||||||
|
/* Fill in the timestamps */
|
||||||
|
list = g_list_first(sainfo->list);
|
||||||
|
while (list)
|
||||||
|
{
|
||||||
|
seq_analysis_item_t *seq_item = (seq_analysis_item_t *)list->data;
|
||||||
|
set_fd_time(cf->epan, seq_item->fd, time_str);
|
||||||
|
seq_item->time_str = g_strdup(time_str);
|
||||||
|
list = g_list_next(list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sequence_analysis_list_free(seq_analysis_info_t *sainfo)
|
||||||
|
{
|
||||||
|
GList *list;
|
||||||
|
|
||||||
|
if (!sainfo) return;
|
||||||
|
|
||||||
|
/* free the graph data items */
|
||||||
|
list = g_list_first(sainfo->list);
|
||||||
|
while (list)
|
||||||
|
{
|
||||||
|
seq_analysis_item_t *seq_item = (seq_analysis_item_t *)list->data;
|
||||||
|
g_free(seq_item->frame_label);
|
||||||
|
g_free(seq_item->time_str);
|
||||||
|
g_free(seq_item->comment);
|
||||||
|
g_free(list->data);
|
||||||
|
list = g_list_next(list);
|
||||||
|
}
|
||||||
|
g_list_free(sainfo->list);
|
||||||
|
sainfo->nconv = 0;
|
||||||
|
sainfo->list = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/* Adds trailing characters to complete the requested length. */
|
||||||
|
/****************************************************************************/
|
||||||
|
|
||||||
|
static void enlarge_string(GString *gstr, guint32 length, char pad) {
|
||||||
|
|
||||||
|
gsize i;
|
||||||
|
|
||||||
|
for (i = gstr->len; i < length; i++) {
|
||||||
|
g_string_append_c(gstr, pad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/* overwrites the characters in a string, between positions p1 and p2, with */
|
||||||
|
/* the characters of text_to_insert */
|
||||||
|
/* NB: it does not check that p1 and p2 fit into string */
|
||||||
|
/****************************************************************************/
|
||||||
|
|
||||||
|
static void overwrite (GString *gstr, char *text_to_insert, guint32 p1, guint32 p2) {
|
||||||
|
|
||||||
|
gsize len;
|
||||||
|
gsize pos;
|
||||||
|
|
||||||
|
if (p1 == p2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (p1 > p2) {
|
||||||
|
pos = p2;
|
||||||
|
len = p1 - p2;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
pos = p1;
|
||||||
|
len = p2 - p1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len > strlen(text_to_insert)) {
|
||||||
|
len = strlen(text_to_insert);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pos > gstr->len)
|
||||||
|
pos = gstr->len;
|
||||||
|
|
||||||
|
/* ouch this is ugly but gtk1 needs it */
|
||||||
|
if ((pos + len) > gstr->len)
|
||||||
|
g_string_truncate(gstr, pos);
|
||||||
|
else
|
||||||
|
g_string_erase(gstr, pos, len);
|
||||||
|
|
||||||
|
g_string_insert(gstr, pos, text_to_insert);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the index array if the node is in the array. Return -1 if there is room in the array
|
||||||
|
* and Return -2 if the array is full
|
||||||
|
*/
|
||||||
|
/****************************************************************************/
|
||||||
|
static gint add_or_get_node(seq_analysis_info_t *sainfo, address *node) {
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
if (node->type == AT_NONE) return NODE_OVERFLOW;
|
||||||
|
|
||||||
|
for (i=0; i<MAX_NUM_NODES && i < sainfo->num_nodes ; i++) {
|
||||||
|
if ( CMP_ADDRESS(&(sainfo->nodes[i]), node) == 0 ) return i; /* it is in the array */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == MAX_NUM_NODES) {
|
||||||
|
return NODE_OVERFLOW;
|
||||||
|
} else {
|
||||||
|
sainfo->num_nodes++;
|
||||||
|
COPY_ADDRESS(&(sainfo->nodes[i]), node);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the nodes from the list */
|
||||||
|
/****************************************************************************/
|
||||||
|
int
|
||||||
|
sequence_analysis_get_nodes(seq_analysis_info_t *sainfo)
|
||||||
|
{
|
||||||
|
GList *list;
|
||||||
|
seq_analysis_item_t *gai;
|
||||||
|
int num_items = 0;
|
||||||
|
|
||||||
|
/* fill the node array */
|
||||||
|
list = g_list_first(sainfo->list);
|
||||||
|
while (list)
|
||||||
|
{
|
||||||
|
gai = (seq_analysis_item_t *)list->data;
|
||||||
|
if (gai->display) {
|
||||||
|
num_items++;
|
||||||
|
#if 0 /* inverse is always false ? */
|
||||||
|
if (!user_data->dlg.inverse) {
|
||||||
|
#endif
|
||||||
|
gai->src_node = (guint16)add_or_get_node(sainfo, &(gai->src_addr));
|
||||||
|
gai->dst_node = (guint16)add_or_get_node(sainfo, &(gai->dst_addr));
|
||||||
|
#if 0 /* inverse is always false ? */
|
||||||
|
} else {
|
||||||
|
gai->dst_node = (guint16)add_or_get_node(sainfo, &(gai->src_addr));
|
||||||
|
gai->src_node = (guint16)add_or_get_node(sainfo, &(gai->dst_addr));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
list = g_list_next(list);
|
||||||
|
}
|
||||||
|
return num_items;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
gboolean
|
||||||
|
sequence_analysis_dump_to_file(char *pathname, seq_analysis_info_t *sainfo, capture_file *cf, unsigned int first_node)
|
||||||
|
{
|
||||||
|
guint32 i, display_items, display_nodes;
|
||||||
|
guint32 start_position, end_position, item_width, header_length;
|
||||||
|
seq_analysis_item_t *sai;
|
||||||
|
guint16 first_conv_num = 0;
|
||||||
|
gboolean several_convs = FALSE;
|
||||||
|
gboolean first_packet = TRUE;
|
||||||
|
|
||||||
|
GString *label_string, *empty_line, *separator_line, *tmp_str, *tmp_str2;
|
||||||
|
const char *empty_header;
|
||||||
|
char src_port[8], dst_port[8];
|
||||||
|
gchar *time_str;
|
||||||
|
GList *list;
|
||||||
|
|
||||||
|
FILE *of;
|
||||||
|
|
||||||
|
of = ws_fopen(pathname, "w");
|
||||||
|
if (of==NULL) {
|
||||||
|
open_failure_alert_box(pathname, errno, TRUE);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
time_str = (gchar *)g_malloc(COL_MAX_LEN);
|
||||||
|
label_string = g_string_new("");
|
||||||
|
empty_line = g_string_new("");
|
||||||
|
separator_line = g_string_new("");
|
||||||
|
tmp_str = g_string_new("");
|
||||||
|
tmp_str2 = g_string_new("");
|
||||||
|
|
||||||
|
display_items = 0;
|
||||||
|
list = g_list_first(sainfo->list);
|
||||||
|
while (list)
|
||||||
|
{
|
||||||
|
sai = (seq_analysis_item_t *)list->data;
|
||||||
|
list = g_list_next(list);
|
||||||
|
|
||||||
|
if (!sai->display)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
display_items += 1;
|
||||||
|
if (first_packet) {
|
||||||
|
first_conv_num = sai->conv_num;
|
||||||
|
first_packet = FALSE;
|
||||||
|
}
|
||||||
|
else if (sai->conv_num != first_conv_num) {
|
||||||
|
several_convs = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if not items to display */
|
||||||
|
if (display_items == 0)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
display_nodes = sainfo->num_nodes;
|
||||||
|
|
||||||
|
/* Write the conv. and time headers */
|
||||||
|
if (several_convs) {
|
||||||
|
fprintf(of, CONV_TIME_HEADER);
|
||||||
|
empty_header = CONV_TIME_EMPTY_HEADER;
|
||||||
|
header_length = CONV_TIME_HEADER_LENGTH;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
fprintf(of, TIME_HEADER);
|
||||||
|
empty_header = TIME_EMPTY_HEADER;
|
||||||
|
header_length = TIME_HEADER_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write the node names on top */
|
||||||
|
for (i=0; i<display_nodes; i+=2) {
|
||||||
|
/* print the node identifiers */
|
||||||
|
g_string_printf(label_string, "| %s",
|
||||||
|
get_addr_name(&(sainfo->nodes[i+first_node])));
|
||||||
|
enlarge_string(label_string, NODE_CHARS_WIDTH*2, ' ');
|
||||||
|
fprintf(of, "%s", label_string->str);
|
||||||
|
g_string_printf(label_string, "| ");
|
||||||
|
enlarge_string(label_string, NODE_CHARS_WIDTH, ' ');
|
||||||
|
g_string_append(empty_line, label_string->str);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(of, "|\n%s", empty_header);
|
||||||
|
g_string_printf(label_string, "| ");
|
||||||
|
enlarge_string(label_string, NODE_CHARS_WIDTH, ' ');
|
||||||
|
fprintf(of, "%s", label_string->str);
|
||||||
|
|
||||||
|
/* Write the node names on top */
|
||||||
|
for (i=1; i<display_nodes; i+=2) {
|
||||||
|
/* print the node identifiers */
|
||||||
|
g_string_printf(label_string, "| %s",
|
||||||
|
get_addr_name(&(sainfo->nodes[i+first_node])));
|
||||||
|
if (label_string->len < NODE_CHARS_WIDTH)
|
||||||
|
{
|
||||||
|
enlarge_string(label_string, NODE_CHARS_WIDTH, ' ');
|
||||||
|
g_string_append(label_string, "| ");
|
||||||
|
}
|
||||||
|
enlarge_string(label_string, NODE_CHARS_WIDTH*2, ' ');
|
||||||
|
fprintf(of, "%s", label_string->str);
|
||||||
|
g_string_printf(label_string, "| ");
|
||||||
|
enlarge_string(label_string, NODE_CHARS_WIDTH, ' ');
|
||||||
|
g_string_append(empty_line, label_string->str);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(of, "\n");
|
||||||
|
|
||||||
|
g_string_append_c(empty_line, '|');
|
||||||
|
|
||||||
|
enlarge_string(separator_line, (guint32) empty_line->len + header_length, '-');
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Draw the items
|
||||||
|
*/
|
||||||
|
|
||||||
|
list = g_list_first(sainfo->list);
|
||||||
|
while (list)
|
||||||
|
{
|
||||||
|
sai = (seq_analysis_item_t *)list->data;
|
||||||
|
list = g_list_next(list);
|
||||||
|
|
||||||
|
if (!sai->display)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
start_position = (sai->src_node-first_node)*NODE_CHARS_WIDTH+NODE_CHARS_WIDTH/2;
|
||||||
|
|
||||||
|
end_position = (sai->dst_node-first_node)*NODE_CHARS_WIDTH+NODE_CHARS_WIDTH/2;
|
||||||
|
|
||||||
|
if (start_position > end_position) {
|
||||||
|
item_width = start_position-end_position;
|
||||||
|
}
|
||||||
|
else if (start_position < end_position) {
|
||||||
|
item_width = end_position-start_position;
|
||||||
|
}
|
||||||
|
else{ /* same origin and destination address */
|
||||||
|
end_position = start_position+NODE_CHARS_WIDTH;
|
||||||
|
item_width = NODE_CHARS_WIDTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* separator between conversations */
|
||||||
|
if (sai->conv_num != first_conv_num) {
|
||||||
|
fprintf(of, "%s\n", separator_line->str);
|
||||||
|
first_conv_num = sai->conv_num;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write the conversation number */
|
||||||
|
if (several_convs) {
|
||||||
|
g_string_printf(label_string, "%i", sai->conv_num);
|
||||||
|
enlarge_string(label_string, 5, ' ');
|
||||||
|
fprintf(of, "%s", label_string->str);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* write the time */
|
||||||
|
g_string_printf(label_string, "|%.3f", nstime_to_sec(&sai->fd->rel_ts));
|
||||||
|
#endif
|
||||||
|
/* Write the time, using the same format as in the time col */
|
||||||
|
set_fd_time(cf->epan, sai->fd, time_str);
|
||||||
|
g_string_printf(label_string, "|%s", time_str);
|
||||||
|
enlarge_string(label_string, 10, ' ');
|
||||||
|
fprintf(of, "%s", label_string->str);
|
||||||
|
|
||||||
|
/* write the frame label */
|
||||||
|
|
||||||
|
g_string_printf(tmp_str, "%s", empty_line->str);
|
||||||
|
overwrite(tmp_str, sai->frame_label,
|
||||||
|
start_position,
|
||||||
|
end_position
|
||||||
|
);
|
||||||
|
fprintf(of, "%s", tmp_str->str);
|
||||||
|
|
||||||
|
/* write the comments */
|
||||||
|
fprintf(of, "%s\n", sai->comment);
|
||||||
|
|
||||||
|
/* write the arrow and frame label*/
|
||||||
|
fprintf(of, "%s", empty_header);
|
||||||
|
|
||||||
|
g_string_printf(tmp_str, "%s", empty_line->str);
|
||||||
|
|
||||||
|
g_string_truncate(tmp_str2, 0);
|
||||||
|
|
||||||
|
if (start_position<end_position) {
|
||||||
|
enlarge_string(tmp_str2, item_width-2, '-');
|
||||||
|
g_string_append_c(tmp_str2, '>');
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
g_string_printf(tmp_str2, "<");
|
||||||
|
enlarge_string(tmp_str2, item_width-1, '-');
|
||||||
|
}
|
||||||
|
|
||||||
|
overwrite(tmp_str, tmp_str2->str,
|
||||||
|
start_position,
|
||||||
|
end_position
|
||||||
|
);
|
||||||
|
|
||||||
|
g_snprintf(src_port, sizeof(src_port), "(%i)", sai->port_src);
|
||||||
|
g_snprintf(dst_port, sizeof(dst_port), "(%i)", sai->port_dst);
|
||||||
|
|
||||||
|
if (start_position<end_position) {
|
||||||
|
overwrite(tmp_str, src_port, start_position-9, start_position-1);
|
||||||
|
overwrite(tmp_str, dst_port, end_position+1, end_position+9);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
overwrite(tmp_str, src_port, start_position+1, start_position+9);
|
||||||
|
overwrite(tmp_str, dst_port, end_position-9, end_position+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(of, "%s\n", tmp_str->str);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
g_string_free(label_string, TRUE);
|
||||||
|
g_string_free(empty_line, TRUE);
|
||||||
|
g_string_free(separator_line, TRUE);
|
||||||
|
g_string_free(tmp_str, TRUE);
|
||||||
|
g_string_free(tmp_str2, TRUE);
|
||||||
|
g_free(time_str);
|
||||||
|
fclose (of);
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Editor modelines
|
||||||
|
*
|
||||||
|
* Local Variables:
|
||||||
|
* c-basic-offset: 4
|
||||||
|
* tab-width: 8
|
||||||
|
* indent-tabs-mode: nil
|
||||||
|
* End:
|
||||||
|
*
|
||||||
|
* ex: set shiftwidth=4 tabstop=8 expandtab:
|
||||||
|
* :indentSize=4:tabSize=8:noTabs=true:
|
||||||
|
*/
|
|
@ -0,0 +1,129 @@
|
||||||
|
/* tap-sequence-analysis.h
|
||||||
|
* Flow sequence analysis
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Copied from gtk/graph_analysis.h
|
||||||
|
*
|
||||||
|
* Copyright 2004, Verso Technologies Inc.
|
||||||
|
* By Alejandro Vaquero <alejandrovaquero@yahoo.com>
|
||||||
|
*
|
||||||
|
* based on rtp_analysis.c and io_stat
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Wireshark - Network traffic analyzer
|
||||||
|
* By Gerald Combs <gerald@wireshark.org>
|
||||||
|
* Copyright 1998 Gerald Combs
|
||||||
|
*
|
||||||
|
* 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 2
|
||||||
|
* 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, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __TAP_SEQUENCE_ANALYSIS_H__
|
||||||
|
#define __TAP_SEQUENCE_ANALYSIS_H__
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include "cfile.h"
|
||||||
|
#include "epan/address.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#define MAX_NUM_NODES 40
|
||||||
|
|
||||||
|
typedef enum seq_analysis_type_ {
|
||||||
|
SEQ_ANALYSIS_ANY,
|
||||||
|
SEQ_ANALYSIS_TCP,
|
||||||
|
SEQ_ANALYSIS_VOIP
|
||||||
|
} seq_analysis_type;
|
||||||
|
|
||||||
|
/** defines an entry for the graph analysis */
|
||||||
|
typedef struct _seq_analysis_item {
|
||||||
|
frame_data *fd; /**< Holds the frame number and time information */
|
||||||
|
address src_addr;
|
||||||
|
guint16 port_src;
|
||||||
|
address dst_addr;
|
||||||
|
guint16 port_dst;
|
||||||
|
gchar *frame_label; /**< the label on top of the arrow */
|
||||||
|
gchar *time_str; /**< timestamp */
|
||||||
|
gchar *comment; /**< a comment that appears at the left of the graph */
|
||||||
|
guint16 conv_num; /**< the conversation number, each conversation will be colored */
|
||||||
|
gboolean display; /**< indicate if the packet is displayed or not in the graph */
|
||||||
|
guint16 src_node; /**< this is used by graph_analysis.c to identify the node */
|
||||||
|
guint16 dst_node; /**< a node is an IP address that will be displayed in columns */
|
||||||
|
guint16 line_style; /**< the arrow line width in pixels*/
|
||||||
|
} seq_analysis_item_t;
|
||||||
|
|
||||||
|
/** defines the graph analysis structure */
|
||||||
|
typedef struct _seq_analysis_info {
|
||||||
|
seq_analysis_type type; /**< sequence type */
|
||||||
|
gboolean all_packets; /**< all packets vs only displayed */
|
||||||
|
gboolean any_addr; /**< any addr (DL+net) vs net-only */
|
||||||
|
int nconv; /**< number of conversations in the list */
|
||||||
|
GList* list; /**< list with the graph analysis items */
|
||||||
|
GHashTable *ht; /**< hash table for retrieving graph analysis items */
|
||||||
|
address nodes[MAX_NUM_NODES]; /**< horizontal node list */
|
||||||
|
guint32 num_nodes; /**< actual number of nodes */
|
||||||
|
} seq_analysis_info_t;
|
||||||
|
|
||||||
|
/** Fill in the segment list for sequence analysis
|
||||||
|
*
|
||||||
|
* @param cf Capture file to scan
|
||||||
|
* @param sai Sequence analysis information. A valid type must be set.
|
||||||
|
*/
|
||||||
|
void sequence_analysis_list_get(capture_file *cf, seq_analysis_info_t *sainfo);
|
||||||
|
|
||||||
|
/** Free the segment list
|
||||||
|
*
|
||||||
|
* @param sai Sequence analysis information.
|
||||||
|
*/
|
||||||
|
void sequence_analysis_list_free(seq_analysis_info_t *sainfo);
|
||||||
|
|
||||||
|
/** Fill in the node address list
|
||||||
|
*
|
||||||
|
* @param sai Sequence analysis information.
|
||||||
|
* @return The number of transaction items (not nodes) processed.
|
||||||
|
*/
|
||||||
|
int sequence_analysis_get_nodes(seq_analysis_info_t *sainfo);
|
||||||
|
|
||||||
|
/** Write an ASCII version of the sequence diagram to a file.
|
||||||
|
*
|
||||||
|
* @param pathname Pathname of the file to write.
|
||||||
|
* @param sai Sequence analysis information.
|
||||||
|
* @param cf Capture file associated with the diagram.
|
||||||
|
* @param first_node Start drawing at this node.
|
||||||
|
* @return TRUE on success, FALSE on failure.
|
||||||
|
*/
|
||||||
|
gboolean sequence_analysis_dump_to_file(char *pathname, seq_analysis_info_t *sainfo, capture_file *cf, unsigned int first_node);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#endif /* __TAP_SEQUENCE_ANALYSIS_H__ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Editor modelines
|
||||||
|
*
|
||||||
|
* Local Variables:
|
||||||
|
* c-basic-offset: 4
|
||||||
|
* tab-width: 8
|
||||||
|
* indent-tabs-mode: nil
|
||||||
|
* End:
|
||||||
|
*
|
||||||
|
* ex: set shiftwidth=4 tabstop=8 expandtab:
|
||||||
|
* :indentSize=4:tabSize=8:noTabs=true:
|
||||||
|
*/
|
Loading…
Reference in New Issue