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