more
[metze/wireshark/wip.git] / sharkd_session.c
1 /* sharkd_session.c
2  *
3  * Copyright (C) 2016 Jakub Zawadzki
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * SPDX-License-Identifier: GPL-2.0-or-later
10  */
11
12 #include <config.h>
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <stdarg.h>
17 #include <string.h>
18 #include <errno.h>
19
20 #include <glib.h>
21
22 #include <wsutil/wsjson.h>
23 #include <wsutil/ws_printf.h>
24
25 #include <file.h>
26 #include <epan/epan_dissect.h>
27 #include <epan/exceptions.h>
28 #include <epan/color_filters.h>
29 #include <epan/prefs.h>
30 #include <epan/prefs-int.h>
31 #include <epan/uat-int.h>
32 #include <wiretap/wtap.h>
33
34 #include <epan/column.h>
35
36 #include <ui/ssl_key_export.h>
37
38 #include <ui/io_graph_item.h>
39 #include <epan/stats_tree_priv.h>
40 #include <epan/stat_tap_ui.h>
41 #include <epan/conversation_table.h>
42 #include <epan/sequence_analysis.h>
43 #include <epan/expert.h>
44 #include <epan/export_object.h>
45 #include <epan/follow.h>
46 #include <epan/rtd_table.h>
47 #include <epan/srt_table.h>
48
49 #include <epan/dissectors/packet-h225.h>
50 #include <epan/rtp_pt.h>
51 #include <ui/voip_calls.h>
52 #include <ui/rtp_stream.h>
53 #include <ui/tap-rtp-common.h>
54 #include <ui/tap-rtp-analysis.h>
55 #include <epan/to_str.h>
56
57 #include <epan/addr_resolv.h>
58 #include <epan/dissectors/packet-rtp.h>
59 #include <ui/rtp_media.h>
60 #ifdef HAVE_SPEEXDSP
61 # include <speex/speex_resampler.h>
62 #else
63 # include <codecs/speex/speex_resampler.h>
64 #endif /* HAVE_SPEEXDSP */
65
66 #include <epan/maxmind_db.h>
67
68 #include <wsutil/pint.h>
69 #include <wsutil/strtoi.h>
70
71 #include "globals.h"
72
73 #include "sharkd.h"
74
75 struct sharkd_filter_item
76 {
77         guint8 *filtered; /* can be NULL if all frames are matching for given filter. */
78 };
79
80 static GHashTable *filter_table = NULL;
81
82 static gboolean
83 json_unescape_str(char *input)
84 {
85         return wsjson_unescape_json_string(input, input);
86 }
87
88 static const char *
89 json_find_attr(const char *buf, const jsmntok_t *tokens, int count, const char *attr)
90 {
91         int i;
92
93         for (i = 0; i < count; i += 2)
94         {
95                 const char *tok_attr  = &buf[tokens[i + 0].start];
96                 const char *tok_value = &buf[tokens[i + 1].start];
97
98                 if (!strcmp(tok_attr, attr))
99                         return tok_value;
100         }
101
102         return NULL;
103 }
104
105 static void
106 json_puts_string(const char *s)
107 {
108         static const char json_cntrl[0x20][6] =
109         {
110                 "u0000", "u0001", "u0002", "u0003", "u0004", "u0005", "u0006", "u0007", "b",     "t",     "n",     "u000b", "f",     "r",     "u000e", "u000f",
111                 "u0010", "u0011", "u0012", "u0013", "u0014", "u0015", "u0016", "u0017", "u0018", "u0019", "u001a", "u001b", "u001c", "u001d", "u001e", "u001f"
112         };
113
114         const unsigned char *str = (const unsigned char *) s ? s : "";
115         int i;
116
117         putchar('"');
118         for (i = 0; str[i]; i++)
119         {
120                 if (str[i] < 0x20)
121                 {
122                         putchar('\\');
123                         fputs(json_cntrl[(guint)str[i]], stdout);
124                 }
125                 else
126                 {
127                         if (str[i] == '\\' || str[i] == '"')
128                                 putchar('\\');
129                         putchar(str[i]);
130                 }
131         }
132
133         putchar('"');
134 }
135
136 static void
137 json_print_base64_step(const guint8 *data, int *state1, int *state2)
138 {
139         gchar buf[(1 / 3 + 1) * 4 + 4 + 1];
140         gsize wrote;
141
142         if (data)
143                 wrote = g_base64_encode_step(data, 1, FALSE, buf, state1, state2);
144         else
145                 wrote = g_base64_encode_close(FALSE, buf, state1, state2);
146
147         if (wrote > 0)
148         {
149                 buf[wrote] = '\0';
150                 fputs(buf, stdout);
151         }
152 }
153
154 static void
155 json_print_base64(const guint8 *data, size_t len)
156 {
157         size_t i;
158         int base64_state1 = 0;
159         int base64_state2 = 0;
160
161         putchar('"');
162
163         for (i = 0; i < len; i++)
164                 json_print_base64_step(&data[i], &base64_state1, &base64_state2);
165
166         json_print_base64_step(NULL, &base64_state1, &base64_state2);
167
168         putchar('"');
169 }
170
171 static void G_GNUC_PRINTF(3, 4)
172 sharkd_json_value_anyf(gboolean sepa, const char *key, const char *valuef, ...)
173 {
174         if (sepa)
175                 putchar(',');
176
177         if (key)
178         {
179                 putchar('"');
180                 fputs(key, stdout);
181                 putchar('"');
182                 putchar(':');
183         }
184
185         if (valuef && *valuef)
186         {
187                 va_list ap;
188
189                 va_start(ap, valuef);
190                 vprintf(valuef, ap);
191                 va_end(ap);
192         }
193 }
194
195 static void
196 sharkd_json_value_string(gboolean sepa, const char *key, const char *str)
197 {
198         sharkd_json_value_anyf(sepa, key, NULL);
199         json_puts_string(str);
200 }
201
202 static void
203 sharkd_json_value_base64(gboolean sepa, const char *key, const guint8 *data, size_t len)
204 {
205         sharkd_json_value_anyf(sepa, key, NULL);
206         json_print_base64(data, len);
207 }
208
209 static void G_GNUC_PRINTF(3, 4)
210 sharkd_json_value_stringf(gboolean sepa, const char *key, const char *format, ...)
211 {
212         va_list ap;
213
214         sharkd_json_value_anyf(sepa, key, NULL);
215
216         va_start(ap, format);
217         putchar('"');
218         vprintf(format, ap);
219         putchar('"');
220         va_end(ap);
221 }
222
223 static void
224 sharkd_json_array_open(gboolean sepa, const char *key)
225 {
226         sharkd_json_value_anyf(sepa, key, "[");
227 }
228
229 static void
230 sharkd_json_array_close(void)
231 {
232         putchar(']');
233 }
234
235 static void
236 sharkd_json_object_open(gboolean sepa)
237 {
238         sharkd_json_value_anyf(sepa, NULL, "{");
239 }
240
241 static void
242 sharkd_json_object_close(void)
243 {
244         putchar('}');
245 }
246
247 static void
248 sharkd_json_finish(void)
249 {
250         putchar('\n');
251 }
252
253 static void
254 sharkd_json_simple_reply(int err, const char *errmsg)
255 {
256         sharkd_json_object_open(FALSE);
257         sharkd_json_value_anyf(FALSE, "err", "%d", err);
258         if (errmsg)
259                 sharkd_json_value_string(TRUE, "errmsg", errmsg);
260
261         sharkd_json_object_close();
262         sharkd_json_finish();
263 }
264
265 static void
266 sharkd_session_filter_free(gpointer data)
267 {
268         struct sharkd_filter_item *l = (struct sharkd_filter_item *) data;
269
270         g_free(l->filtered);
271         g_free(l);
272 }
273
274 static const struct sharkd_filter_item *
275 sharkd_session_filter_data(const char *filter)
276 {
277         struct sharkd_filter_item *l;
278
279         l = (struct sharkd_filter_item *) g_hash_table_lookup(filter_table, filter);
280         if (!l)
281         {
282                 guint8 *filtered = NULL;
283
284                 int ret = sharkd_filter(filter, &filtered);
285
286                 if (ret == -1)
287                         return NULL;
288
289                 l = (struct sharkd_filter_item *) g_malloc(sizeof(struct sharkd_filter_item));
290                 l->filtered = filtered;
291
292                 g_hash_table_insert(filter_table, g_strdup(filter), l);
293         }
294
295         return l;
296 }
297
298 static gboolean
299 sharkd_rtp_match_init(rtpstream_id_t *id, const char *init_str)
300 {
301         gboolean ret = FALSE;
302         char **arr;
303         guint32 tmp_addr_src, tmp_addr_dst;
304         address tmp_src_addr, tmp_dst_addr;
305
306         memset(id, 0, sizeof(*id));
307
308         arr = g_strsplit(init_str, "_", 7); /* pass larger value, so we'll catch incorrect input :) */
309         if (g_strv_length(arr) != 5)
310                 goto fail;
311
312         /* TODO, for now only IPv4 */
313         if (!get_host_ipaddr(arr[0], &tmp_addr_src))
314                 goto fail;
315
316         if (!ws_strtou16(arr[1], NULL, &id->src_port))
317                 goto fail;
318
319         if (!get_host_ipaddr(arr[2], &tmp_addr_dst))
320                 goto fail;
321
322         if (!ws_strtou16(arr[3], NULL, &id->dst_port))
323                 goto fail;
324
325         if (!ws_hexstrtou32(arr[4], NULL, &id->ssrc))
326                 goto fail;
327
328         set_address(&tmp_src_addr, AT_IPv4, 4, &tmp_addr_src);
329         copy_address(&id->src_addr, &tmp_src_addr);
330         set_address(&tmp_dst_addr, AT_IPv4, 4, &tmp_addr_dst);
331         copy_address(&id->dst_addr, &tmp_dst_addr);
332
333         ret = TRUE;
334
335 fail:
336         g_strfreev(arr);
337         return ret;
338 }
339
340 static gboolean
341 sharkd_session_process_info_nstat_cb(const void *key, void *value, void *userdata)
342 {
343         stat_tap_table_ui *stat_tap = (stat_tap_table_ui *) value;
344         int *pi = (int *) userdata;
345
346         sharkd_json_object_open(*pi != 0);
347                 sharkd_json_value_string(FALSE, "name", stat_tap->title);
348                 sharkd_json_value_stringf(TRUE, "tap", "nstat:%s", (const char *) key);
349         sharkd_json_object_close();
350
351         *pi = *pi + 1;
352         return FALSE;
353 }
354
355 static gboolean
356 sharkd_session_process_info_conv_cb(const void* key, void* value, void* userdata)
357 {
358         struct register_ct *table = (struct register_ct *) value;
359         int *pi = (int *) userdata;
360
361         const char *label = (const char *) key;
362
363         if (get_conversation_packet_func(table))
364         {
365                 sharkd_json_object_open(*pi != 0);
366                         sharkd_json_value_stringf(FALSE, "name", "Conversation List/%s", label);
367                         sharkd_json_value_stringf(TRUE, "tap", "conv:%s", label);
368                 sharkd_json_object_close();
369
370                 *pi = *pi + 1;
371         }
372
373         if (get_hostlist_packet_func(table))
374         {
375                 sharkd_json_object_open(*pi != 0);
376                         sharkd_json_value_stringf(FALSE, "name", "Endpoint/%s", label);
377                         sharkd_json_value_stringf(TRUE, "tap", "endpt:%s", label);
378                 sharkd_json_object_close();
379
380                 *pi = *pi + 1;
381         }
382         return FALSE;
383 }
384
385 static gboolean
386 sharkd_session_seq_analysis_cb(const void *key, void *value, void *userdata)
387 {
388         register_analysis_t *analysis = (register_analysis_t *) value;
389         int *pi = (int *) userdata;
390
391         sharkd_json_object_open(*pi != 0);
392                 sharkd_json_value_string(FALSE, "name", sequence_analysis_get_ui_name(analysis));
393                 sharkd_json_value_stringf(TRUE, "tap", "seqa:%s", (const char *) key);
394         sharkd_json_object_close();
395
396         *pi = *pi + 1;
397         return FALSE;
398 }
399
400 static gboolean
401 sharkd_export_object_visit_cb(const void *key _U_, void *value, void *user_data)
402 {
403         register_eo_t *eo = (register_eo_t *) value;
404         int *pi = (int *) user_data;
405
406         const int proto_id = get_eo_proto_id(eo);
407         const char *filter = proto_get_protocol_filter_name(proto_id);
408         const char *label  = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
409
410         sharkd_json_object_open(*pi != 0);
411                 sharkd_json_value_stringf(FALSE, "name", "Export Object/%s", label);
412                 sharkd_json_value_stringf(TRUE, "tap", "eo:%s", filter);
413         sharkd_json_object_close();
414
415         *pi = *pi + 1;
416         return FALSE;
417 }
418
419 static gboolean
420 sharkd_srt_visit_cb(const void *key _U_, void *value, void *user_data)
421 {
422         register_srt_t *srt = (register_srt_t *) value;
423         int *pi = (int *) user_data;
424
425         const int proto_id = get_srt_proto_id(srt);
426         const char *filter = proto_get_protocol_filter_name(proto_id);
427         const char *label  = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
428
429         sharkd_json_object_open(*pi != 0);
430                 sharkd_json_value_stringf(FALSE, "name", "Service Response Time/%s", label);
431                 sharkd_json_value_stringf(TRUE, "tap", "srt:%s", filter);
432         sharkd_json_object_close();
433
434         *pi = *pi + 1;
435         return FALSE;
436 }
437
438 static gboolean
439 sharkd_rtd_visit_cb(const void *key _U_, void *value, void *user_data)
440 {
441         register_rtd_t *rtd = (register_rtd_t *) value;
442         int *pi = (int *) user_data;
443
444         const int proto_id = get_rtd_proto_id(rtd);
445         const char *filter = proto_get_protocol_filter_name(proto_id);
446         const char *label  = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
447
448         sharkd_json_object_open(*pi != 0);
449                 sharkd_json_value_stringf(FALSE, "name", "Response Time Delay/%s", label);
450                 sharkd_json_value_stringf(TRUE, "tap", "rtd:%s", filter);
451         sharkd_json_object_close();
452
453         *pi = *pi + 1;
454         return FALSE;
455 }
456
457 static gboolean
458 sharkd_follower_visit_cb(const void *key _U_, void *value, void *user_data)
459 {
460         register_follow_t *follower = (register_follow_t *) value;
461         int *pi = (int *) user_data;
462
463         const int proto_id = get_follow_proto_id(follower);
464         const char *label  = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
465         const char *filter = label; /* correct: get_follow_by_name() is registered by short name */
466
467         sharkd_json_object_open(*pi != 0);
468                 sharkd_json_value_stringf(FALSE, "name", "Follow/%s", label);
469                 sharkd_json_value_stringf(TRUE, "tap", "follow:%s", filter);
470         sharkd_json_object_close();
471
472         *pi = *pi + 1;
473         return FALSE;
474 }
475
476 /**
477  * sharkd_session_process_info()
478  *
479  * Process info request
480  *
481  * Output object with attributes:
482  *   (m) columns - available column formats, array of object with attributes:
483  *                  'name'   - column name
484  *                  'format' - column format-name
485  *
486  *   (m) stats   - available statistics, array of object with attributes:
487  *                  'name' - statistic name
488  *                  'tap'  - sharkd tap-name for statistic
489  *
490  *   (m) convs   - available conversation list, array of object with attributes:
491  *                  'name' - conversation name
492  *                  'tap'  - sharkd tap-name for conversation
493  *
494  *   (m) eo      - available export object list, array of object with attributes:
495  *                  'name' - export object name
496  *                  'tap'  - sharkd tap-name for eo
497  *
498  *   (m) srt     - available service response time list, array of object with attributes:
499  *                  'name' - service response time name
500  *                  'tap'  - sharkd tap-name for srt
501  *
502  *   (m) rtd     - available response time delay list, array of object with attributes:
503  *                  'name' - response time delay name
504  *                  'tap'  - sharkd tap-name for rtd
505  *
506  *   (m) seqa    - available sequence analysis (flow) list, array of object with attributes:
507  *                  'name' - sequence analysis name
508  *                  'tap'  - sharkd tap-name
509  *
510  *   (m) taps - available taps, array of object with attributes:
511  *                  'name' - tap name
512  *                  'tap'  - sharkd tap-name
513  *
514  *   (m) follow - available followers, array of object with attributes:
515  *                  'name' - tap name
516  *                  'tap'  - sharkd tap-name
517  *
518  *   (m) ftypes   - conversation table for FT_ number to string
519  */
520 static void
521 sharkd_session_process_info(void)
522 {
523         int i;
524
525         sharkd_json_object_open(FALSE);
526
527         sharkd_json_array_open(FALSE, "columns");
528         for (i = 0; i < NUM_COL_FMTS; i++)
529         {
530                 const char *col_format = col_format_to_string(i);
531                 const char *col_descr  = col_format_desc(i);
532
533                 sharkd_json_object_open(i != 0);
534                         sharkd_json_value_string(FALSE, "name", col_descr);
535                         sharkd_json_value_string(TRUE, "format", col_format);
536                 sharkd_json_object_close();
537         }
538         sharkd_json_array_close();
539
540         sharkd_json_array_open(TRUE, "stats");
541         {
542                 GList *cfg_list = stats_tree_get_cfg_list();
543                 GList *l;
544                 gboolean sepa = FALSE;
545
546                 for (l = cfg_list; l; l = l->next)
547                 {
548                         stats_tree_cfg *cfg = (stats_tree_cfg *) l->data;
549
550                         sharkd_json_object_open(sepa);
551                                 sharkd_json_value_string(FALSE, "name", cfg->name);
552                                 sharkd_json_value_stringf(TRUE, "tap", "stat:%s", cfg->abbr);
553                         sharkd_json_object_close();
554                         sepa = TRUE;
555                 }
556
557                 g_list_free(cfg_list);
558         }
559         sharkd_json_array_close();
560
561         sharkd_json_array_open(TRUE, "ftypes");
562         for (i = 0; i < FT_NUM_TYPES; i++)
563                 sharkd_json_value_string(i != 0, NULL, ftype_name((ftenum_t) i));
564         sharkd_json_array_close();
565
566         sharkd_json_value_string(TRUE, "version", sharkd_version());
567
568         sharkd_json_array_open(TRUE, "nstat");
569         i = 0;
570         stat_tap_iterate_tables(sharkd_session_process_info_nstat_cb, &i);
571         sharkd_json_array_close();
572
573         sharkd_json_array_open(TRUE, "convs");
574         i = 0;
575         conversation_table_iterate_tables(sharkd_session_process_info_conv_cb, &i);
576         sharkd_json_array_close();
577
578         sharkd_json_array_open(TRUE, "seqa");
579         i = 0;
580         sequence_analysis_table_iterate_tables(sharkd_session_seq_analysis_cb, &i);
581         sharkd_json_array_close();
582
583         sharkd_json_array_open(TRUE, "taps");
584         {
585                 sharkd_json_object_open(FALSE);
586                 sharkd_json_value_string(FALSE, "name", "RTP streams");
587                 sharkd_json_value_string(TRUE, "tap", "rtp-streams");
588                 sharkd_json_object_close();
589
590                 sharkd_json_object_open(TRUE);
591                 sharkd_json_value_string(FALSE, "name", "Expert Information");
592                 sharkd_json_value_string(TRUE, "tap", "expert");
593                 sharkd_json_object_close();
594         }
595         sharkd_json_array_close();
596
597         sharkd_json_array_open(TRUE, "eo");
598         i = 0;
599         eo_iterate_tables(sharkd_export_object_visit_cb, &i);
600         sharkd_json_array_close();
601
602         sharkd_json_array_open(TRUE, "srt");
603         i = 0;
604         srt_table_iterate_tables(sharkd_srt_visit_cb, &i);
605         sharkd_json_array_close();
606
607         sharkd_json_array_open(TRUE, "rtd");
608         i = 0;
609         rtd_table_iterate_tables(sharkd_rtd_visit_cb, &i);
610         sharkd_json_array_close();
611
612         sharkd_json_array_open(TRUE, "follow");
613         i = 0;
614         follow_iterate_followers(sharkd_follower_visit_cb, &i);
615         sharkd_json_array_close();
616
617         sharkd_json_object_close();
618         sharkd_json_finish();
619 }
620
621 /**
622  * sharkd_session_process_load()
623  *
624  * Process load request
625  *
626  * Input:
627  *   (m) file - file to be loaded
628  *
629  * Output object with attributes:
630  *   (m) err - error code
631  */
632 static void
633 sharkd_session_process_load(const char *buf, const jsmntok_t *tokens, int count)
634 {
635         const char *tok_file = json_find_attr(buf, tokens, count, "file");
636         int err = 0;
637
638         fprintf(stderr, "load: filename=%s\n", tok_file);
639
640         if (!tok_file)
641                 return;
642
643         if (sharkd_cf_open(tok_file, WTAP_TYPE_AUTO, FALSE, &err) != CF_OK)
644         {
645                 sharkd_json_simple_reply(err, NULL);
646                 return;
647         }
648
649         TRY
650         {
651                 err = sharkd_load_cap_file();
652         }
653         CATCH(OutOfMemoryError)
654         {
655                 fprintf(stderr, "load: OutOfMemoryError\n");
656                 err = ENOMEM;
657         }
658         ENDTRY;
659
660         sharkd_json_simple_reply(err, NULL);
661 }
662
663 /**
664  * sharkd_session_process_status()
665  *
666  * Process status request
667  *
668  * Output object with attributes:
669  *   (m) frames   - count of currently loaded frames
670  *   (m) duration - time difference between time of first frame, and last loaded frame
671  *   (o) filename - capture filename
672  *   (o) filesize - capture filesize
673  */
674 static void
675 sharkd_session_process_status(void)
676 {
677         sharkd_json_object_open(FALSE);
678
679         sharkd_json_value_anyf(FALSE, "frames", "%u", cfile.count);
680         sharkd_json_value_anyf(TRUE, "duration", "%.9f", nstime_to_sec(&cfile.elapsed_time));
681
682         if (cfile.filename)
683         {
684                 char *name = g_path_get_basename(cfile.filename);
685
686                 sharkd_json_value_string(TRUE, "filename", name);
687                 g_free(name);
688         }
689
690         if (cfile.provider.wth)
691         {
692                 gint64 file_size = wtap_file_size(cfile.provider.wth, NULL);
693
694                 if (file_size > 0)
695                         sharkd_json_value_anyf(TRUE, "filesize", "%" G_GINT64_FORMAT, file_size);
696         }
697
698         sharkd_json_object_close();
699         sharkd_json_finish();
700 }
701
702 struct sharkd_analyse_data
703 {
704         GHashTable *protocols_set;
705         nstime_t *first_time;
706         nstime_t *last_time;
707 };
708
709 static void
710 sharkd_session_process_analyse_cb(epan_dissect_t *edt, proto_tree *tree, struct epan_column_info *cinfo, const GSList *data_src, void *data)
711 {
712         struct sharkd_analyse_data *analyser = (struct sharkd_analyse_data *) data;
713         packet_info *pi = &edt->pi;
714         frame_data *fdata = pi->fd;
715
716         (void) tree;
717         (void) cinfo;
718         (void) data_src;
719
720         if (analyser->first_time == NULL || nstime_cmp(&fdata->abs_ts, analyser->first_time) < 0)
721                 analyser->first_time = &fdata->abs_ts;
722
723         if (analyser->last_time == NULL || nstime_cmp(&fdata->abs_ts, analyser->last_time) > 0)
724                 analyser->last_time = &fdata->abs_ts;
725
726         if (pi->layers)
727         {
728                 wmem_list_frame_t *frame;
729
730                 for (frame = wmem_list_head(pi->layers); frame; frame = wmem_list_frame_next(frame))
731                 {
732                         int proto_id = GPOINTER_TO_UINT(wmem_list_frame_data(frame));
733
734                         if (!g_hash_table_lookup_extended(analyser->protocols_set, GUINT_TO_POINTER(proto_id), NULL, NULL))
735                         {
736                                 guint proto_count = g_hash_table_size(analyser->protocols_set);
737
738                                 g_hash_table_insert(analyser->protocols_set, GUINT_TO_POINTER(proto_id), GUINT_TO_POINTER(proto_id));
739
740                                 sharkd_json_value_string(proto_count != 0, NULL, proto_get_protocol_filter_name(proto_id));
741                         }
742                 }
743         }
744
745 }
746
747 /**
748  * sharkd_session_process_status()
749  *
750  * Process analyse request
751  *
752  * Output object with attributes:
753  *   (m) frames  - count of currently loaded frames
754  *   (m) protocols - protocol list
755  *   (m) first     - earliest frame time
756  *   (m) last      - latest frame time
757  */
758 static void
759 sharkd_session_process_analyse(void)
760 {
761         unsigned int framenum;
762         struct sharkd_analyse_data analyser;
763
764         analyser.first_time = NULL;
765         analyser.last_time  = NULL;
766         analyser.protocols_set = g_hash_table_new(NULL /* g_direct_hash() */, NULL /* g_direct_equal */);
767
768         sharkd_json_object_open(FALSE);
769
770         sharkd_json_value_anyf(FALSE, "frames", "%u", cfile.count);
771
772         sharkd_json_array_open(TRUE, "protocols");
773         for (framenum = 1; framenum <= cfile.count; framenum++)
774                 sharkd_dissect_request(framenum, (framenum != 1) ? 1 : 0, framenum - 1, &sharkd_session_process_analyse_cb, SHARKD_DISSECT_FLAG_NULL, &analyser);
775         sharkd_json_array_close();
776
777         if (analyser.first_time)
778                 sharkd_json_value_anyf(TRUE, "first", "%.9f", nstime_to_sec(analyser.first_time));
779
780         if (analyser.last_time)
781                 sharkd_json_value_anyf(TRUE, "last", "%.9f", nstime_to_sec(analyser.last_time));
782
783         sharkd_json_object_close();
784         sharkd_json_finish();
785
786         g_hash_table_destroy(analyser.protocols_set);
787 }
788
789 static column_info *
790 sharkd_session_create_columns(column_info *cinfo, const char *buf, const jsmntok_t *tokens, int count)
791 {
792         const char *columns_custom[32];
793         guint16 columns_fmt[32];
794         gint16 columns_occur[32];
795
796         int i, cols;
797
798         for (i = 0; i < 32; i++)
799         {
800                 const char *tok_column;
801                 char tok_column_name[64];
802                 char *custom_sepa;
803
804                 ws_snprintf(tok_column_name, sizeof(tok_column_name), "column%d", i);
805                 tok_column = json_find_attr(buf, tokens, count, tok_column_name);
806                 if (tok_column == NULL)
807                         break;
808
809                 columns_custom[i] = NULL;
810                 columns_occur[i] = 0;
811
812                 if ((custom_sepa = strchr(tok_column, ':')))
813                 {
814                         *custom_sepa = '\0'; /* XXX, C abuse: discarding-const */
815
816                         columns_fmt[i] = COL_CUSTOM;
817                         columns_custom[i] = tok_column;
818
819                         if (!ws_strtoi16(custom_sepa + 1, NULL, &columns_occur[i]))
820                                 return NULL;
821                 }
822                 else
823                 {
824                         if (!ws_strtou16(tok_column, NULL, &columns_fmt[i]))
825                                 return NULL;
826
827                         if (columns_fmt[i] >= NUM_COL_FMTS)
828                                 return NULL;
829
830                         /* if custom, that it shouldn't be just custom number -> error */
831                         if (columns_fmt[i] == COL_CUSTOM)
832                                 return NULL;
833                 }
834         }
835
836         cols = i;
837
838         col_setup(cinfo, cols);
839
840         for (i = 0; i < cols; i++)
841         {
842                 col_item_t *col_item = &cinfo->columns[i];
843
844                 col_item->col_fmt = columns_fmt[i];
845                 col_item->col_title = NULL; /* no need for title */
846
847                 if (col_item->col_fmt == COL_CUSTOM)
848                 {
849                         col_item->col_custom_fields = g_strdup(columns_custom[i]);
850                         col_item->col_custom_occurrence = columns_occur[i];
851                 }
852
853                 col_item->col_fence = 0;
854         }
855
856         col_finalize(cinfo);
857
858         return cinfo;
859 }
860
861 /**
862  * sharkd_session_process_frames()
863  *
864  * Process frames request
865  *
866  * Input:
867  *   (o) column0...columnXX - requested columns either number in range [0..NUM_COL_FMTS), or custom (syntax <dfilter>:<occurence>).
868  *                            If column0 is not specified default column set will be used.
869  *   (o) filter - filter to be used
870  *   (o) skip=N   - skip N frames
871  *   (o) limit=N  - show only N frames
872  *   (o) refs  - list (comma separated) with sorted time reference frame numbers.
873  *
874  * Output array of frames with attributes:
875  *   (m) c   - array of column data
876  *   (m) num - frame number
877  *   (o) i   - if frame is ignored
878  *   (o) m   - if frame is marked
879  *   (o) ct  - if frame is commented
880  *   (o) bg  - color filter - background color in hex
881  *   (o) fg  - color filter - foreground color in hex
882  */
883 static void
884 sharkd_session_process_frames(const char *buf, const jsmntok_t *tokens, int count)
885 {
886         const char *tok_filter = json_find_attr(buf, tokens, count, "filter");
887         const char *tok_column = json_find_attr(buf, tokens, count, "column0");
888         const char *tok_skip   = json_find_attr(buf, tokens, count, "skip");
889         const char *tok_limit  = json_find_attr(buf, tokens, count, "limit");
890         const char *tok_refs   = json_find_attr(buf, tokens, count, "refs");
891
892         const guint8 *filter_data = NULL;
893
894         gboolean frame_sepa = FALSE;
895         int col;
896
897         guint32 framenum, prev_dis_num = 0;
898         guint32 current_ref_frame = 0, next_ref_frame = G_MAXUINT32;
899         guint32 skip;
900         guint32 limit;
901
902         column_info *cinfo = &cfile.cinfo;
903         column_info user_cinfo;
904
905         if (tok_column)
906         {
907                 memset(&user_cinfo, 0, sizeof(user_cinfo));
908                 cinfo = sharkd_session_create_columns(&user_cinfo, buf, tokens, count);
909                 if (!cinfo)
910                         return;
911         }
912
913         if (tok_filter)
914         {
915                 const struct sharkd_filter_item *filter_item;
916
917                 filter_item = sharkd_session_filter_data(tok_filter);
918                 if (!filter_item)
919                         return;
920                 filter_data = filter_item->filtered;
921         }
922
923         skip = 0;
924         if (tok_skip)
925         {
926                 if (!ws_strtou32(tok_skip, NULL, &skip))
927                         return;
928         }
929
930         limit = 0;
931         if (tok_limit)
932         {
933                 if (!ws_strtou32(tok_limit, NULL, &limit))
934                         return;
935         }
936
937         if (tok_refs)
938         {
939                 if (!ws_strtou32(tok_refs, &tok_refs, &next_ref_frame))
940                         return;
941         }
942
943         sharkd_json_array_open(FALSE, NULL);
944         for (framenum = 1; framenum <= cfile.count; framenum++)
945         {
946                 frame_data *fdata;
947                 guint32 ref_frame = (framenum != 1) ? 1 : 0;
948
949                 if (filter_data && !(filter_data[framenum / 8] & (1 << (framenum % 8))))
950                         continue;
951
952                 if (skip)
953                 {
954                         skip--;
955                         prev_dis_num = framenum;
956                         continue;
957                 }
958
959                 if (tok_refs)
960                 {
961                         if (framenum >= next_ref_frame)
962                         {
963                                 current_ref_frame = next_ref_frame;
964
965                                 if (*tok_refs != ',')
966                                         next_ref_frame = G_MAXUINT32;
967
968                                 while (*tok_refs == ',' && framenum >= next_ref_frame)
969                                 {
970                                         current_ref_frame = next_ref_frame;
971
972                                         if (!ws_strtou32(tok_refs + 1, &tok_refs, &next_ref_frame))
973                                         {
974                                                 fprintf(stderr, "sharkd_session_process_frames() wrong format for refs: %s\n", tok_refs);
975                                                 break;
976                                         }
977                                 }
978
979                                 if (*tok_refs == '\0' && framenum >= next_ref_frame)
980                                 {
981                                         current_ref_frame = next_ref_frame;
982                                         next_ref_frame = G_MAXUINT32;
983                                 }
984                         }
985
986                         if (current_ref_frame)
987                                 ref_frame = current_ref_frame;
988                 }
989
990                 fdata = sharkd_get_frame(framenum);
991                 sharkd_dissect_columns(fdata, ref_frame, prev_dis_num, cinfo, (fdata->color_filter == NULL));
992
993                 sharkd_json_object_open(frame_sepa);
994
995                 sharkd_json_array_open(FALSE, "c");
996                 for (col = 0; col < cinfo->num_cols; ++col)
997                 {
998                         const col_item_t *col_item = &cinfo->columns[col];
999
1000                         sharkd_json_value_string(col != 0, NULL, col_item->col_data);
1001                 }
1002                 sharkd_json_array_close();
1003
1004                 sharkd_json_value_anyf(TRUE, "num", "%u", framenum);
1005
1006                 if (fdata->flags.has_user_comment || fdata->flags.has_phdr_comment)
1007                 {
1008                         if (!fdata->flags.has_user_comment || sharkd_get_user_comment(fdata) != NULL)
1009                                 sharkd_json_value_anyf(TRUE, "ct", "true");
1010                 }
1011
1012                 if (fdata->flags.ignored)
1013                         sharkd_json_value_anyf(TRUE, "i", "true");
1014
1015                 if (fdata->flags.marked)
1016                         sharkd_json_value_anyf(TRUE, "m", "true");
1017
1018                 if (fdata->color_filter)
1019                 {
1020                         sharkd_json_value_stringf(TRUE, "bg", "%x", color_t_to_rgb(&fdata->color_filter->bg_color));
1021                         sharkd_json_value_stringf(TRUE, "fg", "%x", color_t_to_rgb(&fdata->color_filter->fg_color));
1022                 }
1023
1024                 sharkd_json_object_close();
1025                 frame_sepa = TRUE;
1026                 prev_dis_num = framenum;
1027
1028                 if (limit && --limit == 0)
1029                         break;
1030         }
1031         sharkd_json_array_close();
1032         sharkd_json_finish();
1033
1034         if (cinfo != &cfile.cinfo)
1035                 col_cleanup(cinfo);
1036 }
1037
1038 static void
1039 sharkd_session_process_tap_stats_node_cb(const stat_node *n)
1040 {
1041         stat_node *node;
1042         gboolean sepa = FALSE;
1043
1044         sharkd_json_array_open(FALSE, NULL);
1045         for (node = n->children; node; node = node->next)
1046         {
1047                 sharkd_json_object_open(sepa);
1048
1049                 /* code based on stats_tree_get_values_from_node() */
1050                 sharkd_json_value_string(FALSE, "name", node->name);
1051                 sharkd_json_value_anyf(TRUE, "count", "%d", node->counter);
1052                 if (node->counter && ((node->st_flags & ST_FLG_AVERAGE) || node->rng))
1053                 {
1054                         sharkd_json_value_anyf(TRUE, "avg", "%.2f", ((float)node->total) / node->counter);
1055                         sharkd_json_value_anyf(TRUE, "min", "%d", node->minvalue);
1056                         sharkd_json_value_anyf(TRUE, "max", "%d", node->maxvalue);
1057                 }
1058
1059                 if (node->st->elapsed)
1060                         sharkd_json_value_anyf(TRUE, "rate", "%.4f", ((float)node->counter) / node->st->elapsed);
1061
1062                 if (node->parent && node->parent->counter)
1063                         sharkd_json_value_anyf(TRUE, "perc", "%.2f", (node->counter * 100.0) / node->parent->counter);
1064                 else if (node->parent == &(node->st->root))
1065                         sharkd_json_value_anyf(TRUE, "perc", "100");
1066
1067                 if (prefs.st_enable_burstinfo && node->max_burst)
1068                 {
1069                         if (prefs.st_burst_showcount)
1070                                 sharkd_json_value_anyf(TRUE, "burstcount", "%d", node->max_burst);
1071                         else
1072                                 sharkd_json_value_anyf(TRUE, "burstrate", "%.4f", ((double)node->max_burst) / prefs.st_burst_windowlen);
1073
1074                         sharkd_json_value_anyf(TRUE, "bursttime", "%.3f", ((double)node->burst_time / 1000.0));
1075                 }
1076
1077                 if (node->children)
1078                 {
1079                         sharkd_json_value_anyf(TRUE, "sub", NULL);
1080                         sharkd_session_process_tap_stats_node_cb(node);
1081                 }
1082                 sharkd_json_object_close();
1083                 sepa = TRUE;
1084         }
1085         sharkd_json_array_close();
1086 }
1087
1088 /**
1089  * sharkd_session_process_tap_stats_cb()
1090  *
1091  * Output stats tap:
1092  *
1093  *   (m) tap        - tap name
1094  *   (m) type:stats - tap output type
1095  *   (m) name       - stat name
1096  *   (m) stats      - array of object with attributes:
1097  *                  (m) name       - stat item name
1098  *                  (m) count      - stat item counter
1099  *                  (o) avg        - stat item averange value
1100  *                  (o) min        - stat item min value
1101  *                  (o) max        - stat item max value
1102  *                  (o) rate       - stat item rate value (ms)
1103  *                  (o) perc       - stat item percentage
1104  *                  (o) burstrate  - stat item burst rate
1105  *                  (o) burstcount - stat item burst count
1106  *                  (o) burstttme  - stat item burst start
1107  *                  (o) sub        - array of object with attributes like in stats node.
1108  */
1109 static void
1110 sharkd_session_process_tap_stats_cb(void *psp)
1111 {
1112         stats_tree *st = (stats_tree *) psp;
1113
1114         sharkd_json_object_open(FALSE);
1115
1116         sharkd_json_value_stringf(FALSE, "tap", "stats:%s", st->cfg->abbr);
1117         sharkd_json_value_string(TRUE, "type", "stats");
1118         sharkd_json_value_string(TRUE, "name", st->cfg->name);
1119
1120         sharkd_json_value_anyf(TRUE, "stats", NULL);
1121         sharkd_session_process_tap_stats_node_cb(&st->root);
1122
1123         sharkd_json_object_close();
1124         putchar(',');
1125 }
1126
1127 static void
1128 sharkd_session_free_tap_stats_cb(void *psp)
1129 {
1130         stats_tree *st = (stats_tree *) psp;
1131
1132         stats_tree_free(st);
1133 }
1134
1135 struct sharkd_expert_tap
1136 {
1137         GSList *details;
1138         GStringChunk *text;
1139 };
1140
1141 /**
1142  * sharkd_session_process_tap_expert_cb()
1143  *
1144  * Output expert tap:
1145  *
1146  *   (m) tap         - tap name
1147  *   (m) type:expert - tap output type
1148  *   (m) details     - array of object with attributes:
1149  *                  (m) f - frame number, which generated expert information
1150  *                  (o) s - severity
1151  *                  (o) g - group
1152  *                  (m) m - expert message
1153  *                  (o) p - protocol
1154  */
1155 static void
1156 sharkd_session_process_tap_expert_cb(void *tapdata)
1157 {
1158         struct sharkd_expert_tap *etd = (struct sharkd_expert_tap *) tapdata;
1159         GSList *list;
1160         gboolean sepa = FALSE;
1161
1162         sharkd_json_object_open(FALSE);
1163
1164         sharkd_json_value_string(FALSE, "tap", "expert");
1165         sharkd_json_value_string(TRUE, "type", "expert");
1166
1167         sharkd_json_array_open(TRUE, "details");
1168         for (list = etd->details; list; list = list->next)
1169         {
1170                 expert_info_t *ei = (expert_info_t *) list->data;
1171                 const char *tmp;
1172
1173                 sharkd_json_object_open(sepa);
1174
1175                 sharkd_json_value_anyf(FALSE, "f", "%u", ei->packet_num);
1176
1177                 tmp = try_val_to_str(ei->severity, expert_severity_vals);
1178                 if (tmp)
1179                         sharkd_json_value_string(TRUE, "s", tmp);
1180
1181                 tmp = try_val_to_str(ei->group, expert_group_vals);
1182                 if (tmp)
1183                         sharkd_json_value_string(TRUE, "g", tmp);
1184
1185                 sharkd_json_value_string(TRUE, "m", ei->summary);
1186
1187                 if (ei->protocol)
1188                         sharkd_json_value_string(TRUE, "p", ei->protocol);
1189
1190                 sharkd_json_object_close();
1191                 sepa = TRUE;
1192         }
1193         sharkd_json_array_close();
1194
1195         sharkd_json_object_close();
1196         putchar(',');
1197 }
1198
1199 static gboolean
1200 sharkd_session_packet_tap_expert_cb(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *pointer)
1201 {
1202         struct sharkd_expert_tap *etd = (struct sharkd_expert_tap *) tapdata;
1203         const expert_info_t *ei       = (const expert_info_t *) pointer;
1204         expert_info_t *ei_copy;
1205
1206         if (ei == NULL)
1207                 return FALSE;
1208
1209         ei_copy = g_new(expert_info_t, 1);
1210         /* Note: this is a shallow copy */
1211         *ei_copy = *ei;
1212
1213         /* ei->protocol, ei->summary might be allocated in packet scope, make a copy. */
1214         ei_copy->protocol = g_string_chunk_insert_const(etd->text, ei_copy->protocol);
1215         ei_copy->summary  = g_string_chunk_insert_const(etd->text, ei_copy->summary);
1216
1217         etd->details = g_slist_prepend(etd->details, ei_copy);
1218
1219         return TRUE;
1220 }
1221
1222 static void
1223 sharkd_session_free_tap_expert_cb(void *tapdata)
1224 {
1225         struct sharkd_expert_tap *etd = (struct sharkd_expert_tap *) tapdata;
1226
1227         g_slist_free_full(etd->details, g_free);
1228         g_string_chunk_free(etd->text);
1229         g_free(etd);
1230 }
1231
1232 /**
1233  * sharkd_session_process_tap_flow_cb()
1234  *
1235  * Output flow tap:
1236  *   (m) tap         - tap name
1237  *   (m) type:flow   - tap output type
1238  *   (m) nodes       - array of strings with node address
1239  *   (m) flows       - array of object with attributes:
1240  *                  (m) t  - frame time string
1241  *                  (m) n  - array of two numbers with source node index and destination node index
1242  *                  (m) pn - array of two numbers with source and destination port
1243  *                  (o) c  - comment
1244  */
1245 static void
1246 sharkd_session_process_tap_flow_cb(void *tapdata)
1247 {
1248         seq_analysis_info_t *graph_analysis = (seq_analysis_info_t *) tapdata;
1249         GList *flow_list;
1250         guint i;
1251
1252         gboolean sepa = FALSE;
1253
1254         sequence_analysis_get_nodes(graph_analysis);
1255
1256         sharkd_json_object_open(FALSE);
1257         sharkd_json_value_stringf(FALSE, "tap", "seqa:%s", graph_analysis->name);
1258         sharkd_json_value_string(TRUE, "type", "flow");
1259
1260         sharkd_json_array_open(TRUE, "nodes");
1261         for (i = 0; i < graph_analysis->num_nodes; i++)
1262         {
1263                 char *addr_str;
1264
1265                 addr_str = address_to_display(NULL, &(graph_analysis->nodes[i]));
1266                 sharkd_json_value_string(i != 0, NULL, addr_str);
1267                 wmem_free(NULL, addr_str);
1268         }
1269         sharkd_json_array_close();
1270
1271         sharkd_json_array_open(TRUE, "flows");
1272         flow_list = g_queue_peek_nth_link(graph_analysis->items, 0);
1273         while (flow_list)
1274         {
1275                 seq_analysis_item_t *sai = (seq_analysis_item_t *) flow_list->data;
1276
1277                 flow_list = g_list_next(flow_list);
1278
1279                 if (!sai->display)
1280                         continue;
1281
1282                 sharkd_json_object_open(sepa);
1283
1284                 sharkd_json_value_string(FALSE, "t", sai->time_str);
1285                 sharkd_json_value_anyf(TRUE, "n", "[%u,%u]", sai->src_node, sai->dst_node);
1286                 sharkd_json_value_anyf(TRUE, "pn", "[%u,%u]", sai->port_src, sai->port_dst);
1287
1288                 if (sai->comment)
1289                         sharkd_json_value_string(TRUE, "c", sai->comment);
1290
1291                 sharkd_json_object_close();
1292                 sepa = TRUE;
1293         }
1294         sharkd_json_array_close();
1295
1296         sharkd_json_object_close();
1297         putchar(',');
1298 }
1299
1300 static void
1301 sharkd_session_free_tap_flow_cb(void *tapdata)
1302 {
1303         seq_analysis_info_t *graph_analysis = (seq_analysis_info_t *) tapdata;
1304
1305         sequence_analysis_info_free(graph_analysis);
1306 }
1307
1308 struct sharkd_conv_tap_data
1309 {
1310         const char *type;
1311         conv_hash_t hash;
1312         gboolean resolve_name;
1313         gboolean resolve_port;
1314 };
1315
1316 static gboolean
1317 sharkd_session_geoip_addr(address *addr, const char *suffix)
1318 {
1319         const mmdb_lookup_t *lookup = NULL;
1320         gboolean with_geoip = FALSE;
1321         char json_key[64];
1322
1323         if (addr->type == AT_IPv4)
1324         {
1325                 guint32 ip;
1326
1327                 memcpy(&ip, addr->data, 4);
1328                 lookup = maxmind_db_lookup_ipv4(ip);
1329         }
1330         else if (addr->type == AT_IPv6)
1331         {
1332                 const ws_in6_addr *ip6 = (const ws_in6_addr *) addr->data;
1333
1334                 lookup = maxmind_db_lookup_ipv6(ip6);
1335         }
1336
1337         if (!lookup || !lookup->found)
1338                 return FALSE;
1339
1340         if (lookup->country)
1341         {
1342                 snprintf(json_key, sizeof(json_key), "geoip_country%s", suffix);
1343                 sharkd_json_value_string(TRUE, json_key, lookup->country);
1344                 with_geoip = TRUE;
1345         }
1346
1347         if (lookup->country_iso)
1348         {
1349                 snprintf(json_key, sizeof(json_key), "geoip_country_iso%s", suffix);
1350                 sharkd_json_value_string(TRUE, json_key, lookup->country_iso);
1351                 with_geoip = TRUE;
1352         }
1353
1354         if (lookup->city)
1355         {
1356                 snprintf(json_key, sizeof(json_key), "geoip_city%s", suffix);
1357                 sharkd_json_value_string(TRUE, json_key, lookup->city);
1358                 with_geoip = TRUE;
1359         }
1360
1361         if (lookup->as_org)
1362         {
1363                 snprintf(json_key, sizeof(json_key), "geoip_as_org%s", suffix);
1364                 sharkd_json_value_string(TRUE, json_key, lookup->as_org);
1365                 with_geoip = TRUE;
1366         }
1367
1368         if (lookup->as_number > 0)
1369         {
1370                 snprintf(json_key, sizeof(json_key), "geoip_as%s", suffix);
1371                 sharkd_json_value_anyf(TRUE, json_key, "%u", lookup->as_number);
1372                 with_geoip = TRUE;
1373         }
1374
1375         if (lookup->latitude >= -90.0 && lookup->latitude <= 90.0)
1376         {
1377                 snprintf(json_key, sizeof(json_key), "geoip_lat%s", suffix);
1378                 sharkd_json_value_anyf(TRUE, json_key, "%f", lookup->latitude);
1379                 with_geoip = TRUE;
1380         }
1381
1382         if (lookup->longitude >= -180.0 && lookup->longitude <= 180.0)
1383         {
1384                 snprintf(json_key, sizeof(json_key), "geoip_lon%s", suffix);
1385                 sharkd_json_value_anyf(TRUE, json_key, "%f", lookup->longitude);
1386                 with_geoip = TRUE;
1387         }
1388
1389         return with_geoip;
1390 }
1391
1392 struct sharkd_analyse_rtp_items
1393 {
1394         guint32 frame_num;
1395         guint32 sequence_num;
1396
1397         double delta;
1398         double jitter;
1399         double skew;
1400         double bandwidth;
1401         gboolean marker;
1402
1403         double arrive_offset;
1404
1405         /* from tap_rtp_stat_t */
1406         guint32 flags;
1407         guint16 pt;
1408 };
1409
1410 struct sharkd_analyse_rtp
1411 {
1412         const char *tap_name;
1413         rtpstream_id_t id;
1414
1415         GSList *packets;
1416         double start_time;
1417         tap_rtp_stat_t statinfo;
1418 };
1419
1420 static void
1421 sharkd_session_process_tap_rtp_free_cb(void *tapdata)
1422 {
1423         struct sharkd_analyse_rtp *rtp_req = (struct sharkd_analyse_rtp *) tapdata;
1424
1425         g_slist_free_full(rtp_req->packets, g_free);
1426         g_free(rtp_req);
1427 }
1428
1429 static gboolean
1430 sharkd_session_packet_tap_rtp_analyse_cb(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_, const void *pointer)
1431 {
1432         struct sharkd_analyse_rtp *rtp_req = (struct sharkd_analyse_rtp *) tapdata;
1433         const struct _rtp_info *rtp_info = (const struct _rtp_info *) pointer;
1434
1435         if (rtpstream_id_equal_pinfo_rtp_info(&rtp_req->id, pinfo, rtp_info))
1436         {
1437                 tap_rtp_stat_t *statinfo = &(rtp_req->statinfo);
1438                 struct sharkd_analyse_rtp_items *item;
1439
1440                 rtppacket_analyse(statinfo, pinfo, rtp_info);
1441
1442                 item = (struct sharkd_analyse_rtp_items *) g_malloc(sizeof(struct sharkd_analyse_rtp_items));
1443
1444                 if (!rtp_req->packets)
1445                         rtp_req->start_time = nstime_to_sec(&pinfo->abs_ts);
1446
1447                 item->frame_num    = pinfo->num;
1448                 item->sequence_num = rtp_info->info_seq_num;
1449                 item->delta        = (statinfo->flags & STAT_FLAG_FIRST) ? 0.0 : statinfo->delta;
1450                 item->jitter       = (statinfo->flags & STAT_FLAG_FIRST) ? 0.0 : statinfo->jitter;
1451                 item->skew         = (statinfo->flags & STAT_FLAG_FIRST) ? 0.0 : statinfo->skew;
1452                 item->bandwidth    = statinfo->bandwidth;
1453                 item->marker       = rtp_info->info_marker_set ? TRUE : FALSE;
1454                 item->arrive_offset= nstime_to_sec(&pinfo->abs_ts) - rtp_req->start_time;
1455
1456                 item->flags = statinfo->flags;
1457                 item->pt    = statinfo->pt;
1458
1459                 /* XXX, O(n) optimize */
1460                 rtp_req->packets = g_slist_append(rtp_req->packets, item);
1461         }
1462
1463         return TRUE;
1464 }
1465
1466 /**
1467  * sharkd_session_process_tap_rtp_analyse_cb()
1468  *
1469  * Output rtp analyse tap:
1470  *   (m) tap   - tap name
1471  *   (m) type  - tap output type
1472  *   (m) ssrc         - RTP SSRC
1473  *   (m) max_delta    - Max delta (ms)
1474  *   (m) max_delta_nr - Max delta packet #
1475  *   (m) max_jitter   - Max jitter (ms)
1476  *   (m) mean_jitter  - Mean jitter (ms)
1477  *   (m) max_skew     - Max skew (ms)
1478  *   (m) total_nr     - Total number of RTP packets
1479  *   (m) seq_err      - Number of sequence errors
1480  *   (m) duration     - Duration (ms)
1481  *   (m) items      - array of object with attributes:
1482  *                  (m) f    - frame number
1483  *                  (m) o    - arrive offset
1484  *                  (m) sn   - sequence number
1485  *                  (m) d    - delta
1486  *                  (m) j    - jitter
1487  *                  (m) sk   - skew
1488  *                  (m) bw   - bandwidth
1489  *                  (o) s    - status string
1490  *                  (o) t    - status type
1491  *                  (o) mark - rtp mark
1492  */
1493 static void
1494 sharkd_session_process_tap_rtp_analyse_cb(void *tapdata)
1495 {
1496         const int RTP_TYPE_CN       = 1;
1497         const int RTP_TYPE_ERROR    = 2;
1498         const int RTP_TYPE_WARN     = 3;
1499         const int RTP_TYPE_PT_EVENT = 4;
1500
1501         const struct sharkd_analyse_rtp *rtp_req = (struct sharkd_analyse_rtp *) tapdata;
1502         const tap_rtp_stat_t *statinfo = &rtp_req->statinfo;
1503
1504         gboolean sepa = FALSE;
1505         GSList *l;
1506
1507         sharkd_json_object_open(FALSE);
1508
1509         sharkd_json_value_string(FALSE, "tap", rtp_req->tap_name);
1510         sharkd_json_value_string(TRUE, "type", "rtp-analyse");
1511         sharkd_json_value_anyf(TRUE, "ssrc", "%u", rtp_req->id.ssrc);
1512
1513         sharkd_json_value_anyf(TRUE, "max_delta", "%f", statinfo->max_delta);
1514         sharkd_json_value_anyf(TRUE, "max_delta_nr", "%u", statinfo->max_nr);
1515         sharkd_json_value_anyf(TRUE, "max_jitter", "%f", statinfo->max_jitter);
1516         sharkd_json_value_anyf(TRUE, "mean_jitter", "%f", statinfo->mean_jitter);
1517         sharkd_json_value_anyf(TRUE, "max_skew", "%f", statinfo->max_skew);
1518         sharkd_json_value_anyf(TRUE, "total_nr", "%u", statinfo->total_nr);
1519         sharkd_json_value_anyf(TRUE, "seq_err", "%u", statinfo->sequence);
1520         sharkd_json_value_anyf(TRUE, "duration", "%f", statinfo->time - statinfo->start_time);
1521
1522         sharkd_json_array_open(TRUE, "items");
1523         for (l = rtp_req->packets; l; l = l->next)
1524         {
1525                 struct sharkd_analyse_rtp_items *item = (struct sharkd_analyse_rtp_items *) l->data;
1526
1527                 sharkd_json_object_open(sepa);
1528
1529                 sharkd_json_value_anyf(FALSE, "f", "%u", item->frame_num);
1530                 sharkd_json_value_anyf(TRUE, "o", "%.9f", item->arrive_offset);
1531                 sharkd_json_value_anyf(TRUE, "sn", "%u", item->sequence_num);
1532                 sharkd_json_value_anyf(TRUE, "d", "%.2f", item->delta);
1533                 sharkd_json_value_anyf(TRUE, "j", "%.2f", item->jitter);
1534                 sharkd_json_value_anyf(TRUE, "sk", "%.2f", item->skew);
1535                 sharkd_json_value_anyf(TRUE, "bw", "%.2f", item->bandwidth);
1536
1537                 if (item->pt == PT_CN)
1538                 {
1539                         sharkd_json_value_string(TRUE, "s", "Comfort noise (PT=13, RFC 3389)");
1540                         sharkd_json_value_anyf(TRUE, "t", "%d", RTP_TYPE_CN);
1541                 }
1542                 else if (item->pt == PT_CN_OLD)
1543                 {
1544                         sharkd_json_value_string(TRUE, "s", "Comfort noise (PT=19, reserved)");
1545                         sharkd_json_value_anyf(TRUE, "t", "%d", RTP_TYPE_CN);
1546                 }
1547                 else if (item->flags & STAT_FLAG_WRONG_SEQ)
1548                 {
1549                         sharkd_json_value_string(TRUE, "s", "Wrong sequence number");
1550                         sharkd_json_value_anyf(TRUE, "t", "%d", RTP_TYPE_ERROR);
1551                 }
1552                 else if (item->flags & STAT_FLAG_DUP_PKT)
1553                 {
1554                         sharkd_json_value_string(TRUE, "s", "Suspected duplicate (MAC address) only delta time calculated");
1555                         sharkd_json_value_anyf(TRUE, "t", "%d", RTP_TYPE_WARN);
1556                 }
1557                 else if (item->flags & STAT_FLAG_REG_PT_CHANGE)
1558                 {
1559                         sharkd_json_value_stringf(TRUE, "s", "Payload changed to PT=%u%s",
1560                                 item->pt,
1561                                 (item->flags & STAT_FLAG_PT_T_EVENT) ? " telephone/event" : "");
1562                         sharkd_json_value_anyf(TRUE, "t", "%d", RTP_TYPE_WARN);
1563                 }
1564                 else if (item->flags & STAT_FLAG_WRONG_TIMESTAMP)
1565                 {
1566                         sharkd_json_value_string(TRUE, "s", "Incorrect timestamp");
1567                         sharkd_json_value_anyf(TRUE, "t", "%d", RTP_TYPE_WARN);
1568                 }
1569                 else if ((item->flags & STAT_FLAG_PT_CHANGE)
1570                         &&  !(item->flags & STAT_FLAG_FIRST)
1571                         &&  !(item->flags & STAT_FLAG_PT_CN)
1572                         &&  (item->flags & STAT_FLAG_FOLLOW_PT_CN)
1573                         &&  !(item->flags & STAT_FLAG_MARKER))
1574                 {
1575                         sharkd_json_value_string(TRUE, "s", "Marker missing?");
1576                         sharkd_json_value_anyf(TRUE, "t", "%d", RTP_TYPE_WARN);
1577                 }
1578                 else if (item->flags & STAT_FLAG_PT_T_EVENT)
1579                 {
1580                         sharkd_json_value_stringf(TRUE, "s", "PT=%u telephone/event", item->pt);
1581                         sharkd_json_value_anyf(TRUE, "t", "%d", RTP_TYPE_PT_EVENT);
1582                 }
1583                 else if (item->flags & STAT_FLAG_MARKER)
1584                 {
1585                         sharkd_json_value_anyf(TRUE, "t", "%d", RTP_TYPE_WARN);
1586                 }
1587
1588                 if (item->marker)
1589                         sharkd_json_value_anyf(TRUE, "mark", "1");
1590
1591                 sharkd_json_object_close();
1592                 sepa = TRUE;
1593         }
1594         sharkd_json_array_close();
1595
1596         sharkd_json_object_close();
1597         putchar(',');
1598 }
1599
1600 /**
1601  * sharkd_session_process_tap_conv_cb()
1602  *
1603  * Output conv tap:
1604  *   (m) tap        - tap name
1605  *   (m) type       - tap output type
1606  *   (m) proto      - protocol short name
1607  *   (o) filter     - filter string
1608  *
1609  *   (o) convs      - array of object with attributes:
1610  *                  (m) saddr - source address
1611  *                  (m) daddr - destination address
1612  *                  (o) sport - source port
1613  *                  (o) dport - destination port
1614  *                  (m) txf   - TX frame count
1615  *                  (m) txb   - TX bytes
1616  *                  (m) rxf   - RX frame count
1617  *                  (m) rxb   - RX bytes
1618  *                  (m) start - (relative) first packet time
1619  *                  (m) stop  - (relative) last packet time
1620  *
1621  *   (o) hosts      - array of object with attributes:
1622  *                  (m) host - host address
1623  *                  (o) port - host port
1624  *                  (m) txf  - TX frame count
1625  *                  (m) txb  - TX bytes
1626  *                  (m) rxf  - RX frame count
1627  *                  (m) rxb  - RX bytes
1628  */
1629 static void
1630 sharkd_session_process_tap_conv_cb(void *arg)
1631 {
1632         conv_hash_t *hash = (conv_hash_t *) arg;
1633         const struct sharkd_conv_tap_data *iu = (struct sharkd_conv_tap_data *) hash->user_data;
1634         const char *proto;
1635         int proto_with_port;
1636         guint i;
1637
1638         int with_geoip = 0;
1639
1640         sharkd_json_object_open(FALSE);
1641         sharkd_json_value_string(FALSE, "tap", iu->type);
1642
1643         if (!strncmp(iu->type, "conv:", 5))
1644         {
1645                 sharkd_json_value_string(TRUE, "type", "conv");
1646                 sharkd_json_array_open(TRUE, "convs");
1647                 proto = iu->type + 5;
1648         }
1649         else if (!strncmp(iu->type, "endpt:", 6))
1650         {
1651                 sharkd_json_value_string(TRUE, "type", "host");
1652                 sharkd_json_array_open(TRUE, "hosts");
1653                 proto = iu->type + 6;
1654         }
1655         else
1656         {
1657                 sharkd_json_value_string(TRUE, "type", "err");
1658                 proto = "";
1659         }
1660
1661         proto_with_port = (!strcmp(proto, "TCP") || !strcmp(proto, "UDP") || !strcmp(proto, "SCTP"));
1662
1663         if (iu->hash.conv_array != NULL && !strncmp(iu->type, "conv:", 5))
1664         {
1665                 for (i = 0; i < iu->hash.conv_array->len; i++)
1666                 {
1667                         conv_item_t *iui = &g_array_index(iu->hash.conv_array, conv_item_t, i);
1668                         char *src_addr, *dst_addr;
1669                         char *src_port, *dst_port;
1670                         char *filter_str;
1671
1672                         sharkd_json_object_open(i != 0);
1673
1674                         sharkd_json_value_string(FALSE, "saddr", (src_addr = get_conversation_address(NULL, &iui->src_address, iu->resolve_name)));
1675                         sharkd_json_value_string(TRUE,  "daddr", (dst_addr = get_conversation_address(NULL, &iui->dst_address, iu->resolve_name)));
1676
1677                         if (proto_with_port)
1678                         {
1679                                 sharkd_json_value_string(TRUE, "sport", (src_port = get_conversation_port(NULL, iui->src_port, iui->etype, iu->resolve_port)));
1680                                 sharkd_json_value_string(TRUE, "dport", (dst_port = get_conversation_port(NULL, iui->dst_port, iui->etype, iu->resolve_port)));
1681
1682                                 wmem_free(NULL, src_port);
1683                                 wmem_free(NULL, dst_port);
1684                         }
1685
1686                         sharkd_json_value_anyf(TRUE, "rxf", "%" G_GUINT64_FORMAT, iui->rx_frames);
1687                         sharkd_json_value_anyf(TRUE, "rxb", "%" G_GUINT64_FORMAT, iui->rx_bytes);
1688
1689                         sharkd_json_value_anyf(TRUE, "txf", "%" G_GUINT64_FORMAT, iui->tx_frames);
1690                         sharkd_json_value_anyf(TRUE, "txb", "%" G_GUINT64_FORMAT, iui->tx_bytes);
1691
1692                         sharkd_json_value_anyf(TRUE, "start", "%.9f", nstime_to_sec(&iui->start_time));
1693                         sharkd_json_value_anyf(TRUE, "stop", "%.9f", nstime_to_sec(&iui->stop_time));
1694
1695                         filter_str = get_conversation_filter(iui, CONV_DIR_A_TO_FROM_B);
1696                         if (filter_str)
1697                         {
1698                                 sharkd_json_value_string(TRUE, "filter", filter_str);
1699                                 g_free(filter_str);
1700                         }
1701
1702                         wmem_free(NULL, src_addr);
1703                         wmem_free(NULL, dst_addr);
1704
1705                         if (sharkd_session_geoip_addr(&(iui->src_address), "1"))
1706                                 with_geoip = 1;
1707                         if (sharkd_session_geoip_addr(&(iui->dst_address), "2"))
1708                                 with_geoip = 1;
1709
1710                         sharkd_json_object_close();
1711                 }
1712         }
1713         else if (iu->hash.conv_array != NULL && !strncmp(iu->type, "endpt:", 6))
1714         {
1715                 for (i = 0; i < iu->hash.conv_array->len; i++)
1716                 {
1717                         hostlist_talker_t *host = &g_array_index(iu->hash.conv_array, hostlist_talker_t, i);
1718                         char *host_str, *port_str;
1719                         char *filter_str;
1720
1721                         sharkd_json_object_open(i != 0);
1722
1723                         sharkd_json_value_string(FALSE, "host", (host_str = get_conversation_address(NULL, &host->myaddress, iu->resolve_name)));
1724
1725                         if (proto_with_port)
1726                         {
1727                                 sharkd_json_value_string(TRUE, "port", (port_str = get_conversation_port(NULL, host->port, host->etype, iu->resolve_port)));
1728
1729                                 wmem_free(NULL, port_str);
1730                         }
1731
1732                         sharkd_json_value_anyf(TRUE, "rxf", "%" G_GUINT64_FORMAT, host->rx_frames);
1733                         sharkd_json_value_anyf(TRUE, "rxb", "%" G_GUINT64_FORMAT, host->rx_bytes);
1734
1735                         sharkd_json_value_anyf(TRUE, "txf", "%" G_GUINT64_FORMAT, host->tx_frames);
1736                         sharkd_json_value_anyf(TRUE, "txb", "%" G_GUINT64_FORMAT, host->tx_bytes);
1737
1738                         filter_str = get_hostlist_filter(host);
1739                         if (filter_str)
1740                         {
1741                                 sharkd_json_value_string(TRUE, "filter", filter_str);
1742                                 g_free(filter_str);
1743                         }
1744
1745                         wmem_free(NULL, host_str);
1746
1747                         if (sharkd_session_geoip_addr(&(host->myaddress), ""))
1748                                 with_geoip = 1;
1749                         sharkd_json_object_close();
1750                 }
1751         }
1752         sharkd_json_array_close();
1753
1754         sharkd_json_value_string(TRUE, "proto", proto);
1755         sharkd_json_value_anyf(TRUE, "geoip", with_geoip ? "true" : "false");
1756
1757         sharkd_json_object_close();
1758         putchar(',');
1759 }
1760
1761 static void
1762 sharkd_session_free_tap_conv_cb(void *arg)
1763 {
1764         conv_hash_t *hash = (conv_hash_t *) arg;
1765         struct sharkd_conv_tap_data *iu = (struct sharkd_conv_tap_data *) hash->user_data;
1766
1767         if (!strncmp(iu->type, "conv:", 5))
1768         {
1769                 reset_conversation_table_data(hash);
1770         }
1771         else if (!strncmp(iu->type, "endpt:", 6))
1772         {
1773                 reset_hostlist_table_data(hash);
1774         }
1775
1776         g_free(iu);
1777 }
1778
1779 /**
1780  * sharkd_session_process_tap_nstat_cb()
1781  *
1782  * Output nstat tap:
1783  *   (m) tap        - tap name
1784  *   (m) type       - tap output type
1785  *   (m) fields: array of objects with attributes:
1786  *                  (m) c - name
1787  *
1788  *   (m) tables: array of object with attributes:
1789  *                  (m) t - table title
1790  *                  (m) i - array of items
1791  */
1792 static void
1793 sharkd_session_process_tap_nstat_cb(void *arg)
1794 {
1795         stat_data_t *stat_data = (stat_data_t *) arg;
1796         guint i, j, k;
1797
1798         sharkd_json_object_open(FALSE);
1799         sharkd_json_value_stringf(FALSE, "tap", "nstat:%s", stat_data->stat_tap_data->cli_string);
1800         sharkd_json_value_string(TRUE, "type", "nstat");
1801
1802         sharkd_json_array_open(TRUE, "fields");
1803         for (i = 0; i < stat_data->stat_tap_data->nfields; i++)
1804         {
1805                 stat_tap_table_item *field = &(stat_data->stat_tap_data->fields[i]);
1806
1807                 sharkd_json_object_open(i != 0);
1808                 sharkd_json_value_string(FALSE, "c", field->column_name);
1809                 sharkd_json_object_close();
1810         }
1811         sharkd_json_array_close();
1812
1813         sharkd_json_array_open(TRUE, "tables");
1814         for (i = 0; i < stat_data->stat_tap_data->tables->len; i++)
1815         {
1816                 stat_tap_table *table = g_array_index(stat_data->stat_tap_data->tables, stat_tap_table *, i);
1817                 gboolean sepa = FALSE;
1818
1819                 sharkd_json_object_open(i != 0);
1820
1821                 sharkd_json_value_string(FALSE, "t", table->title);
1822
1823                 sharkd_json_array_open(TRUE, "i");
1824                 for (j = 0; j < table->num_elements; j++)
1825                 {
1826                         stat_tap_table_item_type *field_data;
1827
1828                         field_data = stat_tap_get_field_data(table, j, 0);
1829                         if (field_data == NULL || field_data->type == TABLE_ITEM_NONE) /* Nothing for us here */
1830                                 continue;
1831
1832                         sharkd_json_array_open(sepa, NULL);
1833                         for (k = 0; k < table->num_fields; k++)
1834                         {
1835                                 field_data = stat_tap_get_field_data(table, j, k);
1836
1837                                 switch (field_data->type)
1838                                 {
1839                                         case TABLE_ITEM_UINT:
1840                                                 sharkd_json_value_anyf(k != 0, NULL, "%u", field_data->value.uint_value);
1841                                                 break;
1842
1843                                         case TABLE_ITEM_INT:
1844                                                 sharkd_json_value_anyf(k != 0, NULL, "%d", field_data->value.int_value);
1845                                                 break;
1846
1847                                         case TABLE_ITEM_STRING:
1848                                                 sharkd_json_value_string(k != 0, NULL, field_data->value.string_value);
1849                                                 break;
1850
1851                                         case TABLE_ITEM_FLOAT:
1852                                                 sharkd_json_value_anyf(k != 0, NULL, "%f", field_data->value.float_value);
1853                                                 break;
1854
1855                                         case TABLE_ITEM_ENUM:
1856                                                 sharkd_json_value_anyf(k != 0, NULL, "%d", field_data->value.enum_value);
1857                                                 break;
1858
1859                                         case TABLE_ITEM_NONE:
1860                                                 sharkd_json_value_anyf(k != 0, NULL, "null");
1861                                                 break;
1862                                 }
1863                         }
1864
1865                         sharkd_json_array_close();
1866                         sepa = TRUE;
1867                 }
1868                 sharkd_json_array_close();
1869                 sharkd_json_object_close();
1870         }
1871         sharkd_json_array_close();
1872
1873         sharkd_json_object_close();
1874         putchar(',');
1875 }
1876
1877 static void
1878 sharkd_session_free_tap_nstat_cb(void *arg)
1879 {
1880         stat_data_t *stat_data = (stat_data_t *) arg;
1881
1882         free_stat_tables(stat_data->stat_tap_data);
1883 }
1884
1885 /**
1886  * sharkd_session_process_tap_rtd_cb()
1887  *
1888  * Output rtd tap:
1889  *   (m) tap        - tap name
1890  *   (m) type       - tap output type
1891  *   (m) stats - statistics rows - array object with attributes:
1892  *                  (m) type - statistic name
1893  *                  (m) num - number of messages
1894  *                  (m) min - minimum SRT time
1895  *                  (m) max - maximum SRT time
1896  *                  (m) tot - total SRT time
1897  *                  (m) min_frame - minimal SRT
1898  *                  (m) max_frame - maximum SRT
1899  *                  (o) open_req - Open Requests
1900  *                  (o) disc_rsp - Discarded Responses
1901  *                  (o) req_dup  - Duplicated Requests
1902  *                  (o) rsp_dup  - Duplicated Responses
1903  *   (o) open_req   - Open Requests
1904  *   (o) disc_rsp   - Discarded Responses
1905  *   (o) req_dup    - Duplicated Requests
1906  *   (o) rsp_dup    - Duplicated Responses
1907  */
1908 static void
1909 sharkd_session_process_tap_rtd_cb(void *arg)
1910 {
1911         rtd_data_t *rtd_data = (rtd_data_t *) arg;
1912         register_rtd_t *rtd  = (register_rtd_t *) rtd_data->user_data;
1913
1914         guint i, j;
1915
1916         const char *filter = proto_get_protocol_filter_name(get_rtd_proto_id(rtd));
1917
1918         /* XXX, some dissectors are having single table and multiple timestats (mgcp, megaco),
1919          *      some multiple table and single timestat (radius, h225)
1920          *      and it seems that value_string is used one for timestamp-ID, other one for table-ID
1921          *      I wonder how it will gonna work with multiple timestats and multiple tables...
1922          * (for usage grep for: register_rtd_table)
1923          */
1924         const value_string *vs = get_rtd_value_string(rtd);
1925         gboolean sepa = FALSE;
1926
1927         sharkd_json_object_open(FALSE);
1928         sharkd_json_value_stringf(FALSE, "tap", "rtd:%s", filter);
1929         sharkd_json_value_string(TRUE, "type", "rtd");
1930
1931         if (rtd_data->stat_table.num_rtds == 1)
1932         {
1933                 const rtd_timestat *ms = &rtd_data->stat_table.time_stats[0];
1934
1935                 sharkd_json_value_anyf(TRUE, "open_req", "%u", ms->open_req_num);
1936                 sharkd_json_value_anyf(TRUE, "disc_rsp", "%u", ms->disc_rsp_num);
1937                 sharkd_json_value_anyf(TRUE, "req_dup", "%u", ms->req_dup_num);
1938                 sharkd_json_value_anyf(TRUE, "rsp_dup", "%u", ms->rsp_dup_num);
1939         }
1940
1941         sharkd_json_array_open(TRUE, "stats");
1942         for (i = 0; i < rtd_data->stat_table.num_rtds; i++)
1943         {
1944                 const rtd_timestat *ms = &rtd_data->stat_table.time_stats[i];
1945
1946                 for (j = 0; j < ms->num_timestat; j++)
1947                 {
1948                         const char *type_str;
1949
1950                         if (ms->rtd[j].num == 0)
1951                                 continue;
1952
1953                         sharkd_json_object_open(sepa);
1954
1955                         if (rtd_data->stat_table.num_rtds == 1)
1956                                 type_str = val_to_str_const(j, vs, "Other"); /* 1 table - description per row */
1957                         else
1958                                 type_str = val_to_str_const(i, vs, "Other"); /* multiple table - description per table */
1959                         sharkd_json_value_string(FALSE, "type", type_str);
1960
1961                         sharkd_json_value_anyf(TRUE, "num", "%u", ms->rtd[j].num);
1962                         sharkd_json_value_anyf(TRUE, "min", "%.9f", nstime_to_sec(&(ms->rtd[j].min)));
1963                         sharkd_json_value_anyf(TRUE, "max", "%.9f", nstime_to_sec(&(ms->rtd[j].max)));
1964                         sharkd_json_value_anyf(TRUE, "tot", "%.9f", nstime_to_sec(&(ms->rtd[j].tot)));
1965                         sharkd_json_value_anyf(TRUE, "min_frame", "%u", ms->rtd[j].min_num);
1966                         sharkd_json_value_anyf(TRUE, "max_frame", "%u", ms->rtd[j].max_num);
1967
1968                         if (rtd_data->stat_table.num_rtds != 1)
1969                         {
1970                                 /* like in tshark, display it on every row */
1971                                 sharkd_json_value_anyf(TRUE, "open_req", "%u", ms->open_req_num);
1972                                 sharkd_json_value_anyf(TRUE, "disc_rsp", "%u", ms->disc_rsp_num);
1973                                 sharkd_json_value_anyf(TRUE, "req_dup", "%u", ms->req_dup_num);
1974                                 sharkd_json_value_anyf(TRUE, "rsp_dup", "%u", ms->rsp_dup_num);
1975                         }
1976
1977                         sharkd_json_object_close();
1978                         sepa = TRUE;
1979                 }
1980         }
1981         sharkd_json_array_close();
1982
1983         sharkd_json_object_close();
1984         putchar(',');
1985 }
1986
1987 static void
1988 sharkd_session_free_tap_rtd_cb(void *arg)
1989 {
1990         rtd_data_t *rtd_data = (rtd_data_t *) arg;
1991
1992         free_rtd_table(&rtd_data->stat_table);
1993         g_free(rtd_data);
1994 }
1995
1996 /**
1997  * sharkd_session_process_tap_srt_cb()
1998  *
1999  * Output srt tap:
2000  *   (m) tap        - tap name
2001  *   (m) type       - tap output type
2002  *
2003  *   (m) tables - array of object with attributes:
2004  *                  (m) n - table name
2005  *                  (m) f - table filter
2006  *                  (o) c - table column name
2007  *                  (m) r - table rows - array object with attributes:
2008  *                            (m) n   - row name
2009  *                            (m) idx - procedure index
2010  *                            (m) num - number of events
2011  *                            (m) min - minimum SRT time
2012  *                            (m) max - maximum SRT time
2013  *                            (m) tot - total SRT time
2014  */
2015 static void
2016 sharkd_session_process_tap_srt_cb(void *arg)
2017 {
2018         srt_data_t *srt_data = (srt_data_t *) arg;
2019         register_srt_t *srt = (register_srt_t *) srt_data->user_data;
2020
2021         const char *filter = proto_get_protocol_filter_name(get_srt_proto_id(srt));
2022
2023         guint i;
2024
2025         sharkd_json_object_open(FALSE);
2026         sharkd_json_value_stringf(FALSE, "tap", "srt:%s", filter);
2027         sharkd_json_value_string(TRUE, "type", "srt");
2028
2029         sharkd_json_array_open(TRUE, "tables");
2030         for (i = 0; i < srt_data->srt_array->len; i++)
2031         {
2032                 /* SRT table */
2033                 srt_stat_table *rst = g_array_index(srt_data->srt_array, srt_stat_table *, i);
2034                 gboolean sepa = FALSE;
2035
2036                 int j;
2037
2038                 sharkd_json_object_open(i != 0);
2039
2040                 if (rst->name)
2041                         sharkd_json_value_string(FALSE, "n", rst->name);
2042                 else if (rst->short_name)
2043                         sharkd_json_value_string(FALSE, "n", rst->short_name);
2044                 else
2045                         sharkd_json_value_stringf(FALSE, "n", "table%u", i);
2046
2047                 if (rst->filter_string)
2048                         sharkd_json_value_string(TRUE, "f", rst->filter_string);
2049
2050                 if (rst->proc_column_name)
2051                         sharkd_json_value_string(TRUE, "c", rst->proc_column_name);
2052
2053                 sharkd_json_array_open(TRUE, "r");
2054                 for (j = 0; j < rst->num_procs; j++)
2055                 {
2056                         /* SRT row */
2057                         srt_procedure_t *proc = &rst->procedures[j];
2058
2059                         if (proc->stats.num == 0)
2060                                 continue;
2061
2062                         sharkd_json_object_open(sepa);
2063
2064                         sharkd_json_value_string(FALSE, "n", proc->procedure);
2065
2066                         if (rst->filter_string)
2067                                 sharkd_json_value_anyf(TRUE, "idx", "%d", proc->proc_index);
2068
2069                         sharkd_json_value_anyf(TRUE, "num", "%u", proc->stats.num);
2070
2071                         sharkd_json_value_anyf(TRUE, "min", "%.9f", nstime_to_sec(&proc->stats.min));
2072                         sharkd_json_value_anyf(TRUE, "max", "%.9f", nstime_to_sec(&proc->stats.max));
2073                         sharkd_json_value_anyf(TRUE, "tot", "%.9f", nstime_to_sec(&proc->stats.tot));
2074
2075                         sharkd_json_object_close();
2076                         sepa = TRUE;
2077                 }
2078                 sharkd_json_array_close();
2079
2080                 sharkd_json_object_close();
2081         }
2082         sharkd_json_array_close();
2083
2084         sharkd_json_object_close();
2085         putchar(',');
2086 }
2087
2088 static void
2089 sharkd_session_free_tap_srt_cb(void *arg)
2090 {
2091         srt_data_t *srt_data = (srt_data_t *) arg;
2092         register_srt_t *srt = (register_srt_t *) srt_data->user_data;
2093
2094         free_srt_table(srt, srt_data->srt_array);
2095         g_array_free(srt_data->srt_array, TRUE);
2096         g_free(srt_data);
2097 }
2098
2099 struct sharkd_export_object_list
2100 {
2101         struct sharkd_export_object_list *next;
2102
2103         char *type;
2104         const char *proto;
2105         GSList *entries;
2106 };
2107
2108 static struct sharkd_export_object_list *sharkd_eo_list;
2109
2110 /**
2111  * sharkd_session_process_tap_eo_cb()
2112  *
2113  * Output eo tap:
2114  *   (m) tap        - tap name
2115  *   (m) type       - tap output type
2116  *   (m) proto      - protocol short name
2117  *   (m) objects    - array of object with attributes:
2118  *                  (m) pkt - packet number
2119  *                  (o) hostname - hostname
2120  *                  (o) type - content type
2121  *                  (o) filename - filename
2122  *                  (m) len - object length
2123  */
2124 static void
2125 sharkd_session_process_tap_eo_cb(void *tapdata)
2126 {
2127         export_object_list_t *tap_object = (export_object_list_t *) tapdata;
2128         struct sharkd_export_object_list *object_list = (struct sharkd_export_object_list *) tap_object->gui_data;
2129         GSList *slist;
2130         int i = 0;
2131
2132         sharkd_json_object_open(FALSE);
2133         sharkd_json_value_string(FALSE, "tap", object_list->type);
2134         sharkd_json_value_string(TRUE, "type", "eo");
2135
2136         sharkd_json_value_string(TRUE, "proto", object_list->proto);
2137
2138         sharkd_json_array_open(TRUE, "objects");
2139         for (slist = object_list->entries; slist; slist = slist->next)
2140         {
2141                 const export_object_entry_t *eo_entry = (export_object_entry_t *) slist->data;
2142
2143                 sharkd_json_object_open(i != 0);
2144
2145                 sharkd_json_value_anyf(FALSE, "pkt", "%u", eo_entry->pkt_num);
2146
2147                 if (eo_entry->hostname)
2148                         sharkd_json_value_string(TRUE, "hostname", eo_entry->hostname);
2149
2150                 if (eo_entry->content_type)
2151                         sharkd_json_value_string(TRUE, "type", eo_entry->content_type);
2152
2153                 if (eo_entry->filename)
2154                         sharkd_json_value_string(TRUE, "filename", eo_entry->filename);
2155
2156                 sharkd_json_value_stringf(TRUE, "_download", "%s_%d", object_list->type, i);
2157
2158                 sharkd_json_value_anyf(TRUE, "len", "%" G_GINT64_FORMAT, eo_entry->payload_len);
2159
2160                 sharkd_json_object_close();
2161
2162                 i++;
2163         }
2164         sharkd_json_array_close();
2165
2166         sharkd_json_object_close();
2167         putchar(',');
2168 }
2169
2170 static void
2171 sharkd_eo_object_list_add_entry(void *gui_data, export_object_entry_t *entry)
2172 {
2173         struct sharkd_export_object_list *object_list = (struct sharkd_export_object_list *) gui_data;
2174
2175         object_list->entries = g_slist_append(object_list->entries, entry);
2176 }
2177
2178 static export_object_entry_t *
2179 sharkd_eo_object_list_get_entry(void *gui_data, int row)
2180 {
2181         struct sharkd_export_object_list *object_list = (struct sharkd_export_object_list *) gui_data;
2182
2183         return (export_object_entry_t *) g_slist_nth_data(object_list->entries, row);
2184 }
2185
2186 /**
2187  * sharkd_session_process_tap_rtp_cb()
2188  *
2189  * Output RTP streams tap:
2190  *   (m) tap        - tap name
2191  *   (m) type       - tap output type
2192  *   (m) streams    - array of object with attributes:
2193  *                  (m) ssrc        - RTP synchronization source identifier
2194  *                  (m) payload     - stream payload
2195  *                  (m) saddr       - source address
2196  *                  (m) sport       - source port
2197  *                  (m) daddr       - destination address
2198  *                  (m) dport       - destination port
2199  *                  (m) pkts        - packets count
2200  *                  (m) max_delta   - max delta (ms)
2201  *                  (m) max_jitter  - max jitter (ms)
2202  *                  (m) mean_jitter - mean jitter (ms)
2203  *                  (m) expectednr  -
2204  *                  (m) totalnr     -
2205  *                  (m) problem     - if analyser found the problem
2206  *                  (m) ipver       - address IP version (4 or 6)
2207  */
2208 static void
2209 sharkd_session_process_tap_rtp_cb(void *arg)
2210 {
2211         rtpstream_tapinfo_t *rtp_tapinfo = (rtpstream_tapinfo_t *) arg;
2212
2213         GList *listx;
2214         gboolean sepa = FALSE;
2215
2216         sharkd_json_object_open(FALSE);
2217         sharkd_json_value_string(FALSE, "tap", "rtp-streams");
2218         sharkd_json_value_string(TRUE, "type", "rtp-streams");
2219
2220         sharkd_json_array_open(TRUE, "streams");
2221         for (listx = g_list_first(rtp_tapinfo->strinfo_list); listx; listx = listx->next)
2222         {
2223                 rtpstream_info_t *streaminfo = (rtpstream_info_t *) listx->data;
2224                 rtpstream_info_calc_t calc;
2225
2226                 rtpstream_info_calculate(streaminfo, &calc);
2227
2228                 sharkd_json_object_open(sepa);
2229
2230                 sharkd_json_value_anyf(FALSE, "ssrc", "%u", calc.ssrc);
2231                 sharkd_json_value_string(TRUE, "payload", calc.all_payload_type_names);
2232
2233                 sharkd_json_value_string(TRUE, "saddr", calc.src_addr_str);
2234                 sharkd_json_value_anyf(TRUE, "sport", "%u", calc.src_port);
2235                 sharkd_json_value_string(TRUE, "daddr", calc.dst_addr_str);
2236                 sharkd_json_value_anyf(TRUE, "dport", "%u", calc.dst_port);
2237
2238                 sharkd_json_value_anyf(TRUE, "pkts", "%u", calc.packet_count);
2239
2240                 sharkd_json_value_anyf(TRUE, "max_delta", "%f",calc.max_delta);
2241                 sharkd_json_value_anyf(TRUE, "max_jitter", "%f", calc.max_jitter);
2242                 sharkd_json_value_anyf(TRUE, "mean_jitter", "%f", calc.mean_jitter);
2243
2244                 sharkd_json_value_anyf(TRUE, "expectednr", "%u", calc.packet_expected);
2245                 sharkd_json_value_anyf(TRUE, "totalnr", "%u", calc.total_nr);
2246
2247                 sharkd_json_value_anyf(TRUE, "problem", calc.problem ? "true" : "false");
2248
2249                 /* for filter */
2250                 sharkd_json_value_anyf(TRUE, "ipver", "%d", (streaminfo->id.src_addr.type == AT_IPv6) ? 6 : 4);
2251
2252                 rtpstream_info_calc_free(&calc);
2253
2254                 sharkd_json_object_close();
2255                 sepa = TRUE;
2256         }
2257         sharkd_json_array_close();
2258
2259         sharkd_json_object_close();
2260         putchar(',');
2261 }
2262
2263 /**
2264  * sharkd_session_process_tap()
2265  *
2266  * Process tap request
2267  *
2268  * Input:
2269  *   (m) tap0         - First tap request
2270  *   (o) tap1...tap15 - Other tap requests
2271  *
2272  * Output object with attributes:
2273  *   (m) taps  - array of object with attributes:
2274  *                  (m) tap  - tap name
2275  *                  (m) type - tap output type
2276  *                  ...
2277  *                  for type:stats see sharkd_session_process_tap_stats_cb()
2278  *                  for type:nstat see sharkd_session_process_tap_nstat_cb()
2279  *                  for type:conv see sharkd_session_process_tap_conv_cb()
2280  *                  for type:host see sharkd_session_process_tap_conv_cb()
2281  *                  for type:rtp-streams see sharkd_session_process_tap_rtp_cb()
2282  *                  for type:rtp-analyse see sharkd_session_process_tap_rtp_analyse_cb()
2283  *                  for type:eo see sharkd_session_process_tap_eo_cb()
2284  *                  for type:expert see sharkd_session_process_tap_expert_cb()
2285  *                  for type:rtd see sharkd_session_process_tap_rtd_cb()
2286  *                  for type:srt see sharkd_session_process_tap_srt_cb()
2287  *                  for type:flow see sharkd_session_process_tap_flow_cb()
2288  *
2289  *   (m) err   - error code
2290  */
2291 static void
2292 sharkd_session_process_tap(char *buf, const jsmntok_t *tokens, int count)
2293 {
2294         void *taps_data[16];
2295         GFreeFunc taps_free[16];
2296         int taps_count = 0;
2297         int i;
2298
2299         rtpstream_tapinfo_t rtp_tapinfo =
2300                 { NULL, NULL, NULL, NULL, 0, NULL, 0, TAP_ANALYSE, NULL, NULL, NULL, FALSE };
2301
2302         for (i = 0; i < 16; i++)
2303         {
2304                 char tapbuf[32];
2305                 const char *tok_tap;
2306
2307                 void *tap_data = NULL;
2308                 GFreeFunc tap_free = NULL;
2309                 const char *tap_filter = "";
2310                 GString *tap_error = NULL;
2311
2312                 ws_snprintf(tapbuf, sizeof(tapbuf), "tap%d", i);
2313                 tok_tap = json_find_attr(buf, tokens, count, tapbuf);
2314                 if (!tok_tap)
2315                         break;
2316
2317                 if (!strncmp(tok_tap, "stat:", 5))
2318                 {
2319                         stats_tree_cfg *cfg = stats_tree_get_cfg_by_abbr(tok_tap + 5);
2320                         stats_tree *st;
2321
2322                         if (!cfg)
2323                         {
2324                                 fprintf(stderr, "sharkd_session_process_tap() stat %s not found\n", tok_tap + 5);
2325                                 continue;
2326                         }
2327
2328                         st = stats_tree_new(cfg, NULL, tap_filter);
2329
2330                         tap_error = register_tap_listener(st->cfg->tapname, st, st->filter, st->cfg->flags, stats_tree_reset, stats_tree_packet, sharkd_session_process_tap_stats_cb, NULL);
2331
2332                         if (!tap_error && cfg->init)
2333                                 cfg->init(st);
2334
2335                         tap_data = st;
2336                         tap_free = sharkd_session_free_tap_stats_cb;
2337                 }
2338                 else if (!strcmp(tok_tap, "expert"))
2339                 {
2340                         struct sharkd_expert_tap *expert_tap;
2341
2342                         expert_tap = g_new0(struct sharkd_expert_tap, 1);
2343                         expert_tap->text = g_string_chunk_new(100);
2344
2345                         tap_error = register_tap_listener("expert", expert_tap, NULL, 0, NULL, sharkd_session_packet_tap_expert_cb, sharkd_session_process_tap_expert_cb, NULL);
2346
2347                         tap_data = expert_tap;
2348                         tap_free = sharkd_session_free_tap_expert_cb;
2349                 }
2350                 else if (!strncmp(tok_tap, "seqa:", 5))
2351                 {
2352                         seq_analysis_info_t *graph_analysis;
2353                         register_analysis_t *analysis;
2354                         const char *tap_name;
2355                         tap_packet_cb tap_func;
2356                         guint tap_flags;
2357
2358                         analysis = sequence_analysis_find_by_name(tok_tap + 5);
2359                         if (!analysis)
2360                         {
2361                                 fprintf(stderr, "sharkd_session_process_tap() seq analysis %s not found\n", tok_tap + 5);
2362                                 continue;
2363                         }
2364
2365                         graph_analysis = sequence_analysis_info_new();
2366                         graph_analysis->name = tok_tap + 5;
2367                         /* TODO, make configurable */
2368                         graph_analysis->any_addr = FALSE;
2369
2370                         tap_name  = sequence_analysis_get_tap_listener_name(analysis);
2371                         tap_flags = sequence_analysis_get_tap_flags(analysis);
2372                         tap_func  = sequence_analysis_get_packet_func(analysis);
2373
2374                         tap_error = register_tap_listener(tap_name, graph_analysis, NULL, tap_flags, NULL, tap_func, sharkd_session_process_tap_flow_cb, NULL);
2375
2376                         tap_data = graph_analysis;
2377                         tap_free = sharkd_session_free_tap_flow_cb;
2378                 }
2379                 else if (!strncmp(tok_tap, "conv:", 5) || !strncmp(tok_tap, "endpt:", 6))
2380                 {
2381                         struct register_ct *ct = NULL;
2382                         const char *ct_tapname;
2383                         struct sharkd_conv_tap_data *ct_data;
2384                         tap_packet_cb tap_func = NULL;
2385
2386                         if (!strncmp(tok_tap, "conv:", 5))
2387                         {
2388                                 ct = get_conversation_by_proto_id(proto_get_id_by_short_name(tok_tap + 5));
2389
2390                                 if (!ct || !(tap_func = get_conversation_packet_func(ct)))
2391                                 {
2392                                         fprintf(stderr, "sharkd_session_process_tap() conv %s not found\n", tok_tap + 5);
2393                                         continue;
2394                                 }
2395                         }
2396                         else if (!strncmp(tok_tap, "endpt:", 6))
2397                         {
2398                                 ct = get_conversation_by_proto_id(proto_get_id_by_short_name(tok_tap + 6));
2399
2400                                 if (!ct || !(tap_func = get_hostlist_packet_func(ct)))
2401                                 {
2402                                         fprintf(stderr, "sharkd_session_process_tap() endpt %s not found\n", tok_tap + 6);
2403                                         continue;
2404                                 }
2405                         }
2406                         else
2407                         {
2408                                 fprintf(stderr, "sharkd_session_process_tap() conv/endpt(?): %s not found\n", tok_tap);
2409                                 continue;
2410                         }
2411
2412                         ct_tapname = proto_get_protocol_filter_name(get_conversation_proto_id(ct));
2413
2414                         ct_data = (struct sharkd_conv_tap_data *) g_malloc0(sizeof(struct sharkd_conv_tap_data));
2415                         ct_data->type = tok_tap;
2416                         ct_data->hash.user_data = ct_data;
2417
2418                         /* XXX: make configurable */
2419                         ct_data->resolve_name = TRUE;
2420                         ct_data->resolve_port = TRUE;
2421
2422                         tap_error = register_tap_listener(ct_tapname, &ct_data->hash, tap_filter, 0, NULL, tap_func, sharkd_session_process_tap_conv_cb, NULL);
2423
2424                         tap_data = &ct_data->hash;
2425                         tap_free = sharkd_session_free_tap_conv_cb;
2426                 }
2427                 else if (!strncmp(tok_tap, "nstat:", 6))
2428                 {
2429                         stat_tap_table_ui *stat_tap = stat_tap_by_name(tok_tap + 6);
2430                         stat_data_t *stat_data;
2431
2432                         if (!stat_tap)
2433                         {
2434                                 fprintf(stderr, "sharkd_session_process_tap() nstat=%s not found\n", tok_tap + 6);
2435                                 continue;
2436                         }
2437
2438                         stat_tap->stat_tap_init_cb(stat_tap);
2439
2440                         stat_data = g_new0(stat_data_t, 1);
2441                         stat_data->stat_tap_data = stat_tap;
2442                         stat_data->user_data = NULL;
2443
2444                         tap_error = register_tap_listener(stat_tap->tap_name, stat_data, tap_filter, 0, NULL, stat_tap->packet_func, sharkd_session_process_tap_nstat_cb, NULL);
2445
2446                         tap_data = stat_data;
2447                         tap_free = sharkd_session_free_tap_nstat_cb;
2448                 }
2449                 else if (!strncmp(tok_tap, "rtd:", 4))
2450                 {
2451                         register_rtd_t *rtd = get_rtd_table_by_name(tok_tap + 4);
2452                         rtd_data_t *rtd_data;
2453                         char *err;
2454
2455                         if (!rtd)
2456                         {
2457                                 fprintf(stderr, "sharkd_session_process_tap() rtd=%s not found\n", tok_tap + 4);
2458                                 continue;
2459                         }
2460
2461                         rtd_table_get_filter(rtd, "", &tap_filter, &err);
2462                         if (err != NULL)
2463                         {
2464                                 fprintf(stderr, "sharkd_session_process_tap() rtd=%s err=%s\n", tok_tap + 4, err);
2465                                 g_free(err);
2466                                 continue;
2467                         }
2468
2469                         rtd_data = g_new0(rtd_data_t, 1);
2470                         rtd_data->user_data = rtd;
2471                         rtd_table_dissector_init(rtd, &rtd_data->stat_table, NULL, NULL);
2472
2473                         tap_error = register_tap_listener(get_rtd_tap_listener_name(rtd), rtd_data, tap_filter, 0, NULL, get_rtd_packet_func(rtd), sharkd_session_process_tap_rtd_cb, NULL);
2474
2475                         tap_data = rtd_data;
2476                         tap_free = sharkd_session_free_tap_rtd_cb;
2477                 }
2478                 else if (!strncmp(tok_tap, "srt:", 4))
2479                 {
2480                         register_srt_t *srt = get_srt_table_by_name(tok_tap + 4);
2481                         srt_data_t *srt_data;
2482                         char *err;
2483
2484                         if (!srt)
2485                         {
2486                                 fprintf(stderr, "sharkd_session_process_tap() srt=%s not found\n", tok_tap + 4);
2487                                 continue;
2488                         }
2489
2490                         srt_table_get_filter(srt, "", &tap_filter, &err);
2491                         if (err != NULL)
2492                         {
2493                                 fprintf(stderr, "sharkd_session_process_tap() srt=%s err=%s\n", tok_tap + 4, err);
2494                                 g_free(err);
2495                                 continue;
2496                         }
2497
2498                         srt_data = g_new0(srt_data_t, 1);
2499                         srt_data->srt_array = g_array_new(FALSE, TRUE, sizeof(srt_stat_table *));
2500                         srt_data->user_data = srt;
2501                         srt_table_dissector_init(srt, srt_data->srt_array);
2502
2503                         tap_error = register_tap_listener(get_srt_tap_listener_name(srt), srt_data, tap_filter, 0, NULL, get_srt_packet_func(srt), sharkd_session_process_tap_srt_cb, NULL);
2504
2505                         tap_data = srt_data;
2506                         tap_free = sharkd_session_free_tap_srt_cb;
2507                 }
2508                 else if (!strncmp(tok_tap, "eo:", 3))
2509                 {
2510                         register_eo_t *eo = get_eo_by_name(tok_tap + 3);
2511                         export_object_list_t *eo_object;
2512                         struct sharkd_export_object_list *object_list;
2513
2514                         if (!eo)
2515                         {
2516                                 fprintf(stderr, "sharkd_session_process_tap() eo=%s not found\n", tok_tap + 3);
2517                                 continue;
2518                         }
2519
2520                         for (object_list = sharkd_eo_list; object_list; object_list = object_list->next)
2521                         {
2522                                 if (!strcmp(object_list->type, tok_tap))
2523                                 {
2524                                         g_slist_free_full(object_list->entries, (GDestroyNotify) eo_free_entry);
2525                                         object_list->entries = NULL;
2526                                         break;
2527                                 }
2528                         }
2529
2530                         if (!object_list)
2531                         {
2532                                 object_list = g_new(struct sharkd_export_object_list, 1);
2533                                 object_list->type = g_strdup(tok_tap);
2534                                 object_list->proto = proto_get_protocol_short_name(find_protocol_by_id(get_eo_proto_id(eo)));
2535                                 object_list->entries = NULL;
2536                                 object_list->next = sharkd_eo_list;
2537                                 sharkd_eo_list = object_list;
2538                         }
2539
2540                         eo_object  = g_new0(export_object_list_t, 1);
2541                         eo_object->add_entry = sharkd_eo_object_list_add_entry;
2542                         eo_object->get_entry = sharkd_eo_object_list_get_entry;
2543                         eo_object->gui_data = (void *) object_list;
2544
2545                         tap_error = register_tap_listener(get_eo_tap_listener_name(eo), eo_object, NULL, 0, NULL, get_eo_packet_func(eo), sharkd_session_process_tap_eo_cb, NULL);
2546
2547                         tap_data = eo_object;
2548                         tap_free = g_free; /* need to free only eo_object, object_list need to be kept for potential download */
2549                 }
2550                 else if (!strcmp(tok_tap, "rtp-streams"))
2551                 {
2552                         tap_error = register_tap_listener("rtp", &rtp_tapinfo, tap_filter, 0, rtpstream_reset_cb, rtpstream_packet_cb, sharkd_session_process_tap_rtp_cb, NULL);
2553
2554                         tap_data = &rtp_tapinfo;
2555                         tap_free = rtpstream_reset_cb;
2556                 }
2557                 else if (!strncmp(tok_tap, "rtp-analyse:", 12))
2558                 {
2559                         struct sharkd_analyse_rtp *rtp_req;
2560
2561                         rtp_req = (struct sharkd_analyse_rtp *) g_malloc0(sizeof(*rtp_req));
2562                         if (!sharkd_rtp_match_init(&rtp_req->id, tok_tap + 12))
2563                         {
2564                                 rtpstream_id_free(&rtp_req->id);
2565                                 g_free(rtp_req);
2566                                 continue;
2567                         }
2568
2569                         rtp_req->tap_name = tok_tap;
2570                         rtp_req->statinfo.first_packet = TRUE;
2571                         rtp_req->statinfo.reg_pt = PT_UNDEFINED;
2572
2573                         tap_error = register_tap_listener("rtp", rtp_req, tap_filter, 0, NULL, sharkd_session_packet_tap_rtp_analyse_cb, sharkd_session_process_tap_rtp_analyse_cb, NULL);
2574
2575                         tap_data = rtp_req;
2576                         tap_free = sharkd_session_process_tap_rtp_free_cb;
2577                 }
2578                 else
2579                 {
2580                         fprintf(stderr, "sharkd_session_process_tap() %s not recognized\n", tok_tap);
2581                         continue;
2582                 }
2583
2584                 if (tap_error)
2585                 {
2586                         fprintf(stderr, "sharkd_session_process_tap() name=%s error=%s", tok_tap, tap_error->str);
2587                         g_string_free(tap_error, TRUE);
2588                         if (tap_free)
2589                                 tap_free(tap_data);
2590                         continue;
2591                 }
2592
2593                 taps_data[taps_count] = tap_data;
2594                 taps_free[taps_count] = tap_free;
2595                 taps_count++;
2596         }
2597
2598         fprintf(stderr, "sharkd_session_process_tap() count=%d\n", taps_count);
2599         if (taps_count == 0)
2600                 return;
2601
2602         sharkd_json_object_open(FALSE);
2603
2604         sharkd_json_array_open(FALSE, "taps");
2605         sharkd_retap();
2606         sharkd_json_value_anyf(FALSE, NULL, "null");
2607         sharkd_json_array_close();
2608
2609         sharkd_json_value_anyf(TRUE, "err", "0");
2610
2611         sharkd_json_object_close();
2612         sharkd_json_finish();
2613
2614         for (i = 0; i < taps_count; i++)
2615         {
2616                 if (taps_data[i])
2617                         remove_tap_listener(taps_data[i]);
2618
2619                 if (taps_free[i])
2620                         taps_free[i](taps_data[i]);
2621         }
2622 }
2623
2624 /**
2625  * sharkd_session_process_follow()
2626  *
2627  * Process follow request
2628  *
2629  * Input:
2630  *   (m) follow  - follow protocol request (e.g. HTTP)
2631  *   (m) filter  - filter request (e.g. tcp.stream == 1)
2632  *
2633  * Output object with attributes:
2634  *
2635  *   (m) err    - error code
2636  *   (m) shost  - server host
2637  *   (m) sport  - server port
2638  *   (m) sbytes - server send bytes count
2639  *   (m) chost  - client host
2640  *   (m) cport  - client port
2641  *   (m) cbytes - client send bytes count
2642  *   (o) payloads - array of object with attributes:
2643  *                  (o) s - set if server sent, else client
2644  *                  (m) n - packet number
2645  *                  (m) d - data base64 encoded
2646  */
2647 static void
2648 sharkd_session_process_follow(char *buf, const jsmntok_t *tokens, int count)
2649 {
2650         const char *tok_follow = json_find_attr(buf, tokens, count, "follow");
2651         const char *tok_filter = json_find_attr(buf, tokens, count, "filter");
2652
2653         register_follow_t *follower;
2654         GString *tap_error;
2655
2656         follow_info_t *follow_info;
2657         const char *host;
2658         char *port;
2659
2660         if (!tok_follow || !tok_filter)
2661                 return;
2662
2663         follower = get_follow_by_name(tok_follow);
2664         if (!follower)
2665         {
2666                 fprintf(stderr, "sharkd_session_process_follow() follower=%s not found\n", tok_follow);
2667                 return;
2668         }
2669
2670         /* follow_reset_stream ? */
2671         follow_info = g_new0(follow_info_t, 1);
2672         /* gui_data, filter_out_filter not set, but not used by dissector */
2673
2674         tap_error = register_tap_listener(get_follow_tap_string(follower), follow_info, tok_filter, 0, NULL, get_follow_tap_handler(follower), NULL, NULL);
2675         if (tap_error)
2676         {
2677                 fprintf(stderr, "sharkd_session_process_follow() name=%s error=%s", tok_follow, tap_error->str);
2678                 g_string_free(tap_error, TRUE);
2679                 g_free(follow_info);
2680                 return;
2681         }
2682
2683         sharkd_retap();
2684
2685         sharkd_json_object_open(FALSE);
2686
2687         sharkd_json_value_anyf(FALSE, "err", "0");
2688
2689         /* Server information: hostname, port, bytes sent */
2690         host = address_to_name(&follow_info->server_ip);
2691         sharkd_json_value_string(TRUE, "shost", host);
2692
2693         port = get_follow_port_to_display(follower)(NULL, follow_info->server_port);
2694         sharkd_json_value_string(TRUE, "sport", port);
2695         wmem_free(NULL, port);
2696
2697         sharkd_json_value_anyf(TRUE, "sbytes", "%u", follow_info->bytes_written[0]);
2698
2699         /* Client information: hostname, port, bytes sent */
2700         host = address_to_name(&follow_info->client_ip);
2701         sharkd_json_value_string(TRUE, "chost", host);
2702
2703         port = get_follow_port_to_display(follower)(NULL, follow_info->client_port);
2704         sharkd_json_value_string(TRUE, "cport", port);
2705         wmem_free(NULL, port);
2706
2707         sharkd_json_value_anyf(TRUE, "cbytes", "%u", follow_info->bytes_written[1]);
2708
2709         if (follow_info->payload)
2710         {
2711                 follow_record_t *follow_record;
2712                 GList *cur;
2713                 gboolean sepa = FALSE;
2714
2715                 sharkd_json_array_open(TRUE, "payloads");
2716                 for (cur = g_list_last(follow_info->payload); cur; cur = g_list_previous(cur))
2717                 {
2718                         follow_record = (follow_record_t *) cur->data;
2719
2720                         sharkd_json_object_open(sepa);
2721
2722                         sharkd_json_value_anyf(FALSE, "n", "%u", follow_record->packet_num);
2723                         sharkd_json_value_base64(TRUE, "d", follow_record->data->data, follow_record->data->len);
2724
2725                         if (follow_record->is_server)
2726                                 sharkd_json_value_anyf(TRUE, "s", "%d", 1);
2727
2728                         sharkd_json_object_close();
2729                         sepa = TRUE;
2730                 }
2731                 sharkd_json_array_close();
2732         }
2733
2734         sharkd_json_object_close();
2735         sharkd_json_finish();
2736
2737         remove_tap_listener(follow_info);
2738         follow_info_free(follow_info);
2739 }
2740
2741 static void
2742 sharkd_session_process_frame_cb_tree(epan_dissect_t *edt, proto_tree *tree, tvbuff_t **tvbs, gboolean display_hidden)
2743 {
2744         proto_node *node;
2745         gboolean sepa = FALSE;
2746
2747         sharkd_json_array_open(FALSE, NULL);
2748         for (node = tree->first_child; node; node = node->next)
2749         {
2750                 field_info *finfo = PNODE_FINFO(node);
2751
2752                 if (!finfo)
2753                         continue;
2754
2755                 if (!display_hidden && FI_GET_FLAG(finfo, FI_HIDDEN))
2756                         continue;
2757
2758                 sharkd_json_object_open(sepa);
2759
2760                 if (!finfo->rep)
2761                 {
2762                         char label_str[ITEM_LABEL_LENGTH];
2763
2764                         label_str[0] = '\0';
2765                         proto_item_fill_label(finfo, label_str);
2766                         sharkd_json_value_string(FALSE, "l", label_str);
2767                 }
2768                 else
2769                 {
2770                         sharkd_json_value_string(FALSE, "l", finfo->rep->representation);
2771                 }
2772
2773                 if (finfo->ds_tvb && tvbs && tvbs[0] != finfo->ds_tvb)
2774                 {
2775                         int idx;
2776
2777                         for (idx = 1; tvbs[idx]; idx++)
2778                         {
2779                                 if (tvbs[idx] == finfo->ds_tvb)
2780                                 {
2781                                         sharkd_json_value_anyf(TRUE, "ds", "%d", idx);
2782                                         break;
2783                                 }
2784                         }
2785                 }
2786
2787                 if (finfo->start >= 0 && finfo->length > 0)
2788                         sharkd_json_value_anyf(TRUE, "h", "[%d,%d]", finfo->start, finfo->length);
2789
2790                 if (finfo->appendix_start >= 0 && finfo->appendix_length > 0)
2791                         sharkd_json_value_anyf(TRUE, "i", "[%d,%d]", finfo->appendix_start, finfo->appendix_length);
2792
2793
2794                 if (finfo->hfinfo)
2795                 {
2796                         char *filter;
2797
2798                         if (finfo->hfinfo->type == FT_PROTOCOL)
2799                         {
2800                                 sharkd_json_value_string(TRUE, "t", "proto");
2801                         }
2802                         else if (finfo->hfinfo->type == FT_FRAMENUM)
2803                         {
2804                                 sharkd_json_value_string(TRUE, "t", "framenum");
2805                                 sharkd_json_value_anyf(TRUE, "fnum", "%u", finfo->value.value.uinteger);
2806                         }
2807                         else if (FI_GET_FLAG(finfo, FI_URL) && IS_FT_STRING(finfo->hfinfo->type))
2808                         {
2809                                 char *url = fvalue_to_string_repr(NULL, &finfo->value, FTREPR_DISPLAY, finfo->hfinfo->display);
2810
2811                                 sharkd_json_value_string(TRUE, "t", "url");
2812                                 sharkd_json_value_string(TRUE, "url", url);
2813                                 wmem_free(NULL, url);
2814                         }
2815
2816                         filter = proto_construct_match_selected_string(finfo, edt);
2817                         if (filter)
2818                         {
2819                                 sharkd_json_value_string(TRUE, "f", filter);
2820                                 wmem_free(NULL, filter);
2821                         }
2822                 }
2823
2824                 if (FI_GET_FLAG(finfo, FI_GENERATED))
2825                         sharkd_json_value_anyf(TRUE, "g", "true");
2826
2827                 if (FI_GET_FLAG(finfo, FI_HIDDEN))
2828                         sharkd_json_value_anyf(TRUE, "v", "true");
2829
2830                 if (FI_GET_FLAG(finfo, PI_SEVERITY_MASK))
2831                 {
2832                         const char *severity = try_val_to_str(FI_GET_FLAG(finfo, PI_SEVERITY_MASK), expert_severity_vals);
2833
2834                         g_assert(severity != NULL);
2835
2836                         sharkd_json_value_string(TRUE, "s", severity);
2837                 }
2838
2839                 if (((proto_tree *) node)->first_child)
2840                 {
2841                         if (finfo->tree_type != -1)
2842                                 sharkd_json_value_anyf(TRUE, "e", "%d", finfo->tree_type);
2843
2844                         sharkd_json_value_anyf(TRUE, "n", NULL);
2845                         sharkd_session_process_frame_cb_tree(edt, (proto_tree *) node, tvbs, display_hidden);
2846                 }
2847
2848                 sharkd_json_object_close();
2849                 sepa = TRUE;
2850         }
2851         sharkd_json_array_close();
2852 }
2853
2854 static gboolean
2855 sharkd_follower_visit_layers_cb(const void *key _U_, void *value, void *user_data)
2856 {
2857         register_follow_t *follower = (register_follow_t *) value;
2858         packet_info *pi = (packet_info *) user_data;
2859
2860         const int proto_id = get_follow_proto_id(follower);
2861
2862         guint32 ignore_stream;
2863
2864         if (proto_is_frame_protocol(pi->layers, proto_get_protocol_filter_name(proto_id)))
2865         {
2866                 const char *layer_proto = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
2867                 char *follow_filter;
2868
2869                 follow_filter = get_follow_conv_func(follower)(pi, &ignore_stream);
2870
2871                 sharkd_json_array_open(TRUE, NULL);
2872                 sharkd_json_value_string(FALSE, NULL, layer_proto);
2873                 sharkd_json_value_string(TRUE, NULL, follow_filter);
2874                 sharkd_json_array_close();
2875
2876                 g_free(follow_filter);
2877         }
2878
2879         return FALSE;
2880 }
2881
2882 struct sharkd_frame_request_data
2883 {
2884         gboolean display_hidden;
2885 };
2886
2887 static void
2888 sharkd_session_process_frame_cb(epan_dissect_t *edt, proto_tree *tree, struct epan_column_info *cinfo, const GSList *data_src, void *data)
2889 {
2890         packet_info *pi = &edt->pi;
2891         frame_data *fdata = pi->fd;
2892         const char *pkt_comment = NULL;
2893
2894         const struct sharkd_frame_request_data * const req_data = (const struct sharkd_frame_request_data * const) data;
2895         const gboolean display_hidden = (req_data) ? req_data->display_hidden : FALSE;
2896
2897         sharkd_json_object_open(FALSE);
2898
2899         sharkd_json_value_anyf(FALSE, "err", "0");
2900
2901         if (fdata->flags.has_user_comment)
2902                 pkt_comment = sharkd_get_user_comment(fdata);
2903         else if (fdata->flags.has_phdr_comment)
2904                 pkt_comment = pi->rec->opt_comment;
2905
2906         if (pkt_comment)
2907                 sharkd_json_value_string(TRUE, "comment", pkt_comment);
2908
2909         if (tree)
2910         {
2911                 tvbuff_t **tvbs = NULL;
2912
2913                 /* arrayize data src, to speedup searching for ds_tvb index */
2914                 if (data_src && data_src->next /* only needed if there are more than one data source */)
2915                 {
2916                         guint count = g_slist_length((GSList *) data_src);
2917                         guint i;
2918
2919                         tvbs = (tvbuff_t **) g_malloc((count + 1) * sizeof(*tvbs));
2920
2921                         for (i = 0; i < count; i++)
2922                         {
2923                                 const struct data_source *src = (const struct data_source *) g_slist_nth_data((GSList *) data_src, i);
2924
2925                                 tvbs[i] = get_data_source_tvb(src);
2926                         }
2927
2928                         tvbs[count] = NULL;
2929                 }
2930
2931                 sharkd_json_value_anyf(TRUE, "tree", NULL);
2932                 sharkd_session_process_frame_cb_tree(edt, tree, tvbs, display_hidden);
2933
2934                 g_free(tvbs);
2935         }
2936
2937         if (cinfo)
2938         {
2939                 int col;
2940
2941                 sharkd_json_array_open(TRUE, "col");
2942                 for (col = 0; col < cinfo->num_cols; ++col)
2943                 {
2944                         const col_item_t *col_item = &cinfo->columns[col];
2945
2946                         sharkd_json_value_string(col != 0, NULL, col_item->col_data);
2947                 }
2948                 sharkd_json_array_close();
2949         }
2950
2951         if (fdata->flags.ignored)
2952                 sharkd_json_value_anyf(TRUE, "i", "true");
2953
2954         if (fdata->flags.marked)
2955                 sharkd_json_value_anyf(TRUE, "m", "true");
2956
2957         if (fdata->color_filter)
2958         {
2959                 sharkd_json_value_stringf(TRUE, "bg", "%x", color_t_to_rgb(&fdata->color_filter->bg_color));
2960                 sharkd_json_value_stringf(TRUE, "fg", "%x", color_t_to_rgb(&fdata->color_filter->fg_color));
2961         }
2962
2963         if (data_src)
2964         {
2965                 struct data_source *src = (struct data_source *) data_src->data;
2966                 gboolean ds_sepa = FALSE;
2967                 gboolean ds_open = FALSE;
2968
2969                 tvbuff_t *tvb;
2970                 guint length;
2971
2972                 tvb = get_data_source_tvb(src);
2973                 length = tvb_captured_length(tvb);
2974
2975                 if (length != 0)
2976                 {
2977                         const guchar *cp = tvb_get_ptr(tvb, 0, length);
2978
2979                         /* XXX pi.fd->flags.encoding */
2980                         sharkd_json_value_base64(TRUE, "bytes", cp, length);
2981                 }
2982                 else
2983                 {
2984                         sharkd_json_value_base64(TRUE, "bytes", "", 0);
2985                 }
2986
2987                 data_src = data_src->next;
2988                 if (data_src)
2989                 {
2990                         sharkd_json_array_open(TRUE, "ds");
2991                         ds_open = TRUE;
2992                 }
2993
2994                 while (data_src)
2995                 {
2996                         src = (struct data_source *) data_src->data;
2997
2998                         sharkd_json_object_open(ds_sepa);
2999
3000                         {
3001                                 char *src_name = get_data_source_name(src);
3002
3003                                 sharkd_json_value_string(FALSE, "name", src_name);
3004                                 wmem_free(NULL, src_name);
3005                         }
3006
3007                         tvb = get_data_source_tvb(src);
3008                         length = tvb_captured_length(tvb);
3009
3010                         if (length != 0)
3011                         {
3012                                 const guchar *cp = tvb_get_ptr(tvb, 0, length);
3013
3014                                 /* XXX pi.fd->flags.encoding */
3015                                 sharkd_json_value_base64(TRUE, "bytes", cp, length);
3016                         }
3017                         else
3018                         {
3019                                 sharkd_json_value_base64(TRUE, "bytes", "", 0);
3020                         }
3021
3022                         sharkd_json_object_close();
3023                         ds_sepa = TRUE;
3024
3025                         data_src = data_src->next;
3026                 }
3027
3028                 /* close ds, only if was opened */
3029                 if (ds_open)
3030                         sharkd_json_array_close();
3031         }
3032
3033         sharkd_json_array_open(TRUE, "fol");
3034         sharkd_json_value_anyf(FALSE, NULL, "0");
3035         follow_iterate_followers(sharkd_follower_visit_layers_cb, pi);
3036         sharkd_json_array_close();
3037
3038         sharkd_json_object_close();
3039         sharkd_json_finish();
3040 }
3041
3042 #define SHARKD_IOGRAPH_MAX_ITEMS 250000 /* 250k limit of items is taken from wireshark-qt, on x86_64 sizeof(io_graph_item_t) is 152, so single graph can take max 36 MB */
3043
3044 struct sharkd_iograph
3045 {
3046         /* config */
3047         int hf_index;
3048         io_graph_item_unit_t calc_type;
3049         guint32 interval;
3050
3051         /* result */
3052         int space_items;
3053         int num_items;
3054         io_graph_item_t *items;
3055         GString *error;
3056 };
3057
3058 static gboolean
3059 sharkd_iograph_packet(void *g, packet_info *pinfo, epan_dissect_t *edt, const void *dummy _U_)
3060 {
3061         struct sharkd_iograph *graph = (struct sharkd_iograph *) g;
3062         int idx;
3063
3064         idx = get_io_graph_index(pinfo, graph->interval);
3065         if (idx < 0 || idx >= SHARKD_IOGRAPH_MAX_ITEMS)
3066                 return FALSE;
3067
3068         if (idx + 1 > graph->num_items)
3069         {
3070                 if (idx + 1 > graph->space_items)
3071                 {
3072                         int new_size = idx + 1024;
3073
3074                         graph->items = (io_graph_item_t *) g_realloc(graph->items, sizeof(io_graph_item_t) * new_size);
3075                         reset_io_graph_items(&graph->items[graph->space_items], new_size - graph->space_items);
3076
3077                         graph->space_items = new_size;
3078                 }
3079                 else if (graph->items == NULL)
3080                 {
3081                         graph->items = (io_graph_item_t *) g_malloc(sizeof(io_graph_item_t) * graph->space_items);
3082                         reset_io_graph_items(graph->items, graph->space_items);
3083                 }
3084
3085                 graph->num_items = idx + 1;
3086         }
3087
3088         return update_io_graph_item(graph->items, idx, pinfo, edt, graph->hf_index, graph->calc_type, graph->interval);
3089 }
3090
3091 /**
3092  * sharkd_session_process_iograph()
3093  *
3094  * Process iograph request
3095  *
3096  * Input:
3097  *   (o) interval - interval time in ms, if not specified: 1000ms
3098  *   (m) graph0             - First graph request
3099  *   (o) graph1...graph9    - Other graph requests
3100  *   (o) filter0            - First graph filter
3101  *   (o) filter1...filter9  - Other graph filters
3102  *
3103  * Graph requests can be one of: "packets", "bytes", "bits", "sum:<field>", "frames:<field>", "max:<field>", "min:<field>", "avg:<field>", "load:<field>",
3104  * if you use variant with <field>, you need to pass field name in filter request.
3105  *
3106  * Output object with attributes:
3107  *   (m) iograph - array of graph results with attributes:
3108  *                  errmsg - graph cannot be constructed
3109  *                  items  - graph values, zeros are skipped, if value is not a number it's next index encoded as hex string
3110  */
3111 static void
3112 sharkd_session_process_iograph(char *buf, const jsmntok_t *tokens, int count)
3113 {
3114         const char *tok_interval = json_find_attr(buf, tokens, count, "interval");
3115         struct sharkd_iograph graphs[10];
3116         gboolean is_any_ok = FALSE;
3117         int graph_count;
3118
3119         guint32 interval_ms = 1000; /* default: one per second */
3120         int i;
3121
3122         if (tok_interval)
3123         {
3124                 if (!ws_strtou32(tok_interval, NULL, &interval_ms) || interval_ms == 0)
3125                 {
3126                         fprintf(stderr, "Invalid interval parameter: %s.\n", tok_interval);
3127                         return;
3128                 }
3129         }
3130
3131         for (i = graph_count = 0; i < (int) G_N_ELEMENTS(graphs); i++)
3132         {
3133                 struct sharkd_iograph *graph = &graphs[graph_count];
3134
3135                 const char *tok_graph;
3136                 const char *tok_filter;
3137                 char tok_format_buf[32];
3138                 const char *field_name;
3139
3140                 snprintf(tok_format_buf, sizeof(tok_format_buf), "graph%d", i);
3141                 tok_graph = json_find_attr(buf, tokens, count, tok_format_buf);
3142                 if (!tok_graph)
3143                         break;
3144
3145                 snprintf(tok_format_buf, sizeof(tok_format_buf), "filter%d", i);
3146                 tok_filter = json_find_attr(buf, tokens, count, tok_format_buf);
3147
3148                 if (!strcmp(tok_graph, "packets"))
3149                         graph->calc_type = IOG_ITEM_UNIT_PACKETS;
3150                 else if (!strcmp(tok_graph, "bytes"))
3151                         graph->calc_type = IOG_ITEM_UNIT_BYTES;
3152                 else if (!strcmp(tok_graph, "bits"))
3153                         graph->calc_type = IOG_ITEM_UNIT_BITS;
3154                 else if (g_str_has_prefix(tok_graph, "sum:"))
3155                         graph->calc_type = IOG_ITEM_UNIT_CALC_SUM;
3156                 else if (g_str_has_prefix(tok_graph, "frames:"))
3157                         graph->calc_type = IOG_ITEM_UNIT_CALC_FRAMES;
3158                 else if (g_str_has_prefix(tok_graph, "fields:"))
3159                         graph->calc_type = IOG_ITEM_UNIT_CALC_FIELDS;
3160                 else if (g_str_has_prefix(tok_graph, "max:"))
3161                         graph->calc_type = IOG_ITEM_UNIT_CALC_MAX;
3162                 else if (g_str_has_prefix(tok_graph, "min:"))
3163                         graph->calc_type = IOG_ITEM_UNIT_CALC_MIN;
3164                 else if (g_str_has_prefix(tok_graph, "avg:"))
3165                         graph->calc_type = IOG_ITEM_UNIT_CALC_AVERAGE;
3166                 else if (g_str_has_prefix(tok_graph, "load:"))
3167                         graph->calc_type = IOG_ITEM_UNIT_CALC_LOAD;
3168                 else
3169                         break;
3170
3171                 field_name = strchr(tok_graph, ':');
3172                 if (field_name)
3173                         field_name = field_name + 1;
3174
3175                 graph->interval = interval_ms;
3176
3177                 graph->hf_index = -1;
3178                 graph->error = check_field_unit(field_name, &graph->hf_index, graph->calc_type);
3179
3180                 graph->space_items = 0; /* TODO, can avoid realloc()s in sharkd_iograph_packet() by calculating: capture_time / interval */
3181                 graph->num_items = 0;
3182                 graph->items = NULL;
3183
3184                 if (!graph->error)
3185                         graph->error = register_tap_listener("frame", graph, tok_filter, TL_REQUIRES_PROTO_TREE, NULL, sharkd_iograph_packet, NULL, NULL);
3186
3187                 graph_count++;
3188
3189                 if (graph->error == NULL)
3190                         is_any_ok = TRUE;
3191         }
3192
3193         /* retap only if we have at least one ok */
3194         if (is_any_ok)
3195                 sharkd_retap();
3196
3197         sharkd_json_object_open(FALSE);
3198
3199         sharkd_json_array_open(FALSE, "iograph");
3200         for (i = 0; i < graph_count; i++)
3201         {
3202                 struct sharkd_iograph *graph = &graphs[i];
3203
3204                 sharkd_json_object_open(i != 0);
3205
3206                 if (graph->error)
3207                 {
3208                         sharkd_json_value_string(FALSE, "errmsg", graph->error->str);
3209                         g_string_free(graph->error, TRUE);
3210                 }
3211                 else
3212                 {
3213                         int idx;
3214                         int next_idx = 0;
3215
3216                         sharkd_json_array_open(FALSE, "items");
3217                         for (idx = 0; idx < graph->num_items; idx++)
3218                         {
3219                                 double val;
3220
3221                                 val = get_io_graph_item(graph->items, graph->calc_type, idx, graph->hf_index, &cfile, graph->interval, graph->num_items);
3222
3223                                 /* if it's zero, don't display */
3224                                 if (val == 0.0)
3225                                         continue;
3226
3227                                 /* cause zeros are not printed, need to output index */
3228                                 if (next_idx != idx)
3229                                         sharkd_json_value_stringf(next_idx != 0, NULL, "%x", idx);
3230
3231                                 sharkd_json_value_anyf(idx != 0, NULL, "%f", val);
3232                                 next_idx = idx + 1;
3233                         }
3234                         sharkd_json_array_close();
3235                 }
3236                 sharkd_json_object_close();
3237
3238                 remove_tap_listener(graph);
3239                 g_free(graph->items);
3240         }
3241         sharkd_json_array_close();
3242
3243         sharkd_json_object_close();
3244         sharkd_json_finish();
3245 }
3246
3247 /**
3248  * sharkd_session_process_intervals()
3249  *
3250  * Process intervals request - generate basic capture file statistics per requested interval.
3251  *
3252  * Input:
3253  *   (o) interval - interval time in ms, if not specified: 1000ms
3254  *   (o) filter   - filter for generating interval request
3255  *
3256  * Output object with attributes:
3257  *   (m) intervals - array of intervals, with indexes:
3258  *             [0] - index of interval,
3259  *             [1] - number of frames during interval,
3260  *             [2] - number of bytes during interval.
3261  *
3262  *   (m) last   - last interval number.
3263  *   (m) frames - total number of frames
3264  *   (m) bytes  - total number of bytes
3265  *
3266  * NOTE: If frames are not in order, there might be items with same interval index, or even negative one.
3267  */
3268 static void
3269 sharkd_session_process_intervals(char *buf, const jsmntok_t *tokens, int count)
3270 {
3271         const char *tok_interval = json_find_attr(buf, tokens, count, "interval");
3272         const char *tok_filter = json_find_attr(buf, tokens, count, "filter");
3273
3274         const guint8 *filter_data = NULL;
3275
3276         struct
3277         {
3278                 unsigned int frames;
3279                 guint64 bytes;
3280         } st, st_total;
3281
3282         nstime_t *start_ts;
3283
3284         guint32 interval_ms = 1000; /* default: one per second */
3285
3286         gboolean sepa = FALSE;
3287         unsigned int framenum;
3288         gint64 idx;
3289         gint64 max_idx = 0;
3290
3291         if (tok_interval)
3292         {
3293                 if (!ws_strtou32(tok_interval, NULL, &interval_ms) || interval_ms == 0)
3294                 {
3295                         fprintf(stderr, "Invalid interval parameter: %s.\n", tok_interval);
3296                         return;
3297                 }
3298         }
3299
3300         if (tok_filter)
3301         {
3302                 const struct sharkd_filter_item *filter_item;
3303
3304                 filter_item = sharkd_session_filter_data(tok_filter);
3305                 if (!filter_item)
3306                         return;