Get rid of some GTK+-only stuff.
[metze/wireshark/wip.git] / ui / io_graph_item.h
1 /* io_graph_item.h
2  * Definitions and functions for IO graph items
3  *
4  * Copied from gtk/io_stat.c, (c) 2002 Ronnie Sahlberg
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * SPDX-License-Identifier: GPL-2.0-or-later
11  */
12
13 #ifndef __IO_GRAPH_ITEM_H__
14 #define __IO_GRAPH_ITEM_H__
15
16 #ifdef __cplusplus
17 extern "C" {
18 #endif /* __cplusplus */
19
20 typedef enum {
21     IOG_ITEM_UNIT_FIRST,
22     IOG_ITEM_UNIT_PACKETS = IOG_ITEM_UNIT_FIRST,
23     IOG_ITEM_UNIT_BYTES,
24     IOG_ITEM_UNIT_BITS,
25     IOG_ITEM_UNIT_CALC_SUM,
26     IOG_ITEM_UNIT_CALC_FRAMES,
27     IOG_ITEM_UNIT_CALC_FIELDS,
28     IOG_ITEM_UNIT_CALC_MAX,
29     IOG_ITEM_UNIT_CALC_MIN,
30     IOG_ITEM_UNIT_CALC_AVERAGE,
31     IOG_ITEM_UNIT_CALC_LOAD,
32     IOG_ITEM_UNIT_LAST = IOG_ITEM_UNIT_CALC_LOAD,
33     NUM_IOG_ITEM_UNITS
34 } io_graph_item_unit_t;
35
36 typedef struct _io_graph_item_t {
37     guint32  frames;            /* always calculated, will hold number of frames*/
38     guint64  bytes;             /* always calculated, will hold number of bytes*/
39     guint64  fields;
40     gint64   int_max;
41     gint64   int_min;
42     gint64   int_tot;
43     /* XXX - Why do we always use 64-bit ints but split floats between
44      * gfloat and gdouble?
45      */
46     gfloat   float_max;
47     gfloat   float_min;
48     gfloat   float_tot;
49     gdouble  double_max;
50     gdouble  double_min;
51     gdouble  double_tot;
52     nstime_t time_max;
53     nstime_t time_min;
54     nstime_t time_tot;
55     guint32  first_frame_in_invl;
56     guint32  extreme_frame_in_invl; /* frame with min/max value */
57     guint32  last_frame_in_invl;
58 } io_graph_item_t;
59
60 /** Reset (zero) an io_graph_item_t.
61  *
62  * @param items [in,out] Array containing the items to reset.
63  * @param count [in] The number of items in the array.
64  */
65 static inline void
66 reset_io_graph_items(io_graph_item_t *items, gsize count) {
67     io_graph_item_t *item;
68     gsize i;
69
70     for (i = 0; i < count; i++) {
71         item = &items[i];
72
73         item->frames     = 0;
74         item->bytes      = 0;
75         item->fields     = 0;
76         item->int_max    = 0;
77         item->int_min    = 0;
78         item->int_tot    = 0;
79         item->float_max  = 0;
80         item->float_min  = 0;
81         item->float_tot  = 0;
82         item->double_max = 0;
83         item->double_min = 0;
84         item->double_tot = 0;
85         nstime_set_zero(&item->time_max);
86         nstime_set_zero(&item->time_min);
87         nstime_set_zero(&item->time_tot);
88         item->first_frame_in_invl = 0;
89         item->extreme_frame_in_invl = 0;
90         item->last_frame_in_invl  = 0;
91     }
92 }
93
94 /** Get the interval (array index) for a packet
95  *
96  * It is up to the caller to determine if the return value is valid.
97  *
98  * @param [in] pinfo Packet of interest.
99  * @param [in] interval Time interval in milliseconds.
100  * @return Array index on success, -1 on failure.
101  */
102 int get_io_graph_index(packet_info *pinfo, int interval);
103
104 /** Check field and item unit compatibility
105  *
106  * @param field_name [in] Header field name to check
107  * @param hf_index [out] Assigned the header field index corresponding to field_name if valid.
108  *                       Can be NULL.
109  * @param item_unit [in] The type of unit to calculate. From IOG_ITEM_UNITS.
110  * @return NULL if compatible, otherwise an error string. The string must
111  *         be freed by the caller.
112  */
113 GString *check_field_unit(const char *field_name, int *hf_index, io_graph_item_unit_t item_unit);
114
115 /** Update the values of an io_graph_item_t.
116  *
117  * Frame and byte counts are always calculated. If edt is non-NULL advanced
118  * statistics are calculated using hfindex.
119  *
120  * @param items [in,out] Array containing the item to update.
121  * @param idx [in] Index of the item to update.
122  * @param pinfo [in] Packet containing update information.
123  * @param edt [in] Dissection information for advanced statistics. May be NULL.
124  * @param hf_index [in] Header field index for advanced statistics.
125  * @param item_unit [in] The type of unit to calculate. From IOG_ITEM_UNITS.
126  * @param interval [in] Timing interval in ms.
127  * @return TRUE if the update was successful, otherwise FALSE.
128  */
129 static inline gboolean
130 update_io_graph_item(io_graph_item_t *items, int idx, packet_info *pinfo, epan_dissect_t *edt, int hf_index, int item_unit, guint32 interval) {
131     io_graph_item_t *item = &items[idx];
132
133     /* Set the first and last frame num in current interval matching the target field+filter  */
134     if (item->first_frame_in_invl == 0) {
135         item->first_frame_in_invl = pinfo->num;
136     }
137     item->last_frame_in_invl = pinfo->num;
138
139     if (edt && hf_index >= 0) {
140         GPtrArray *gp;
141         guint i;
142
143         gp = proto_get_finfo_ptr_array(edt->tree, hf_index);
144         if (!gp) {
145             return FALSE;
146         }
147
148         /* Update the appropriate counters. If fields == 0, this is the first seen
149          *  value so set any min/max values accordingly. */
150         for (i=0; i < gp->len; i++) {
151             int new_int;
152             gint64 new_int64;
153             float new_float;
154             double new_double;
155             nstime_t *new_time;
156
157             switch (proto_registrar_get_ftype(hf_index)) {
158             case FT_UINT8:
159             case FT_UINT16:
160             case FT_UINT24:
161             case FT_UINT32:
162                 new_int = fvalue_get_uinteger(&((field_info *)gp->pdata[i])->value);
163
164                 if ((new_int > item->int_max) || (item->fields == 0)) {
165                     item->int_max = new_int;
166                     if (item_unit == IOG_ITEM_UNIT_CALC_MAX) {
167                         item->extreme_frame_in_invl = pinfo->num;
168                     }
169                 }
170                 if ((new_int < item->int_min) || (item->fields == 0)) {
171                     item->int_min = new_int;
172                     if (item_unit == IOG_ITEM_UNIT_CALC_MIN) {
173                         item->extreme_frame_in_invl = pinfo->num;
174                     }
175                 }
176                 item->int_tot += new_int;
177                 item->fields++;
178                 break;
179             case FT_INT8:
180             case FT_INT16:
181             case FT_INT24:
182             case FT_INT32:
183                 new_int = fvalue_get_sinteger(&((field_info *)gp->pdata[i])->value);
184                 if ((new_int > item->int_max) || (item->fields == 0)) {
185                     item->int_max = new_int;
186                     if (item_unit == IOG_ITEM_UNIT_CALC_MAX) {
187                         item->extreme_frame_in_invl = pinfo->num;
188                     }
189                 }
190                 if ((new_int < item->int_min) || (item->fields == 0)) {
191                     item->int_min = new_int;
192                     if (item_unit == IOG_ITEM_UNIT_CALC_MIN) {
193                         item->extreme_frame_in_invl = pinfo->num;
194                     }
195                 }
196                 item->int_tot += new_int;
197                 item->fields++;
198                 break;
199             case FT_UINT40:
200             case FT_UINT48:
201             case FT_UINT56:
202             case FT_UINT64:
203                 new_int64 = fvalue_get_uinteger64(&((field_info *)gp->pdata[i])->value);
204                 if ((new_int64 > item->int_max) || (item->fields == 0)) {
205                     item->int_max = new_int64;
206                     if (item_unit == IOG_ITEM_UNIT_CALC_MAX) {
207                         item->extreme_frame_in_invl = pinfo->num;
208                     }
209                 }
210                 if ((new_int64 < item->int_min) || (item->fields == 0)) {
211                     item->int_min = new_int64;
212                     if (item_unit == IOG_ITEM_UNIT_CALC_MIN) {
213                         item->extreme_frame_in_invl = pinfo->num;
214                     }
215                 }
216                 item->int_tot += new_int64;
217                 item->fields++;
218                 break;
219             case FT_INT40:
220             case FT_INT48:
221             case FT_INT56:
222             case FT_INT64:
223                 new_int64 = fvalue_get_sinteger64(&((field_info *)gp->pdata[i])->value);
224                 if ((new_int64 > item->int_max) || (item->fields == 0)) {
225                     item->int_max = new_int64;
226                     if (item_unit == IOG_ITEM_UNIT_CALC_MAX) {
227                         item->extreme_frame_in_invl = pinfo->num;
228                     }
229                 }
230                 if ((new_int64 < item->int_min) || (item->fields == 0)) {
231                     item->int_min = new_int64;
232                     if (item_unit == IOG_ITEM_UNIT_CALC_MIN) {
233                         item->extreme_frame_in_invl = pinfo->num;
234                     }
235                 }
236                 item->int_tot += new_int64;
237                 item->fields++;
238                 break;
239             case FT_FLOAT:
240                 new_float = (gfloat)fvalue_get_floating(&((field_info *)gp->pdata[i])->value);
241                 if ((new_float > item->float_max) || (item->fields == 0)) {
242                     item->float_max = new_float;
243                     if (item_unit == IOG_ITEM_UNIT_CALC_MAX) {
244                         item->extreme_frame_in_invl = pinfo->num;
245                     }
246                 }
247                 if ((new_float < item->float_min) || (item->fields == 0)) {
248                     item->float_min = new_float;
249                     if (item_unit == IOG_ITEM_UNIT_CALC_MIN) {
250                         item->extreme_frame_in_invl = pinfo->num;
251                     }
252                 }
253                 item->float_tot += new_float;
254                 item->fields++;
255                 break;
256             case FT_DOUBLE:
257                 new_double = fvalue_get_floating(&((field_info *)gp->pdata[i])->value);
258                 if ((new_double > item->double_max) || (item->fields == 0)) {
259                     item->double_max = new_double;
260                     if (item_unit == IOG_ITEM_UNIT_CALC_MAX) {
261                         item->extreme_frame_in_invl = pinfo->num;
262                     }
263                 }
264                 if ((new_double < item->double_min) || (item->fields == 0)) {
265                     item->double_min = new_double;
266                     if (item_unit == IOG_ITEM_UNIT_CALC_MIN) {
267                         item->extreme_frame_in_invl = pinfo->num;
268                     }
269                 }
270                 item->double_tot += new_double;
271                 item->fields++;
272                 break;
273             case FT_RELATIVE_TIME:
274                 new_time = (nstime_t *)fvalue_get(&((field_info *)gp->pdata[i])->value);
275
276                 switch (item_unit) {
277                 case IOG_ITEM_UNIT_CALC_LOAD:
278                 {
279                     guint64 t, pt; /* time in us */
280                     int j;
281                     /*
282                      * Add the time this call spanned each interval according to its contribution
283                      * to that interval.
284                      */
285                     t = new_time->secs;
286                     t = t * 1000000 + new_time->nsecs / 1000;
287                     j = idx;
288                     /*
289                      * Handle current interval
290                      */
291                     pt = pinfo->rel_ts.secs * 1000000 + pinfo->rel_ts.nsecs / 1000;
292                     pt = pt % (interval * 1000);
293                     if (pt > t) {
294                         pt = t;
295                     }
296                     while (t) {
297                         io_graph_item_t *load_item;
298
299                         load_item = &items[j];
300                         load_item->time_tot.nsecs += (int) (pt * 1000);
301                         if (load_item->time_tot.nsecs > 1000000000) {
302                             load_item->time_tot.secs++;
303                             load_item->time_tot.nsecs -= 1000000000;
304                         }
305
306                         if (j == 0) {
307                             break;
308                         }
309                         j--;
310                         t -= pt;
311                         if (t > (guint64) interval * 1000) {
312                             pt = (guint64) interval * 1000;
313                         } else {
314                             pt = t;
315                         }
316                     }
317                     break;
318                 }
319                 default:
320                     if ( (new_time->secs > item->time_max.secs)
321                          || ( (new_time->secs == item->time_max.secs)
322                               && (new_time->nsecs > item->time_max.nsecs))
323                          || (item->fields == 0)) {
324                         item->time_max = *new_time;
325                         if (item_unit == IOG_ITEM_UNIT_CALC_MAX) {
326                             item->extreme_frame_in_invl = pinfo->num;
327                         }
328                     }
329                     if ( (new_time->secs<item->time_min.secs)
330                          || ( (new_time->secs == item->time_min.secs)
331                               && (new_time->nsecs < item->time_min.nsecs))
332                          || (item->fields == 0)) {
333                         item->time_min = *new_time;
334                         if (item_unit == IOG_ITEM_UNIT_CALC_MIN) {
335                             item->extreme_frame_in_invl = pinfo->num;
336                         }
337                     }
338                     nstime_add(&item->time_tot, new_time);
339                     item->fields++;
340                 }
341                 break;
342             default:
343                 if ((item_unit == IOG_ITEM_UNIT_CALC_FRAMES) ||
344                     (item_unit == IOG_ITEM_UNIT_CALC_FIELDS)) {
345                     /*
346                      * It's not an integeresque type, but
347                      * all we want to do is count it, so
348                      * that's all right.
349                      */
350                     item->fields++;
351                 }
352                 else {
353                     /*
354                      * "Can't happen"; see the "check that the
355                      * type is compatible" check in
356                      * filter_callback().
357                      */
358                     g_assert_not_reached();
359                 }
360                 break;
361             }
362         }
363     }
364
365     item->frames++;
366     item->bytes += pinfo->fd->pkt_len;
367
368     return TRUE;
369 }
370
371
372 #ifdef __cplusplus
373 }
374 #endif /* __cplusplus */
375
376 #endif /* __IO_GRAPH_ITEM_H__ */
377
378 /*
379  * Editor modelines
380  *
381  * Local Variables:
382  * c-basic-offset: 4
383  * tab-width: 8
384  * indent-tabs-mode: nil
385  * End:
386  *
387  * ex: set shiftwidth=4 tabstop=8 expandtab:
388  * :indentSize=4:tabSize=8:noTabs=true:
389  */