aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoland Knall <roland.knall@br-automation.com>2015-06-05 11:19:37 +0200
committerAnders Broman <a.broman58@gmail.com>2015-06-25 16:23:08 +0000
commitacc581081e84c93e878a678fbb3655aba253607a (patch)
tree10ad9f0c0195475d01f42d64509e0c6ef53abb79
parentd4aa1a1c24e984339806c4ddb000ea9f9b352659 (diff)
Plugin Interface: Add GUI callbacks
Rename ext_menubar to a more appropriate plugin_if. External menus can be implemented by plugins to present additional menus for deep-packet analysis. One side-effect of such menus being implemented as plugins is, that they are being executed in different threads and therefore can only use limited access to the main GUI. Also, there is no safe cross-gui (GTK and Qt) way for many features. This patch implements a first functionality, by which a plugin implemented using ext_menubar can apply a display filter to the main view. For now the implementation supports filtering, as well as saving a preference. Change-Id: Iffe4caa954bbeb8ce356352de4dae348a50efba9 Reviewed-on: https://code.wireshark.org/review/8773 Reviewed-by: Roland Knall <rknall@gmail.com> Petri-Dish: Anders Broman <a.broman58@gmail.com> Reviewed-by: Anders Broman <a.broman58@gmail.com>
-rw-r--r--doc/README.plugins26
-rw-r--r--epan/CMakeLists.txt2
-rw-r--r--epan/Makefile.common4
-rw-r--r--epan/plugin_if.c (renamed from epan/ext_menubar.c)89
-rw-r--r--epan/plugin_if.h (renamed from epan/ext_menubar.h)42
-rw-r--r--ui/gtk/main_filter_toolbar.c24
-rw-r--r--ui/gtk/main_menubar.c2
-rw-r--r--ui/gtk/packet_list.c24
-rw-r--r--ui/preference_utils.c42
-rw-r--r--ui/preference_utils.h10
-rw-r--r--ui/qt/main_window.cpp44
-rw-r--r--ui/qt/main_window.h2
12 files changed, 292 insertions, 19 deletions
diff --git a/doc/README.plugins b/doc/README.plugins
index eca52da251..e8cac10246 100644
--- a/doc/README.plugins
+++ b/doc/README.plugins
@@ -321,12 +321,14 @@ is encouraged to update their plugins as outlined below:
the DOCSIS plugin.
-6 How to implement a plugin related menu
+6 How to plugin related interface options
+
+6.1 Implement a plugin GUI menu
A plugin (as well as built-in dissectors) may implement a menu within
Wireshark to be used to trigger options, start tools, open Websites, ...
-This menu structure is built using the ext_menubar.h interface and it's
+This menu structure is built using the plugin_if.h interface and it's
corresponding functions.
The menu items all call a callback provided by the plugin, which takes
@@ -365,7 +367,25 @@ Using the Gtk Version and a Mac OSX operating system, this will not work, and
the Gtk interface is currently not supported on this plattform. The Qt interface
on Mac provides the menu.
-For a more detailed information, please refer to ext_menubar.h
+For a more detailed information, please refer to plugin_if.h
+
+6.2 Implement interactions with the main interface
+
+Due to memory constraints on most plattforms, plugin functionality cannot be
+called directly from a DLL context. Instead special functions will be used, which
+will implement certain options for plugins to utilize.
+
+The following methods exist so far:
+
+ /* Applies the given filter string as display filter */
+ WS_DLL_PUBLIC void plugin_if_apply_filter
+ (const char * filter_string, gboolean force);
+
+ /* Saves the given preference to the main preference storage */
+ WS_DLL_PUBLIC void plugin_if_save_preference
+ (const char * pref_module, const char * pref_key, const char * pref_value);
+
+
----------------
diff --git a/epan/CMakeLists.txt b/epan/CMakeLists.txt
index aa37191ddc..36d141bf0d 100644
--- a/epan/CMakeLists.txt
+++ b/epan/CMakeLists.txt
@@ -1600,7 +1600,7 @@ set(LIBWIRESHARK_FILES
except.c
expert.c
exported_pdu.c
- ext_menubar.c
+ plugin_if.c
filter_expressions.c
follow.c
frame_data.c
diff --git a/epan/Makefile.common b/epan/Makefile.common
index a8c3bb5ad1..fe81b1c7ea 100644
--- a/epan/Makefile.common
+++ b/epan/Makefile.common
@@ -51,7 +51,7 @@ LIBWIRESHARK_SRC = \
except.c \
expert.c \
exported_pdu.c \
- ext_menubar.c \
+ plugin_if.c \
filter_expressions.c \
follow.c \
frame_data.c \
@@ -192,7 +192,7 @@ LIBWIRESHARK_INCLUDES = \
exceptions.h \
expert.h \
exported_pdu.h \
- ext_menubar.h \
+ plugin_if.h \
filter_expressions.h \
follow.h \
frame_data.h \
diff --git a/epan/ext_menubar.c b/epan/plugin_if.c
index 25501520c7..62244dd4fd 100644
--- a/epan/ext_menubar.c
+++ b/epan/plugin_if.c
@@ -1,9 +1,12 @@
-/* ext_menubar.c
- * A menubar API for Wireshark dissectors
+/* plugin_if.c
+ * An API for Wireshark plugins
*
* This enables wireshark dissectors, especially those implemented by plugins
* to register menubar entries, which then will call a pre-defined callback
- * function for the dissector or plugin
+ * function for the dissector or plugin.
+ *
+ * Also it implements additional methods, which allow plugins to interoperate
+ * with the main GUI.
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
@@ -30,7 +33,7 @@
#include <epan/epan.h>
#include <epan/proto.h>
-#include "ext_menubar.h"
+#include "plugin_if.h"
static GList * menubar_entries = NULL;
static GList * menubar_menunames = NULL;
@@ -158,6 +161,84 @@ extern void ext_menubar_add_separator(ext_menu_t *parent)
ext_menubar_add_generic_entry ( EXT_MENUBAR_SEPARATOR, parent, g_strdup("-"), NULL, NULL, NULL );
}
+/* Implementation of GUI callback methods follows.
+ * This is a necessity, as using modern UI systems, gui interfaces often operate
+ * in different threads then the calling application. Even more so, if the calling
+ * application is implemented using a separate plugin. Therefore the external menubars
+ * cannot call gui functionality directly, the gui has to perform the function within
+ * it' own scope. */
+
+static GHashTable * plugin_if_callback_functions;
+
+static void
+plugin_if_init_hashtable(void)
+{
+ if ( plugin_if_callback_functions == 0 )
+ plugin_if_callback_functions = g_hash_table_new(g_int_hash, g_int_equal);
+}
+
+static void plugin_if_call_gui_cb(plugin_if_callback_t actionType, GHashTable * dataSet)
+{
+ plugin_if_gui_cb action;
+ gint * key = 0;
+
+ key = (gint *)g_malloc0(sizeof(gint));
+ *key = (gint) actionType;
+
+ plugin_if_init_hashtable();
+
+ if ( g_hash_table_size(plugin_if_callback_functions) != 0 )
+ {
+ if ( g_hash_table_contains(plugin_if_callback_functions, key) )
+ {
+ action = (plugin_if_gui_cb)g_hash_table_lookup(plugin_if_callback_functions, key);
+ if ( action != NULL )
+ action(dataSet);
+ }
+ }
+}
+
+extern void plugin_if_apply_filter(const char * filter_string, gboolean force)
+{
+ plugin_if_callback_t actionType;
+ GHashTable * dataSet = NULL;
+
+ actionType = ( force == TRUE ) ? PLUGIN_IF_FILTER_ACTION_APPLY : PLUGIN_IF_FILTER_ACTION_PREPARE;
+ dataSet = g_hash_table_new(g_str_hash, g_str_equal);
+
+ g_hash_table_insert( dataSet, g_strdup("action_type"), (gpointer) &actionType );
+ g_hash_table_insert( dataSet, g_strdup("filter_string"), g_strdup(filter_string) );
+ g_hash_table_insert( dataSet, g_strdup("force"), (gpointer) &force );
+
+ plugin_if_call_gui_cb(actionType, dataSet);
+}
+
+extern void plugin_if_save_preference(const char * pref_module, const char * pref_key, const char * pref_value)
+{
+ GHashTable * dataSet = NULL;
+
+ dataSet = g_hash_table_new(g_str_hash, g_str_equal);
+
+ g_hash_table_insert( dataSet, g_strdup("pref_module"), g_strdup(pref_module) );
+ g_hash_table_insert( dataSet, g_strdup("pref_key"), g_strdup(pref_key) );
+ g_hash_table_insert( dataSet, g_strdup("pref_value"), g_strdup(pref_value) );
+
+ plugin_if_call_gui_cb(PLUGIN_IF_PREFERENCE_SAVE, dataSet);
+}
+
+extern void plugin_if_register_gui_cb(plugin_if_callback_t actionType, plugin_if_gui_cb callback)
+{
+ gint * key = 0;
+
+ key = (gint *)g_malloc0(sizeof(gint));
+ *key = actionType;
+
+ plugin_if_init_hashtable();
+
+ if ( ! g_hash_table_contains(plugin_if_callback_functions, key ) )
+ g_hash_table_insert(plugin_if_callback_functions, key, callback);
+}
+
/*
* Editor modelines
*
diff --git a/epan/ext_menubar.h b/epan/plugin_if.h
index acffa8f2e8..df9ea6e846 100644
--- a/epan/ext_menubar.h
+++ b/epan/plugin_if.h
@@ -1,9 +1,12 @@
-/* ext_menubar.h
- * A menubar API for Wireshark dissectors
+/* plugin_if.h
+ * An API for Wireshark plugins
*
* This enables wireshark dissectors, especially those implemented by plugins
* to register menubar entries, which then will call a pre-defined callback
- * function for the dissector or plugin
+ * function for the dissector or plugin.
+ *
+ * Also it implements additional methods, which allow plugins to interoperate
+ * with the main GUI.
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
@@ -23,8 +26,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifndef EPAN_EXT_MENUBAR_H_
-#define EPAN_EXT_MENUBAR_H_
+#ifndef EPAN_PLUGIN_IF_H
+#define EPAN_PLUGIN_IF_H
#include <config.h>
@@ -146,6 +149,33 @@ WS_DLL_PUBLIC void ext_menubar_add_separator(ext_menu_t *parent_menu);
WS_DLL_PUBLIC void ext_menubar_add_website(ext_menu_t * parent, const gchar *label,
const gchar *tooltip, const gchar *url);
+
+/*
+ * Enumeration of possible actions, which are registered in GUI interfaces
+ */
+typedef enum
+{
+ /* Applies a given string as filter */
+ PLUGIN_IF_FILTER_ACTION_APPLY,
+
+ /* Prepares the given string as filter */
+ PLUGIN_IF_FILTER_ACTION_PREPARE,
+
+ /* Saves a preference entry */
+ PLUGIN_IF_PREFERENCE_SAVE
+} plugin_if_callback_t;
+
+
+typedef void (*plugin_if_gui_cb)(gconstpointer user_data);
+
+WS_DLL_PUBLIC void plugin_if_register_gui_cb(plugin_if_callback_t actionType, plugin_if_gui_cb callback);
+
+/* Applies the given filter string as display filter */
+WS_DLL_PUBLIC void plugin_if_apply_filter(const char * filter_string, gboolean force);
+
+/* Saves the given preference to the main preference storage */
+WS_DLL_PUBLIC void plugin_if_save_preference(const char * pref_module, const char * pref_key, const char * pref_value);
+
/* Private Method for retrieving the menubar entries
*
* Is only to be used by the UI interfaces to retrieve the menu entries
@@ -156,7 +186,7 @@ WS_DLL_PUBLIC GList * ext_menubar_get_entries(void);
}
#endif /* __cplusplus */
-#endif /* EPAN_EXT_MENUBAR_H_ */
+#endif /* EPAN_PLUGIN_IF_H */
/*
* Editor modelines
diff --git a/ui/gtk/main_filter_toolbar.c b/ui/gtk/main_filter_toolbar.c
index f47e7819dc..eed3ee3cc2 100644
--- a/ui/gtk/main_filter_toolbar.c
+++ b/ui/gtk/main_filter_toolbar.c
@@ -39,6 +39,7 @@
#include "filter_autocomplete.h"
#include "epan/prefs.h"
+#include "epan/plugin_if.h"
#include "keys.h"
#include "gtkglobals.h"
@@ -109,6 +110,26 @@ filter_save_cb(GtkWidget *w _U_, GtkWindow *parent_w)
filter_expression_save_dlg(parent_w);
}
+static void
+plugin_if_filter_apply(gconstpointer filter_text)
+{
+ /* code is derived from voip_calls_dlg.c::voip_calls_on_filter */
+
+ int pos = 0;
+ size_t filter_length;
+ size_t max_filter_length = 2048;
+ gchar *filter_string;
+
+ if ( main_display_filter_widget != 0 )
+ {
+ filter_string = g_strndup((const char *)filter_text, max_filter_length);
+ filter_length = strlen(filter_string);
+ pos = (int)filter_length;
+
+ if ( filter_length < max_filter_length )
+ gtk_editable_insert_text(GTK_EDITABLE(main_display_filter_widget), filter_string, -1, &pos);
+ }
+}
GtkWidget *
filter_toolbar_new(void)
@@ -279,6 +300,9 @@ filter_toolbar_new(void)
/* make current preferences effective */
toolbar_redraw_all();
+ plugin_if_register_gui_cb(PLUGIN_IF_FILTER_ACTION_APPLY, plugin_if_filter_apply );
+ plugin_if_register_gui_cb(PLUGIN_IF_FILTER_ACTION_PREPARE, plugin_if_filter_apply );
+
return filter_tb;
}
diff --git a/ui/gtk/main_menubar.c b/ui/gtk/main_menubar.c
index b4c24d986a..50292d049e 100644
--- a/ui/gtk/main_menubar.c
+++ b/ui/gtk/main_menubar.c
@@ -36,7 +36,7 @@
#include <epan/epan_dissect.h>
#include <epan/column.h>
#include <epan/stats_tree_priv.h>
-#include <epan/ext_menubar.h>
+#include <epan/plugin_if.h>
#include "globals.h"
#include "color_filters.h"
diff --git a/ui/gtk/packet_list.c b/ui/gtk/packet_list.c
index f9a4f298e7..57ab4f95bb 100644
--- a/ui/gtk/packet_list.c
+++ b/ui/gtk/packet_list.c
@@ -34,6 +34,7 @@
#include <epan/packet.h>
#include <epan/column.h>
#include <epan/strutil.h>
+#include <epan/plugin_if.h>
#include "ui/main_statusbar.h"
#include "ui/packet_list_utils.h"
@@ -91,6 +92,7 @@ static void show_cell_data_func(GtkTreeViewColumn *col,
static gint row_number_from_iter(GtkTreeIter *iter);
static void scroll_to_current(void);
static gboolean query_packet_list_tooltip_cb(GtkWidget *widget, gint x, gint y, gboolean keyboard_tip, GtkTooltip *tooltip, gpointer data _U_);
+static void plugin_if_pktlist_preference(gconstpointer user_data);
GtkWidget *
packet_list_create(void)
@@ -105,6 +107,8 @@ packet_list_create(void)
g_object_set_data(G_OBJECT(popup_menu_object), E_MPACKET_LIST_KEY, view);
+ plugin_if_register_gui_cb(PLUGIN_IF_PREFERENCE_SAVE, plugin_if_pktlist_preference);
+
return scrollwin;
}
@@ -1730,6 +1734,26 @@ query_packet_list_tooltip_cb(GtkWidget *widget, gint x, gint y, gboolean keyboar
return result;
}
+void plugin_if_pktlist_preference(gconstpointer user_data)
+{
+ if ( packetlist != NULL && user_data != NULL )
+ {
+ GHashTable * dataSet = (GHashTable *) user_data;
+ if ( g_hash_table_contains(dataSet, "pref_module" ) &&
+ g_hash_table_contains(dataSet, "pref_value" ) &&
+ g_hash_table_contains(dataSet, "pref_value" ) )
+ {
+ const char * module_name = (const char *)g_hash_table_lookup(dataSet, "pref_module");
+ const char * pref_name = (const char *)g_hash_table_lookup(dataSet, "pref_key");
+ const char * pref_value = (const char *)g_hash_table_lookup(dataSet, "pref_value");
+
+ if ( prefs_store_ext(module_name, pref_name, pref_value) )
+ packet_list_recreate();
+
+ }
+ }
+}
+
/*
* Editor modelines - http://www.wireshark.org/tools/modelines.html
*
diff --git a/ui/preference_utils.c b/ui/preference_utils.c
index 1e358bd7d0..0f80ef6742 100644
--- a/ui/preference_utils.c
+++ b/ui/preference_utils.c
@@ -273,6 +273,48 @@ prefs_main_write(void)
}
}
+gboolean
+prefs_store_ext(const char * module_name, const char *pref_name, const char *pref_value)
+{
+ module_t * module = NULL;
+ pref_t * pref = NULL;
+ gboolean pref_changed = TRUE;
+
+ if ( ! prefs_is_registered_protocol(module_name))
+ return FALSE;
+
+ module = prefs_find_module(module_name);
+ if ( ! module )
+ return FALSE;
+
+ pref = prefs_find_preference(module, pref_name);
+
+ if (!pref)
+ return FALSE;
+
+ if ( pref->type == PREF_STRING )
+ {
+ g_free((void *)pref->stashed_val.string);
+ pref->stashed_val.string = (gchar *) g_strdup(pref_value);
+ /* unstash - taken from preferences_util */
+ if (strcmp(*pref->varp.string, pref->stashed_val.string) != 0)
+ {
+ pref_changed = TRUE;
+ g_free((void *)*pref->varp.string);
+ *pref->varp.string = g_strdup(pref->stashed_val.string);
+ }
+ }
+
+ if ( pref_changed )
+ {
+ prefs_main_write();
+ prefs_apply_all();
+ prefs_to_capture_opts();
+ }
+
+ return TRUE;
+}
+
gint
column_prefs_add_custom(gint fmt, const gchar *title, const gchar *custom_field, gint custom_occurrence)
{
diff --git a/ui/preference_utils.h b/ui/preference_utils.h
index 882555d70a..a0b345d043 100644
--- a/ui/preference_utils.h
+++ b/ui/preference_utils.h
@@ -80,6 +80,16 @@ extern void prefs_to_capture_opts(void);
*/
extern void prefs_main_write(void);
+/** Convenient function for plugin_if
+ *
+ * @param module the module for the preference
+ * @param key the key for the preference
+ * @param value the new value as string for the preference
+ *
+ * @return true if the value has been stored successfully
+ */
+extern gboolean prefs_store_ext(const char * module, const char * key, const char * value);
+
/** Add a custom column.
*
* @param fmt column format
diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp
index abae150c71..35e110c39b 100644
--- a/ui/qt/main_window.cpp
+++ b/ui/qt/main_window.cpp
@@ -27,7 +27,7 @@
#include <wsutil/filesystem.h>
#include <epan/prefs.h>
#include <epan/stats_tree_priv.h>
-#include <epan/ext_menubar.h>
+#include <epan/plugin_if.h>
#ifdef HAVE_LIBPCAP
#include "ui/capture.h"
@@ -42,6 +42,7 @@
#include "ui/main_statusbar.h"
#include "ui/recent.h"
#include "ui/util.h"
+#include "ui/preference_utils.h"
#include "byte_view_tab.h"
#include "display_filter_edit.h"
@@ -83,6 +84,42 @@ void pipe_input_set_handler(gint source, gpointer user_data, ws_process_id *chil
gbl_cur_main_window_->setPipeInputHandler(source, user_data, child_process, input_cb);
}
+void plugin_if_mainwindow_apply_filter(gconstpointer user_data)
+{
+ if ( gbl_cur_main_window_ != NULL && user_data != NULL )
+ {
+ GHashTable * dataSet = (GHashTable *) user_data;
+
+ if ( g_hash_table_contains(dataSet, "filter_string" ) )
+ {
+ QString filter((const char *)g_hash_table_lookup(dataSet, "filter_string"));
+ gbl_cur_main_window_->filterPackets(filter);
+ }
+ }
+}
+
+void plugin_if_mainwindow_preference(gconstpointer user_data)
+{
+ if ( gbl_cur_main_window_ != NULL && user_data != NULL )
+ {
+ GHashTable * dataSet = (GHashTable *) user_data;
+ if ( g_hash_table_contains(dataSet, "pref_module" ) &&
+ g_hash_table_contains(dataSet, "pref_value" ) &&
+ g_hash_table_contains(dataSet, "pref_value" ) )
+ {
+ const char * module_name = (const char *)g_hash_table_lookup(dataSet, "pref_module");
+ const char * pref_name = (const char *)g_hash_table_lookup(dataSet, "pref_key");
+ const char * pref_value = (const char *)g_hash_table_lookup(dataSet, "pref_value");
+
+ if ( prefs_store_ext(module_name, pref_name, pref_value) )
+ {
+ wsApp->emitAppSignal(WiresharkApplication::PacketDissectionChanged);
+ wsApp->emitAppSignal(WiresharkApplication::PreferencesChanged);
+ }
+ }
+ }
+}
+
gpointer
simple_dialog(ESD_TYPE_E type, gint btn_mask, const gchar *msg_format, ...)
{
@@ -479,6 +516,11 @@ MainWindow::MainWindow(QWidget *parent) :
this->main_welcome_->getInterfaceTree(), SLOT(interfaceListChanged()));
#endif
+ /* Create plugin_if hooks */
+ plugin_if_register_gui_cb(PLUGIN_IF_FILTER_ACTION_APPLY, plugin_if_mainwindow_apply_filter );
+ plugin_if_register_gui_cb(PLUGIN_IF_FILTER_ACTION_PREPARE, plugin_if_mainwindow_apply_filter );
+ plugin_if_register_gui_cb(PLUGIN_IF_PREFERENCE_SAVE, plugin_if_mainwindow_preference);
+
main_ui_->mainStack->setCurrentWidget(main_welcome_);
}
diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h
index 220bc63ffe..dbb85847aa 100644
--- a/ui/qt/main_window.h
+++ b/ui/qt/main_window.h
@@ -33,7 +33,7 @@
#include "ui/ui_util.h"
#include <epan/prefs.h>
-#include <epan/ext_menubar.h>
+#include <epan/plugin_if.h>
#ifdef HAVE_LIBPCAP
#include "capture_opts.h"