2000-02-29 06:24:41 +00:00
|
|
|
/* packet_win.c
|
|
|
|
* Routines for popping a window to display current packet
|
|
|
|
*
|
|
|
|
* Copyright 2000, Jeffrey C. Foster <jfoste@woodward.com>
|
|
|
|
*
|
We already set the foreground and background color for every frame,
which means we're already doing a "do something to the last row in the
packet list" operation on every frame we add to the list, so adding a
call to "gtk_clist_set_row_data()" won't make matters worse.
In addition, we already set one column in a row on a "change time
format" operation, so finding the row for a frame by calling
"gtk_clist_find_row_from_data()" doesn't turn a constant-time operation
into a linear-time operation, it just cranks the proportionality
constant up - it was quadratic before, alas, and it's still quadratic.
Adding calls to "gtk_clist_find_row_from_data()" to the "Find Frame" and
"Go To Frame" code does add an extra linear operation there, but those
operations shouldn't be common - and "Go To Frame", going to the last
frame on an ~100,000-frame big capture file, was quick, at least on my
450 MHz Pentium II machine, so maybe it won't be too bad.
And "select_packet()" either has to search the frame table for the frame
with the specified row number, or has to call "gtk_clist_get_row_data()"
to do that - the first is linear in the position of the frame in the
frame table, and the latter is linear in its position in the CList, and
the latter is less than or equal to the former, so the only thing making
it worse would be a change in the proportionality constant.
So it probably won't hurt performance by much.
Furthermore, if we add the ability to sort the display on an arbitrary
column, or to delete frames from the display - both of which are in the
wish list - storing the row number of the frame in the "frame_data"
structure won't necessarily work, as the row number can change out from
under us.
Therefore, reinstate the old way of doing things, where we associate
with each row a pointer to the "frame_data" structure for the row, using
"gtk_clist_set_row_data()".
svn path=/trunk/; revision=1703
2000-03-08 06:48:01 +00:00
|
|
|
* $Id: packet_win.c,v 1.4 2000/03/08 06:48:01 guy Exp $
|
2000-02-29 06:24:41 +00:00
|
|
|
*
|
|
|
|
* Ethereal - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@zing.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*
|
|
|
|
* To do:
|
|
|
|
* - Add close button to bottom.
|
|
|
|
* - improve the window Title and allow user to config it
|
|
|
|
* - Add print support ? ( could be a mess)
|
|
|
|
* - Add button to have main window jump to this packet ?
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#ifdef HAVE_UNISTD_H
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "main.h"
|
|
|
|
#include "timestamp.h"
|
|
|
|
#include "packet.h"
|
|
|
|
#include "capture.h"
|
|
|
|
#include "summary.h"
|
|
|
|
#include "file.h"
|
|
|
|
#include "menu.h"
|
|
|
|
#include "../menu.h"
|
|
|
|
#include "prefs_dlg.h"
|
|
|
|
#include "column.h"
|
|
|
|
#include "print.h"
|
|
|
|
#include "resolv.h"
|
|
|
|
#include "follow.h"
|
|
|
|
#include "util.h"
|
|
|
|
#include "packet_win.h"
|
|
|
|
#include "simple_dialog.h"
|
|
|
|
#include "ui_util.h"
|
|
|
|
#include "proto_draw.h"
|
|
|
|
#include "dfilter.h"
|
|
|
|
#include "keys.h"
|
|
|
|
#include "gtkglobals.h"
|
|
|
|
#include "plugins.h"
|
|
|
|
|
|
|
|
/* Data structure holding information about a packet-detail window. */
|
|
|
|
struct PacketWinData {
|
|
|
|
gint cap_len;
|
|
|
|
gint encoding;
|
|
|
|
guint8 *pd; /* Data for packet */
|
|
|
|
proto_tree *protocol_tree; /* Protocol tree for packet */
|
|
|
|
GtkWidget *main;
|
|
|
|
GtkWidget *tv_scrollw;
|
|
|
|
GtkWidget *tree_view;
|
2000-03-02 07:05:57 +00:00
|
|
|
GtkWidget *bv_scrollw;
|
2000-02-29 06:24:41 +00:00
|
|
|
GtkWidget *byte_view;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* List of all the packet-detail windows popped up. */
|
|
|
|
static GList *detail_windows;
|
|
|
|
|
|
|
|
static void new_tree_view_select_row_cb( GtkCTree *ctree, GList *node,
|
|
|
|
gint column, gpointer user_data);
|
|
|
|
|
|
|
|
static void new_tree_view_unselect_row_cb( GtkCTree *ctree, GList *node,
|
|
|
|
gint column, gpointer user_data);
|
|
|
|
|
|
|
|
static void create_new_window( char *Title, gint tv_size, gint bv_size);
|
2000-03-01 06:50:18 +00:00
|
|
|
static void destroy_new_window(GtkObject *object, gpointer user_data);
|
2000-02-29 06:24:41 +00:00
|
|
|
|
|
|
|
void new_window_cb(GtkWidget *w){
|
|
|
|
|
|
|
|
#define NewWinTitleLen 1000
|
|
|
|
|
We already set the foreground and background color for every frame,
which means we're already doing a "do something to the last row in the
packet list" operation on every frame we add to the list, so adding a
call to "gtk_clist_set_row_data()" won't make matters worse.
In addition, we already set one column in a row on a "change time
format" operation, so finding the row for a frame by calling
"gtk_clist_find_row_from_data()" doesn't turn a constant-time operation
into a linear-time operation, it just cranks the proportionality
constant up - it was quadratic before, alas, and it's still quadratic.
Adding calls to "gtk_clist_find_row_from_data()" to the "Find Frame" and
"Go To Frame" code does add an extra linear operation there, but those
operations shouldn't be common - and "Go To Frame", going to the last
frame on an ~100,000-frame big capture file, was quick, at least on my
450 MHz Pentium II machine, so maybe it won't be too bad.
And "select_packet()" either has to search the frame table for the frame
with the specified row number, or has to call "gtk_clist_get_row_data()"
to do that - the first is linear in the position of the frame in the
frame table, and the latter is linear in its position in the CList, and
the latter is less than or equal to the former, so the only thing making
it worse would be a change in the proportionality constant.
So it probably won't hurt performance by much.
Furthermore, if we add the ability to sort the display on an arbitrary
column, or to delete frames from the display - both of which are in the
wish list - storing the row number of the frame in the "frame_data"
structure won't necessarily work, as the row number can change out from
under us.
Therefore, reinstate the old way of doing things, where we associate
with each row a pointer to the "frame_data" structure for the row, using
"gtk_clist_set_row_data()".
svn path=/trunk/; revision=1703
2000-03-08 06:48:01 +00:00
|
|
|
int row;
|
2000-02-29 06:24:41 +00:00
|
|
|
gint tv_size = 95, bv_size = 75;
|
|
|
|
int i;
|
|
|
|
char Title[ NewWinTitleLen] = "";
|
|
|
|
char *TextPtr;
|
|
|
|
|
|
|
|
/* build title of window by getting */
|
|
|
|
/* data from the packet_list GtkCList */
|
We already set the foreground and background color for every frame,
which means we're already doing a "do something to the last row in the
packet list" operation on every frame we add to the list, so adding a
call to "gtk_clist_set_row_data()" won't make matters worse.
In addition, we already set one column in a row on a "change time
format" operation, so finding the row for a frame by calling
"gtk_clist_find_row_from_data()" doesn't turn a constant-time operation
into a linear-time operation, it just cranks the proportionality
constant up - it was quadratic before, alas, and it's still quadratic.
Adding calls to "gtk_clist_find_row_from_data()" to the "Find Frame" and
"Go To Frame" code does add an extra linear operation there, but those
operations shouldn't be common - and "Go To Frame", going to the last
frame on an ~100,000-frame big capture file, was quick, at least on my
450 MHz Pentium II machine, so maybe it won't be too bad.
And "select_packet()" either has to search the frame table for the frame
with the specified row number, or has to call "gtk_clist_get_row_data()"
to do that - the first is linear in the position of the frame in the
frame table, and the latter is linear in its position in the CList, and
the latter is less than or equal to the former, so the only thing making
it worse would be a change in the proportionality constant.
So it probably won't hurt performance by much.
Furthermore, if we add the ability to sort the display on an arbitrary
column, or to delete frames from the display - both of which are in the
wish list - storing the row number of the frame in the "frame_data"
structure won't necessarily work, as the row number can change out from
under us.
Therefore, reinstate the old way of doing things, where we associate
with each row a pointer to the "frame_data" structure for the row, using
"gtk_clist_set_row_data()".
svn path=/trunk/; revision=1703
2000-03-08 06:48:01 +00:00
|
|
|
/* Find what row this packet is in. */
|
|
|
|
row = gtk_clist_find_row_from_data(GTK_CLIST(packet_list),
|
|
|
|
cf.current_frame);
|
|
|
|
g_assert(row != -1);
|
2000-02-29 06:24:41 +00:00
|
|
|
for( i = 0; i < cf.cinfo.num_cols; ++i){
|
|
|
|
|
|
|
|
if ( gtk_clist_get_text(GTK_CLIST( packet_list),
|
We already set the foreground and background color for every frame,
which means we're already doing a "do something to the last row in the
packet list" operation on every frame we add to the list, so adding a
call to "gtk_clist_set_row_data()" won't make matters worse.
In addition, we already set one column in a row on a "change time
format" operation, so finding the row for a frame by calling
"gtk_clist_find_row_from_data()" doesn't turn a constant-time operation
into a linear-time operation, it just cranks the proportionality
constant up - it was quadratic before, alas, and it's still quadratic.
Adding calls to "gtk_clist_find_row_from_data()" to the "Find Frame" and
"Go To Frame" code does add an extra linear operation there, but those
operations shouldn't be common - and "Go To Frame", going to the last
frame on an ~100,000-frame big capture file, was quick, at least on my
450 MHz Pentium II machine, so maybe it won't be too bad.
And "select_packet()" either has to search the frame table for the frame
with the specified row number, or has to call "gtk_clist_get_row_data()"
to do that - the first is linear in the position of the frame in the
frame table, and the latter is linear in its position in the CList, and
the latter is less than or equal to the former, so the only thing making
it worse would be a change in the proportionality constant.
So it probably won't hurt performance by much.
Furthermore, if we add the ability to sort the display on an arbitrary
column, or to delete frames from the display - both of which are in the
wish list - storing the row number of the frame in the "frame_data"
structure won't necessarily work, as the row number can change out from
under us.
Therefore, reinstate the old way of doing things, where we associate
with each row a pointer to the "frame_data" structure for the row, using
"gtk_clist_set_row_data()".
svn path=/trunk/; revision=1703
2000-03-08 06:48:01 +00:00
|
|
|
row, i, &TextPtr)){
|
2000-02-29 06:24:41 +00:00
|
|
|
|
|
|
|
if (( strlen( Title) + strlen( TextPtr))
|
|
|
|
< ( NewWinTitleLen - 1)){
|
|
|
|
|
|
|
|
strcat( Title, TextPtr);
|
|
|
|
strcat( Title, " ");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
create_new_window ( Title, tv_size, bv_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
create_new_window ( char *Title, gint tv_size, gint bv_size){
|
|
|
|
|
|
|
|
GtkWidget *main_w, *main_vbox, *pane,
|
|
|
|
*tree_view, *byte_view, *tv_scrollw,
|
2000-03-02 07:05:57 +00:00
|
|
|
*bv_scrollw;
|
2000-02-29 06:24:41 +00:00
|
|
|
struct PacketWinData *DataPtr;
|
|
|
|
|
|
|
|
main_w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
|
|
|
|
|
|
|
gtk_window_set_title(GTK_WINDOW(main_w), Title);
|
|
|
|
gtk_window_set_default_size(GTK_WINDOW(main_w), DEF_WIDTH, -1);
|
|
|
|
|
|
|
|
/* Container for paned windows */
|
|
|
|
main_vbox = gtk_vbox_new(FALSE, 1);
|
|
|
|
gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
|
|
|
|
gtk_container_add(GTK_CONTAINER(main_w), main_vbox);
|
|
|
|
gtk_widget_show(main_vbox);
|
|
|
|
|
|
|
|
/* Panes for the tree and byte view */
|
|
|
|
pane = gtk_vpaned_new();
|
|
|
|
gtk_paned_gutter_size(GTK_PANED(pane), (GTK_PANED(pane))->handle_size);
|
|
|
|
gtk_container_add(GTK_CONTAINER(main_vbox), pane);
|
|
|
|
gtk_widget_show(pane);
|
|
|
|
|
|
|
|
/* Tree view */
|
2000-03-02 07:05:57 +00:00
|
|
|
create_tree_view(tv_size, &prefs, pane, &tv_scrollw, &tree_view,
|
|
|
|
prefs.gui_scrollbar_on_right);
|
2000-02-29 06:24:41 +00:00
|
|
|
gtk_widget_show(tree_view);
|
|
|
|
|
|
|
|
/* Byte view */
|
2000-03-02 07:05:57 +00:00
|
|
|
create_byte_view(bv_size, pane, &byte_view, &bv_scrollw,
|
|
|
|
prefs.gui_scrollbar_on_right);
|
2000-02-29 06:24:41 +00:00
|
|
|
|
|
|
|
/* Allocate data structure to represent this window. */
|
|
|
|
DataPtr = (struct PacketWinData *) g_malloc(sizeof(struct PacketWinData));
|
|
|
|
|
|
|
|
DataPtr->cap_len = cf.current_frame->cap_len;
|
|
|
|
DataPtr->encoding = cf.current_frame->encoding;
|
|
|
|
DataPtr->pd = g_malloc(DataPtr->cap_len);
|
|
|
|
memcpy(DataPtr->pd, cf.pd, DataPtr->cap_len);
|
|
|
|
DataPtr->protocol_tree = proto_tree_create_root();
|
|
|
|
dissect_packet(DataPtr->pd, cf.current_frame, DataPtr->protocol_tree);
|
|
|
|
DataPtr->main = main_w;
|
|
|
|
DataPtr->tv_scrollw = tv_scrollw;
|
|
|
|
DataPtr->tree_view = tree_view;
|
|
|
|
DataPtr->byte_view = byte_view;
|
2000-03-02 07:05:57 +00:00
|
|
|
DataPtr->bv_scrollw = bv_scrollw;
|
2000-02-29 06:24:41 +00:00
|
|
|
detail_windows = g_list_append(detail_windows, DataPtr);
|
|
|
|
|
|
|
|
/* load callback handlers */
|
|
|
|
gtk_signal_connect(GTK_OBJECT(tree_view), "tree-select-row",
|
|
|
|
GTK_SIGNAL_FUNC(new_tree_view_select_row_cb), DataPtr);
|
|
|
|
|
2000-03-01 06:50:18 +00:00
|
|
|
gtk_signal_connect(GTK_OBJECT(tree_view), "tree-unselect-row",
|
|
|
|
GTK_SIGNAL_FUNC(new_tree_view_unselect_row_cb), DataPtr);
|
|
|
|
|
|
|
|
gtk_signal_connect(GTK_OBJECT(main_w), "destroy",
|
|
|
|
GTK_SIGNAL_FUNC(destroy_new_window), DataPtr);
|
2000-02-29 06:24:41 +00:00
|
|
|
|
|
|
|
/* draw the protocol tree & print hex data */
|
|
|
|
proto_tree_draw(DataPtr->protocol_tree, tree_view);
|
|
|
|
packet_hex_print( GTK_TEXT(byte_view), DataPtr->pd,
|
|
|
|
DataPtr->cap_len, -1, -1, DataPtr->encoding);
|
|
|
|
|
|
|
|
gtk_widget_show(main_w);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2000-03-01 06:50:18 +00:00
|
|
|
destroy_new_window(GtkObject *object, gpointer user_data)
|
2000-02-29 06:24:41 +00:00
|
|
|
{
|
2000-03-01 06:50:18 +00:00
|
|
|
struct PacketWinData *DataPtr = user_data;
|
2000-02-29 06:24:41 +00:00
|
|
|
|
|
|
|
detail_windows = g_list_remove(detail_windows, DataPtr);
|
2000-03-02 07:05:57 +00:00
|
|
|
forget_scrolled_window(DataPtr->tv_scrollw);
|
|
|
|
forget_scrolled_window(DataPtr->bv_scrollw);
|
2000-02-29 06:24:41 +00:00
|
|
|
proto_tree_free(DataPtr->protocol_tree);
|
|
|
|
g_free(DataPtr->pd);
|
|
|
|
g_free(DataPtr);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
new_tree_view_select_row_cb(GtkCTree *ctree, GList *node, gint column,
|
|
|
|
gpointer user_data){
|
|
|
|
|
|
|
|
/* called when a tree row is selected in the popup packet window */
|
|
|
|
|
|
|
|
field_info *finfo;
|
|
|
|
|
|
|
|
struct PacketWinData *DataPtr = (struct PacketWinData*)user_data;
|
|
|
|
|
|
|
|
g_assert(node);
|
|
|
|
finfo = gtk_ctree_node_get_row_data( ctree, GTK_CTREE_NODE(node) );
|
|
|
|
if (!finfo) return;
|
|
|
|
|
|
|
|
finfo_selected = finfo;
|
|
|
|
|
|
|
|
packet_hex_print(GTK_TEXT(DataPtr->byte_view), DataPtr->pd,
|
|
|
|
DataPtr->cap_len, finfo->start, finfo->length,
|
|
|
|
DataPtr->encoding);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
new_tree_view_unselect_row_cb(GtkCTree *ctree, GList *node, gint column,
|
|
|
|
gpointer user_data){
|
|
|
|
|
|
|
|
/* called when a tree row is unselected in the popup packet window */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct PacketWinData *DataPtr = (struct PacketWinData*)user_data;
|
|
|
|
|
|
|
|
packet_hex_print(GTK_TEXT(DataPtr->byte_view), DataPtr->pd,
|
|
|
|
DataPtr->cap_len, -1, -1, DataPtr->encoding);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Functions called from elsewhere to act on all popup packet windows. */
|
|
|
|
|
|
|
|
/* Destroy all popup packet windows. */
|
|
|
|
void
|
|
|
|
destroy_packet_wins(void)
|
|
|
|
{
|
|
|
|
struct PacketWinData *DataPtr;
|
|
|
|
|
|
|
|
/* Destroying a packet window causes it to be removed from
|
|
|
|
the list of packet windows, so we can't do a "g_list_foreach()"
|
|
|
|
to go through the list of all packet windows and destroy them
|
|
|
|
as we find them; instead, as long as the list is non-empty,
|
|
|
|
we destroy the first window on the list. */
|
|
|
|
while (detail_windows != NULL) {
|
|
|
|
DataPtr = (struct PacketWinData *)(detail_windows->data);
|
|
|
|
gtk_widget_destroy(DataPtr->main);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
set_ptree_sel_browse_cb(gpointer data, gpointer user_data)
|
|
|
|
{
|
|
|
|
struct PacketWinData *DataPtr = (struct PacketWinData *)data;
|
|
|
|
|
|
|
|
set_ptree_sel_browse(DataPtr->tree_view, *(gboolean *)user_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set the selection mode of all the popup packet windows. */
|
|
|
|
void
|
|
|
|
set_ptree_sel_browse_packet_wins(gboolean val)
|
|
|
|
{
|
|
|
|
g_list_foreach(detail_windows, set_ptree_sel_browse_cb, &val);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
set_ptree_line_style_cb(gpointer data, gpointer user_data)
|
|
|
|
{
|
|
|
|
struct PacketWinData *DataPtr = (struct PacketWinData *)data;
|
|
|
|
|
|
|
|
set_ptree_line_style(DataPtr->tree_view, *(gint *)user_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set the selection mode of all the popup packet windows. */
|
|
|
|
void
|
|
|
|
set_ptree_line_style_packet_wins(gint style)
|
|
|
|
{
|
|
|
|
g_list_foreach(detail_windows, set_ptree_line_style_cb, &style);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
set_ptree_expander_style_cb(gpointer data, gpointer user_data)
|
|
|
|
{
|
|
|
|
struct PacketWinData *DataPtr = (struct PacketWinData *)data;
|
|
|
|
|
|
|
|
set_ptree_expander_style(DataPtr->tree_view, *(gint *)user_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set the selection mode of all the popup packet windows. */
|
|
|
|
void
|
|
|
|
set_ptree_expander_style_packet_wins(gint style)
|
|
|
|
{
|
|
|
|
g_list_foreach(detail_windows, set_ptree_expander_style_cb, &style);
|
|
|
|
}
|