Switch conversations to use wmem_tree_t instead of (sorted) GSList.

Change-Id: Ifaf25ca5a7974f1d398ceebbb4c6733d4d3e001a
Reviewed-on: https://code.wireshark.org/review/20006
Reviewed-by: Michael Mann <mmann78@netscape.net>
Petri-Dish: Michael Mann <mmann78@netscape.net>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
Michael Mann 2017-02-07 17:05:17 -05:00 committed by Anders Broman
parent cfa50019b6
commit 56aaa5b705
12 changed files with 93 additions and 125 deletions

View File

@ -699,7 +699,6 @@ libwireshark.so.0 libwireshark0 #MINVER#
get_conversation_packet_func@Base 1.99.0
get_conversation_port@Base 1.99.0
get_conversation_proto_id@Base 1.99.0
get_conversation_table_by_num@Base 1.99.0
get_data_source_name@Base 1.9.1
get_data_source_tvb@Base 1.9.1
get_data_source_tvb_by_name@Base 2.3.0
@ -1821,6 +1820,7 @@ libwireshark.so.0 libwireshark0 #MINVER#
wmem_strndup@Base 1.9.1
wmem_strong_hash@Base 1.12.0~rc1
wmem_strsplit@Base 1.12.0~rc1
wmem_tree_count@Base 2.3.0
wmem_tree_foreach@Base 1.12.0~rc1
wmem_tree_insert32@Base 1.12.0~rc1
wmem_tree_insert32_array@Base 1.12.0~rc1

View File

@ -65,7 +65,7 @@ tap_packet_cb get_hostlist_packet_func(register_ct_t* ct)
return ct->host_func;
}
static GSList *registered_ct_tables = NULL;
static wmem_tree_t *registered_ct_tables = NULL;
void
dissector_conversation_init(const char *opt_arg, void* userdata)
@ -114,25 +114,7 @@ dissector_hostlist_init(const char *opt_arg, void* userdata)
*/
register_ct_t* get_conversation_by_proto_id(int proto_id)
{
GSList *ct;
register_ct_t *table;
for(ct = registered_ct_tables; ct != NULL; ct = g_slist_next(ct)){
table = (register_ct_t*)ct->data;
if ((table) && (table->proto_id == proto_id))
return table;
}
return NULL;
}
static gint
insert_sorted_by_table_name(gconstpointer aparam, gconstpointer bparam)
{
const register_ct_t *a = (const register_ct_t *)aparam;
const register_ct_t *b = (const register_ct_t *)bparam;
return g_ascii_strcasecmp(proto_get_protocol_short_name(find_protocol_by_id(a->proto_id)), proto_get_protocol_short_name(find_protocol_by_id(b->proto_id)));
return (register_ct_t*)wmem_tree_lookup_string(registered_ct_tables, proto_get_protocol_short_name(find_protocol_by_id(proto_id)), 0);
}
void
@ -140,7 +122,7 @@ register_conversation_table(const int proto_id, gboolean hide_ports, tap_packet_
{
register_ct_t *table;
table = g_new(register_ct_t,1);
table = wmem_new(wmem_epan_scope(), register_ct_t);
table->hide_ports = hide_ports;
table->proto_id = proto_id;
@ -149,18 +131,21 @@ register_conversation_table(const int proto_id, gboolean hide_ports, tap_packet_
table->conv_gui_init = NULL;
table->host_gui_init = NULL;
registered_ct_tables = g_slist_insert_sorted(registered_ct_tables, table, insert_sorted_by_table_name);
if (registered_ct_tables == NULL)
registered_ct_tables = wmem_tree_new(wmem_epan_scope());
wmem_tree_insert_string(registered_ct_tables, proto_get_protocol_short_name(find_protocol_by_id(proto_id)), table, 0);
}
/* Set GUI fields for register_ct list */
static void
set_conv_gui_data(gpointer data, gpointer user_data)
static gboolean
set_conv_gui_data(const void *key _U_, void *value, void *userdata)
{
GString *conv_cmd_str = g_string_new("conv,");
stat_tap_ui ui_info;
register_ct_t *table = (register_ct_t*)data;
register_ct_t *table = (register_ct_t*)value;
table->conv_gui_init = (conv_gui_init_cb)user_data;
table->conv_gui_init = (conv_gui_init_cb)userdata;
g_string_append(conv_cmd_str, proto_get_protocol_filter_name(table->proto_id));
ui_info.group = REGISTER_STAT_GROUP_CONVERSATION_LIST;
@ -171,50 +156,46 @@ set_conv_gui_data(gpointer data, gpointer user_data)
ui_info.params = NULL;
register_stat_tap_ui(&ui_info, table);
g_free((char*)ui_info.cli_string);
return FALSE;
}
void conversation_table_set_gui_info(conv_gui_init_cb init_cb)
{
g_slist_foreach(registered_ct_tables, set_conv_gui_data, (gpointer)init_cb);
wmem_tree_foreach(registered_ct_tables, set_conv_gui_data, (void*)init_cb);
}
static void
set_host_gui_data(gpointer data, gpointer user_data)
static gboolean
set_host_gui_data(const void *key _U_, void *value, void *userdata)
{
stat_tap_ui ui_info;
register_ct_t *table = (register_ct_t*)data;
register_ct_t *table = (register_ct_t*)value;
table->host_gui_init = (host_gui_init_cb)user_data;
table->host_gui_init = (host_gui_init_cb)userdata;
ui_info.group = REGISTER_STAT_GROUP_ENDPOINT_LIST;
ui_info.title = NULL; /* construct this from the protocol info? */
ui_info.cli_string = wmem_strdup_printf(wmem_epan_scope(), "%s,%s",
HOSTLIST_TAP_PREFIX, proto_get_protocol_filter_name(table->proto_id));
ui_info.cli_string = g_strdup_printf("%s,%s", HOSTLIST_TAP_PREFIX, proto_get_protocol_filter_name(table->proto_id));
ui_info.tap_init_cb = dissector_hostlist_init;
ui_info.nparams = 0;
ui_info.params = NULL;
register_stat_tap_ui(&ui_info, table);
g_free((char*)ui_info.cli_string);
return FALSE;
}
void hostlist_table_set_gui_info(host_gui_init_cb init_cb)
{
g_slist_foreach(registered_ct_tables, set_host_gui_data, (gpointer)init_cb);
wmem_tree_foreach(registered_ct_tables, set_host_gui_data, (void*)init_cb);
}
void conversation_table_iterate_tables(GFunc func, gpointer user_data)
void conversation_table_iterate_tables(wmem_foreach_func func, void* user_data)
{
g_slist_foreach(registered_ct_tables, func, user_data);
wmem_tree_foreach(registered_ct_tables, func, user_data);
}
guint conversation_table_get_num(void)
{
return g_slist_length(registered_ct_tables);
}
register_ct_t *get_conversation_table_by_num(guint table_num)
{
return (register_ct_t *) g_slist_nth_data(registered_ct_tables, table_num);
return wmem_tree_count(registered_ct_tables);
}
/** Compute the hash value for two given address/port pairs.
@ -828,19 +809,6 @@ add_hostlist_table_data(conv_hash_t *ch, const address *addr, guint32 port, gboo
}
}
static void
ct_table_free(gpointer p, gpointer user_data _U_)
{
g_free(p);
}
void
conversation_table_cleanup(void)
{
g_slist_foreach(registered_ct_tables, ct_table_free, NULL);
g_slist_free(registered_ct_tables);
}
/*
* Editor modelines
*

View File

@ -26,6 +26,7 @@
#include "conv_id.h"
#include "tap.h"
#include "wmem/wmem.h"
#ifdef __cplusplus
extern "C" {
@ -205,26 +206,17 @@ WS_DLL_PUBLIC void conversation_table_set_gui_info(conv_gui_init_cb init_cb);
*/
WS_DLL_PUBLIC void hostlist_table_set_gui_info(host_gui_init_cb init_cb);
/** Interator to walk converation tables and execute func
* a GUI menu (only used in GTK)
/** Iterator to walk converation tables and execute func
*
* @param func action to be performed on all converation tables
* @param user_data any data needed to help perform function
*/
WS_DLL_PUBLIC void conversation_table_iterate_tables(GFunc func, gpointer user_data);
WS_DLL_PUBLIC void conversation_table_iterate_tables(wmem_foreach_func func, void* user_data);
/** Total number of converation tables
*/
WS_DLL_PUBLIC guint conversation_table_get_num(void);
/** Get conversation table by its number
* Tables are ordered alphabetically by title.
*
* @param table_num Item to fetch.
* @return table pointer or NULL.
*/
WS_DLL_PUBLIC register_ct_t* get_conversation_table_by_num(guint table_num);
/** Remove all entries from the conversation table.
*
* @param ch the table to reset
@ -340,10 +332,6 @@ add_conversation_table_data_with_conv_id(conv_hash_t *ch, const address *src, co
void add_hostlist_table_data(conv_hash_t *ch, const address *addr,
guint32 port, gboolean sender, int num_frames, int num_bytes, hostlist_dissector_info_t *host_info, port_type port_type_val);
/** Cleanup internal structures
*/
void conversation_table_cleanup(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -216,7 +216,6 @@ epan_cleanup(void)
proto_cleanup();
prefs_cleanup();
decode_clear_all();
conversation_table_cleanup();
conversation_filters_cleanup();
reassembly_table_cleanup();
tap_cleanup();

View File

@ -67,20 +67,7 @@
static struct register_ct *
_get_conversation_table_by_name(const char *name)
{
guint count = conversation_table_get_num();
guint i;
/* XXX, wow O(n^2), move to libwireshark */
for (i = 0; i < count; i++)
{
struct register_ct *table = get_conversation_table_by_num(i);
const char *label = proto_get_protocol_short_name(find_protocol_by_id(get_conversation_proto_id(table)));
if (!strcmp(label, name))
return table;
}
return NULL;
return get_conversation_by_proto_id(proto_get_id_by_short_name(name));
}
static void
@ -226,13 +213,13 @@ sharkd_session_filter_data(const char *filter)
}
}
static void
sharkd_session_process_info_conv_cb(gpointer data, gpointer user_data)
static gboolean
sharkd_session_process_info_conv_cb(const void* key, void* value, void* userdata)
{
struct register_ct *table = (struct register_ct *) data;
int *pi = (int *) user_data;
struct register_ct *table = (struct register_ct *) value;
int *pi = (int *) userdata;
const char *label = proto_get_protocol_short_name(find_protocol_by_id(get_conversation_proto_id(table)));
const char *label = (const char*)key;
if (get_conversation_packet_func(table))
{
@ -253,6 +240,7 @@ sharkd_session_process_info_conv_cb(gpointer data, gpointer user_data)
*pi = *pi + 1;
}
return FALSE;
}
/**

View File

@ -2435,11 +2435,11 @@ typedef struct _init_ct_page_data {
GtkWidget *win;
} init_ct_page_data;
static void
init_ct_page(gpointer data, gpointer user_data)
static gboolean
init_ct_page(const void *key _U_, void *value, void *userdata)
{
register_ct_t *table = (register_ct_t*)data;
init_ct_page_data* ct_page_data = (init_ct_page_data*)user_data;
register_ct_t *table = (register_ct_t*)value;
init_ct_page_data* ct_page_data = (init_ct_page_data*)userdata;
conversations_table *conversations;
GtkWidget *page_lb;
@ -2454,6 +2454,7 @@ init_ct_page(gpointer data, gpointer user_data)
conversations->page_lb = page_lb;
ct_page_data->pages[++ct_page_data->page] = conversations;
}
return FALSE;
}
void

View File

@ -1230,11 +1230,11 @@ typedef struct _init_host_page_data {
GtkWidget *win;
} init_host_page_data;
static void
init_host_page(gpointer data, gpointer user_data)
static gboolean
init_host_page(const void *key _U_, void *value, void *userdata)
{
register_ct_t *table = (register_ct_t*)data;
init_host_page_data* host_page_data = (init_host_page_data*)user_data;
register_ct_t *table = (register_ct_t*)value;
init_host_page_data* host_page_data = (init_host_page_data*)userdata;
hostlist_table *hosttable;
GtkWidget *page_lb;
@ -1248,6 +1248,8 @@ init_host_page(gpointer data, gpointer user_data)
hosttable->page_lb = page_lb;
host_page_data->pages[++host_page_data->page] = hosttable;
}
return FALSE;
}
void

View File

@ -2688,11 +2688,11 @@ typedef struct {
int counter;
} conv_menu_t;
static void
add_conversation_menuitem(gpointer data, gpointer user_data)
static gboolean
add_conversation_menuitem(const void *key, void *value, void *userdata)
{
register_ct_t *table = (register_ct_t*)data;
conv_menu_t *conv = (conv_menu_t*)user_data;
register_ct_t *table = (register_ct_t*)value;
conv_menu_t *conv = (conv_menu_t*)userdata;
gchar *action_name;
GtkAction *action;
@ -2700,7 +2700,7 @@ add_conversation_menuitem(gpointer data, gpointer user_data)
/*g_warning("action_name %s, filter_entry->name %s",action_name,filter_entry->name);*/
action = (GtkAction *)g_object_new (GTK_TYPE_ACTION,
"name", action_name,
"label", proto_get_protocol_short_name(find_protocol_by_id(get_conversation_proto_id(table))),
"label", key,
"sensitive", TRUE,
NULL);
g_signal_connect (action, "activate",
@ -2716,6 +2716,7 @@ add_conversation_menuitem(gpointer data, gpointer user_data)
FALSE);
g_free(action_name);
conv->counter++;
return FALSE;
}
static void
@ -2750,11 +2751,11 @@ menu_hostlist_cb(GtkAction *action _U_, gpointer user_data)
hostlist_endpoint_cb(table);
}
static void
add_hostlist_menuitem(gpointer data, gpointer user_data)
static gboolean
add_hostlist_menuitem(const void *key, void *value, void *userdata)
{
register_ct_t *table = (register_ct_t*)data;
conv_menu_t *conv = (conv_menu_t*)user_data;
register_ct_t *table = (register_ct_t*)value;
conv_menu_t *conv = (conv_menu_t*)userdata;
gchar *action_name;
GtkAction *action;
@ -2762,7 +2763,7 @@ add_hostlist_menuitem(gpointer data, gpointer user_data)
/*g_warning("action_name %s, filter_entry->name %s",action_name,filter_entry->name);*/
action = (GtkAction *)g_object_new (GTK_TYPE_ACTION,
"name", action_name,
"label", proto_get_protocol_short_name(find_protocol_by_id(get_conversation_proto_id(table))),
"label", key,
"sensitive", TRUE,
NULL);
g_signal_connect (action, "activate",
@ -2778,6 +2779,7 @@ add_hostlist_menuitem(gpointer data, gpointer user_data)
FALSE);
g_free(action_name);
conv->counter++;
return FALSE;
}
static void

View File

@ -92,7 +92,7 @@ ConversationDialog::ConversationDialog(QWidget &parent, CaptureFile &cf, int cli
}
// Bring the command-line specified type to the front.
if (get_conversation_by_proto_id(cli_proto_id)) {
if ((cli_proto_id > 0) && (get_conversation_by_proto_id(cli_proto_id))) {
conv_protos.removeAll(cli_proto_id);
conv_protos.prepend(cli_proto_id);
}

View File

@ -71,7 +71,7 @@ EndpointDialog::EndpointDialog(QWidget &parent, CaptureFile &cf, int cli_proto_i
}
// Bring the command-line specified type to the front.
if (get_conversation_by_proto_id(cli_proto_id)) {
if ((cli_proto_id > 0) && (get_conversation_by_proto_id(cli_proto_id))) {
endp_protos.removeAll(cli_proto_id);
endp_protos.prepend(cli_proto_id);
}

View File

@ -112,22 +112,41 @@ const QList<int> TrafficTableDialog::defaultProtos() const
<< proto_get_id_by_filter_name("udp");
}
class fillTypeMenuData
{
public:
fillTypeMenuData(TrafficTableDialog* dialog, QList<int> &enabled_protos)
: dialog_(dialog),
enabled_protos_(enabled_protos)
{
}
TrafficTableDialog* dialog_;
QList<int> &enabled_protos_;
};
gboolean TrafficTableDialog::fillTypeMenuFunc(const void *key, void *value, void *userdata)
{
register_ct_t* ct = (register_ct_t*)value;
QString title = (gchar*)key;
fillTypeMenuData* data = (fillTypeMenuData*)userdata;
int proto_id = get_conversation_proto_id(ct);
QAction *endp_action = new QAction(title, data->dialog_);
endp_action->setData(qVariantFromValue(proto_id));
endp_action->setCheckable(true);
endp_action->setChecked(data->enabled_protos_.contains(proto_id));
data->dialog_->connect(endp_action, SIGNAL(triggered()), data->dialog_, SLOT(data->dialog_->toggleTable()));
data->dialog_->traffic_type_menu_.addAction(endp_action);
return FALSE;
}
void TrafficTableDialog::fillTypeMenu(QList<int> &enabled_protos)
{
for (guint i = 0; i < conversation_table_get_num(); i++) {
int proto_id = get_conversation_proto_id(get_conversation_table_by_num(i));
if (proto_id < 0) {
continue;
}
QString title = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
fillTypeMenuData data(this, enabled_protos);
QAction *endp_action = new QAction(title, this);
endp_action->setData(qVariantFromValue(proto_id));
endp_action->setCheckable(true);
endp_action->setChecked(enabled_protos.contains(proto_id));
connect(endp_action, SIGNAL(triggered()), this, SLOT(toggleTable()));
traffic_type_menu_.addAction(endp_action);
}
conversation_table_iterate_tables(fillTypeMenuFunc, &data);
}
void TrafficTableDialog::addProgressFrame(QObject *parent)

View File

@ -145,6 +145,7 @@ protected:
QMap<int, TrafficTableTreeWidget *> proto_id_to_tree_;
const QList<int> defaultProtos() const;
static gboolean fillTypeMenuFunc(const void *key, void *value, void *userdata);
void fillTypeMenu(QList<int> &enabled_protos);
// Adds a conversation tree. Returns true if the tree was freshly created, false if it was cached.
virtual bool addTrafficTable(register_ct_t*) { return false; }