]> git.samba.org - metze/wireshark/wip.git/blob - epan/stat_tap_ui.c
Qt: Add copy from another profile in UAT dialogs
[metze/wireshark/wip.git] / epan / stat_tap_ui.c
1 /* stat_tap_ui.c
2  * Routines to register UI information for stats
3  *
4  * Wireshark - Network traffic analyzer
5  * By Gerald Combs <gerald@wireshark.org>
6  * Copyright 1998 Gerald Combs
7  *
8  * SPDX-License-Identifier: GPL-2.0-or-later
9  */
10
11 #include "config.h"
12
13 #include <stdio.h>
14
15 #include <string.h>
16
17 #include <glib.h>
18
19 #include <epan/stat_tap_ui.h>
20
21 /* structure to keep track of what stats have registered command-line
22    arguments.
23  */
24 typedef struct _stat_cmd_arg {
25     stat_tap_ui *ui;
26     const char *cmd;
27     void (*func)(const char *arg, void* userdata);
28     void* userdata;
29 } stat_cmd_arg;
30
31 static wmem_list_t *stat_cmd_arg_list=NULL;
32
33 /* structure to keep track of what stats have been specified on the
34    command line.
35  */
36 typedef struct {
37     stat_cmd_arg *sca;
38     char *arg;
39 } stat_requested;
40 static GSList *stats_requested = NULL;
41
42 /* **********************************************************************
43  * Function called from stat to register the stat's command-line argument
44  * and initialization routine
45  * ********************************************************************** */
46 static gint
47 search_duplicate(gconstpointer a, gconstpointer b)
48 {
49     return strcmp(((const stat_cmd_arg *)a)->cmd, (const char *)b);
50 }
51
52 static gint
53 sort_by_name(gconstpointer a, gconstpointer b)
54 {
55     return strcmp(((const stat_cmd_arg *)a)->cmd, ((const stat_cmd_arg *)b)->cmd);
56 }
57
58 void
59 register_stat_tap_ui(stat_tap_ui *ui, void *userdata)
60 {
61     stat_cmd_arg *newsca;
62
63     if (stat_cmd_arg_list == NULL)
64         stat_cmd_arg_list = wmem_list_new(wmem_epan_scope());
65
66     /* Key is already present */
67     if (wmem_list_find_custom(stat_cmd_arg_list, ui->cli_string, search_duplicate))
68         return;
69
70     newsca = wmem_new(wmem_epan_scope(), stat_cmd_arg);
71     newsca->cmd= wmem_strdup(wmem_epan_scope(), ui->cli_string);
72     newsca->func=ui->tap_init_cb;
73     newsca->userdata=userdata;
74
75     wmem_list_insert_sorted(stat_cmd_arg_list, newsca, sort_by_name);
76 }
77
78 /* **********************************************************************
79  * Function called for a stat command-line argument
80  * ********************************************************************** */
81 gboolean
82 process_stat_cmd_arg(char *optstr)
83 {
84     wmem_list_frame_t *entry;
85     stat_cmd_arg *sca;
86     stat_requested *tr;
87
88     /* Renamed in Wireshark 3.0, backwards compatibility. */
89     if (!strncmp(optstr, "follow,ssl", strlen("follow,ssl"))) {
90         memcpy(optstr + 7, "tls", 3);
91     }
92
93     /* The strings "ipx" or "ipv6" must be tested before "ip" to select the
94       right tap so the sorting does matter.  And it's also why the list is
95       walked backwards */
96     for (entry = wmem_list_tail(stat_cmd_arg_list); entry; entry = wmem_list_frame_prev(entry)) {
97         sca = (stat_cmd_arg*)wmem_list_frame_data(entry);
98         if(!strncmp(sca->cmd, optstr, strlen(sca->cmd))) {
99             tr=(stat_requested *)g_malloc(sizeof (stat_requested));
100             tr->sca = sca;
101             tr->arg=g_strdup(optstr);
102             stats_requested = g_slist_append(stats_requested, tr);
103             return TRUE;
104         }
105     }
106     return FALSE;
107 }
108
109 /* **********************************************************************
110  * Function to list all possible tap command-line arguments
111  * ********************************************************************** */
112 static void
113 list_stat_cmd_args_func(gpointer data, gpointer userdata _U_)
114 {
115     fprintf(stderr,"     %s\n", ((stat_cmd_arg*)data)->cmd);
116 }
117
118 void
119 list_stat_cmd_args(void)
120 {
121     wmem_list_foreach(stat_cmd_arg_list, list_stat_cmd_args_func, NULL);
122 }
123
124 /* **********************************************************************
125  * Function to process stats requested with command-line arguments
126  * ********************************************************************** */
127 void
128 start_requested_stats(void)
129 {
130     stat_requested *sr;
131
132     while(stats_requested){
133         sr=(stat_requested *)stats_requested->data;
134         (*sr->sca->func)(sr->arg,sr->sca->userdata);
135         stats_requested=g_slist_remove(stats_requested, sr);
136         g_free(sr->arg);
137         g_free(sr);
138     }
139 }
140
141 static wmem_tree_t *registered_stat_tables = NULL;
142
143 void register_stat_tap_table_ui(stat_tap_table_ui *ui)
144 {
145     if (registered_stat_tables == NULL)
146         registered_stat_tables = wmem_tree_new(wmem_epan_scope());
147
148     wmem_tree_insert_string(registered_stat_tables, ui->cli_string, ui, 0);
149 }
150
151 stat_tap_table_ui *stat_tap_by_name(const char *name)
152 {
153     return (stat_tap_table_ui *) wmem_tree_lookup_string(registered_stat_tables, name, 0);
154 }
155
156 void stat_tap_iterate_tables(wmem_foreach_func func, gpointer user_data)
157 {
158     wmem_tree_foreach(registered_stat_tables, func, user_data);
159 }
160
161 void stat_tap_get_filter(stat_tap_table_ui* new_stat, const char *opt_arg, const char **filter, char** err)
162 {
163     guint len = (guint) strlen(new_stat->cli_string);
164     *filter=NULL;
165     *err=NULL;
166
167     if (!strncmp(opt_arg, new_stat->cli_string, len))
168     {
169         if (opt_arg[len] == ',')
170         {
171            *filter = opt_arg + len+1;
172         }
173     }
174
175     if (new_stat->stat_filter_check_cb)
176         new_stat->stat_filter_check_cb(opt_arg, filter, err);
177 }
178
179 stat_tap_table* stat_tap_init_table(const char *name, int num_fields, int num_elements,
180                 const char *filter_string)
181 {
182     stat_tap_table* new_table = g_new0(stat_tap_table, 1);
183
184     new_table->title = name;
185     new_table->num_elements = num_elements;
186     new_table->num_fields = num_fields;
187     new_table->filter_string = filter_string;
188     new_table->elements = g_new0(stat_tap_table_item_type*, num_elements);
189
190     return new_table;
191 }
192
193 void stat_tap_add_table(stat_tap_table_ui* new_stat, stat_tap_table* table)
194 {
195     if (new_stat->tables == NULL)
196         new_stat->tables = g_array_new(FALSE, TRUE, sizeof(stat_tap_table*));
197
198     g_array_insert_val(new_stat->tables, new_stat->tables->len, table);
199 }
200
201 void stat_tap_init_table_row(stat_tap_table *stat_table, guint table_index, guint num_fields, const stat_tap_table_item_type* fields)
202 {
203     /* we have discovered a new procedure. Extend the table accordingly */
204     if(table_index>=stat_table->num_elements){
205         guint old_num_elements=stat_table->num_elements;
206         guint i;
207
208         stat_table->num_elements=table_index+1;
209         stat_table->elements = (stat_tap_table_item_type**)g_realloc(stat_table->elements, sizeof(stat_tap_table_item_type*)*(stat_table->num_elements));
210         for(i=old_num_elements;i<stat_table->num_elements;i++){
211             stat_table->elements[i] = g_new0(stat_tap_table_item_type, stat_table->num_fields);
212         }
213     }
214     memcpy(stat_table->elements[table_index], fields, num_fields*sizeof(stat_tap_table_item_type));
215
216 }
217
218 stat_tap_table_item_type* stat_tap_get_field_data(const stat_tap_table *stat_table, guint table_index, guint field_index)
219 {
220     stat_tap_table_item_type* field_value;
221     g_assert(table_index < stat_table->num_elements);
222
223     field_value = stat_table->elements[table_index];
224
225     g_assert(field_index < stat_table->num_fields);
226
227     return &field_value[field_index];
228 }
229
230 void stat_tap_set_field_data(stat_tap_table *stat_table, guint table_index, guint field_index, stat_tap_table_item_type* field_data)
231 {
232     stat_tap_table_item_type* field_value;
233     g_assert(table_index < stat_table->num_elements);
234
235     field_value = stat_table->elements[table_index];
236
237     g_assert(field_index < stat_table->num_fields);
238
239     field_value[field_index] = *field_data;
240 }
241
242 void reset_stat_table(stat_tap_table_ui* new_stat)
243 {
244     guint i = 0;
245     stat_tap_table *stat_table;
246
247     for (i = 0; i < new_stat->tables->len; i++)
248     {
249         stat_table = g_array_index(new_stat->tables, stat_tap_table*, i);
250
251         if (new_stat->stat_tap_reset_table_cb)
252             new_stat->stat_tap_reset_table_cb(stat_table);
253     }
254 }
255
256 void free_stat_tables(stat_tap_table_ui* new_stat)
257 {
258     guint i = 0, element, field_index;
259     stat_tap_table *stat_table;
260     stat_tap_table_item_type* field_data;
261
262     for (i = 0; i < new_stat->tables->len; i++)
263     {
264         stat_table = g_array_index(new_stat->tables, stat_tap_table*, i);
265
266         for (element = 0; element < stat_table->num_elements; element++)
267         {
268             for (field_index = 0; field_index < stat_table->num_fields; field_index++)
269             {
270                 field_data = stat_tap_get_field_data(stat_table, element, field_index);
271                 /* Give dissector a crack at it */
272                 /* XXX Should this be per-row instead? */
273                 if (new_stat->stat_tap_free_table_item_cb)
274                     new_stat->stat_tap_free_table_item_cb(stat_table, element, field_index, field_data);
275             }
276             g_free(stat_table->elements[element]);
277         }
278         g_free(stat_table->elements);
279         g_free(stat_table);
280     }
281     g_array_set_size(new_stat->tables, 0);
282 }
283
284
285 /*
286  * Editor modelines
287  *
288  * Local Variables:
289  * c-basic-offset: 4
290  * tab-width: 8
291  * indent-tabs-mode: nil
292  * End:
293  *
294  * ex: set shiftwidth=4 tabstop=8 expandtab:
295  * :indentSize=4:tabSize=8:noTabs=true:
296  */