1 /*
2  *  funnel.c
3  *
4  * EPAN's GUI mini-API
5  *
6  * (c) 2006, Luis E. Garcia Ontanon <luis@ontanon.org>
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * SPDX-License-Identifier: GPL-2.0-or-later
13  */
14 
15 #include "config.h"
16 
17 #include <epan/funnel.h>
18 #include <wsutil/glib-compat.h>
19 
20 typedef struct _funnel_menu_t {
21     char *name;
22     register_stat_group_t group;
23     funnel_menu_callback callback;
24     gpointer callback_data;
25     funnel_menu_callback_data_free callback_data_free;
26     gboolean retap;
27     struct _funnel_menu_t* next;
28 } funnel_menu_t;
29 
30 /* XXX This assumes one main window and one capture file. */
31 static const funnel_ops_t* ops = NULL;
32 static funnel_menu_t* registered_menus = NULL;
33 static funnel_menu_t* added_menus = NULL;
34 static funnel_menu_t* removed_menus = NULL;
35 static gboolean menus_registered = FALSE;
36 
funnel_get_funnel_ops(void)37 const funnel_ops_t* funnel_get_funnel_ops(void) { return ops;  }
funnel_set_funnel_ops(const funnel_ops_t * o)38 void funnel_set_funnel_ops(const funnel_ops_t* o) { ops = o; }
39 
funnel_insert_menu(funnel_menu_t ** menu_list,funnel_menu_t * menu)40 static void funnel_insert_menu (funnel_menu_t** menu_list, funnel_menu_t *menu)
41 {
42     if (!(*menu_list))  {
43         *menu_list = menu;
44     } else {
45         funnel_menu_t* c;
46         for (c = *menu_list; c->next; c = c->next);
47         c->next = menu;
48     }
49 }
50 
funnel_remove_menu(funnel_menu_t ** menu_list,funnel_menu_t * menu)51 static void funnel_remove_menu (funnel_menu_t ** menu_list, funnel_menu_t *menu)
52 {
53     funnel_menu_t *m = *menu_list, *p = NULL;
54 
55     while (m) {
56         if (m->callback == menu->callback) {
57             if (p) {
58                 p->next = m->next;
59             } else {
60                 *menu_list = m->next;
61             }
62             g_free(m->name);
63             if (m->callback_data_free) {
64                 m->callback_data_free(m->callback_data);
65             }
66             g_free(m);
67             if (p) {
68                 m = p->next;
69             } else {
70                 m = *menu_list;
71             }
72         } else {
73             p = m;
74             m = m->next;
75         }
76     }
77 }
78 
funnel_clear_menu(funnel_menu_t ** menu_list)79 static void funnel_clear_menu (funnel_menu_t** menu_list)
80 {
81     funnel_menu_t *m;
82 
83     while (*menu_list) {
84         m = *menu_list;
85         *menu_list = m->next;
86         g_free(m->name);
87         g_free(m);
88     }
89     *menu_list = NULL;
90 }
91 
funnel_register_menu(const char * name,register_stat_group_t group,funnel_menu_callback callback,gpointer callback_data,funnel_menu_callback_data_free callback_data_free,gboolean retap)92 void funnel_register_menu(const char *name,
93                           register_stat_group_t group,
94                           funnel_menu_callback callback,
95                           gpointer callback_data,
96                           funnel_menu_callback_data_free callback_data_free,
97                           gboolean retap)
98 {
99     funnel_menu_t* m = g_new(funnel_menu_t, 1);
100     m->name = g_strdup(name);
101     m->group = group;
102     m->callback = callback;
103     m->callback_data = callback_data;
104     m->callback_data_free = callback_data_free;
105     m->retap = retap;
106     m->next = NULL;
107 
108     funnel_insert_menu(&registered_menus, m);
109     if (menus_registered) {
110         funnel_menu_t* m_r = (funnel_menu_t *)g_memdup2(m, sizeof *m);
111         m_r->name = g_strdup(name);
112         funnel_insert_menu(&added_menus, m_r);
113     }
114 }
115 
funnel_deregister_menus(funnel_menu_callback callback)116 void funnel_deregister_menus(funnel_menu_callback callback)
117 {
118     funnel_menu_t* m = g_new0(funnel_menu_t, 1);
119     m->callback = callback;
120 
121     funnel_remove_menu(&registered_menus, m);
122     funnel_insert_menu(&removed_menus, m);
123 }
124 
funnel_register_all_menus(funnel_registration_cb_t r_cb)125 void funnel_register_all_menus(funnel_registration_cb_t r_cb)
126 {
127     funnel_menu_t* c;
128     for (c = registered_menus; c; c = c->next) {
129         r_cb(c->name,c->group,c->callback,c->callback_data,c->retap);
130     }
131     menus_registered = TRUE;
132 }
133 
funnel_reload_menus(funnel_deregistration_cb_t d_cb,funnel_registration_cb_t r_cb)134 void funnel_reload_menus(funnel_deregistration_cb_t d_cb,
135                          funnel_registration_cb_t r_cb)
136 {
137     funnel_menu_t* c;
138     for (c = removed_menus; c; c = c->next) {
139         d_cb(c->callback);
140     }
141     for (c = added_menus; c; c = c->next) {
142         r_cb(c->name,c->group,c->callback,c->callback_data,c->retap);
143     }
144 
145     funnel_clear_menu(&removed_menus);
146     funnel_clear_menu(&added_menus);
147 }
148 
funnel_cleanup(void)149 void funnel_cleanup(void)
150 {
151     funnel_clear_menu(&registered_menus);
152 }
153 
154 /*
155  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
156  *
157  * Local variables:
158  * c-basic-offset: 4
159  * tab-width: 8
160  * indent-tabs-mode: nil
161  * End:
162  *
163  * vi: set shiftwidth=4 tabstop=8 expandtab:
164  * :indentSize=4:tabSize=8:noTabs=true:
165  */
166