diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:34:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:34:10 +0000 |
commit | e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc (patch) | |
tree | 68cb5ef9081156392f1dd62a00c6ccc1451b93df /epan/register.c | |
parent | Initial commit. (diff) | |
download | wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.tar.xz wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.zip |
Adding upstream version 4.2.2.upstream/4.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'epan/register.c')
-rw-r--r-- | epan/register.c | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/epan/register.c b/epan/register.c new file mode 100644 index 00000000..1f8f2c2f --- /dev/null +++ b/epan/register.c @@ -0,0 +1,164 @@ +/* register.c + * Definitions for protocol registration + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "register-int.h" +#include "ws_attributes.h" + +#include <glib.h> + +#include <epan/exceptions.h> + +#include "epan/dissectors/dissectors.h" + +static const char *cur_cb_name = NULL; +// We could use g_atomic_pointer_set/get instead of a mutex, but that causes +// a false positive with Clang and TSAN for GLib < 2.64.0 (Issue #17753): +// https://gitlab.gnome.org/GNOME/glib/-/issues/1843 +static GMutex cur_cb_name_mtx; +static GAsyncQueue *register_cb_done_q; + +#define CB_WAIT_TIME (150 * 1000) // microseconds + +static void set_cb_name(const char *proto) { + g_mutex_lock(&cur_cb_name_mtx); + cur_cb_name = proto; + g_mutex_unlock(&cur_cb_name_mtx); +} + +static void * +register_all_protocols_worker(void *arg _U_) +{ + void *volatile error_message = NULL; + + TRY { + for (gulong i = 0; i < dissector_reg_proto_count; i++) { + set_cb_name(dissector_reg_proto[i].cb_name); + dissector_reg_proto[i].cb_func(); + } + } + CATCH(DissectorError) { + /* + * This is probably a dissector, or something it calls, + * calling REPORT_DISSECTOR_ERROR() in a registration + * routine or something else outside the normal dissection + * code path. + * + * The message gets freed by ENDTRY, so we must make a copy + * of it. + */ + error_message = g_strdup(GET_MESSAGE); + } + ENDTRY; + + g_async_queue_push(register_cb_done_q, GINT_TO_POINTER(TRUE)); + return (void *) error_message; +} + +void +register_all_protocols(register_cb cb, gpointer cb_data) +{ + const char *cb_name; + register_cb_done_q = g_async_queue_new(); + gboolean called_back = FALSE; + GThread *rapw_thread; + const char *error_message; + + rapw_thread = g_thread_new("register_all_protocols_worker", ®ister_all_protocols_worker, NULL); + while (!g_async_queue_timeout_pop(register_cb_done_q, CB_WAIT_TIME)) { + g_mutex_lock(&cur_cb_name_mtx); + cb_name = cur_cb_name; + g_mutex_unlock(&cur_cb_name_mtx); + if (cb && cb_name) { + cb(RA_REGISTER, cb_name, cb_data); + called_back = TRUE; + } + } + error_message = (const char *) g_thread_join(rapw_thread); + if (error_message != NULL) + THROW_MESSAGE(DissectorError, error_message); + if (cb && !called_back) { + cb(RA_REGISTER, "finished", cb_data); + } +} + +static void * +register_all_protocol_handoffs_worker(void *arg _U_) +{ + void *volatile error_message = NULL; + + TRY { + for (gulong i = 0; i < dissector_reg_handoff_count; i++) { + set_cb_name(dissector_reg_handoff[i].cb_name); + dissector_reg_handoff[i].cb_func(); + } + } + CATCH(DissectorError) { + /* + * This is probably a dissector, or something it calls, + * calling REPORT_DISSECTOR_ERROR() in a registration + * routine or something else outside the normal dissection + * code path. + * + * The message gets freed by ENDTRY, so we must make a copy + * of it. + */ + error_message = g_strdup(GET_MESSAGE); + } + ENDTRY; + + g_async_queue_push(register_cb_done_q, GINT_TO_POINTER(TRUE)); + return (void *) error_message; +} + +void +register_all_protocol_handoffs(register_cb cb, gpointer cb_data) +{ + const char *cb_name; + gboolean called_back = FALSE; + GThread *raphw_thread; + const char *error_message; + + set_cb_name(NULL); + raphw_thread = g_thread_new("register_all_protocol_handoffs_worker", ®ister_all_protocol_handoffs_worker, NULL); + while (!g_async_queue_timeout_pop(register_cb_done_q, CB_WAIT_TIME)) { + g_mutex_lock(&cur_cb_name_mtx); + cb_name = cur_cb_name; + g_mutex_unlock(&cur_cb_name_mtx); + if (cb && cb_name) { + cb(RA_HANDOFF, cb_name, cb_data); + called_back = TRUE; + } + } + error_message = (const char *) g_thread_join(raphw_thread); + if (error_message != NULL) + THROW_MESSAGE(DissectorError, error_message); + if (cb && !called_back) { + cb(RA_HANDOFF, "finished", cb_data); + } + g_async_queue_unref(register_cb_done_q); +} + +gulong register_count(void) +{ + return dissector_reg_proto_count + dissector_reg_handoff_count; +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local Variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ |