WSDG: Update docbook info
[metze/wireshark/wip.git] / epan / srt_table.c
1 /* srt_table.c
2  * Helper routines common to all SRT taps.
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 <string.h>
14
15 #include "proto.h"
16 #include "packet_info.h"
17 #include "srt_table.h"
18
19 struct register_srt {
20     int proto_id;              /* protocol id (0-indexed) */
21     const char* tap_listen_str;      /* string used in register_tap_listener (NULL to use protocol name) */
22     int max_tables;            /* Maximum number of tables expected (used by GUI to determine how to display tables) */
23     tap_packet_cb srt_func;    /* function to be called for new incoming packets for SRT */
24     srt_init_cb srt_init;      /* function to create dissector SRT tables */
25     srt_param_handler_cb param_cb; /* function to parse parameters of optional arguments of tap string */
26     void* param_data;          /* Storage for tap parameter data */
27 };
28
29 int get_srt_proto_id(register_srt_t* srt)
30 {
31     if (!srt) {
32         return -1;
33     }
34     return srt->proto_id;
35 }
36
37 const char* get_srt_tap_listener_name(register_srt_t* srt)
38 {
39     return srt->tap_listen_str;
40 }
41
42 int get_srt_max_tables(register_srt_t* srt)
43 {
44     return srt->max_tables;
45 }
46
47 tap_packet_cb get_srt_packet_func(register_srt_t* srt)
48 {
49     return srt->srt_func;
50 }
51
52 void set_srt_table_param_data(register_srt_t* srt, void* data)
53 {
54     srt->param_data = data;
55 }
56
57 void* get_srt_table_param_data(register_srt_t* srt)
58 {
59     return srt->param_data;
60 }
61
62 void
63 free_srt_table_data(srt_stat_table *rst)
64 {
65     int i;
66
67     for(i=0;i<rst->num_procs;i++){
68         g_free(rst->procedures[i].procedure);
69         rst->procedures[i].procedure=NULL;
70     }
71     g_free(rst->filter_string);
72     rst->filter_string=NULL;
73     g_free(rst->procedures);
74     rst->procedures=NULL;
75     rst->num_procs=0;
76 }
77
78 void free_srt_table(register_srt_t *srt, GArray* srt_array, srt_gui_free_cb gui_callback, void *callback_data)
79 {
80     guint i = 0;
81     srt_stat_table *srt_table;
82
83     for (i = 0; i < srt_array->len; i++)
84     {
85         srt_table = g_array_index(srt_array, srt_stat_table*, i);
86
87         /* Give GUI the first crack at it before we clean up */
88         if (gui_callback)
89             gui_callback(srt_table, callback_data);
90
91         free_srt_table_data(srt_table);
92         g_free(srt_table);
93     }
94
95     /* Clear the tables */
96     g_array_set_size(srt_array, 0);
97
98     /* Clear out any possible parameter data */
99     g_free(srt->param_data);
100     srt->param_data = NULL;
101 }
102
103 static void reset_srt_table_data(srt_stat_table *rst)
104 {
105     int i;
106
107     for(i=0;i<rst->num_procs;i++){
108         time_stat_init(&rst->procedures[i].stats);
109     }
110 }
111
112 void reset_srt_table(GArray* srt_array, srt_gui_reset_cb gui_callback, void *callback_data)
113 {
114     guint i = 0;
115     srt_stat_table *srt_table;
116
117     for (i = 0; i < srt_array->len; i++)
118     {
119         srt_table = g_array_index(srt_array, srt_stat_table*, i);
120
121         /* Give GUI the first crack at it before we clean up */
122         if (gui_callback)
123             gui_callback(srt_table, callback_data);
124
125         reset_srt_table_data(srt_table);
126     }
127 }
128
129 static wmem_tree_t *registered_srt_tables = NULL;
130
131 register_srt_t* get_srt_table_by_name(const char* name)
132 {
133     return (register_srt_t*)wmem_tree_lookup_string(registered_srt_tables, name, 0);
134 }
135
136 gchar* srt_table_get_tap_string(register_srt_t* srt)
137 {
138     GString *cmd_str = g_string_new(proto_get_protocol_filter_name(srt->proto_id));
139     g_string_append(cmd_str, ",srt");
140     return g_string_free(cmd_str, FALSE);
141 }
142
143 void srt_table_get_filter(register_srt_t* srt, const char *opt_arg, const char **filter, char** err)
144 {
145     gchar* cmd_str = srt_table_get_tap_string(srt);
146     guint len = (guint32)strlen(cmd_str);
147     guint pos = len;
148     *filter=NULL;
149     *err = NULL;
150
151     if(!strncmp(opt_arg, cmd_str, len))
152     {
153         if (srt->param_cb != NULL)
154         {
155             pos = srt->param_cb(srt, opt_arg + len, err);
156             if (*err != NULL)
157                 return;
158
159             if (pos > 0)
160                 pos += len;
161         }
162
163         if (opt_arg[pos] == ',')
164         {
165            *filter = opt_arg + pos+1;
166         }
167     }
168
169     g_free(cmd_str);
170 }
171
172 void srt_table_dissector_init(register_srt_t* srt, GArray* srt_array, srt_gui_init_cb gui_callback, void *callback_data)
173 {
174     srt->srt_init(srt, srt_array, gui_callback, callback_data);
175 }
176
177 void
178 register_srt_table(const int proto_id, const char* tap_listener, int max_tables, tap_packet_cb srt_packet_func, srt_init_cb init_cb, srt_param_handler_cb param_cb)
179 {
180     register_srt_t *table;
181     DISSECTOR_ASSERT(init_cb);
182     DISSECTOR_ASSERT(srt_packet_func);
183
184     table = wmem_new(wmem_epan_scope(), register_srt_t);
185
186     table->proto_id      = proto_id;
187     if (tap_listener != NULL)
188         table->tap_listen_str = tap_listener;
189     else
190         table->tap_listen_str = proto_get_protocol_filter_name(proto_id);
191     table->max_tables    = max_tables;
192     table->srt_func      = srt_packet_func;
193     table->srt_init      = init_cb;
194     table->param_cb      = param_cb;
195     table->param_data    = NULL;
196
197     if (registered_srt_tables == NULL)
198         registered_srt_tables = wmem_tree_new(wmem_epan_scope());
199
200     wmem_tree_insert_string(registered_srt_tables, proto_get_protocol_filter_name(proto_id), table, 0);
201 }
202
203 void srt_table_iterate_tables(wmem_foreach_func func, gpointer user_data)
204 {
205     wmem_tree_foreach(registered_srt_tables, func, user_data);
206 }
207
208 srt_stat_table*
209 init_srt_table(const char *name, const char *short_name, GArray *srt_array, int num_procs, const char* proc_column_name,
210                 const char *filter_string, srt_gui_init_cb gui_callback, void* gui_data, void* table_specific_data)
211 {
212     int i;
213     srt_stat_table *table = g_new(srt_stat_table, 1);
214
215     table->filter_string = g_strdup(filter_string);
216
217     table->name = name;
218     table->short_name = short_name;
219     table->proc_column_name = proc_column_name;
220     table->num_procs=num_procs;
221     table->procedures=(srt_procedure_t *)g_malloc(sizeof(srt_procedure_t)*num_procs);
222     for(i=0;i<num_procs;i++){
223         time_stat_init(&table->procedures[i].stats);
224         table->procedures[i].proc_index = 0;
225         table->procedures[i].procedure = NULL;
226     }
227
228     g_array_insert_val(srt_array, srt_array->len, table);
229
230     table->table_specific_data = table_specific_data;
231
232     if (gui_callback)
233         gui_callback(table, gui_data);
234
235     return table;
236 }
237
238 void
239 init_srt_table_row(srt_stat_table *rst, int indx, const char *procedure)
240 {
241     /* we have discovered a new procedure. Extend the table accordingly */
242     if(indx>=rst->num_procs){
243         int old_num_procs=rst->num_procs;
244         int i;
245
246         rst->num_procs=indx+1;
247         rst->procedures=(srt_procedure_t *)g_realloc(rst->procedures, sizeof(srt_procedure_t)*(rst->num_procs));
248         for(i=old_num_procs;i<rst->num_procs;i++){
249             time_stat_init(&rst->procedures[i].stats);
250             rst->procedures[i].proc_index = i;
251             rst->procedures[i].procedure=NULL;
252         }
253     }
254     rst->procedures[indx].proc_index = indx;
255     rst->procedures[indx].procedure=g_strdup(procedure);
256 }
257
258 void
259 add_srt_table_data(srt_stat_table *rst, int indx, const nstime_t *req_time, packet_info *pinfo)
260 {
261     srt_procedure_t *rp;
262     nstime_t t, delta;
263
264     g_assert(indx >= 0 && indx < rst->num_procs);
265     rp=&rst->procedures[indx];
266
267     /* calculate time delta between request and reply */
268     t=pinfo->abs_ts;
269     nstime_delta(&delta, &t, req_time);
270
271     time_stat_update(&rp->stats, &delta, pinfo);
272 }
273
274 /*
275  * Editor modelines
276  *
277  * Local Variables:
278  * c-basic-offset: 4
279  * tab-width: 8
280  * indent-tabs-mode: nil
281  * End:
282  *
283  * ex: set shiftwidth=4 tabstop=8 expandtab:
284  * :indentSize=4:tabSize=8:noTabs=true:
285  */