Try to squeeze some bytes out of the frame_data structure.
[gd/wireshark/.git] / sharkd_session.c
1 /* sharkd_session.c
2  *
3  * Copyright (C) 2016 Jakub Zawadzki
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * SPDX-License-Identifier: GPL-2.0-or-later
10  */
11
12 #include <config.h>
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <stdarg.h>
17 #include <string.h>
18 #include <errno.h>
19
20 #include <glib.h>
21
22 #include <wsutil/wsjson.h>
23 #include <wsutil/ws_printf.h>
24
25 #include <file.h>
26 #include <epan/epan_dissect.h>
27 #include <epan/exceptions.h>
28 #include <epan/color_filters.h>
29 #include <epan/prefs.h>
30 #include <epan/prefs-int.h>
31 #include <epan/uat-int.h>
32 #include <wiretap/wtap.h>
33
34 #include <epan/column.h>
35
36 #include <ui/ssl_key_export.h>
37
38 #include <ui/io_graph_item.h>
39 #include <epan/stats_tree_priv.h>
40 #include <epan/stat_tap_ui.h>
41 #include <epan/conversation_table.h>
42 #include <epan/sequence_analysis.h>
43 #include <epan/expert.h>
44 #include <epan/export_object.h>
45 #include <epan/follow.h>
46 #include <epan/rtd_table.h>
47 #include <epan/srt_table.h>
48
49 #include <epan/dissectors/packet-h225.h>
50 #include <epan/rtp_pt.h>
51 #include <ui/voip_calls.h>
52 #include <ui/rtp_stream.h>
53 #include <ui/tap-rtp-common.h>
54 #include <ui/tap-rtp-analysis.h>
55 #include <epan/to_str.h>
56
57 #include <epan/addr_resolv.h>
58 #include <epan/dissectors/packet-rtp.h>
59 #include <ui/rtp_media.h>
60 #ifdef HAVE_SPEEXDSP
61 # include <speex/speex_resampler.h>
62 #else
63 # include <codecs/speex/speex_resampler.h>
64 #endif /* HAVE_SPEEXDSP */
65
66 #include <epan/maxmind_db.h>
67
68 #include <wsutil/pint.h>
69 #include <wsutil/strtoi.h>
70
71 #include "globals.h"
72
73 #include "sharkd.h"
74
75 struct sharkd_filter_item
76 {
77         guint8 *filtered; /* can be NULL if all frames are matching for given filter. */
78 };
79
80 static GHashTable *filter_table = NULL;
81
82 static const char *
83 json_find_attr(const char *buf, const jsmntok_t *tokens, int count, const char *attr)
84 {
85         int i;
86
87         for (i = 0; i < count; i += 2)
88         {
89                 const char *tok_attr  = &buf[tokens[i + 0].start];
90                 const char *tok_value = &buf[tokens[i + 1].start];
91
92                 if (!strcmp(tok_attr, attr))
93                         return tok_value;
94         }
95
96         return NULL;
97 }
98
99 static void
100 json_puts_string(const char *s)
101 {
102         static const char json_cntrl[0x20][6] =
103         {
104                 "u0000", "u0001", "u0002", "u0003", "u0004", "u0005", "u0006", "u0007", "b",     "t",     "n",     "u000b", "f",     "r",     "u000e", "u000f",
105                 "u0010", "u0011", "u0012", "u0013", "u0014", "u0015", "u0016", "u0017", "u0018", "u0019", "u001a", "u001b", "u001c", "u001d", "u001e", "u001f"
106         };
107
108         const unsigned char *str = (const unsigned char *) s ? s : "";
109         int i;
110
111         putchar('"');
112         for (i = 0; str[i]; i++)
113         {
114                 if (str[i] < 0x20)
115                 {
116                         putchar('\\');
117                         fputs(json_cntrl[(guint)str[i]], stdout);
118                 }
119                 else
120                 {
121                         if (str[i] == '\\' || str[i] == '"')
122                                 putchar('\\');
123                         putchar(str[i]);
124                 }
125         }
126
127         putchar('"');
128 }
129
130 static void
131 json_print_base64_step(const guint8 *data, int *state1, int *state2)
132 {
133         gchar buf[(1 / 3 + 1) * 4 + 4 + 1];
134         gsize wrote;
135
136         if (data)
137                 wrote = g_base64_encode_step(data, 1, FALSE, buf, state1, state2);
138         else
139                 wrote = g_base64_encode_close(FALSE, buf, state1, state2);
140
141         if (wrote > 0)
142         {
143                 buf[wrote] = '\0';
144                 fputs(buf, stdout);
145         }
146 }
147
148 static void
149 json_print_base64(const guint8 *data, size_t len)
150 {
151         size_t i;
152         int base64_state1 = 0;
153         int base64_state2 = 0;
154
155         putchar('"');
156
157         for (i = 0; i < len; i++)
158                 json_print_base64_step(&data[i], &base64_state1, &base64_state2);
159
160         json_print_base64_step(NULL, &base64_state1, &base64_state2);
161
162         putchar('"');
163 }
164
165 static void G_GNUC_PRINTF(3, 4)
166 sharkd_json_value_anyf(gboolean sepa, const char *key, const char *valuef, ...)
167 {
168         if (sepa)
169                 putchar(',');
170
171         if (key)
172         {
173                 putchar('"');
174                 fputs(key, stdout);
175                 putchar('"');
176                 putchar(':');
177         }
178
179         if (valuef && *valuef)
180         {
181                 va_list ap;
182
183                 va_start(ap, valuef);
184                 vprintf(valuef, ap);
185                 va_end(ap);
186         }
187 }
188
189 static void
190 sharkd_json_value_string(gboolean sepa, const char *key, const char *str)
191 {
192         sharkd_json_value_anyf(sepa, key, NULL);
193         json_puts_string(str);
194 }
195
196 static void
197 sharkd_json_value_base64(gboolean sepa, const char *key, const guint8 *data, size_t len)
198 {
199         sharkd_json_value_anyf(sepa, key, NULL);
200         json_print_base64(data, len);
201 }
202
203 static void G_GNUC_PRINTF(3, 4)
204 sharkd_json_value_stringf(gboolean sepa, const char *key, const char *format, ...)
205 {
206         va_list ap;
207
208         sharkd_json_value_anyf(sepa, key, NULL);
209
210         va_start(ap, format);
211         putchar('"');
212         vprintf(format, ap);
213         putchar('"');
214         va_end(ap);
215 }
216
217 static void
218 sharkd_json_array_open(gboolean sepa, const char *key)
219 {
220         sharkd_json_value_anyf(sepa, key, "[");
221 }
222
223 static void
224 sharkd_json_array_close(void)
225 {
226         putchar(']');
227 }
228
229 static void
230 sharkd_json_object_open(gboolean sepa)
231 {
232         sharkd_json_value_anyf(sepa, NULL, "{");
233 }
234
235 static void
236 sharkd_json_object_close(void)
237 {
238         putchar('}');
239 }
240
241 static void
242 sharkd_json_finish(void)
243 {
244         putchar('\n');
245 }
246
247 static void
248 sharkd_json_simple_reply(int err, const char *errmsg)
249 {
250         sharkd_json_object_open(FALSE);
251         sharkd_json_value_anyf(FALSE, "err", "%d", err);
252         if (errmsg)
253                 sharkd_json_value_string(TRUE, "errmsg", errmsg);
254
255         sharkd_json_object_close();
256         sharkd_json_finish();
257 }
258
259 static void
260 sharkd_session_filter_free(gpointer data)
261 {
262         struct sharkd_filter_item *l = (struct sharkd_filter_item *) data;
263
264         g_free(l->filtered);
265         g_free(l);
266 }
267
268 static const struct sharkd_filter_item *
269 sharkd_session_filter_data(const char *filter)
270 {
271         struct sharkd_filter_item *l;
272
273         l = (struct sharkd_filter_item *) g_hash_table_lookup(filter_table, filter);
274         if (!l)
275         {
276                 guint8 *filtered = NULL;
277
278                 int ret = sharkd_filter(filter, &filtered);
279
280                 if (ret == -1)
281                         return NULL;
282
283                 l = (struct sharkd_filter_item *) g_malloc(sizeof(struct sharkd_filter_item));
284                 l->filtered = filtered;
285
286                 g_hash_table_insert(filter_table, g_strdup(filter), l);
287         }
288
289         return l;
290 }
291
292 static gboolean
293 sharkd_rtp_match_init(rtpstream_id_t *id, const char *init_str)
294 {
295         gboolean ret = FALSE;
296         char **arr;
297         guint32 tmp_addr_src, tmp_addr_dst;
298         address tmp_src_addr, tmp_dst_addr;
299
300         memset(id, 0, sizeof(*id));
301
302         arr = g_strsplit(init_str, "_", 7); /* pass larger value, so we'll catch incorrect input :) */
303         if (g_strv_length(arr) != 5)
304                 goto fail;
305
306         /* TODO, for now only IPv4 */
307         if (!get_host_ipaddr(arr[0], &tmp_addr_src))
308                 goto fail;
309
310         if (!ws_strtou16(arr[1], NULL, &id->src_port))
311                 goto fail;
312
313         if (!get_host_ipaddr(arr[2], &tmp_addr_dst))
314                 goto fail;
315
316         if (!ws_strtou16(arr[3], NULL, &id->dst_port))
317                 goto fail;
318
319         if (!ws_hexstrtou32(arr[4], NULL, &id->ssrc))
320                 goto fail;
321
322         set_address(&tmp_src_addr, AT_IPv4, 4, &tmp_addr_src);
323         copy_address(&id->src_addr, &tmp_src_addr);
324         set_address(&tmp_dst_addr, AT_IPv4, 4, &tmp_addr_dst);
325         copy_address(&id->dst_addr, &tmp_dst_addr);
326
327         ret = TRUE;
328
329 fail:
330         g_strfreev(arr);
331         return ret;
332 }
333
334 static gboolean
335 sharkd_session_process_info_nstat_cb(const void *key, void *value, void *userdata)
336 {
337         stat_tap_table_ui *stat_tap = (stat_tap_table_ui *) value;
338         int *pi = (int *) userdata;
339
340         sharkd_json_object_open(*pi != 0);
341                 sharkd_json_value_string(FALSE, "name", stat_tap->title);
342                 sharkd_json_value_stringf(TRUE, "tap", "nstat:%s", (const char *) key);
343         sharkd_json_object_close();
344
345         *pi = *pi + 1;
346         return FALSE;
347 }
348
349 static gboolean
350 sharkd_session_process_info_conv_cb(const void* key, void* value, void* userdata)
351 {
352         struct register_ct *table = (struct register_ct *) value;
353         int *pi = (int *) userdata;
354
355         const char *label = (const char *) key;
356
357         if (get_conversation_packet_func(table))
358         {
359                 sharkd_json_object_open(*pi != 0);
360                         sharkd_json_value_stringf(FALSE, "name", "Conversation List/%s", label);
361                         sharkd_json_value_stringf(TRUE, "tap", "conv:%s", label);
362                 sharkd_json_object_close();
363
364                 *pi = *pi + 1;
365         }
366
367         if (get_hostlist_packet_func(table))
368         {
369                 sharkd_json_object_open(*pi != 0);
370                         sharkd_json_value_stringf(FALSE, "name", "Endpoint/%s", label);
371                         sharkd_json_value_stringf(TRUE, "tap", "endpt:%s", label);
372                 sharkd_json_object_close();
373
374                 *pi = *pi + 1;
375         }
376         return FALSE;
377 }
378
379 static gboolean
380 sharkd_session_seq_analysis_cb(const void *key, void *value, void *userdata)
381 {
382         register_analysis_t *analysis = (register_analysis_t *) value;
383         int *pi = (int *) userdata;
384
385         sharkd_json_object_open(*pi != 0);
386                 sharkd_json_value_string(FALSE, "name", sequence_analysis_get_ui_name(analysis));
387                 sharkd_json_value_stringf(TRUE, "tap", "seqa:%s", (const char *) key);
388         sharkd_json_object_close();
389
390         *pi = *pi + 1;
391         return FALSE;
392 }
393
394 static gboolean
395 sharkd_export_object_visit_cb(const void *key _U_, void *value, void *user_data)
396 {
397         register_eo_t *eo = (register_eo_t *) value;
398         int *pi = (int *) user_data;
399
400         const int proto_id = get_eo_proto_id(eo);
401         const char *filter = proto_get_protocol_filter_name(proto_id);
402         const char *label  = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
403
404         sharkd_json_object_open(*pi != 0);
405                 sharkd_json_value_stringf(FALSE, "name", "Export Object/%s", label);
406                 sharkd_json_value_stringf(TRUE, "tap", "eo:%s", filter);
407         sharkd_json_object_close();
408
409         *pi = *pi + 1;
410         return FALSE;
411 }
412
413 static gboolean
414 sharkd_srt_visit_cb(const void *key _U_, void *value, void *user_data)
415 {
416         register_srt_t *srt = (register_srt_t *) value;
417         int *pi = (int *) user_data;
418
419         const int proto_id = get_srt_proto_id(srt);
420         const char *filter = proto_get_protocol_filter_name(proto_id);
421         const char *label  = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
422
423         sharkd_json_object_open(*pi != 0);
424                 sharkd_json_value_stringf(FALSE, "name", "Service Response Time/%s", label);
425                 sharkd_json_value_stringf(TRUE, "tap", "srt:%s", filter);
426         sharkd_json_object_close();
427
428         *pi = *pi + 1;
429         return FALSE;
430 }
431
432 static gboolean
433 sharkd_rtd_visit_cb(const void *key _U_, void *value, void *user_data)
434 {
435         register_rtd_t *rtd = (register_rtd_t *) value;
436         int *pi = (int *) user_data;
437
438         const int proto_id = get_rtd_proto_id(rtd);
439         const char *filter = proto_get_protocol_filter_name(proto_id);
440         const char *label  = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
441
442         sharkd_json_object_open(*pi != 0);
443                 sharkd_json_value_stringf(FALSE, "name", "Response Time Delay/%s", label);
444                 sharkd_json_value_stringf(TRUE, "tap", "rtd:%s", filter);
445         sharkd_json_object_close();
446
447         *pi = *pi + 1;
448         return FALSE;
449 }
450
451 static gboolean
452 sharkd_follower_visit_cb(const void *key _U_, void *value, void *user_data)
453 {
454         register_follow_t *follower = (register_follow_t *) value;
455         int *pi = (int *) user_data;
456
457         const int proto_id = get_follow_proto_id(follower);
458         const char *label  = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
459         const char *filter = label; /* correct: get_follow_by_name() is registered by short name */
460
461         sharkd_json_object_open(*pi != 0);
462                 sharkd_json_value_stringf(FALSE, "name", "Follow/%s", label);
463                 sharkd_json_value_stringf(TRUE, "tap", "follow:%s", filter);
464         sharkd_json_object_close();
465
466         *pi = *pi + 1;
467         return FALSE;
468 }
469
470 /**
471  * sharkd_session_process_info()
472  *
473  * Process info request
474  *
475  * Output object with attributes:
476  *   (m) version - version number
477  *
478  *   (m) columns - available column formats, array of object with attributes:
479  *                  'name'   - column name
480  *                  'format' - column format-name
481  *
482  *   (m) stats   - available statistics, array of object with attributes:
483  *                  'name' - statistic name
484  *                  'tap'  - sharkd tap-name for statistic
485  *
486  *   (m) convs   - available conversation list, array of object with attributes:
487  *                  'name' - conversation name
488  *                  'tap'  - sharkd tap-name for conversation
489  *
490  *   (m) eo      - available export object list, array of object with attributes:
491  *                  'name' - export object name
492  *                  'tap'  - sharkd tap-name for eo
493  *
494  *   (m) srt     - available service response time list, array of object with attributes:
495  *                  'name' - service response time name
496  *                  'tap'  - sharkd tap-name for srt
497  *
498  *   (m) rtd     - available response time delay list, array of object with attributes:
499  *                  'name' - response time delay name
500  *                  'tap'  - sharkd tap-name for rtd
501  *
502  *   (m) seqa    - available sequence analysis (flow) list, array of object with attributes:
503  *                  'name' - sequence analysis name
504  *                  'tap'  - sharkd tap-name
505  *
506  *   (m) taps    - available taps, array of object with attributes:
507  *                  'name' - tap name
508  *                  'tap'  - sharkd tap-name
509  *
510  *   (m) follow  - available followers, array of object with attributes:
511  *                  'name' - tap name
512  *                  'tap'  - sharkd tap-name
513  *
514  *   (m) ftypes  - conversation table for FT_ number to string, array of FT_xxx strings.
515  *
516  *   (m) nstat   - available table-based taps, array of object with attributes:
517  *                  'name' - tap name
518  *                  'tap'  - sharkd tap-name
519  *
520  */
521 static void
522 sharkd_session_process_info(void)
523 {
524         int i;
525
526         sharkd_json_object_open(FALSE);
527
528         sharkd_json_array_open(FALSE, "columns");
529         for (i = 0; i < NUM_COL_FMTS; i++)
530         {
531                 const char *col_format = col_format_to_string(i);
532                 const char *col_descr  = col_format_desc(i);
533
534                 sharkd_json_object_open(i != 0);
535                         sharkd_json_value_string(FALSE, "name", col_descr);
536                         sharkd_json_value_string(TRUE, "format", col_format);
537                 sharkd_json_object_close();
538         }
539         sharkd_json_array_close();
540
541         sharkd_json_array_open(TRUE, "stats");
542         {
543                 GList *cfg_list = stats_tree_get_cfg_list();
544                 GList *l;
545                 gboolean sepa = FALSE;
546
547                 for (l = cfg_list; l; l = l->next)
548                 {
549                         stats_tree_cfg *cfg = (stats_tree_cfg *) l->data;
550
551                         sharkd_json_object_open(sepa);
552                                 sharkd_json_value_string(FALSE, "name", cfg->name);
553                                 sharkd_json_value_stringf(TRUE, "tap", "stat:%s", cfg->abbr);
554                         sharkd_json_object_close();
555                         sepa = TRUE;
556                 }
557
558                 g_list_free(cfg_list);
559         }
560         sharkd_json_array_close();
561
562         sharkd_json_array_open(TRUE, "ftypes");
563         for (i = 0; i < FT_NUM_TYPES; i++)
564                 sharkd_json_value_string(i != 0, NULL, ftype_name((ftenum_t) i));
565         sharkd_json_array_close();
566
567         sharkd_json_value_string(TRUE, "version", sharkd_version());
568
569         sharkd_json_array_open(TRUE, "nstat");
570         i = 0;
571         stat_tap_iterate_tables(sharkd_session_process_info_nstat_cb, &i);
572         sharkd_json_array_close();
573
574         sharkd_json_array_open(TRUE, "convs");
575         i = 0;
576         conversation_table_iterate_tables(sharkd_session_process_info_conv_cb, &i);
577         sharkd_json_array_close();
578
579         sharkd_json_array_open(TRUE, "seqa");
580         i = 0;
581         sequence_analysis_table_iterate_tables(sharkd_session_seq_analysis_cb, &i);
582         sharkd_json_array_close();
583
584         sharkd_json_array_open(TRUE, "taps");
585         {
586                 sharkd_json_object_open(FALSE);
587                 sharkd_json_value_string(FALSE, "name", "RTP streams");
588                 sharkd_json_value_string(TRUE, "tap", "rtp-streams");
589                 sharkd_json_object_close();
590
591                 sharkd_json_object_open(TRUE);
592                 sharkd_json_value_string(FALSE, "name", "Expert Information");
593                 sharkd_json_value_string(TRUE, "tap", "expert");
594                 sharkd_json_object_close();
595         }
596         sharkd_json_array_close();
597
598         sharkd_json_array_open(TRUE, "eo");
599         i = 0;
600         eo_iterate_tables(sharkd_export_object_visit_cb, &i);
601         sharkd_json_array_close();
602
603         sharkd_json_array_open(TRUE, "srt");
604         i = 0;
605         srt_table_iterate_tables(sharkd_srt_visit_cb, &i);
606         sharkd_json_array_close();
607
608         sharkd_json_array_open(TRUE, "rtd");
609         i = 0;
610         rtd_table_iterate_tables(sharkd_rtd_visit_cb, &i);
611         sharkd_json_array_close();
612
613         sharkd_json_array_open(TRUE, "follow");
614         i = 0;
615         follow_iterate_followers(sharkd_follower_visit_cb, &i);
616         sharkd_json_array_close();
617
618         sharkd_json_object_close();
619         sharkd_json_finish();
620 }
621
622 /**
623  * sharkd_session_process_load()
624  *
625  * Process load request
626  *
627  * Input:
628  *   (m) file - file to be loaded
629  *
630  * Output object with attributes:
631  *   (m) err - error code
632  */
633 static void
634 sharkd_session_process_load(const char *buf, const jsmntok_t *tokens, int count)
635 {
636         const char *tok_file = json_find_attr(buf, tokens, count, "file");
637         int err = 0;
638
639         fprintf(stderr, "load: filename=%s\n", tok_file);
640
641         if (!tok_file)
642                 return;
643
644         if (sharkd_cf_open(tok_file, WTAP_TYPE_AUTO, FALSE, &err) != CF_OK)
645         {
646                 sharkd_json_simple_reply(err, NULL);
647                 return;
648         }
649
650         TRY
651         {
652                 err = sharkd_load_cap_file();
653         }
654         CATCH(OutOfMemoryError)
655         {
656                 fprintf(stderr, "load: OutOfMemoryError\n");
657                 err = ENOMEM;
658         }
659         ENDTRY;
660
661         sharkd_json_simple_reply(err, NULL);
662 }
663
664 /**
665  * sharkd_session_process_status()
666  *
667  * Process status request
668  *
669  * Output object with attributes:
670  *   (m) frames   - count of currently loaded frames
671  *   (m) duration - time difference between time of first frame, and last loaded frame
672  *   (o) filename - capture filename
673  *   (o) filesize - capture filesize
674  */
675 static void
676 sharkd_session_process_status(void)
677 {
678         sharkd_json_object_open(FALSE);
679
680         sharkd_json_value_anyf(FALSE, "frames", "%u", cfile.count);
681         sharkd_json_value_anyf(TRUE, "duration", "%.9f", nstime_to_sec(&cfile.elapsed_time));
682
683         if (cfile.filename)
684         {
685                 char *name = g_path_get_basename(cfile.filename);
686
687                 sharkd_json_value_string(TRUE, "filename", name);
688                 g_free(name);
689         }
690
691         if (cfile.provider.wth)
692         {
693                 gint64 file_size = wtap_file_size(cfile.provider.wth, NULL);
694
695                 if (file_size > 0)
696                         sharkd_json_value_anyf(TRUE, "filesize", "%" G_GINT64_FORMAT, file_size);
697         }
698
699         sharkd_json_object_close();
700         sharkd_json_finish();
701 }
702
703 struct sharkd_analyse_data
704 {
705         GHashTable *protocols_set;
706         nstime_t *first_time;
707         nstime_t *last_time;
708 };
709
710 static void
711 sharkd_session_process_analyse_cb(epan_dissect_t *edt, proto_tree *tree, struct epan_column_info *cinfo, const GSList *data_src, void *data)
712 {
713         struct sharkd_analyse_data *analyser = (struct sharkd_analyse_data *) data;
714         packet_info *pi = &edt->pi;
715         frame_data *fdata = pi->fd;
716
717         (void) tree;
718         (void) cinfo;
719         (void) data_src;
720
721         if (analyser->first_time == NULL || nstime_cmp(&fdata->abs_ts, analyser->first_time) < 0)
722                 analyser->first_time = &fdata->abs_ts;
723
724         if (analyser->last_time == NULL || nstime_cmp(&fdata->abs_ts, analyser->last_time) > 0)
725                 analyser->last_time = &fdata->abs_ts;
726
727         if (pi->layers)
728         {
729                 wmem_list_frame_t *frame;
730
731                 for (frame = wmem_list_head(pi->layers); frame; frame = wmem_list_frame_next(frame))
732                 {
733                         int proto_id = GPOINTER_TO_UINT(wmem_list_frame_data(frame));
734
735                         if (!g_hash_table_lookup_extended(analyser->protocols_set, GUINT_TO_POINTER(proto_id), NULL, NULL))
736                         {
737                                 guint proto_count = g_hash_table_size(analyser->protocols_set);
738
739                                 g_hash_table_insert(analyser->protocols_set, GUINT_TO_POINTER(proto_id), GUINT_TO_POINTER(proto_id));
740
741                                 sharkd_json_value_string(proto_count != 0, NULL, proto_get_protocol_filter_name(proto_id));
742                         }
743                 }
744         }
745
746 }
747
748 /**
749  * sharkd_session_process_status()
750  *
751  * Process analyse request
752  *
753  * Output object with attributes:
754  *   (m) frames  - count of currently loaded frames
755  *   (m) protocols - protocol list
756  *   (m) first     - earliest frame time
757  *   (m) last      - latest frame time
758  */
759 static void
760 sharkd_session_process_analyse(void)
761 {
762         unsigned int framenum;
763         struct sharkd_analyse_data analyser;
764
765         analyser.first_time = NULL;
766         analyser.last_time  = NULL;
767         analyser.protocols_set = g_hash_table_new(NULL /* g_direct_hash() */, NULL /* g_direct_equal */);
768
769         sharkd_json_object_open(FALSE);
770
771         sharkd_json_value_anyf(FALSE, "frames", "%u", cfile.count);
772
773         sharkd_json_array_open(TRUE, "protocols");
774         for (framenum = 1; framenum <= cfile.count; framenum++)
775                 sharkd_dissect_request(framenum, (framenum != 1) ? 1 : 0, framenum - 1, &sharkd_session_process_analyse_cb, SHARKD_DISSECT_FLAG_NULL, &analyser);
776         sharkd_json_array_close();
777
778         if (analyser.first_time)
779                 sharkd_json_value_anyf(TRUE, "first", "%.9f", nstime_to_sec(analyser.first_time));
780
781         if (analyser.last_time)
782                 sharkd_json_value_anyf(TRUE, "last", "%.9f", nstime_to_sec(analyser.last_time));
783
784         sharkd_json_object_close();
785         sharkd_json_finish();
786
787         g_hash_table_destroy(analyser.protocols_set);
788 }
789
790 static column_info *
791 sharkd_session_create_columns(column_info *cinfo, const char *buf, const jsmntok_t *tokens, int count)
792 {
793         const char *columns_custom[32];
794         guint16 columns_fmt[32];
795         gint16 columns_occur[32];
796
797         int i, cols;
798
799         for (i = 0; i < 32; i++)
800         {
801                 const char *tok_column;
802                 char tok_column_name[64];
803                 char *custom_sepa;
804
805                 ws_snprintf(tok_column_name, sizeof(tok_column_name), "column%d", i);
806                 tok_column = json_find_attr(buf, tokens, count, tok_column_name);
807                 if (tok_column == NULL)
808                         break;
809
810                 columns_custom[i] = NULL;
811                 columns_occur[i] = 0;
812
813                 if ((custom_sepa = strchr(tok_column, ':')))
814                 {
815                         *custom_sepa = '\0'; /* XXX, C abuse: discarding-const */
816
817                         columns_fmt[i] = COL_CUSTOM;
818                         columns_custom[i] = tok_column;
819
820                         if (!ws_strtoi16(custom_sepa + 1, NULL, &columns_occur[i]))
821                                 return NULL;
822                 }
823                 else
824                 {
825                         if (!ws_strtou16(tok_column, NULL, &columns_fmt[i]))
826                                 return NULL;
827
828                         if (columns_fmt[i] >= NUM_COL_FMTS)
829                                 return NULL;
830
831                         /* if custom, that it shouldn't be just custom number -> error */
832                         if (columns_fmt[i] == COL_CUSTOM)
833                                 return NULL;
834                 }
835         }
836
837         cols = i;
838
839         col_setup(cinfo, cols);
840
841         for (i = 0; i < cols; i++)
842         {
843                 col_item_t *col_item = &cinfo->columns[i];
844
845                 col_item->col_fmt = columns_fmt[i];
846                 col_item->col_title = NULL; /* no need for title */
847
848                 if (col_item->col_fmt == COL_CUSTOM)
849                 {
850                         col_item->col_custom_fields = g_strdup(columns_custom[i]);
851                         col_item->col_custom_occurrence = columns_occur[i];
852                 }
853
854                 col_item->col_fence = 0;
855         }
856
857         col_finalize(cinfo);
858
859         return cinfo;
860 }
861
862 /**
863  * sharkd_session_process_frames()
864  *
865  * Process frames request
866  *
867  * Input:
868  *   (o) column0...columnXX - requested columns either number in range [0..NUM_COL_FMTS), or custom (syntax <dfilter>:<occurence>).
869  *                            If column0 is not specified default column set will be used.
870  *   (o) filter - filter to be used
871  *   (o) skip=N   - skip N frames
872  *   (o) limit=N  - show only N frames
873  *   (o) refs  - list (comma separated) with sorted time reference frame numbers.
874  *
875  * Output array of frames with attributes:
876  *   (m) c   - array of column data
877  *   (m) num - frame number
878  *   (o) i   - if frame is ignored
879  *   (o) m   - if frame is marked
880  *   (o) ct  - if frame is commented
881  *   (o) bg  - color filter - background color in hex
882  *   (o) fg  - color filter - foreground color in hex
883  */
884 static void
885 sharkd_session_process_frames(const char *buf, const jsmntok_t *tokens, int count)
886 {
887         const char *tok_filter = json_find_attr(buf, tokens, count, "filter");
888         const char *tok_column = json_find_attr(buf, tokens, count, "column0");
889         const char *tok_skip   = json_find_attr(buf, tokens, count, "skip");
890         const char *tok_limit  = json_find_attr(buf, tokens, count, "limit");
891         const char *tok_refs   = json_find_attr(buf, tokens, count, "refs");
892
893         const guint8 *filter_data = NULL;
894
895         gboolean frame_sepa = FALSE;
896         int col;
897
898         guint32 framenum, prev_dis_num = 0;
899         guint32 current_ref_frame = 0, next_ref_frame = G_MAXUINT32;
900         guint32 skip;
901         guint32 limit;
902
903         column_info *cinfo = &cfile.cinfo;
904         column_info user_cinfo;
905
906         if (tok_column)
907         {
908                 memset(&user_cinfo, 0, sizeof(user_cinfo));
909                 cinfo = sharkd_session_create_columns(&user_cinfo, buf, tokens, count);
910                 if (!cinfo)
911                         return;
912         }
913
914         if (tok_filter)
915         {
916                 const struct sharkd_filter_item *filter_item;
917
918                 filter_item = sharkd_session_filter_data(tok_filter);
919                 if (!filter_item)
920                         return;
921                 filter_data = filter_item->filtered;
922         }
923
924         skip = 0;
925         if (tok_skip)
926         {
927                 if (!ws_strtou32(tok_skip, NULL, &skip))
928                         return;
929         }
930
931         limit = 0;
932         if (tok_limit)
933         {
934                 if (!ws_strtou32(tok_limit, NULL, &limit))
935                         return;
936         }
937
938         if (tok_refs)
939         {
940                 if (!ws_strtou32(tok_refs, &tok_refs, &next_ref_frame))
941                         return;
942         }
943
944         sharkd_json_array_open(FALSE, NULL);
945         for (framenum = 1; framenum <= cfile.count; framenum++)
946         {
947                 frame_data *fdata;
948                 guint32 ref_frame = (framenum != 1) ? 1 : 0;
949
950                 if (filter_data && !(filter_data[framenum / 8] & (1 << (framenum % 8))))
951                         continue;
952
953                 if (skip)
954                 {
955                         skip--;
956                         prev_dis_num = framenum;
957                         continue;
958                 }
959
960                 if (tok_refs)
961                 {
962                         if (framenum >= next_ref_frame)
963                         {
964                                 current_ref_frame = next_ref_frame;
965
966                                 if (*tok_refs != ',')
967                                         next_ref_frame = G_MAXUINT32;
968
969                                 while (*tok_refs == ',' && framenum >= next_ref_frame)
970                                 {
971                                         current_ref_frame = next_ref_frame;
972
973                                         if (!ws_strtou32(tok_refs + 1, &tok_refs, &next_ref_frame))
974                                         {
975                                                 fprintf(stderr, "sharkd_session_process_frames() wrong format for refs: %s\n", tok_refs);
976                                                 break;
977                                         }
978                                 }
979
980                                 if (*tok_refs == '\0' && framenum >= next_ref_frame)
981                                 {
982                                         current_ref_frame = next_ref_frame;
983                                         next_ref_frame = G_MAXUINT32;
984                                 }
985                         }
986
987                         if (current_ref_frame)
988                                 ref_frame = current_ref_frame;
989                 }
990
991                 fdata = sharkd_get_frame(framenum);
992                 sharkd_dissect_columns(fdata, ref_frame, prev_dis_num, cinfo, (fdata->color_filter == NULL));
993
994                 sharkd_json_object_open(frame_sepa);
995
996                 sharkd_json_array_open(FALSE, "c");
997                 for (col = 0; col < cinfo->num_cols; ++col)
998                 {
999                         const col_item_t *col_item = &cinfo->columns[col];
1000
1001                         sharkd_json_value_string(col != 0, NULL, col_item->col_data);
1002                 }
1003                 sharkd_json_array_close();
1004
1005                 sharkd_json_value_anyf(TRUE, "num", "%u", framenum);
1006
1007                 if (fdata->has_user_comment || fdata->has_phdr_comment)
1008                 {
1009                         if (!fdata->has_user_comment || sharkd_get_user_comment(fdata) != NULL)
1010                                 sharkd_json_value_anyf(TRUE, "ct", "true");
1011                 }
1012
1013                 if (fdata->ignored)
1014                         sharkd_json_value_anyf(TRUE, "i", "true");
1015
1016                 if (fdata->marked)
1017                         sharkd_json_value_anyf(TRUE, "m", "true");
1018
1019                 if (fdata->color_filter)
1020                 {
1021                         sharkd_json_value_stringf(TRUE, "bg", "%x", color_t_to_rgb(&fdata->color_filter->bg_color));
1022                         sharkd_json_value_stringf(TRUE, "fg", "%x", color_t_to_rgb(&fdata->color_filter->fg_color));
1023                 }
1024
1025                 sharkd_json_object_close();
1026                 frame_sepa = TRUE;
1027                 prev_dis_num = framenum;
1028
1029                 if (limit && --limit == 0)
1030                         break;
1031         }
1032         sharkd_json_array_close();
1033         sharkd_json_finish();
1034
1035         if (cinfo != &cfile.cinfo)
1036                 col_cleanup(cinfo);
1037 }
1038
1039 static void
1040 sharkd_session_process_tap_stats_node_cb(const stat_node *n)
1041 {
1042         stat_node *node;
1043         gboolean sepa = FALSE;
1044
1045         sharkd_json_array_open(FALSE, NULL);
1046         for (node = n->children; node; node = node->next)
1047         {
1048                 sharkd_json_object_open(sepa);
1049
1050                 /* code based on stats_tree_get_values_from_node() */
1051                 sharkd_json_value_string(FALSE, "name", node->name);
1052                 sharkd_json_value_anyf(TRUE, "count", "%d", node->counter);
1053                 if (node->counter && ((node->st_flags & ST_FLG_AVERAGE) || node->rng))
1054                 {
1055                         sharkd_json_value_anyf(TRUE, "avg", "%.2f", ((float)node->total) / node->counter);
1056                         sharkd_json_value_anyf(TRUE, "min", "%d", node->minvalue);
1057                         sharkd_json_value_anyf(TRUE, "max", "%d", node->maxvalue);
1058                 }
1059
1060                 if (node->st->elapsed)
1061                         sharkd_json_value_anyf(TRUE, "rate", "%.4f", ((float)node->counter) / node->st->elapsed);
1062
1063                 if (node->parent && node->parent->counter)
1064                         sharkd_json_value_anyf(TRUE, "perc", "%.2f", (node->counter * 100.0) / node->parent->counter);
1065                 else if (node->parent == &(node->st->root))
1066                         sharkd_json_value_anyf(TRUE, "perc", "100");
1067
1068                 if (prefs.st_enable_burstinfo && node->max_burst)
1069                 {
1070                         if (prefs.st_burst_showcount)
1071                                 sharkd_json_value_anyf(TRUE, "burstcount", "%d", node->max_burst);
1072                         else
1073                                 sharkd_json_value_anyf(TRUE, "burstrate", "%.4f", ((double)node->max_burst) / prefs.st_burst_windowlen);
1074
1075                         sharkd_json_value_anyf(TRUE, "bursttime", "%.3f", ((double)node->burst_time / 1000.0));
1076                 }
1077
1078                 if (node->children)
1079                 {
1080                         sharkd_json_value_anyf(TRUE, "sub", NULL);
1081                         sharkd_session_process_tap_stats_node_cb(node);
1082                 }
1083                 sharkd_json_object_close();
1084                 sepa = TRUE;
1085         }
1086         sharkd_json_array_close();
1087 }
1088
1089 /**
1090  * sharkd_session_process_tap_stats_cb()
1091  *
1092  * Output stats tap:
1093  *
1094  *   (m) tap        - tap name
1095  *   (m) type:stats - tap output type
1096  *   (m) name       - stat name
1097  *   (m) stats      - array of object with attributes:
1098  *                  (m) name       - stat item name
1099  *                  (m) count      - stat item counter
1100  *                  (o) avg        - stat item averange value
1101  *                  (o) min        - stat item min value
1102  *                  (o) max        - stat item max value
1103  *                  (o) rate       - stat item rate value (ms)
1104  *                  (o) perc       - stat item percentage
1105  *                  (o) burstrate  - stat item burst rate
1106  *                  (o) burstcount - stat item burst count
1107  *                  (o) burstttme  - stat item burst start
1108  *                  (o) sub        - array of object with attributes like in stats node.
1109  */
1110 static void
1111 sharkd_session_process_tap_stats_cb(void *psp)
1112 {
1113         stats_tree *st = (stats_tree *) psp;
1114
1115         sharkd_json_object_open(FALSE);
1116
1117         sharkd_json_value_stringf(FALSE, "tap", "stats:%s", st->cfg->abbr);
1118         sharkd_json_value_string(TRUE, "type", "stats");
1119         sharkd_json_value_string(TRUE, "name", st->cfg->name);
1120
1121         sharkd_json_value_anyf(TRUE, "stats", NULL);
1122         sharkd_session_process_tap_stats_node_cb(&st->root);
1123
1124         sharkd_json_object_close();
1125         putchar(',');
1126 }
1127
1128 static void
1129 sharkd_session_free_tap_stats_cb(void *psp)
1130 {
1131         stats_tree *st = (stats_tree *) psp;
1132
1133         stats_tree_free(st);
1134 }
1135
1136 struct sharkd_expert_tap
1137 {
1138         GSList *details;
1139         GStringChunk *text;
1140 };
1141
1142 /**
1143  * sharkd_session_process_tap_expert_cb()
1144  *
1145  * Output expert tap:
1146  *
1147  *   (m) tap         - tap name
1148  *   (m) type:expert - tap output type
1149  *   (m) details     - array of object with attributes:
1150  *                  (m) f - frame number, which generated expert information
1151  *                  (o) s - severity
1152  *                  (o) g - group
1153  *                  (m) m - expert message
1154  *                  (o) p - protocol
1155  */
1156 static void
1157 sharkd_session_process_tap_expert_cb(void *tapdata)
1158 {
1159         struct sharkd_expert_tap *etd = (struct sharkd_expert_tap *) tapdata;
1160         GSList *list;
1161         gboolean sepa = FALSE;
1162
1163         sharkd_json_object_open(FALSE);
1164
1165         sharkd_json_value_string(FALSE, "tap", "expert");
1166         sharkd_json_value_string(TRUE, "type", "expert");
1167
1168         sharkd_json_array_open(TRUE, "details");
1169         for (list = etd->details; list; list = list->next)
1170         {
1171                 expert_info_t *ei = (expert_info_t *) list->data;
1172                 const char *tmp;
1173
1174                 sharkd_json_object_open(sepa);
1175
1176                 sharkd_json_value_anyf(FALSE, "f", "%u", ei->packet_num);
1177
1178                 tmp = try_val_to_str(ei->severity, expert_severity_vals);
1179                 if (tmp)
1180                         sharkd_json_value_string(TRUE, "s", tmp);
1181
1182                 tmp = try_val_to_str(ei->group, expert_group_vals);
1183                 if (tmp)
1184                         sharkd_json_value_string(TRUE, "g", tmp);
1185
1186                 sharkd_json_value_string(TRUE, "m", ei->summary);
1187
1188                 if (ei->protocol)
1189                         sharkd_json_value_string(TRUE, "p", ei->protocol);
1190
1191                 sharkd_json_object_close();
1192                 sepa = TRUE;
1193         }
1194         sharkd_json_array_close();
1195
1196         sharkd_json_object_close();
1197         putchar(',');
1198 }
1199
1200 static gboolean
1201 sharkd_session_packet_tap_expert_cb(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *pointer)
1202 {
1203         struct sharkd_expert_tap *etd = (struct sharkd_expert_tap *) tapdata;
1204         const expert_info_t *ei       = (const expert_info_t *) pointer;
1205         expert_info_t *ei_copy;
1206
1207         if (ei == NULL)
1208                 return FALSE;
1209
1210         ei_copy = g_new(expert_info_t, 1);
1211         /* Note: this is a shallow copy */
1212         *ei_copy = *ei;
1213
1214         /* ei->protocol, ei->summary might be allocated in packet scope, make a copy. */
1215         ei_copy->protocol = g_string_chunk_insert_const(etd->text, ei_copy->protocol);
1216         ei_copy->summary  = g_string_chunk_insert_const(etd->text, ei_copy->summary);
1217
1218         etd->details = g_slist_prepend(etd->details, ei_copy);
1219
1220         return TRUE;
1221 }
1222
1223 static void
1224 sharkd_session_free_tap_expert_cb(void *tapdata)
1225 {
1226         struct sharkd_expert_tap *etd = (struct sharkd_expert_tap *) tapdata;
1227
1228         g_slist_free_full(etd->details, g_free);
1229         g_string_chunk_free(etd->text);
1230         g_free(etd);
1231 }
1232
1233 /**
1234  * sharkd_session_process_tap_flow_cb()
1235  *
1236  * Output flow tap:
1237  *   (m) tap         - tap name
1238  *   (m) type:flow   - tap output type
1239  *   (m) nodes       - array of strings with node address
1240  *   (m) flows       - array of object with attributes:
1241  *                  (m) t  - frame time string
1242  *                  (m) n  - array of two numbers with source node index and destination node index
1243  *                  (m) pn - array of two numbers with source and destination port
1244  *                  (o) c  - comment
1245  */
1246 static void
1247 sharkd_session_process_tap_flow_cb(void *tapdata)
1248 {
1249         seq_analysis_info_t *graph_analysis = (seq_analysis_info_t *) tapdata;
1250         GList *flow_list;
1251         guint i;
1252
1253         gboolean sepa = FALSE;
1254
1255         sequence_analysis_get_nodes(graph_analysis);
1256
1257         sharkd_json_object_open(FALSE);
1258         sharkd_json_value_stringf(FALSE, "tap", "seqa:%s", graph_analysis->name);
1259         sharkd_json_value_string(TRUE, "type", "flow");
1260
1261         sharkd_json_array_open(TRUE, "nodes");
1262         for (i = 0; i < graph_analysis->num_nodes; i++)
1263         {
1264                 char *addr_str;
1265
1266                 addr_str = address_to_display(NULL, &(graph_analysis->nodes[i]));
1267                 sharkd_json_value_string(i != 0, NULL, addr_str);
1268                 wmem_free(NULL, addr_str);
1269         }
1270         sharkd_json_array_close();
1271
1272         sharkd_json_array_open(TRUE, "flows");
1273         flow_list = g_queue_peek_nth_link(graph_analysis->items, 0);
1274         while (flow_list)
1275         {
1276                 seq_analysis_item_t *sai = (seq_analysis_item_t *) flow_list->data;
1277
1278                 flow_list = g_list_next(flow_list);
1279
1280                 if (!sai->display)
1281                         continue;
1282
1283                 sharkd_json_object_open(sepa);
1284
1285                 sharkd_json_value_string(FALSE, "t", sai->time_str);
1286                 sharkd_json_value_anyf(TRUE, "n", "[%u,%u]", sai->src_node, sai->dst_node);
1287                 sharkd_json_value_anyf(TRUE, "pn", "[%u,%u]", sai->port_src, sai->port_dst);
1288
1289                 if (sai->comment)
1290                         sharkd_json_value_string(TRUE, "c", sai->comment);
1291
1292                 sharkd_json_object_close();
1293                 sepa = TRUE;
1294         }
1295         sharkd_json_array_close();
1296
1297         sharkd_json_object_close();
1298         putchar(',');
1299 }
1300
1301 static void
1302 sharkd_session_free_tap_flow_cb(void *tapdata)
1303 {
1304         seq_analysis_info_t *graph_analysis = (seq_analysis_info_t *) tapdata;
1305
1306         sequence_analysis_info_free(graph_analysis);
1307 }
1308
1309 struct sharkd_conv_tap_data
1310 {
1311         const char *type;
1312         conv_hash_t hash;
1313         gboolean resolve_name;
1314         gboolean resolve_port;
1315 };
1316
1317 static gboolean
1318 sharkd_session_geoip_addr(address *addr, const char *suffix)
1319 {
1320         const mmdb_lookup_t *lookup = NULL;
1321         gboolean with_geoip = FALSE;
1322         char json_key[64];
1323
1324         if (addr->type == AT_IPv4)
1325         {
1326                 guint32 ip;
1327
1328                 memcpy(&ip, addr->data, 4);
1329                 lookup = maxmind_db_lookup_ipv4(ip);
1330         }
1331         else if (addr->type == AT_IPv6)
1332         {
1333                 const ws_in6_addr *ip6 = (const ws_in6_addr *) addr->data;
1334
1335                 lookup = maxmind_db_lookup_ipv6(ip6);
1336         }
1337
1338         if (!lookup || !lookup->found)
1339                 return FALSE;
1340
1341         if (lookup->country)
1342         {
1343                 snprintf(json_key, sizeof(json_key), "geoip_country%s", suffix);
1344                 sharkd_json_value_string(TRUE, json_key, lookup->country);
1345                 with_geoip = TRUE;
1346         }
1347
1348         if (lookup->country_iso)
1349         {
1350                 snprintf(json_key, sizeof(json_key), "geoip_country_iso%s", suffix);
1351                 sharkd_json_value_string(TRUE, json_key, lookup->country_iso);
1352                 with_geoip = TRUE;
1353         }
1354
1355         if (lookup->city)
1356         {
1357                 snprintf(json_key, sizeof(json_key), "geoip_city%s", suffix);
1358                 sharkd_json_value_string(TRUE, json_key, lookup->city);
1359                 with_geoip = TRUE;
1360         }
1361
1362         if (lookup->as_org)
1363         {
1364                 snprintf(json_key, sizeof(json_key), "geoip_as_org%s", suffix);
1365                 sharkd_json_value_string(TRUE, json_key, lookup->as_org);
1366                 with_geoip = TRUE;
1367         }
1368
1369         if (lookup->as_number > 0)
1370         {
1371                 snprintf(json_key, sizeof(json_key), "geoip_as%s", suffix);
1372                 sharkd_json_value_anyf(TRUE, json_key, "%u", lookup->as_number);
1373                 with_geoip = TRUE;
1374         }
1375
1376         if (lookup->latitude >= -90.0 && lookup->latitude <= 90.0)
1377         {
1378                 snprintf(json_key, sizeof(json_key), "geoip_lat%s", suffix);
1379                 sharkd_json_value_anyf(TRUE, json_key, "%f", lookup->latitude);
1380                 with_geoip = TRUE;
1381         }
1382
1383         if (lookup->longitude >= -180.0 && lookup->longitude <= 180.0)
1384         {
1385                 snprintf(json_key, sizeof(json_key), "geoip_lon%s", suffix);
1386                 sharkd_json_value_anyf(TRUE, json_key, "%f", lookup->longitude);
1387                 with_geoip = TRUE;
1388         }
1389
1390         return with_geoip;
1391 }
1392
1393 struct sharkd_analyse_rtp_items
1394 {
1395         guint32 frame_num;
1396         guint32 sequence_num;
1397
1398         double delta;
1399         double jitter;
1400         double skew;
1401         double bandwidth;
1402         gboolean marker;
1403
1404         double arrive_offset;
1405
1406         /* from tap_rtp_stat_t */
1407         guint32 flags;
1408         guint16 pt;
1409 };
1410
1411 struct sharkd_analyse_rtp
1412 {
1413         const char *tap_name;
1414         rtpstream_id_t id;
1415
1416         GSList *packets;
1417         double start_time;
1418         tap_rtp_stat_t statinfo;
1419 };
1420
1421 static void
1422 sharkd_session_process_tap_rtp_free_cb(void *tapdata)
1423 {
1424         struct sharkd_analyse_rtp *rtp_req = (struct sharkd_analyse_rtp *) tapdata;
1425
1426         g_slist_free_full(rtp_req->packets, g_free);
1427         g_free(rtp_req);
1428 }
1429
1430 static gboolean
1431 sharkd_session_packet_tap_rtp_analyse_cb(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_, const void *pointer)
1432 {
1433         struct sharkd_analyse_rtp *rtp_req = (struct sharkd_analyse_rtp *) tapdata;
1434         const struct _rtp_info *rtp_info = (const struct _rtp_info *) pointer;
1435
1436         if (rtpstream_id_equal_pinfo_rtp_info(&rtp_req->id, pinfo, rtp_info))
1437         {
1438                 tap_rtp_stat_t *statinfo = &(rtp_req->statinfo);
1439                 struct sharkd_analyse_rtp_items *item;
1440
1441                 rtppacket_analyse(statinfo, pinfo, rtp_info);
1442
1443                 item = (struct sharkd_analyse_rtp_items *) g_malloc(sizeof(struct sharkd_analyse_rtp_items));
1444
1445                 if (!rtp_req->packets)
1446                         rtp_req->start_time = nstime_to_sec(&pinfo->abs_ts);
1447
1448                 item->frame_num    = pinfo->num;
1449                 item->sequence_num = rtp_info->info_seq_num;
1450                 item->delta        = (statinfo->flags & STAT_FLAG_FIRST) ? 0.0 : statinfo->delta;
1451                 item->jitter       = (statinfo->flags & STAT_FLAG_FIRST) ? 0.0 : statinfo->jitter;
1452                 item->skew         = (statinfo->flags & STAT_FLAG_FIRST) ? 0.0 : statinfo->skew;
1453                 item->bandwidth    = statinfo->bandwidth;
1454                 item->marker       = rtp_info->info_marker_set ? TRUE : FALSE;
1455                 item->arrive_offset= nstime_to_sec(&pinfo->abs_ts) - rtp_req->start_time;
1456
1457                 item->flags = statinfo->flags;
1458                 item->pt    = statinfo->pt;
1459
1460                 /* XXX, O(n) optimize */
1461                 rtp_req->packets = g_slist_append(rtp_req->packets, item);
1462         }
1463
1464         return TRUE;
1465 }
1466
1467 /**
1468  * sharkd_session_process_tap_rtp_analyse_cb()
1469  *
1470  * Output rtp analyse tap:
1471  *   (m) tap   - tap name
1472  *   (m) type  - tap output type
1473  *   (m) ssrc         - RTP SSRC
1474  *   (m) max_delta    - Max delta (ms)
1475  *   (m) max_delta_nr - Max delta packet #
1476  *   (m) max_jitter   - Max jitter (ms)
1477  *   (m) mean_jitter  - Mean jitter (ms)
1478  *   (m) max_skew     - Max skew (ms)
1479  *   (m) total_nr     - Total number of RTP packets
1480  *   (m) seq_err      - Number of sequence errors
1481  *   (m) duration     - Duration (ms)
1482  *   (m) items      - array of object with attributes:
1483  *                  (m) f    - frame number
1484  *                  (m) o    - arrive offset
1485  *                  (m) sn   - sequence number
1486  *                  (m) d    - delta
1487  *                  (m) j    - jitter
1488  *                  (m) sk   - skew
1489  *                  (m) bw   - bandwidth
1490  *                  (o) s    - status string
1491  *                  (o) t    - status type
1492  *                  (o) mark - rtp mark
1493  */
1494 static void
1495 sharkd_session_process_tap_rtp_analyse_cb(void *tapdata)
1496 {
1497         const int RTP_TYPE_CN       = 1;
1498         const int RTP_TYPE_ERROR    = 2;
1499         const int RTP_TYPE_WARN     = 3;
1500         const int RTP_TYPE_PT_EVENT = 4;
1501
1502         const struct sharkd_analyse_rtp *rtp_req = (struct sharkd_analyse_rtp *) tapdata;
1503         const tap_rtp_stat_t *statinfo = &rtp_req->statinfo;
1504
1505         gboolean sepa = FALSE;
1506         GSList *l;
1507
1508         sharkd_json_object_open(FALSE);
1509
1510         sharkd_json_value_string(FALSE, "tap", rtp_req->tap_name);
1511         sharkd_json_value_string(TRUE, "type", "rtp-analyse");
1512         sharkd_json_value_anyf(TRUE, "ssrc", "%u", rtp_req->id.ssrc);
1513
1514         sharkd_json_value_anyf(TRUE, "max_delta", "%f", statinfo->max_delta);
1515         sharkd_json_value_anyf(TRUE, "max_delta_nr", "%u", statinfo->max_nr);
1516         sharkd_json_value_anyf(TRUE, "max_jitter", "%f", statinfo->max_jitter);
1517         sharkd_json_value_anyf(TRUE, "mean_jitter", "%f", statinfo->mean_jitter);
1518         sharkd_json_value_anyf(TRUE, "max_skew", "%f", statinfo->max_skew);
1519         sharkd_json_value_anyf(TRUE, "total_nr", "%u", statinfo->total_nr);
1520         sharkd_json_value_anyf(TRUE, "seq_err", "%u", statinfo->sequence);
1521         sharkd_json_value_anyf(TRUE, "duration", "%f", statinfo->time - statinfo->start_time);
1522
1523         sharkd_json_array_open(TRUE, "items");
1524         for (l = rtp_req->packets; l; l = l->next)
1525         {
1526                 struct sharkd_analyse_rtp_items *item = (struct sharkd_analyse_rtp_items *) l->data;
1527
1528                 sharkd_json_object_open(sepa);
1529
1530                 sharkd_json_value_anyf(FALSE, "f", "%u", item->frame_num);
1531                 sharkd_json_value_anyf(TRUE, "o", "%.9f", item->arrive_offset);
1532                 sharkd_json_value_anyf(TRUE, "sn", "%u", item->sequence_num);
1533                 sharkd_json_value_anyf(TRUE, "d", "%.2f", item->delta);
1534                 sharkd_json_value_anyf(TRUE, "j", "%.2f", item->jitter);
1535                 sharkd_json_value_anyf(TRUE, "sk", "%.2f", item->skew);
1536                 sharkd_json_value_anyf(TRUE, "bw", "%.2f", item->bandwidth);
1537
1538                 if (item->pt == PT_CN)
1539                 {
1540                         sharkd_json_value_string(TRUE, "s", "Comfort noise (PT=13, RFC 3389)");
1541                         sharkd_json_value_anyf(TRUE, "t", "%d", RTP_TYPE_CN);
1542                 }
1543                 else if (item->pt == PT_CN_OLD)
1544                 {
1545                         sharkd_json_value_string(TRUE, "s", "Comfort noise (PT=19, reserved)");
1546                         sharkd_json_value_anyf(TRUE, "t", "%d", RTP_TYPE_CN);
1547                 }
1548                 else if (item->flags & STAT_FLAG_WRONG_SEQ)
1549                 {
1550                         sharkd_json_value_string(TRUE, "s", "Wrong sequence number");
1551                         sharkd_json_value_anyf(TRUE, "t", "%d", RTP_TYPE_ERROR);
1552                 }
1553                 else if (item->flags & STAT_FLAG_DUP_PKT)
1554                 {
1555                         sharkd_json_value_string(TRUE, "s", "Suspected duplicate (MAC address) only delta time calculated");
1556                         sharkd_json_value_anyf(TRUE, "t", "%d", RTP_TYPE_WARN);
1557                 }
1558                 else if (item->flags & STAT_FLAG_REG_PT_CHANGE)
1559                 {
1560                         sharkd_json_value_stringf(TRUE, "s", "Payload changed to PT=%u%s",
1561                                 item->pt,
1562                                 (item->flags & STAT_FLAG_PT_T_EVENT) ? " telephone/event" : "");
1563                         sharkd_json_value_anyf(TRUE, "t", "%d", RTP_TYPE_WARN);
1564                 }
1565                 else if (item->flags & STAT_FLAG_WRONG_TIMESTAMP)
1566                 {
1567                         sharkd_json_value_string(TRUE, "s", "Incorrect timestamp");
1568                         sharkd_json_value_anyf(TRUE, "t", "%d", RTP_TYPE_WARN);
1569                 }
1570                 else if ((item->flags & STAT_FLAG_PT_CHANGE)
1571                         &&  !(item->flags & STAT_FLAG_FIRST)
1572                         &&  !(item->flags & STAT_FLAG_PT_CN)
1573                         &&  (item->flags & STAT_FLAG_FOLLOW_PT_CN)
1574                         &&  !(item->flags & STAT_FLAG_MARKER))
1575                 {
1576                         sharkd_json_value_string(TRUE, "s", "Marker missing?");
1577                         sharkd_json_value_anyf(TRUE, "t", "%d", RTP_TYPE_WARN);
1578                 }
1579                 else if (item->flags & STAT_FLAG_PT_T_EVENT)
1580                 {
1581                         sharkd_json_value_stringf(TRUE, "s", "PT=%u telephone/event", item->pt);
1582                         sharkd_json_value_anyf(TRUE, "t", "%d", RTP_TYPE_PT_EVENT);
1583                 }
1584                 else if (item->flags & STAT_FLAG_MARKER)
1585                 {
1586                         sharkd_json_value_anyf(TRUE, "t", "%d", RTP_TYPE_WARN);
1587                 }
1588
1589                 if (item->marker)
1590                         sharkd_json_value_anyf(TRUE, "mark", "1");
1591
1592                 sharkd_json_object_close();
1593                 sepa = TRUE;
1594         }
1595         sharkd_json_array_close();
1596
1597         sharkd_json_object_close();
1598         putchar(',');
1599 }
1600
1601 /**
1602  * sharkd_session_process_tap_conv_cb()
1603  *
1604  * Output conv tap:
1605  *   (m) tap        - tap name
1606  *   (m) type       - tap output type
1607  *   (m) proto      - protocol short name
1608  *   (o) filter     - filter string
1609  *   (o) geoip      - whether GeoIP information is available, boolean
1610  *
1611  *   (o) convs      - array of object with attributes:
1612  *                  (m) saddr - source address
1613  *                  (m) daddr - destination address
1614  *                  (o) sport - source port
1615  *                  (o) dport - destination port
1616  *                  (m) txf   - TX frame count
1617  *                  (m) txb   - TX bytes
1618  *                  (m) rxf   - RX frame count
1619  *                  (m) rxb   - RX bytes
1620  *                  (m) start - (relative) first packet time
1621  *                  (m) stop  - (relative) last packet time
1622  *                  (o) filter - conversation filter
1623  *
1624  *   (o) hosts      - array of object with attributes:
1625  *                  (m) host - host address
1626  *                  (o) port - host port
1627  *                  (m) txf  - TX frame count
1628  *                  (m) txb  - TX bytes
1629  *                  (m) rxf  - RX frame count
1630  *                  (m) rxb  - RX bytes
1631  */
1632 static void
1633 sharkd_session_process_tap_conv_cb(void *arg)
1634 {
1635         conv_hash_t *hash = (conv_hash_t *) arg;
1636         const struct sharkd_conv_tap_data *iu = (struct sharkd_conv_tap_data *) hash->user_data;
1637         const char *proto;
1638         int proto_with_port;
1639         guint i;
1640
1641         int with_geoip = 0;
1642
1643         sharkd_json_object_open(FALSE);
1644         sharkd_json_value_string(FALSE, "tap", iu->type);
1645
1646         if (!strncmp(iu->type, "conv:", 5))
1647         {
1648                 sharkd_json_value_string(TRUE, "type", "conv");
1649                 sharkd_json_array_open(TRUE, "convs");
1650                 proto = iu->type + 5;
1651         }
1652         else if (!strncmp(iu->type, "endpt:", 6))
1653         {
1654                 sharkd_json_value_string(TRUE, "type", "host");
1655                 sharkd_json_array_open(TRUE, "hosts");
1656                 proto = iu->type + 6;
1657         }
1658         else
1659         {
1660                 sharkd_json_value_string(TRUE, "type", "err");
1661                 proto = "";
1662         }
1663
1664         proto_with_port = (!strcmp(proto, "TCP") || !strcmp(proto, "UDP") || !strcmp(proto, "SCTP"));
1665
1666         if (iu->hash.conv_array != NULL && !strncmp(iu->type, "conv:", 5))
1667         {
1668                 for (i = 0; i < iu->hash.conv_array->len; i++)
1669                 {
1670                         conv_item_t *iui = &g_array_index(iu->hash.conv_array, conv_item_t, i);
1671                         char *src_addr, *dst_addr;
1672                         char *src_port, *dst_port;
1673                         char *filter_str;
1674
1675                         sharkd_json_object_open(i != 0);
1676
1677                         sharkd_json_value_string(FALSE, "saddr", (src_addr = get_conversation_address(NULL, &iui->src_address, iu->resolve_name)));
1678                         sharkd_json_value_string(TRUE,  "daddr", (dst_addr = get_conversation_address(NULL, &iui->dst_address, iu->resolve_name)));
1679
1680                         if (proto_with_port)
1681                         {
1682                                 sharkd_json_value_string(TRUE, "sport", (src_port = get_conversation_port(NULL, iui->src_port, iui->etype, iu->resolve_port)));
1683                                 sharkd_json_value_string(TRUE, "dport", (dst_port = get_conversation_port(NULL, iui->dst_port, iui->etype, iu->resolve_port)));
1684
1685                                 wmem_free(NULL, src_port);
1686                                 wmem_free(NULL, dst_port);
1687                         }
1688
1689                         sharkd_json_value_anyf(TRUE, "rxf", "%" G_GUINT64_FORMAT, iui->rx_frames);
1690                         sharkd_json_value_anyf(TRUE, "rxb", "%" G_GUINT64_FORMAT, iui->rx_bytes);
1691
1692                         sharkd_json_value_anyf(TRUE, "txf", "%" G_GUINT64_FORMAT, iui->tx_frames);
1693                         sharkd_json_value_anyf(TRUE, "txb", "%" G_GUINT64_FORMAT, iui->tx_bytes);
1694
1695                         sharkd_json_value_anyf(TRUE, "start", "%.9f", nstime_to_sec(&iui->start_time));
1696                         sharkd_json_value_anyf(TRUE, "stop", "%.9f", nstime_to_sec(&iui->stop_time));
1697
1698                         filter_str = get_conversation_filter(iui, CONV_DIR_A_TO_FROM_B);
1699                         if (filter_str)
1700                         {
1701                                 sharkd_json_value_string(TRUE, "filter", filter_str);
1702                                 g_free(filter_str);
1703                         }
1704
1705                         wmem_free(NULL, src_addr);
1706                         wmem_free(NULL, dst_addr);
1707
1708                         if (sharkd_session_geoip_addr(&(iui->src_address), "1"))
1709                                 with_geoip = 1;
1710                         if (sharkd_session_geoip_addr(&(iui->dst_address), "2"))
1711                                 with_geoip = 1;
1712
1713                         sharkd_json_object_close();
1714                 }
1715         }
1716         else if (iu->hash.conv_array != NULL && !strncmp(iu->type, "endpt:", 6))
1717         {
1718                 for (i = 0; i < iu->hash.conv_array->len; i++)
1719                 {
1720                         hostlist_talker_t *host = &g_array_index(iu->hash.conv_array, hostlist_talker_t, i);
1721                         char *host_str, *port_str;
1722                         char *filter_str;
1723
1724                         sharkd_json_object_open(i != 0);
1725
1726                         sharkd_json_value_string(FALSE, "host", (host_str = get_conversation_address(NULL, &host->myaddress, iu->resolve_name)));
1727
1728                         if (proto_with_port)
1729                         {
1730                                 sharkd_json_value_string(TRUE, "port", (port_str = get_conversation_port(NULL, host->port, host->etype, iu->resolve_port)));
1731
1732                                 wmem_free(NULL, port_str);
1733                         }
1734
1735                         sharkd_json_value_anyf(TRUE, "rxf", "%" G_GUINT64_FORMAT, host->rx_frames);
1736                         sharkd_json_value_anyf(TRUE, "rxb", "%" G_GUINT64_FORMAT, host->rx_bytes);
1737
1738                         sharkd_json_value_anyf(TRUE, "txf", "%" G_GUINT64_FORMAT, host->tx_frames);
1739                         sharkd_json_value_anyf(TRUE, "txb", "%" G_GUINT64_FORMAT, host->tx_bytes);
1740
1741                         filter_str = get_hostlist_filter(host);
1742                         if (filter_str)
1743                         {
1744                                 sharkd_json_value_string(TRUE, "filter", filter_str);
1745                                 g_free(filter_str);
1746                         }
1747
1748                         wmem_free(NULL, host_str);
1749
1750                         if (sharkd_session_geoip_addr(&(host->myaddress), ""))
1751                                 with_geoip = 1;
1752                         sharkd_json_object_close();
1753                 }
1754         }
1755         sharkd_json_array_close();
1756
1757         sharkd_json_value_string(TRUE, "proto", proto);
1758         sharkd_json_value_anyf(TRUE, "geoip", with_geoip ? "true" : "false");
1759
1760         sharkd_json_object_close();
1761         putchar(',');
1762 }
1763
1764 static void
1765 sharkd_session_free_tap_conv_cb(void *arg)
1766 {
1767         conv_hash_t *hash = (conv_hash_t *) arg;
1768         struct sharkd_conv_tap_data *iu = (struct sharkd_conv_tap_data *) hash->user_data;
1769
1770         if (!strncmp(iu->type, "conv:", 5))
1771         {
1772                 reset_conversation_table_data(hash);
1773         }
1774         else if (!strncmp(iu->type, "endpt:", 6))
1775         {
1776                 reset_hostlist_table_data(hash);
1777         }
1778
1779         g_free(iu);
1780 }
1781
1782 /**
1783  * sharkd_session_process_tap_nstat_cb()
1784  *
1785  * Output nstat tap:
1786  *   (m) tap        - tap name
1787  *   (m) type       - tap output type
1788  *   (m) fields: array of objects with attributes:
1789  *                  (m) c - name
1790  *
1791  *   (m) tables: array of object with attributes:
1792  *                  (m) t - table title
1793  *                  (m) i - array of items
1794  */
1795 static void
1796 sharkd_session_process_tap_nstat_cb(void *arg)
1797 {
1798         stat_data_t *stat_data = (stat_data_t *) arg;
1799         guint i, j, k;
1800
1801         sharkd_json_object_open(FALSE);
1802         sharkd_json_value_stringf(FALSE, "tap", "nstat:%s", stat_data->stat_tap_data->cli_string);
1803         sharkd_json_value_string(TRUE, "type", "nstat");
1804
1805         sharkd_json_array_open(TRUE, "fields");
1806         for (i = 0; i < stat_data->stat_tap_data->nfields; i++)
1807         {
1808                 stat_tap_table_item *field = &(stat_data->stat_tap_data->fields[i]);
1809
1810                 sharkd_json_object_open(i != 0);
1811                 sharkd_json_value_string(FALSE, "c", field->column_name);
1812                 sharkd_json_object_close();
1813         }
1814         sharkd_json_array_close();
1815
1816         sharkd_json_array_open(TRUE, "tables");
1817         for (i = 0; i < stat_data->stat_tap_data->tables->len; i++)
1818         {
1819                 stat_tap_table *table = g_array_index(stat_data->stat_tap_data->tables, stat_tap_table *, i);
1820                 gboolean sepa = FALSE;
1821
1822                 sharkd_json_object_open(i != 0);
1823
1824                 sharkd_json_value_string(FALSE, "t", table->title);
1825
1826                 sharkd_json_array_open(TRUE, "i");
1827                 for (j = 0; j < table->num_elements; j++)
1828                 {
1829                         stat_tap_table_item_type *field_data;
1830
1831                         field_data = stat_tap_get_field_data(table, j, 0);
1832                         if (field_data == NULL || field_data->type == TABLE_ITEM_NONE) /* Nothing for us here */
1833                                 continue;
1834
1835                         sharkd_json_array_open(sepa, NULL);
1836                         for (k = 0; k < table->num_fields; k++)
1837                         {
1838                                 field_data = stat_tap_get_field_data(table, j, k);
1839
1840                                 switch (field_data->type)
1841                                 {
1842                                         case TABLE_ITEM_UINT:
1843                                                 sharkd_json_value_anyf(k != 0, NULL, "%u", field_data->value.uint_value);
1844                                                 break;
1845
1846                                         case TABLE_ITEM_INT:
1847                                                 sharkd_json_value_anyf(k != 0, NULL, "%d", field_data->value.int_value);
1848                                                 break;
1849
1850                                         case TABLE_ITEM_STRING:
1851                                                 sharkd_json_value_string(k != 0, NULL, field_data->value.string_value);
1852                                                 break;
1853
1854                                         case TABLE_ITEM_FLOAT:
1855                                                 sharkd_json_value_anyf(k != 0, NULL, "%f", field_data->value.float_value);
1856                                                 break;
1857
1858                                         case TABLE_ITEM_ENUM:
1859                                                 sharkd_json_value_anyf(k != 0, NULL, "%d", field_data->value.enum_value);
1860                                                 break;
1861
1862                                         case TABLE_ITEM_NONE:
1863                                                 sharkd_json_value_anyf(k != 0, NULL, "null");
1864                                                 break;
1865                                 }
1866                         }
1867
1868                         sharkd_json_array_close();
1869                         sepa = TRUE;
1870                 }
1871                 sharkd_json_array_close();
1872                 sharkd_json_object_close();
1873         }
1874         sharkd_json_array_close();
1875
1876         sharkd_json_object_close();
1877         putchar(',');
1878 }
1879
1880 static void
1881 sharkd_session_free_tap_nstat_cb(void *arg)
1882 {
1883         stat_data_t *stat_data = (stat_data_t *) arg;
1884
1885         free_stat_tables(stat_data->stat_tap_data);
1886 }
1887
1888 /**
1889  * sharkd_session_process_tap_rtd_cb()
1890  *
1891  * Output rtd tap:
1892  *   (m) tap        - tap name
1893  *   (m) type       - tap output type
1894  *   (m) stats - statistics rows - array object with attributes:
1895  *                  (m) type - statistic name
1896  *                  (m) num - number of messages
1897  *                  (m) min - minimum SRT time
1898  *                  (m) max - maximum SRT time
1899  *                  (m) tot - total SRT time
1900  *                  (m) min_frame - minimal SRT
1901  *                  (m) max_frame - maximum SRT
1902  *                  (o) open_req - Open Requests
1903  *                  (o) disc_rsp - Discarded Responses
1904  *                  (o) req_dup  - Duplicated Requests
1905  *                  (o) rsp_dup  - Duplicated Responses
1906  *   (o) open_req   - Open Requests
1907  *   (o) disc_rsp   - Discarded Responses
1908  *   (o) req_dup    - Duplicated Requests
1909  *   (o) rsp_dup    - Duplicated Responses
1910  */
1911 static void
1912 sharkd_session_process_tap_rtd_cb(void *arg)
1913 {
1914         rtd_data_t *rtd_data = (rtd_data_t *) arg;
1915         register_rtd_t *rtd  = (register_rtd_t *) rtd_data->user_data;
1916
1917         guint i, j;
1918
1919         const char *filter = proto_get_protocol_filter_name(get_rtd_proto_id(rtd));
1920
1921         /* XXX, some dissectors are having single table and multiple timestats (mgcp, megaco),
1922          *      some multiple table and single timestat (radius, h225)
1923          *      and it seems that value_string is used one for timestamp-ID, other one for table-ID
1924          *      I wonder how it will gonna work with multiple timestats and multiple tables...
1925          * (for usage grep for: register_rtd_table)
1926          */
1927         const value_string *vs = get_rtd_value_string(rtd);
1928         gboolean sepa = FALSE;
1929
1930         sharkd_json_object_open(FALSE);
1931         sharkd_json_value_stringf(FALSE, "tap", "rtd:%s", filter);
1932         sharkd_json_value_string(TRUE, "type", "rtd");
1933
1934         if (rtd_data->stat_table.num_rtds == 1)
1935         {
1936                 const rtd_timestat *ms = &rtd_data->stat_table.time_stats[0];
1937
1938                 sharkd_json_value_anyf(TRUE, "open_req", "%u", ms->open_req_num);
1939                 sharkd_json_value_anyf(TRUE, "disc_rsp", "%u", ms->disc_rsp_num);
1940                 sharkd_json_value_anyf(TRUE, "req_dup", "%u", ms->req_dup_num);
1941                 sharkd_json_value_anyf(TRUE, "rsp_dup", "%u", ms->rsp_dup_num);
1942         }
1943
1944         sharkd_json_array_open(TRUE, "stats");
1945         for (i = 0; i < rtd_data->stat_table.num_rtds; i++)
1946         {
1947                 const rtd_timestat *ms = &rtd_data->stat_table.time_stats[i];
1948
1949                 for (j = 0; j < ms->num_timestat; j++)
1950                 {
1951                         const char *type_str;
1952
1953                         if (ms->rtd[j].num == 0)
1954                                 continue;
1955
1956                         sharkd_json_object_open(sepa);
1957
1958                         if (rtd_data->stat_table.num_rtds == 1)
1959                                 type_str = val_to_str_const(j, vs, "Other"); /* 1 table - description per row */
1960                         else
1961                                 type_str = val_to_str_const(i, vs, "Other"); /* multiple table - description per table */
1962                         sharkd_json_value_string(FALSE, "type", type_str);
1963
1964                         sharkd_json_value_anyf(TRUE, "num", "%u", ms->rtd[j].num);
1965                         sharkd_json_value_anyf(TRUE, "min", "%.9f", nstime_to_sec(&(ms->rtd[j].min)));
1966                         sharkd_json_value_anyf(TRUE, "max", "%.9f", nstime_to_sec(&(ms->rtd[j].max)));
1967                         sharkd_json_value_anyf(TRUE, "tot", "%.9f", nstime_to_sec(&(ms->rtd[j].tot)));
1968                         sharkd_json_value_anyf(TRUE, "min_frame", "%u", ms->rtd[j].min_num);
1969                         sharkd_json_value_anyf(TRUE, "max_frame", "%u", ms->rtd[j].max_num);
1970
1971                         if (rtd_data->stat_table.num_rtds != 1)
1972                         {
1973                                 /* like in tshark, display it on every row */
1974                                 sharkd_json_value_anyf(TRUE, "open_req", "%u", ms->open_req_num);
1975                                 sharkd_json_value_anyf(TRUE, "disc_rsp", "%u", ms->disc_rsp_num);
1976                                 sharkd_json_value_anyf(TRUE, "req_dup", "%u", ms->req_dup_num);
1977                                 sharkd_json_value_anyf(TRUE, "rsp_dup", "%u", ms->rsp_dup_num);
1978                         }
1979
1980                         sharkd_json_object_close();
1981                         sepa = TRUE;
1982                 }
1983         }
1984         sharkd_json_array_close();
1985
1986         sharkd_json_object_close();
1987         putchar(',');
1988 }
1989
1990 static void
1991 sharkd_session_free_tap_rtd_cb(void *arg)
1992 {
1993         rtd_data_t *rtd_data = (rtd_data_t *) arg;
1994
1995         free_rtd_table(&rtd_data->stat_table);
1996         g_free(rtd_data);
1997 }
1998
1999 /**
2000  * sharkd_session_process_tap_srt_cb()
2001  *
2002  * Output srt tap:
2003  *   (m) tap        - tap name
2004  *   (m) type       - tap output type
2005  *
2006  *   (m) tables - array of object with attributes:
2007  *                  (m) n - table name
2008  *                  (m) f - table filter
2009  *                  (o) c - table column name
2010  *                  (m) r - table rows - array object with attributes:
2011  *                            (m) n   - row name
2012  *                            (m) idx - procedure index
2013  *                            (m) num - number of events
2014  *                            (m) min - minimum SRT time
2015  *                            (m) max - maximum SRT time
2016  *                            (m) tot - total SRT time
2017  */
2018 static void
2019 sharkd_session_process_tap_srt_cb(void *arg)
2020 {
2021         srt_data_t *srt_data = (srt_data_t *) arg;
2022         register_srt_t *srt = (register_srt_t *) srt_data->user_data;
2023
2024         const char *filter = proto_get_protocol_filter_name(get_srt_proto_id(srt));
2025
2026         guint i;
2027
2028         sharkd_json_object_open(FALSE);
2029         sharkd_json_value_stringf(FALSE, "tap", "srt:%s", filter);
2030         sharkd_json_value_string(TRUE, "type", "srt");
2031
2032         sharkd_json_array_open(TRUE, "tables");
2033         for (i = 0; i < srt_data->srt_array->len; i++)
2034         {
2035                 /* SRT table */
2036                 srt_stat_table *rst = g_array_index(srt_data->srt_array, srt_stat_table *, i);
2037                 gboolean sepa = FALSE;
2038
2039                 int j;
2040
2041                 sharkd_json_object_open(i != 0);
2042
2043                 if (rst->name)
2044                         sharkd_json_value_string(FALSE, "n", rst->name);
2045                 else if (rst->short_name)
2046                         sharkd_json_value_string(FALSE, "n", rst->short_name);
2047                 else
2048                         sharkd_json_value_stringf(FALSE, "n", "table%u", i);
2049
2050                 if (rst->filter_string)
2051                         sharkd_json_value_string(TRUE, "f", rst->filter_string);
2052
2053                 if (rst->proc_column_name)
2054                         sharkd_json_value_string(TRUE, "c", rst->proc_column_name);
2055
2056                 sharkd_json_array_open(TRUE, "r");
2057                 for (j = 0; j < rst->num_procs; j++)
2058                 {
2059                         /* SRT row */
2060                         srt_procedure_t *proc = &rst->procedures[j];
2061
2062                         if (proc->stats.num == 0)
2063                                 continue;
2064
2065                         sharkd_json_object_open(sepa);
2066
2067                         sharkd_json_value_string(FALSE, "n", proc->procedure);
2068
2069                         if (rst->filter_string)
2070                                 sharkd_json_value_anyf(TRUE, "idx", "%d", proc->proc_index);
2071
2072                         sharkd_json_value_anyf(TRUE, "num", "%u", proc->stats.num);
2073
2074                         sharkd_json_value_anyf(TRUE, "min", "%.9f", nstime_to_sec(&proc->stats.min));
2075                         sharkd_json_value_anyf(TRUE, "max", "%.9f", nstime_to_sec(&proc->stats.max));
2076                         sharkd_json_value_anyf(TRUE, "tot", "%.9f", nstime_to_sec(&proc->stats.tot));
2077
2078                         sharkd_json_object_close();
2079                         sepa = TRUE;
2080                 }
2081                 sharkd_json_array_close();
2082
2083                 sharkd_json_object_close();
2084         }
2085         sharkd_json_array_close();
2086
2087         sharkd_json_object_close();
2088         putchar(',');
2089 }
2090
2091 static void
2092 sharkd_session_free_tap_srt_cb(void *arg)
2093 {
2094         srt_data_t *srt_data = (srt_data_t *) arg;
2095         register_srt_t *srt = (register_srt_t *) srt_data->user_data;
2096
2097         free_srt_table(srt, srt_data->srt_array);
2098         g_array_free(srt_data->srt_array, TRUE);
2099         g_free(srt_data);
2100 }
2101
2102 struct sharkd_export_object_list
2103 {
2104         struct sharkd_export_object_list *next;
2105
2106         char *type;
2107         const char *proto;
2108         GSList *entries;
2109 };
2110
2111 static struct sharkd_export_object_list *sharkd_eo_list;
2112
2113 /**
2114  * sharkd_session_process_tap_eo_cb()
2115  *
2116  * Output eo tap:
2117  *   (m) tap        - tap name
2118  *   (m) type       - tap output type
2119  *   (m) proto      - protocol short name
2120  *   (m) objects    - array of object with attributes:
2121  *                  (m) pkt - packet number
2122  *                  (o) hostname - hostname
2123  *                  (o) type - content type
2124  *                  (o) filename - filename
2125  *                  (m) len - object length
2126  */
2127 static void
2128 sharkd_session_process_tap_eo_cb(void *tapdata)
2129 {
2130         export_object_list_t *tap_object = (export_object_list_t *) tapdata;
2131         struct sharkd_export_object_list *object_list = (struct sharkd_export_object_list *) tap_object->gui_data;
2132         GSList *slist;
2133         int i = 0;
2134
2135         sharkd_json_object_open(FALSE);
2136         sharkd_json_value_string(FALSE, "tap", object_list->type);
2137         sharkd_json_value_string(TRUE, "type", "eo");
2138
2139         sharkd_json_value_string(TRUE, "proto", object_list->proto);
2140
2141         sharkd_json_array_open(TRUE, "objects");
2142         for (slist = object_list->entries; slist; slist = slist->next)
2143         {
2144                 const export_object_entry_t *eo_entry = (export_object_entry_t *) slist->data;
2145
2146                 sharkd_json_object_open(i != 0);
2147
2148                 sharkd_json_value_anyf(FALSE, "pkt", "%u", eo_entry->pkt_num);
2149
2150                 if (eo_entry->hostname)
2151                         sharkd_json_value_string(TRUE, "hostname", eo_entry->hostname);
2152
2153                 if (eo_entry->content_type)
2154                         sharkd_json_value_string(TRUE, "type", eo_entry->content_type);
2155
2156                 if (eo_entry->filename)
2157                         sharkd_json_value_string(TRUE, "filename", eo_entry->filename);
2158
2159                 sharkd_json_value_stringf(TRUE, "_download", "%s_%d", object_list->type, i);
2160
2161                 sharkd_json_value_anyf(TRUE, "len", "%" G_GINT64_FORMAT, eo_entry->payload_len);
2162
2163                 sharkd_json_object_close();
2164
2165                 i++;
2166         }
2167         sharkd_json_array_close();
2168
2169         sharkd_json_object_close();
2170         putchar(',');
2171 }
2172
2173 static void
2174 sharkd_eo_object_list_add_entry(void *gui_data, export_object_entry_t *entry)
2175 {
2176         struct sharkd_export_object_list *object_list = (struct sharkd_export_object_list *) gui_data;
2177
2178         object_list->entries = g_slist_append(object_list->entries, entry);
2179 }
2180
2181 static export_object_entry_t *
2182 sharkd_eo_object_list_get_entry(void *gui_data, int row)
2183 {
2184         struct sharkd_export_object_list *object_list = (struct sharkd_export_object_list *) gui_data;
2185
2186         return (export_object_entry_t *) g_slist_nth_data(object_list->entries, row);
2187 }
2188
2189 /**
2190  * sharkd_session_process_tap_rtp_cb()
2191  *
2192  * Output RTP streams tap:
2193  *   (m) tap        - tap name
2194  *   (m) type       - tap output type
2195  *   (m) streams    - array of object with attributes:
2196  *                  (m) ssrc        - RTP synchronization source identifier
2197  *                  (m) payload     - stream payload
2198  *                  (m) saddr       - source address
2199  *                  (m) sport       - source port
2200  *                  (m) daddr       - destination address
2201  *                  (m) dport       - destination port
2202  *                  (m) pkts        - packets count
2203  *                  (m) max_delta   - max delta (ms)
2204  *                  (m) max_jitter  - max jitter (ms)
2205  *                  (m) mean_jitter - mean jitter (ms)
2206  *                  (m) expectednr  -
2207  *                  (m) totalnr     -
2208  *                  (m) problem     - if analyser found the problem
2209  *                  (m) ipver       - address IP version (4 or 6)
2210  */
2211 static void
2212 sharkd_session_process_tap_rtp_cb(void *arg)
2213 {
2214         rtpstream_tapinfo_t *rtp_tapinfo = (rtpstream_tapinfo_t *) arg;
2215
2216         GList *listx;
2217         gboolean sepa = FALSE;
2218
2219         sharkd_json_object_open(FALSE);
2220         sharkd_json_value_string(FALSE, "tap", "rtp-streams");
2221         sharkd_json_value_string(TRUE, "type", "rtp-streams");
2222
2223         sharkd_json_array_open(TRUE, "streams");
2224         for (listx = g_list_first(rtp_tapinfo->strinfo_list); listx; listx = listx->next)
2225         {
2226                 rtpstream_info_t *streaminfo = (rtpstream_info_t *) listx->data;
2227                 rtpstream_info_calc_t calc;
2228
2229                 rtpstream_info_calculate(streaminfo, &calc);
2230
2231                 sharkd_json_object_open(sepa);
2232
2233                 sharkd_json_value_anyf(FALSE, "ssrc", "%u", calc.ssrc);
2234                 sharkd_json_value_string(TRUE, "payload", calc.all_payload_type_names);
2235
2236                 sharkd_json_value_string(TRUE, "saddr", calc.src_addr_str);
2237                 sharkd_json_value_anyf(TRUE, "sport", "%u", calc.src_port);
2238                 sharkd_json_value_string(TRUE, "daddr", calc.dst_addr_str);
2239                 sharkd_json_value_anyf(TRUE, "dport", "%u", calc.dst_port);
2240
2241                 sharkd_json_value_anyf(TRUE, "pkts", "%u", calc.packet_count);
2242
2243                 sharkd_json_value_anyf(TRUE, "max_delta", "%f",calc.max_delta);
2244                 sharkd_json_value_anyf(TRUE, "max_jitter", "%f", calc.max_jitter);
2245                 sharkd_json_value_anyf(TRUE, "mean_jitter", "%f", calc.mean_jitter);
2246
2247                 sharkd_json_value_anyf(TRUE, "expectednr", "%u", calc.packet_expected);
2248                 sharkd_json_value_anyf(TRUE, "totalnr", "%u", calc.total_nr);
2249
2250                 sharkd_json_value_anyf(TRUE, "problem", calc.problem ? "true" : "false");
2251
2252                 /* for filter */
2253                 sharkd_json_value_anyf(TRUE, "ipver", "%d", (streaminfo->id.src_addr.type == AT_IPv6) ? 6 : 4);
2254
2255                 rtpstream_info_calc_free(&calc);
2256
2257                 sharkd_json_object_close();
2258                 sepa = TRUE;
2259         }
2260         sharkd_json_array_close();
2261
2262         sharkd_json_object_close();
2263         putchar(',');
2264 }
2265
2266 /**
2267  * sharkd_session_process_tap()
2268  *
2269  * Process tap request
2270  *
2271  * Input:
2272  *   (m) tap0         - First tap request
2273  *   (o) tap1...tap15 - Other tap requests
2274  *
2275  * Output object with attributes:
2276  *   (m) taps  - array of object with attributes:
2277  *                  (m) tap  - tap name
2278  *                  (m) type - tap output type
2279  *                  ...
2280  *                  for type:stats see sharkd_session_process_tap_stats_cb()
2281  *                  for type:nstat see sharkd_session_process_tap_nstat_cb()
2282  *                  for type:conv see sharkd_session_process_tap_conv_cb()
2283  *                  for type:host see sharkd_session_process_tap_conv_cb()
2284  *                  for type:rtp-streams see sharkd_session_process_tap_rtp_cb()
2285  *                  for type:rtp-analyse see sharkd_session_process_tap_rtp_analyse_cb()
2286  *                  for type:eo see sharkd_session_process_tap_eo_cb()
2287  *                  for type:expert see sharkd_session_process_tap_expert_cb()
2288  *                  for type:rtd see sharkd_session_process_tap_rtd_cb()
2289  *                  for type:srt see sharkd_session_process_tap_srt_cb()
2290  *                  for type:flow see sharkd_session_process_tap_flow_cb()
2291  *
2292  *   (m) err   - error code
2293  */
2294 static void
2295 sharkd_session_process_tap(char *buf, const jsmntok_t *tokens, int count)
2296 {
2297         void *taps_data[16];
2298         GFreeFunc taps_free[16];
2299         int taps_count = 0;
2300         int i;
2301
2302         rtpstream_tapinfo_t rtp_tapinfo =
2303                 { NULL, NULL, NULL, NULL, 0, NULL, 0, TAP_ANALYSE, NULL, NULL, NULL, FALSE };
2304
2305         for (i = 0; i < 16; i++)
2306         {
2307                 char tapbuf[32];
2308                 const char *tok_tap;
2309
2310                 void *tap_data = NULL;
2311                 GFreeFunc tap_free = NULL;
2312                 const char *tap_filter = "";
2313                 GString *tap_error = NULL;
2314
2315                 ws_snprintf(tapbuf, sizeof(tapbuf), "tap%d", i);
2316                 tok_tap = json_find_attr(buf, tokens, count, tapbuf);
2317                 if (!tok_tap)
2318                         break;
2319
2320                 if (!strncmp(tok_tap, "stat:", 5))
2321                 {
2322                         stats_tree_cfg *cfg = stats_tree_get_cfg_by_abbr(tok_tap + 5);
2323                         stats_tree *st;
2324
2325                         if (!cfg)
2326                         {
2327                                 fprintf(stderr, "sharkd_session_process_tap() stat %s not found\n", tok_tap + 5);
2328                                 continue;
2329                         }
2330
2331                         st = stats_tree_new(cfg, NULL, tap_filter);
2332
2333                         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);
2334
2335                         if (!tap_error && cfg->init)
2336                                 cfg->init(st);
2337
2338                         tap_data = st;
2339                         tap_free = sharkd_session_free_tap_stats_cb;
2340                 }
2341                 else if (!strcmp(tok_tap, "expert"))
2342                 {
2343                         struct sharkd_expert_tap *expert_tap;
2344
2345                         expert_tap = g_new0(struct sharkd_expert_tap, 1);
2346                         expert_tap->text = g_string_chunk_new(100);
2347
2348                         tap_error = register_tap_listener("expert", expert_tap, NULL, 0, NULL, sharkd_session_packet_tap_expert_cb, sharkd_session_process_tap_expert_cb, NULL);
2349
2350                         tap_data = expert_tap;
2351                         tap_free = sharkd_session_free_tap_expert_cb;
2352                 }
2353                 else if (!strncmp(tok_tap, "seqa:", 5))
2354                 {
2355                         seq_analysis_info_t *graph_analysis;
2356                         register_analysis_t *analysis;
2357                         const char *tap_name;
2358                         tap_packet_cb tap_func;
2359                         guint tap_flags;
2360
2361                         analysis = sequence_analysis_find_by_name(tok_tap + 5);
2362                         if (!analysis)
2363                         {
2364                                 fprintf(stderr, "sharkd_session_process_tap() seq analysis %s not found\n", tok_tap + 5);
2365                                 continue;
2366                         }
2367
2368                         graph_analysis = sequence_analysis_info_new();
2369                         graph_analysis->name = tok_tap + 5;
2370                         /* TODO, make configurable */
2371                         graph_analysis->any_addr = FALSE;
2372
2373                         tap_name  = sequence_analysis_get_tap_listener_name(analysis);
2374                         tap_flags = sequence_analysis_get_tap_flags(analysis);
2375                         tap_func  = sequence_analysis_get_packet_func(analysis);
2376
2377                         tap_error = register_tap_listener(tap_name, graph_analysis, NULL, tap_flags, NULL, tap_func, sharkd_session_process_tap_flow_cb, NULL);
2378
2379                         tap_data = graph_analysis;
2380                         tap_free = sharkd_session_free_tap_flow_cb;
2381                 }
2382                 else if (!strncmp(tok_tap, "conv:", 5) || !strncmp(tok_tap, "endpt:", 6))
2383                 {
2384                         struct register_ct *ct = NULL;
2385                         const char *ct_tapname;
2386                         struct sharkd_conv_tap_data *ct_data;
2387                         tap_packet_cb tap_func = NULL;
2388
2389                         if (!strncmp(tok_tap, "conv:", 5))
2390                         {
2391                                 ct = get_conversation_by_proto_id(proto_get_id_by_short_name(tok_tap + 5));
2392
2393                                 if (!ct || !(tap_func = get_conversation_packet_func(ct)))
2394                                 {
2395                                         fprintf(stderr, "sharkd_session_process_tap() conv %s not found\n", tok_tap + 5);
2396                                         continue;
2397                                 }
2398                         }
2399                         else if (!strncmp(tok_tap, "endpt:", 6))
2400                         {
2401                                 ct = get_conversation_by_proto_id(proto_get_id_by_short_name(tok_tap + 6));
2402
2403                                 if (!ct || !(tap_func = get_hostlist_packet_func(ct)))
2404                                 {
2405                                         fprintf(stderr, "sharkd_session_process_tap() endpt %s not found\n", tok_tap + 6);
2406                                         continue;
2407                                 }
2408                         }
2409                         else
2410                         {
2411                                 fprintf(stderr, "sharkd_session_process_tap() conv/endpt(?): %s not found\n", tok_tap);
2412                                 continue;
2413                         }
2414
2415                         ct_tapname = proto_get_protocol_filter_name(get_conversation_proto_id(ct));
2416
2417                         ct_data = (struct sharkd_conv_tap_data *) g_malloc0(sizeof(struct sharkd_conv_tap_data));
2418                         ct_data->type = tok_tap;
2419                         ct_data->hash.user_data = ct_data;
2420
2421                         /* XXX: make configurable */
2422                         ct_data->resolve_name = TRUE;
2423                         ct_data->resolve_port = TRUE;
2424
2425                         tap_error = register_tap_listener(ct_tapname, &ct_data->hash, tap_filter, 0, NULL, tap_func, sharkd_session_process_tap_conv_cb, NULL);
2426
2427                         tap_data = &ct_data->hash;
2428                         tap_free = sharkd_session_free_tap_conv_cb;
2429                 }
2430                 else if (!strncmp(tok_tap, "nstat:", 6))
2431                 {
2432                         stat_tap_table_ui *stat_tap = stat_tap_by_name(tok_tap + 6);
2433                         stat_data_t *stat_data;
2434
2435                         if (!stat_tap)
2436                         {
2437                                 fprintf(stderr, "sharkd_session_process_tap() nstat=%s not found\n", tok_tap + 6);
2438                                 continue;
2439                         }
2440
2441                         stat_tap->stat_tap_init_cb(stat_tap);
2442
2443                         stat_data = g_new0(stat_data_t, 1);
2444                         stat_data->stat_tap_data = stat_tap;
2445                         stat_data->user_data = NULL;
2446
2447                         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);
2448
2449                         tap_data = stat_data;
2450                         tap_free = sharkd_session_free_tap_nstat_cb;
2451                 }
2452                 else if (!strncmp(tok_tap, "rtd:", 4))
2453                 {
2454                         register_rtd_t *rtd = get_rtd_table_by_name(tok_tap + 4);
2455                         rtd_data_t *rtd_data;
2456                         char *err;
2457
2458                         if (!rtd)
2459                         {
2460                                 fprintf(stderr, "sharkd_session_process_tap() rtd=%s not found\n", tok_tap + 4);
2461                                 continue;
2462                         }
2463
2464                         rtd_table_get_filter(rtd, "", &tap_filter, &err);
2465                         if (err != NULL)
2466                         {
2467                                 fprintf(stderr, "sharkd_session_process_tap() rtd=%s err=%s\n", tok_tap + 4, err);
2468                                 g_free(err);
2469                                 continue;
2470                         }
2471
2472                         rtd_data = g_new0(rtd_data_t, 1);
2473                         rtd_data->user_data = rtd;
2474                         rtd_table_dissector_init(rtd, &rtd_data->stat_table, NULL, NULL);
2475
2476                         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);
2477
2478                         tap_data = rtd_data;
2479                         tap_free = sharkd_session_free_tap_rtd_cb;
2480                 }
2481                 else if (!strncmp(tok_tap, "srt:", 4))
2482                 {
2483                         register_srt_t *srt = get_srt_table_by_name(tok_tap + 4);
2484                         srt_data_t *srt_data;
2485                         char *err;
2486
2487                         if (!srt)
2488                         {
2489                                 fprintf(stderr, "sharkd_session_process_tap() srt=%s not found\n", tok_tap + 4);
2490                                 continue;
2491                         }
2492
2493                         srt_table_get_filter(srt, "", &tap_filter, &err);
2494                         if (err != NULL)
2495                         {
2496                                 fprintf(stderr, "sharkd_session_process_tap() srt=%s err=%s\n", tok_tap + 4, err);
2497                                 g_free(err);
2498                                 continue;
2499                         }
2500
2501                         srt_data = g_new0(srt_data_t, 1);
2502                         srt_data->srt_array = g_array_new(FALSE, TRUE, sizeof(srt_stat_table *));
2503                         srt_data->user_data = srt;
2504                         srt_table_dissector_init(srt, srt_data->srt_array);
2505
2506                         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);
2507
2508                         tap_data = srt_data;
2509                         tap_free = sharkd_session_free_tap_srt_cb;
2510                 }
2511                 else if (!strncmp(tok_tap, "eo:", 3))
2512                 {
2513                         register_eo_t *eo = get_eo_by_name(tok_tap + 3);
2514                         export_object_list_t *eo_object;
2515                         struct sharkd_export_object_list *object_list;
2516
2517                         if (!eo)
2518                         {
2519                                 fprintf(stderr, "sharkd_session_process_tap() eo=%s not found\n", tok_tap + 3);
2520                                 continue;
2521                         }
2522
2523                         for (object_list = sharkd_eo_list; object_list; object_list = object_list->next)
2524                         {
2525                                 if (!strcmp(object_list->type, tok_tap))
2526                                 {
2527                                         g_slist_free_full(object_list->entries, (GDestroyNotify) eo_free_entry);
2528                                         object_list->entries = NULL;
2529                                         break;
2530                                 }
2531                         }
2532
2533                         if (!object_list)
2534                         {
2535                                 object_list = g_new(struct sharkd_export_object_list, 1);
2536                                 object_list->type = g_strdup(tok_tap);
2537                                 object_list->proto = proto_get_protocol_short_name(find_protocol_by_id(get_eo_proto_id(eo)));
2538                                 object_list->entries = NULL;
2539                                 object_list->next = sharkd_eo_list;
2540                                 sharkd_eo_list = object_list;
2541                         }
2542
2543                         eo_object  = g_new0(export_object_list_t, 1);
2544                         eo_object->add_entry = sharkd_eo_object_list_add_entry;
2545                         eo_object->get_entry = sharkd_eo_object_list_get_entry;
2546                         eo_object->gui_data = (void *) object_list;
2547
2548                         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);
2549
2550                         tap_data = eo_object;
2551                         tap_free = g_free; /* need to free only eo_object, object_list need to be kept for potential download */
2552                 }
2553                 else if (!strcmp(tok_tap, "rtp-streams"))
2554                 {
2555                         tap_error = register_tap_listener("rtp", &rtp_tapinfo, tap_filter, 0, rtpstream_reset_cb, rtpstream_packet_cb, sharkd_session_process_tap_rtp_cb, NULL);
2556
2557                         tap_data = &rtp_tapinfo;
2558                         tap_free = rtpstream_reset_cb;
2559                 }
2560                 else if (!strncmp(tok_tap, "rtp-analyse:", 12))
2561                 {
2562                         struct sharkd_analyse_rtp *rtp_req;
2563
2564                         rtp_req = (struct sharkd_analyse_rtp *) g_malloc0(sizeof(*rtp_req));
2565                         if (!sharkd_rtp_match_init(&rtp_req->id, tok_tap + 12))
2566                         {
2567                                 rtpstream_id_free(&rtp_req->id);
2568                                 g_free(rtp_req);
2569                                 continue;
2570                         }
2571
2572                         rtp_req->tap_name = tok_tap;
2573                         rtp_req->statinfo.first_packet = TRUE;
2574                         rtp_req->statinfo.reg_pt = PT_UNDEFINED;
2575
2576                         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);
2577
2578                         tap_data = rtp_req;
2579                         tap_free = sharkd_session_process_tap_rtp_free_cb;
2580                 }
2581                 else
2582                 {
2583                         fprintf(stderr, "sharkd_session_process_tap() %s not recognized\n", tok_tap);
2584                         continue;
2585                 }
2586
2587                 if (tap_error)
2588                 {
2589                         fprintf(stderr, "sharkd_session_process_tap() name=%s error=%s", tok_tap, tap_error->str);
2590                         g_string_free(tap_error, TRUE);
2591                         if (tap_free)
2592                                 tap_free(tap_data);
2593                         continue;
2594                 }
2595
2596                 taps_data[taps_count] = tap_data;
2597                 taps_free[taps_count] = tap_free;
2598                 taps_count++;
2599         }
2600
2601         fprintf(stderr, "sharkd_session_process_tap() count=%d\n", taps_count);
2602         if (taps_count == 0)
2603                 return;
2604
2605         sharkd_json_object_open(FALSE);
2606
2607         sharkd_json_array_open(FALSE, "taps");
2608         sharkd_retap();
2609         // This dummy value exists to permit unconditionally adding ',' in the taps callback.
2610         // XXX convert to json_dumper and remove this.
2611         sharkd_json_value_anyf(FALSE, NULL, "null");
2612         sharkd_json_array_close();
2613
2614         sharkd_json_value_anyf(TRUE, "err", "0");
2615
2616         sharkd_json_object_close();
2617         sharkd_json_finish();
2618
2619         for (i = 0; i < taps_count; i++)
2620         {
2621                 if (taps_data[i])
2622                         remove_tap_listener(taps_data[i]);
2623
2624                 if (taps_free[i])
2625                         taps_free[i](taps_data[i]);
2626         }
2627 }
2628
2629 /**
2630  * sharkd_session_process_follow()
2631  *
2632  * Process follow request
2633  *
2634  * Input:
2635  *   (m) follow  - follow protocol request (e.g. HTTP)
2636  *   (m) filter  - filter request (e.g. tcp.stream == 1)
2637  *
2638  * Output object with attributes:
2639  *
2640  *   (m) err    - error code
2641  *   (m) shost  - server host
2642  *   (m) sport  - server port
2643  *   (m) sbytes - server send bytes count
2644  *   (m) chost  - client host
2645  *   (m) cport  - client port
2646  *   (m) cbytes - client send bytes count
2647  *   (o) payloads - array of object with attributes:
2648  *                  (o) s - set if server sent, else client
2649  *                  (m) n - packet number
2650  *                  (m) d - data base64 encoded
2651  */
2652 static void
2653 sharkd_session_process_follow(char *buf, const jsmntok_t *tokens, int count)
2654 {
2655         const char *tok_follow = json_find_attr(buf, tokens, count, "follow");
2656         const char *tok_filter = json_find_attr(buf, tokens, count, "filter");
2657
2658         register_follow_t *follower;
2659         GString *tap_error;
2660
2661         follow_info_t *follow_info;
2662         const char *host;
2663         char *port;
2664
2665         if (!tok_follow || !tok_filter)
2666                 return;
2667
2668         follower = get_follow_by_name(tok_follow);
2669         if (!follower)
2670         {
2671                 fprintf(stderr, "sharkd_session_process_follow() follower=%s not found\n", tok_follow);
2672                 return;
2673         }
2674
2675         /* follow_reset_stream ? */
2676         follow_info = g_new0(follow_info_t, 1);
2677         /* gui_data, filter_out_filter not set, but not used by dissector */
2678
2679         tap_error = register_tap_listener(get_follow_tap_string(follower), follow_info, tok_filter, 0, NULL, get_follow_tap_handler(follower), NULL, NULL);
2680         if (tap_error)
2681         {
2682                 fprintf(stderr, "sharkd_session_process_follow() name=%s error=%s", tok_follow, tap_error->str);
2683                 g_string_free(tap_error, TRUE);
2684                 g_free(follow_info);
2685                 return;
2686         }
2687
2688         sharkd_retap();
2689
2690         sharkd_json_object_open(FALSE);
2691
2692         sharkd_json_value_anyf(FALSE, "err", "0");
2693
2694         /* Server information: hostname, port, bytes sent */
2695         host = address_to_name(&follow_info->server_ip);
2696         sharkd_json_value_string(TRUE, "shost", host);
2697
2698         port = get_follow_port_to_display(follower)(NULL, follow_info->server_port);
2699         sharkd_json_value_string(TRUE, "sport", port);
2700         wmem_free(NULL, port);
2701
2702         sharkd_json_value_anyf(TRUE, "sbytes", "%u", follow_info->bytes_written[0]);
2703
2704         /* Client information: hostname, port, bytes sent */
2705         host = address_to_name(&follow_info->client_ip);
2706         sharkd_json_value_string(TRUE, "chost", host);
2707
2708         port = get_follow_port_to_display(follower)(NULL, follow_info->client_port);
2709         sharkd_json_value_string(TRUE, "cport", port);
2710         wmem_free(NULL, port);
2711
2712         sharkd_json_value_anyf(TRUE, "cbytes", "%u", follow_info->bytes_written[1]);
2713
2714         if (follow_info->payload)
2715         {
2716                 follow_record_t *follow_record;
2717                 GList *cur;
2718                 gboolean sepa = FALSE;
2719
2720                 sharkd_json_array_open(TRUE, "payloads");
2721                 for (cur = g_list_last(follow_info->payload); cur; cur = g_list_previous(cur))
2722                 {
2723                         follow_record = (follow_record_t *) cur->data;
2724
2725                         sharkd_json_object_open(sepa);
2726
2727                         sharkd_json_value_anyf(FALSE, "n", "%u", follow_record->packet_num);
2728                         sharkd_json_value_base64(TRUE, "d", follow_record->data->data, follow_record->data->len);
2729
2730                         if (follow_record->is_server)
2731                                 sharkd_json_value_anyf(TRUE, "s", "%d", 1);
2732
2733                         sharkd_json_object_close();
2734                         sepa = TRUE;
2735                 }
2736                 sharkd_json_array_close();
2737         }
2738
2739         sharkd_json_object_close();
2740         sharkd_json_finish();
2741
2742         remove_tap_listener(follow_info);
2743         follow_info_free(follow_info);
2744 }
2745
2746 static void
2747 sharkd_session_process_frame_cb_tree(epan_dissect_t *edt, proto_tree *tree, tvbuff_t **tvbs, gboolean display_hidden)
2748 {
2749         proto_node *node;
2750         gboolean sepa = FALSE;
2751
2752         sharkd_json_array_open(FALSE, NULL);
2753         for (node = tree->first_child; node; node = node->next)
2754         {
2755                 field_info *finfo = PNODE_FINFO(node);
2756
2757                 if (!finfo)
2758                         continue;
2759
2760                 if (!display_hidden && FI_GET_FLAG(finfo, FI_HIDDEN))
2761                         continue;
2762
2763                 sharkd_json_object_open(sepa);
2764
2765                 if (!finfo->rep)
2766                 {
2767                         char label_str[ITEM_LABEL_LENGTH];
2768
2769                         label_str[0] = '\0';
2770                         proto_item_fill_label(finfo, label_str);
2771                         sharkd_json_value_string(FALSE, "l", label_str);
2772                 }
2773                 else
2774                 {
2775                         sharkd_json_value_string(FALSE, "l", finfo->rep->representation);
2776                 }
2777
2778                 if (finfo->ds_tvb && tvbs && tvbs[0] != finfo->ds_tvb)
2779                 {
2780                         int idx;
2781
2782                         for (idx = 1; tvbs[idx]; idx++)
2783                         {
2784                                 if (tvbs[idx] == finfo->ds_tvb)
2785                                 {
2786                                         sharkd_json_value_anyf(TRUE, "ds", "%d", idx);
2787                                         break;
2788                                 }
2789                         }
2790                 }
2791
2792                 if (finfo->start >= 0 && finfo->length > 0)
2793                         sharkd_json_value_anyf(TRUE, "h", "[%d,%d]", finfo->start, finfo->length);
2794
2795                 if (finfo->appendix_start >= 0 && finfo->appendix_length > 0)
2796                         sharkd_json_value_anyf(TRUE, "i", "[%d,%d]", finfo->appendix_start, finfo->appendix_length);
2797
2798
2799                 if (finfo->hfinfo)
2800                 {
2801                         char *filter;
2802
2803                         if (finfo->hfinfo->type == FT_PROTOCOL)
2804                         {
2805                                 sharkd_json_value_string(TRUE, "t", "proto");
2806                         }
2807                         else if (finfo->hfinfo->type == FT_FRAMENUM)
2808                         {
2809                                 sharkd_json_value_string(TRUE, "t", "framenum");
2810                                 sharkd_json_value_anyf(TRUE, "fnum", "%u", finfo->value.value.uinteger);
2811                         }
2812                         else if (FI_GET_FLAG(finfo, FI_URL) && IS_FT_STRING(finfo->hfinfo->type))
2813                         {
2814                                 char *url = fvalue_to_string_repr(NULL, &finfo->value, FTREPR_DISPLAY, finfo->hfinfo->display);
2815
2816                                 sharkd_json_value_string(TRUE, "t", "url");
2817                                 sharkd_json_value_string(TRUE, "url", url);
2818                                 wmem_free(NULL, url);
2819                         }
2820
2821                         filter = proto_construct_match_selected_string(finfo, edt);
2822                         if (filter)
2823                         {
2824                                 sharkd_json_value_string(TRUE, "f", filter);
2825                                 wmem_free(NULL, filter);
2826                         }
2827                 }
2828
2829                 if (FI_GET_FLAG(finfo, FI_GENERATED))
2830                         sharkd_json_value_anyf(TRUE, "g", "true");
2831
2832                 if (FI_GET_FLAG(finfo, FI_HIDDEN))
2833                         sharkd_json_value_anyf(TRUE, "v", "true");
2834
2835                 if (FI_GET_FLAG(finfo, PI_SEVERITY_MASK))
2836                 {
2837                         const char *severity = try_val_to_str(FI_GET_FLAG(finfo, PI_SEVERITY_MASK), expert_severity_vals);
2838
2839                         g_assert(severity != NULL);
2840
2841                         sharkd_json_value_string(TRUE, "s", severity);
2842                 }
2843
2844                 if (((proto_tree *) node)->first_child)
2845                 {
2846                         if (finfo->tree_type != -1)
2847                                 sharkd_json_value_anyf(TRUE, "e", "%d", finfo->tree_type);
2848
2849                         sharkd_json_value_anyf(TRUE, "n", NULL);
2850                         sharkd_session_process_frame_cb_tree(edt, (proto_tree *) node, tvbs, display_hidden);
2851                 }
2852
2853                 sharkd_json_object_close();
2854                 sepa = TRUE;
2855         }
2856         sharkd_json_array_close();
2857 }
2858
2859 static gboolean
2860 sharkd_follower_visit_layers_cb(const void *key _U_, void *value, void *user_data)
2861 {
2862         register_follow_t *follower = (register_follow_t *) value;
2863         packet_info *pi = (packet_info *) user_data;
2864
2865         const int proto_id = get_follow_proto_id(follower);
2866
2867         guint32 ignore_stream;
2868
2869         if (proto_is_frame_protocol(pi->layers, proto_get_protocol_filter_name(proto_id)))
2870         {
2871                 const char *layer_proto = proto_get_protocol_short_name(find_protocol_by_id(proto_id));
2872                 char *follow_filter;
2873
2874                 follow_filter = get_follow_conv_func(follower)(pi, &ignore_stream);
2875
2876                 sharkd_json_array_open(TRUE, NULL);
2877                 sharkd_json_value_string(FALSE, NULL, layer_proto);
2878                 sharkd_json_value_string(TRUE, NULL, follow_filter);
2879                 sharkd_json_array_close();
2880
2881                 g_free(follow_filter);
2882         }
2883
2884         return FALSE;
2885 }
2886
2887 struct sharkd_frame_request_data
2888 {
2889         gboolean display_hidden;
2890 };
2891
2892 static void
2893 sharkd_session_process_frame_cb(epan_dissect_t *edt, proto_tree *tree, struct epan_column_info *cinfo, const GSList *data_src, void *data)
2894 {
2895         packet_info *pi = &edt->pi;
2896         frame_data *fdata = pi->fd;
2897         const char *pkt_comment = NULL;
2898
2899         const struct sharkd_frame_request_data * const req_data = (const struct sharkd_frame_request_data * const) data;
2900         const gboolean display_hidden = (req_data) ? req_data->display_hidden : FALSE;
2901
2902         sharkd_json_object_open(FALSE);
2903
2904         sharkd_json_value_anyf(FALSE, "err", "0");
2905
2906         if (fdata->has_user_comment)
2907                 pkt_comment = sharkd_get_user_comment(fdata);
2908         else if (fdata->has_phdr_comment)
2909                 pkt_comment = pi->rec->opt_comment;
2910
2911         if (pkt_comment)
2912                 sharkd_json_value_string(TRUE, "comment", pkt_comment);
2913
2914         if (tree)
2915         {
2916                 tvbuff_t **tvbs = NULL;
2917
2918                 /* arrayize data src, to speedup searching for ds_tvb index */
2919                 if (data_src && data_src->next /* only needed if there are more than one data source */)
2920                 {
2921                         guint count = g_slist_length((GSList *) data_src);
2922                         guint i;
2923
2924                         tvbs = (tvbuff_t **) g_malloc((count + 1) * sizeof(*tvbs));
2925
2926                         for (i = 0; i < count; i++)
2927                         {
2928                                 const struct data_source *src = (const struct data_source *) g_slist_nth_data((GSList *) data_src, i);
2929
2930                                 tvbs[i] = get_data_source_tvb(src);
2931                         }
2932
2933                         tvbs[count] = NULL;
2934                 }
2935
2936                 sharkd_json_value_anyf(TRUE, "tree", NULL);
2937                 sharkd_session_process_frame_cb_tree(edt, tree, tvbs, display_hidden);
2938
2939                 g_free(tvbs);
2940         }
2941
2942         if (cinfo)
2943         {
2944                 int col;
2945
2946                 sharkd_json_array_open(TRUE, "col");
2947                 for (col = 0; col < cinfo->num_cols; ++col)
2948                 {
2949                         const col_item_t *col_item = &cinfo->columns[col];
2950
2951                         sharkd_json_value_string(col != 0, NULL, col_item->col_data);
2952                 }
2953                 sharkd_json_array_close();
2954         }
2955
2956         if (fdata->ignored)
2957                 sharkd_json_value_anyf(TRUE, "i", "true");
2958
2959         if (fdata->marked)
2960                 sharkd_json_value_anyf(TRUE, "m", "true");
2961
2962         if (fdata->color_filter)
2963         {
2964                 sharkd_json_value_stringf(TRUE, "bg", "%x", color_t_to_rgb(&fdata->color_filter->bg_color));
2965                 sharkd_json_value_stringf(TRUE, "fg", "%x", color_t_to_rgb(&fdata->color_filter->fg_color));
2966         }
2967
2968         if (data_src)
2969         {
2970                 struct data_source *src = (struct data_source *) data_src->data;
2971                 gboolean ds_sepa = FALSE;
2972                 gboolean ds_open = FALSE;
2973
2974                 tvbuff_t *tvb;
2975                 guint length;
2976
2977                 tvb = get_data_source_tvb(src);
2978                 length = tvb_captured_length(tvb);
2979
2980                 if (length != 0)
2981                 {
2982                         const guchar *cp = tvb_get_ptr(tvb, 0, length);
2983
2984                         /* XXX pi.fd->encoding */
2985                         sharkd_json_value_base64(TRUE, "bytes", cp, length);
2986                 }
2987                 else
2988                 {
2989                         sharkd_json_value_base64(TRUE, "bytes", "", 0);
2990                 }
2991
2992                 data_src = data_src->next;
2993                 if (data_src)
2994                 {
2995                         sharkd_json_array_open(TRUE, "ds");
2996                         ds_open = TRUE;
2997                 }
2998
2999                 while (data_src)
3000                 {
3001                         src = (struct data_source *) data_src->data;
3002
3003                         sharkd_json_object_open(ds_sepa);
3004
3005                         {
3006                                 char *src_name = get_data_source_name(src);
3007
3008                                 sharkd_json_value_string(FALSE, "name", src_name);
3009                                 wmem_free(NULL, src_name);
3010                         }
3011
3012                         tvb = get_data_source_tvb(src);
3013                         length = tvb_captured_length(tvb);
3014
3015                         if (length != 0)
3016                         {
3017                                 const guchar *cp = tvb_get_ptr(tvb, 0, length);
3018
3019                                 /* XXX pi.fd->encoding */
3020                                 sharkd_json_value_base64(TRUE, "bytes", cp, length);
3021                         }
3022                         else
3023                         {
3024                                 sharkd_json_value_base64(TRUE, "bytes", "", 0);
3025                         }
3026
3027                         sharkd_json_object_close();
3028                         ds_sepa = TRUE;
3029
3030                         data_src = data_src->next;
3031                 }
3032
3033                 /* close ds, only if was opened */
3034                 if (ds_open)
3035                         sharkd_json_array_close();
3036         }
3037
3038         sharkd_json_array_open(TRUE, "fol");
3039         // This dummy entry allows sharkd_follower_visit_layers_cb() to always insert ',' before dumping item.
3040         // XXX convert to json_dumper and remove the dummy entry.
3041         sharkd_json_value_anyf(FALSE, NULL, "0");
3042         follow_iterate_followers(sharkd_follower_visit_layers_cb, pi);
3043         sharkd_json_array_close();
3044
3045         sharkd_json_object_close();
3046         sharkd_json_finish();
3047 }
3048
3049 #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 */
3050
3051 struct sharkd_iograph
3052 {
3053         /* config */
3054         int hf_index;
3055         io_graph_item_unit_t calc_type;
3056         guint32 interval;
3057
3058         /* result */
3059         int space_items;
3060         int num_items;
3061         io_graph_item_t *items;
3062         GString *error;
3063 };
3064
3065 static gboolean
3066 sharkd_iograph_packet(void *g, packet_info *pinfo, epan_dissect_t *edt, const void *dummy _U_)
3067 {
3068         struct sharkd_iograph *graph = (struct sharkd_iograph *) g;
3069         int idx;
3070
3071         idx = get_io_graph_index(pinfo, graph->interval);
3072         if (idx < 0 || idx >= SHARKD_IOGRAPH_MAX_ITEMS)
3073                 return FALSE;
3074
3075         if (idx + 1 > graph->num_items)
3076         {
3077                 if (idx + 1 > graph->space_items)
3078                 {
3079                         int new_size = idx + 1024;
3080
3081                         graph->items = (io_graph_item_t *) g_realloc(graph->items, sizeof(io_graph_item_t) * new_size);
3082                         reset_io_graph_items(&graph->items[graph->space_items], new_size - graph->space_items);
3083
3084                         graph->space_items = new_size;
3085                 }
3086                 else if (graph->items == NULL)
3087                 {
3088                         graph->items = (io_graph_item_t *) g_malloc(sizeof(io_graph_item_t) * graph->space_items);
3089                         reset_io_graph_items(graph->items, graph->space_items);
3090                 }
3091
3092                 graph->num_items = idx + 1;
3093         }
3094
3095         return update_io_graph_item(graph->items, idx, pinfo, edt, graph->hf_index, graph->calc_type, graph->interval);
3096 }
3097
3098 /**
3099  * sharkd_session_process_iograph()
3100  *
3101  * Process iograph request
3102  *
3103  * Input:
3104  *   (o) interval - interval time in ms, if not specified: 1000ms
3105  *   (m) graph0             - First graph request
3106  *   (o) graph1...graph9    - Other graph requests
3107  *   (o) filter0            - First graph filter
3108  *   (o) filter1...filter9  - Other graph filters
3109  *
3110  * Graph requests can be one of: "packets", "bytes", "bits", "sum:<field>", "frames:<field>", "max:<field>", "min:<field>", "avg:<field>", "load:<field>",
3111  * if you use variant with <field>, you need to pass field name in filter request.
3112  *
3113  * Output object with attributes:
3114  *   (m) iograph - array of graph results with attributes:
3115  *                  errmsg - graph cannot be constructed
3116  *                  items  - graph values, zeros are skipped, if value is not a number it's next index encoded as hex string
3117  */
3118 static void
3119 sharkd_session_process_iograph(char *buf, const jsmntok_t *tokens, int count)
3120 {
3121         const char *tok_interval = json_find_attr(buf, tokens, count, "interval");
3122         struct sharkd_iograph graphs[10];
3123         gboolean is_any_ok = FALSE;
3124         int graph_count;
3125
3126         guint32 interval_ms = 1000; /* default: one per second */
3127         int i;
3128
3129         if (tok_interval)
3130         {
3131                 if (!ws_strtou32(tok_interval, NULL, &interval_ms) || interval_ms == 0)
3132                 {
3133                         fprintf(stderr, "Invalid interval parameter: %s.\n", tok_interval);
3134                         return;
3135                 }
3136         }
3137
3138         for (i = graph_count = 0; i < (int) G_N_ELEMENTS(graphs); i++)
3139         {
3140                 struct sharkd_iograph *graph = &graphs[graph_count];
3141
3142                 const char *tok_graph;
3143                 const char *tok_filter;
3144                 char tok_format_buf[32];
3145                 const char *field_name;
3146
3147                 snprintf(tok_format_buf, sizeof(tok_format_buf), "graph%d", i);
3148                 tok_graph = json_find_attr(buf, tokens, count, tok_format_buf);
3149                 if (!tok_graph)
3150                         break;
3151
3152                 snprintf(tok_format_buf, sizeof(tok_format_buf), "filter%d", i);
3153                 tok_filter = json_find_attr(buf, tokens, count, tok_format_buf);
3154
3155                 if (!strcmp(tok_graph, "packets"))
3156                         graph->calc_type = IOG_ITEM_UNIT_PACKETS;
3157                 else if (!strcmp(tok_graph, "bytes"))
3158                         graph->calc_type = IOG_ITEM_UNIT_BYTES;
3159                 else if (!strcmp(tok_graph, "bits"))
3160                         graph->calc_type = IOG_ITEM_UNIT_BITS;
3161                 else if (g_str_has_prefix(tok_graph, "sum:"))
3162                         graph->calc_type = IOG_ITEM_UNIT_CALC_SUM;
3163                 else if (g_str_has_prefix(tok_graph, "frames:"))
3164                         graph->calc_type = IOG_ITEM_UNIT_CALC_FRAMES;
3165                 else if (g_str_has_prefix(tok_graph, "fields:"))
3166                         graph->calc_type = IOG_ITEM_UNIT_CALC_FIELDS;
3167                 else if (g_str_has_prefix(tok_graph, "max:"))
3168                         graph->calc_type = IOG_ITEM_UNIT_CALC_MAX;
3169                 else if (g_str_has_prefix(tok_graph, "min:"))
3170                         graph->calc_type = IOG_ITEM_UNIT_CALC_MIN;
3171                 else if (g_str_has_prefix(tok_graph, "avg:"))
3172                         graph->calc_type = IOG_ITEM_UNIT_CALC_AVERAGE;
3173                 else if (g_str_has_prefix(tok_graph, "load:"))
3174                         graph->calc_type = IOG_ITEM_UNIT_CALC_LOAD;
3175                 else
3176                         break;
3177
3178                 field_name = strchr(tok_graph, ':');
3179                 if (field_name)
3180                         field_name = field_name + 1;
3181
3182                 graph->interval = interval_ms;
3183
3184                 graph->hf_index = -1;
3185                 graph->error = check_field_unit(field_name, &graph->hf_index, graph->calc_type);
3186
3187                 graph->space_items = 0; /* TODO, can avoid realloc()s in sharkd_iograph_packet() by calculating: capture_time / interval */
3188                 graph->num_items = 0;
3189                 graph->items = NULL;
3190
3191                 if (!graph->error)
3192                         graph->error = register_tap_listener("frame", graph, tok_filter, TL_REQUIRES_PROTO_TREE, NULL, sharkd_iograph_packet, NULL, NULL);
3193
3194                 graph_count++;
3195
3196                 if (graph->error == NULL)
3197                         is_any_ok = TRUE;
3198         }
3199
3200         /* retap only if we have at least one ok */
3201         if (is_any_ok)
3202                 sharkd_retap();
3203
3204         sharkd_json_object_open(FALSE);
3205
3206         sharkd_json_array_open(FALSE, "iograph");
3207         for (i = 0; i < graph_count; i++)
3208         {
3209                 struct sharkd_iograph *graph = &graphs[i];
3210
3211                 sharkd_json_object_open(i != 0);
3212
3213                 if (graph->error)
3214                 {
3215                         sharkd_json_value_string(FALSE, "errmsg", graph->error->str);
3216                         g_string_free(graph->error, TRUE);
3217                 }
3218                 else
3219                 {
3220                         int idx;
3221                         int next_idx = 0;
3222
3223                         sharkd_json_array_open(FALSE, "items");
3224                         for (idx = 0; idx < graph->num_items; idx++)
3225                         {
3226                                 double val;
3227
3228                                 val = get_io_graph_item(graph->items, graph->calc_type, idx, graph->hf_index, &cfile, graph->interval, graph->num_items);
3229
3230                                 /* if it's zero, don't display */
3231                                 if (val == 0.0)
3232                                         continue;
3233
3234                                 /* cause zeros are not printed, need to output index */
3235                                 if (next_idx != idx)
3236                                         sharkd_json_value_stringf(next_idx != 0, NULL, "%x", idx);
3237
3238                                 sharkd_json_value_anyf(idx != 0, NULL, "%f", val);
3239                                 next_idx = idx + 1;
3240                         }
3241                         sharkd_json_array_close();
3242                 }
3243                 sharkd_json_object_close();
3244
3245                 remove_tap_listener(graph);
3246                 g_free(graph->items);
3247         }
3248         sharkd_json_array_close();
3249
3250         sharkd_json_object_close();
3251         sharkd_json_finish();
3252 }
3253
3254 /**
3255  * sharkd_session_process_intervals()
3256  *
3257  * Process intervals request - generate basic capture file statistics per requested interval.
3258  *
3259  * Input:
3260  *   (o) interval - interval time in ms, if not specified: 1000ms
3261  *   (o) filter   - filter for generating interval request
3262  *
3263  * Output object with attributes:
3264  *   (m) intervals - array of intervals, with indexes:
3265  *             [0] - index of interval,
3266  *             [1] - number of frames during interval,
3267  *             [2] - number of bytes during interval.
3268  *
3269  *   (m) last   - last interval number.
3270  *   (m) frames - total number of frames
3271  *   (m) bytes  - total number of bytes
3272  *
3273  * NOTE: If frames are not in order, there might be items with same interval index, or even negative one.
3274  */
3275 static void
3276 sharkd_session_process_intervals(char *buf, const jsmntok_t *tokens, int count)
3277 {
3278         const char *tok_interval = json_find_attr(buf, tokens, count, "interval");
3279         const char *tok_filter = json_find_attr(buf, tokens, count, "filter");
3280
3281         const guint8 *filter_data = NULL;
3282
3283         struct
3284         {
3285                 unsigned int frames;
3286                 guint64 bytes;
3287         } st, st_total;
3288
3289         nstime_t *start_ts;
3290
3291         guint32 interval_ms = 1000; /* default: one per second */
3292
3293         gboolean sepa = FALSE;
3294         unsigned int framenum;
3295         gint64 idx;
3296         gint64 max_idx = 0;
3297
3298         if (tok_interval)
3299         {
3300                 if (!ws_strtou32(tok_interval, NULL, &interval_ms) || interval_ms == 0)
3301                 {
3302                         fprintf(stderr, "Invalid interval parameter: %s.\n", tok_interval);
3303                         return;
3304                 }
3305         }
3306
3307         if (tok_filter)
3308         {
3309                 const struct sharkd_filter_item *filter_item;
3310
3311                 filter_item = sharkd_session_filter_data(tok_filter);
3312                 if (!filter_item)
3313                         return;
3314                 filter_data = filter_item->filtered;
3315         }
3316
3317         st_total.frames = 0;
3318         st_total.bytes  = 0;
3319
3320         st.frames = 0;
3321         st.bytes  = 0;
3322
3323         idx = 0;
3324
3325         sharkd_json_object_open(FALSE);
3326         sharkd_json_array_open(FALSE, "intervals");
3327
3328         start_ts = (cfile.count >= 1) ? &(sharkd_get_frame(1)->abs_ts) : NULL;
3329
3330         for (framenum = 1; framenum <= cfile.count; framenum++)
3331         {
3332                 frame_data *fdata;
3333                 gint64 msec_rel;
3334                 gint64 new_idx;
3335
3336                 if (filter_data && !(filter_data[framenum / 8] & (1 << (framenum % 8))))
3337                         continue;
3338
3339                 fdata = sharkd_get_frame(framenum);
3340
3341                 msec_rel = (fdata->abs_ts.secs - start_ts->secs) * (gint64) 1000 + (fdata->abs_ts.nsecs - start_ts->nsecs) / 1000000;
3342                 new_idx  = msec_rel / interval_ms;
3343
3344                 if (idx != new_idx)
3345                 {
3346                         if (st.frames != 0)
3347                         {
3348                                 sharkd_json_value_anyf(sepa, NULL, "[%" G_GINT64_FORMAT ",%u,%" G_GUINT64_FORMAT "]", idx, st.frames, st.bytes);
3349                                 sepa = TRUE;
3350                         }
3351
3352                         idx = new_idx;
3353                         if (idx > max_idx)
3354                                 max_idx = idx;
3355
3356                         st.frames = 0;
3357                         st.bytes  = 0;
3358                 }
3359
3360                 st.frames += 1;
3361                 st.bytes  += fdata->pkt_len;
3362
3363                 st_total.frames += 1;
3364                 st_total.bytes  += fdata->pkt_len;
3365         }
3366
3367         if (st.frames != 0)
3368         {
3369                 sharkd_json_value_anyf(sepa, NULL, "[%" G_GINT64_FORMAT ",%u,%" G_GUINT64_FORMAT "]", idx, st.frames, st.bytes);
3370                 /* sepa = TRUE; */
3371         }
3372         sharkd_json_array_close();
3373
3374         sharkd_json_value_anyf(TRUE, "last", "%" G_GINT64_FORMAT, max_idx);
3375         sharkd_json_value_anyf(TRUE, "frames", "%u", st_total.frames);
3376         sharkd_json_value_anyf(TRUE, "bytes", "%" G_GUINT64_FORMAT, st_total.bytes);
3377
3378         sharkd_json_object_close();
3379         sharkd_json_finish();
3380 }
3381
3382 /**
3383  * sharkd_session_process_frame()
3384  *
3385  * Process frame request
3386  *
3387  * Input:
3388  *   (m) frame - requested frame number
3389  *   (o) ref_frame - time reference frame number
3390  *   (o) prev_frame - previously displayed frame number
3391  *   (o) proto - set if output frame tree
3392  *   (o) columns - set if output frame columns
3393  *   (o) color - set if output color-filter bg/fg
3394  *   (o) bytes - set if output frame bytes
3395  *   (o) hidden - set if output hidden tree fields
3396  *
3397  * Output object with attributes:
3398  *   (m) err   - 0 if succeed
3399  *   (o) tree  - array of frame nodes with attributes:
3400  *                  l - label
3401  *                  t: 'proto', 'framenum', 'url' - type of node
3402  *                  f - filter string
3403  *                  s - severity
3404  *                  e - subtree ett index
3405  *                  n - array of subtree nodes
3406  *                  h - two item array: (item start, item length)
3407  *                  i - two item array: (appendix start, appendix length)
3408  *                  p - [RESERVED] two item array: (protocol start, protocol length)
3409  *                  ds- data src index
3410  *                  url  - only for t:'url', url
3411  *                  fnum - only for t:'framenum', frame number
3412  *                  g - if field is generated by Wireshark
3413  *                  v - if field is hidden
3414  *
3415  *   (o) col   - array of column data
3416  *   (o) bytes - base64 of frame bytes
3417  *   (o) ds    - array of other data srcs
3418  *   (o) comment - frame comment
3419  *   (o) fol   - array of follow filters:
3420  *                  [0] - protocol
3421  *                  [1] - filter string
3422  *   (o) i   - if frame is ignored
3423  *   (o) m   - if frame is marked
3424  *   (o) bg  - color filter - background color in hex
3425  *   (o) fg  - color filter - foreground color in hex
3426  */
3427 static void
3428 sharkd_session_process_frame(char *buf, const jsmntok_t *tokens, int count)
3429 {
3430         const char *tok_frame = json_find_attr(buf, tokens, count, "frame");
3431         const char *tok_ref_frame = json_find_attr(buf, tokens, count, "ref_frame");
3432         const char *tok_prev_frame = json_find_attr(buf, tokens, count, "prev_frame");
3433
3434         guint32 framenum, ref_frame_num, prev_dis_num;
3435         guint32 dissect_flags = SHARKD_DISSECT_FLAG_NULL;
3436         struct sharkd_frame_request_data req_data;
3437
3438         if (!tok_frame || !ws_strtou32(tok_frame, NULL, &framenum) || framenum == 0)
3439                 return;
3440
3441         ref_frame_num = (framenum != 1) ? 1 : 0;
3442         if (tok_ref_frame && (!ws_strtou32(tok_ref_frame, NULL, &ref_frame_num) || ref_frame_num > framenum))
3443                 return;
3444
3445         prev_dis_num = framenum - 1;
3446         if (tok_prev_frame && (!ws_strtou32(tok_prev_frame, NULL, &prev_dis_num) || prev_dis_num >= framenum))
3447                 return;
3448
3449         if (json_find_attr(buf, tokens, count, "proto") != NULL)
3450                 dissect_flags |= SHARKD_DISSECT_FLAG_PROTO_TREE;
3451         if (json_find_attr(buf, tokens, count, "bytes") != NULL)
3452                 dissect_flags |= SHARKD_DISSECT_FLAG_BYTES;
3453         if (json_find_attr(buf, tokens, count, "columns") != NULL)
3454                 dissect_flags |= SHARKD_DISSECT_FLAG_COLUMNS;
3455         if (json_find_attr(buf, tokens, count, "color") != NULL)
3456                 dissect_flags |= SHARKD_DISSECT_FLAG_COLOR;
3457
3458         req_data.display_hidden = (json_find_attr(buf, tokens, count, "v") != NULL);
3459
3460         sharkd_dissect_request(framenum, ref_frame_num, prev_dis_num, &sharkd_session_process_frame_cb, dissect_flags, &req_data);
3461 }
3462
3463 /**
3464  * sharkd_session_process_check()
3465  *
3466  * Process check request.
3467  *
3468  * Input:
3469  *   (o) filter - filter to be checked
3470  *   (o) field - field to be checked
3471  *
3472  * Output object with attributes:
3473  *   (m) err - always 0
3474  *   (o) filter - 'ok', 'warn' or error message
3475  *   (o) field - 'ok', or 'notfound'
3476  */
3477 static int
3478 sharkd_session_process_check(char *buf, const jsmntok_t *tokens, int count)
3479 {
3480         const char *tok_filter = json_find_attr(buf, tokens, count, "filter");
3481         const char *tok_field = json_find_attr(buf, tokens, count, "field");
3482
3483         sharkd_json_object_open(FALSE);
3484         sharkd_json_value_anyf(FALSE, "err", "0");
3485
3486         if (tok_filter != NULL)
3487         {
3488                 char *err_msg = NULL;
3489                 dfilter_t *dfp;
3490
3491                 if (dfilter_compile(tok_filter, &dfp, &err_msg))
3492                 {
3493                         const char *s = "ok";
3494
3495                         if (dfp && dfilter_deprecated_tokens(dfp))
3496                                 s = "warn";
3497
3498                         sharkd_json_value_string(TRUE, "filter", s);
3499                         dfilter_free(dfp);
3500                 }
3501                 else
3502                 {
3503                         sharkd_json_value_string(TRUE, "filter", err_msg);
3504                         g_free(err_msg);
3505                 }
3506         }
3507
3508         if (tok_field != NULL)
3509         {
3510                 header_field_info *hfi = proto_registrar_get_byname(tok_field);
3511
3512                 sharkd_json_value_string(TRUE, "field", (hfi) ? "ok" : "notfound");
3513         }
3514
3515         sharkd_json_object_close();
3516         sharkd_json_finish();
3517
3518         return 0;
3519 }
3520
3521 struct sharkd_session_process_complete_pref_data
3522 {
3523         const char *module;
3524         const char *pref;
3525         gboolean sepa;
3526 };
3527
3528 static guint
3529 sharkd_session_process_complete_pref_cb(module_t *module, gpointer d)
3530 {
3531         struct sharkd_session_process_complete_pref_data *data = (struct sharkd_session_process_complete_pref_data *) d;
3532
3533         if (strncmp(data->pref, module->name, strlen(data->pref)) != 0)
3534                 return 0;
3535
3536         sharkd_json_object_open(data->sepa);
3537         sharkd_json_value_string(FALSE, "f", module->name);
3538         sharkd_json_value_string(TRUE, "d", module->title);
3539         sharkd_json_object_close();
3540
3541         data->sepa = TRUE;
3542
3543         return 0;
3544 }
3545
3546 static guint
3547 sharkd_session_process_complete_pref_option_cb(pref_t *pref, gpointer d)
3548 {
3549         struct sharkd_session_process_complete_pref_data *data = (struct sharkd_session_process_complete_pref_data *) d;
3550         const char *pref_name = prefs_get_name(pref);
3551         const char *pref_title = prefs_get_title(pref);
3552
3553         if (strncmp(data->pref, pref_name, strlen(data->pref)) != 0)
3554                 return 0;
3555
3556         sharkd_json_object_open(data->sepa);
3557         sharkd_json_value_stringf(FALSE, "f", "%s.%s", data->module, pref_name);
3558         sharkd_json_value_string(TRUE, "d", pref_title);
3559         sharkd_json_object_close();
3560
3561         data->sepa = TRUE;
3562
3563         return 0; /* continue */
3564 }
3565
3566 /**
3567  * sharkd_session_process_complete()
3568  *
3569  * Process complete request
3570  *
3571  * Input:
3572  *   (o) field - field to be completed
3573  *   (o) pref  - preference to be completed
3574  *
3575  * Output object with attributes:
3576  *   (m) err - always 0
3577  *   (o) field - array of object with attributes:
3578  *                  (m) f - field text
3579  *                  (o) t - field type (FT_ number)
3580  *                  (o) n - field name
3581  *   (o) pref  - array of object with attributes:
3582  *                  (m) f - pref name
3583  *                  (o) d - pref description
3584  */
3585 static int
3586 sharkd_session_process_complete(char *buf, const jsmntok_t *tokens, int count)
3587 {
3588         const char *tok_field = json_find_attr(buf, tokens, count, "field");
3589         const char *tok_pref  = json_find_attr(buf, tokens, count, "pref");
3590
3591         sharkd_json_object_open(FALSE);
3592         sharkd_json_value_anyf(FALSE, "err", "0");
3593
3594         if (tok_field != NULL && tok_field[0])
3595         {
3596                 const size_t filter_length = strlen(tok_field);
3597                 const int filter_with_dot = !!strchr(tok_field, '.');
3598
3599                 void *proto_cookie;
3600                 void *field_cookie;
3601                 int proto_id;
3602                 gboolean sepa = FALSE;
3603
3604                 sharkd_json_array_open(TRUE, "field");
3605
3606                 for (proto_id = proto_get_first_protocol(&proto_cookie); proto_id != -1; proto_id = proto_get_next_protocol(&proto_cookie))
3607                 {
3608                         protocol_t *protocol = find_protocol_by_id(proto_id);
3609                         const char *protocol_filter;
3610                         const char *protocol_name;
3611                         header_field_info *hfinfo;
3612
3613                         if (!proto_is_protocol_enabled(protocol))
3614                                 continue;
3615
3616                         protocol_name   = proto_get_protocol_long_name(protocol);
3617                         protocol_filter = proto_get_protocol_filter_name(proto_id);
3618
3619                         if (strlen(protocol_filter) >= filter_length && !g_ascii_strncasecmp(tok_field, protocol_filter, filter_length))
3620                         {
3621                                 sharkd_json_object_open(sepa);
3622                                 {
3623                                         sharkd_json_value_string(FALSE, "f", protocol_filter);
3624                                         sharkd_json_value_anyf(TRUE, "t", "%d", FT_PROTOCOL);
3625                                         sharkd_json_value_string(TRUE, "n", protocol_name);
3626                                 }
3627                                 sharkd_json_object_close();
3628                                 sepa = TRUE;
3629                         }
3630
3631                         if (!filter_with_dot)
3632                                 continue;
3633
3634                         for (hfinfo = proto_get_first_protocol_field(proto_id, &field_cookie); hfinfo != NULL; hfinfo = proto_get_next_protocol_field(proto_id, &field_cookie))
3635                         {
3636                                 if (hfinfo->same_name_prev_id != -1) /* ignore duplicate names */
3637                                         continue;
3638
3639                                 if (strlen(hfinfo->abbrev) >= filter_length && !g_ascii_strncasecmp(tok_field, hfinfo->abbrev, filter_length))
3640                                 {
3641                                         sharkd_json_object_open(sepa);
3642                                         {
3643                                                 sharkd_json_value_string(FALSE, "f", hfinfo->abbrev);
3644
3645                                                 /* XXX, skip displaying name, if there are multiple (to not confuse user) */
3646                                                 if (hfinfo->same_name_next == NULL)
3647                                                 {
3648                                                         sharkd_json_value_anyf(TRUE, "t", "%d", hfinfo->type);
3649                                                         sharkd_json_value_string(TRUE, "n", hfinfo->name);
3650                                                 }
3651                                         }
3652                                         sharkd_json_object_close();
3653                                         sepa = TRUE;
3654                                 }
3655                         }
3656                 }
3657
3658                 sharkd_json_array_close();
3659         }
3660
3661         if (tok_pref != NULL && tok_pref[0])
3662         {
3663                 struct sharkd_session_process_complete_pref_data data;
3664                 char *dot_sepa;
3665
3666                 data.module = tok_pref;
3667                 data.pref = tok_pref;
3668                 data.sepa = FALSE;
3669
3670                 sharkd_json_array_open(TRUE, "pref");
3671                 if ((dot_sepa = strchr(tok_pref, '.')))
3672                 {
3673                         module_t *pref_mod;
3674
3675                         *dot_sepa = '\0'; /* XXX, C abuse: discarding-const */
3676                         data.pref = dot_sepa + 1;
3677
3678                         pref_mod = prefs_find_module(data.module);
3679                         if (pref_mod)
3680                                 prefs_pref_foreach(pref_mod, sharkd_session_process_complete_pref_option_cb, &data);
3681
3682                         *dot_sepa = '.';
3683                 }
3684                 else
3685                 {
3686                         prefs_modules_foreach(sharkd_session_process_complete_pref_cb, &data);
3687                 }
3688                 sharkd_json_array_close();
3689         }
3690
3691         sharkd_json_object_close();
3692         sharkd_json_finish();
3693
3694         return 0;
3695 }
3696
3697 /**
3698  * sharkd_session_process_setcomment()
3699  *
3700  * Process setcomment request
3701  *
3702  * Input:
3703  *   (m) frame - frame number
3704  *   (o) comment - user comment
3705  *
3706  * Output object with attributes:
3707  *   (m) err   - error code: 0 succeed
3708  */
3709 static void
3710 sharkd_session_process_setcomment(char *buf, const jsmntok_t *tokens, int count)
3711 {
3712         const char *tok_frame   = json_find_attr(buf, tokens, count, "frame");
3713         const char *tok_comment = json_find_attr(buf, tokens, count, "comment");
3714
3715         guint32 framenum;
3716         frame_data *fdata;
3717         int ret;
3718
3719         if (!tok_frame || !ws_strtou32(tok_frame, NULL, &framenum) || framenum == 0)
3720                 return;
3721
3722         fdata = sharkd_get_frame(framenum);
3723         if (!fdata)
3724                 return;
3725
3726         ret = sharkd_set_user_comment(fdata, tok_comment);
3727
3728         sharkd_json_simple_reply(ret, NULL);
3729 }
3730
3731 /**
3732  * sharkd_session_process_setconf()
3733  *
3734  * Process setconf request
3735  *
3736  * Input:
3737  *   (m) name  - preference name
3738  *   (m) value - preference value
3739  *
3740  * Output object with attributes:
3741  *   (m) err   - error code: 0 succeed
3742  */
3743 static void
3744 sharkd_session_process_setconf(char *buf, const jsmntok_t *tokens, int count)
3745 {
3746         const char *tok_name = json_find_attr(buf, tokens, count, "name");
3747         const char *tok_value = json_find_attr(buf, tokens, count, "value");
3748         char pref[4096];
3749         char *errmsg = NULL;
3750
3751         prefs_set_pref_e ret;
3752
3753         if (!tok_name || tok_name[0] == '\0' || !tok_value)
3754                 return;
3755
3756         ws_snprintf(pref, sizeof(pref), "%s:%s", tok_name, tok_value);
3757
3758         ret = prefs_set_pref(pref, &errmsg);
3759
3760         sharkd_json_simple_reply(ret, errmsg);
3761         g_free(errmsg);
3762 }
3763
3764 struct sharkd_session_process_dumpconf_data
3765 {
3766         module_t *module;
3767         gboolean sepa;
3768 };
3769
3770 static guint
3771 sharkd_session_process_dumpconf_cb(pref_t *pref, gpointer d)
3772 {
3773         struct sharkd_session_process_dumpconf_data *data = (struct sharkd_session_process_dumpconf_data *) d;
3774         const char *pref_name = prefs_get_name(pref);
3775
3776         char json_pref_key[512];
3777
3778         snprintf(json_pref_key, sizeof(json_pref_key), "%s.%s", data->module->name, pref_name);
3779         sharkd_json_value_anyf(data->sepa, json_pref_key, "{");
3780
3781         switch (prefs_get_type(pref))
3782         {
3783                 case PREF_UINT:
3784                 case PREF_DECODE_AS_UINT:
3785                         sharkd_json_value_anyf(FALSE, "u", "%u", prefs_get_uint_value_real(pref, pref_current));
3786                         if (prefs_get_uint_base(pref) != 10)
3787                                 sharkd_json_value_anyf(TRUE, "ub", "%u", prefs_get_uint_base(pref));
3788                         break;
3789
3790                 case PREF_BOOL:
3791                         sharkd_json_value_anyf(FALSE, "b", prefs_get_bool_value(pref, pref_current) ? "1" : "0");
3792                         break;
3793
3794                 case PREF_STRING:
3795                 case PREF_SAVE_FILENAME:
3796                 case PREF_OPEN_FILENAME:
3797                 case PREF_DIRNAME:
3798                         sharkd_json_value_string(FALSE, "s", prefs_get_string_value(pref, pref_current));
3799                         break;
3800
3801                 case PREF_ENUM:
3802                 {
3803                         const enum_val_t *enums;
3804                         gboolean enum_sepa = FALSE;
3805
3806                         sharkd_json_array_open(FALSE, "e");
3807                         for (enums = prefs_get_enumvals(pref); enums->name; enums++)
3808                         {
3809                                 sharkd_json_object_open(enum_sepa);
3810
3811                                 sharkd_json_value_anyf(FALSE, "v", "%d", enums->value);
3812
3813                                 if (enums->value == prefs_get_enum_value(pref, pref_current))
3814                                         sharkd_json_value_anyf(TRUE, "s", "1");
3815
3816                                 sharkd_json_value_string(TRUE, "d", enums->description);
3817
3818                                 sharkd_json_object_close();
3819                                 enum_sepa = TRUE;
3820                         }
3821                         sharkd_json_array_close();
3822                         break;
3823                 }
3824
3825                 case PREF_RANGE:
3826                 case PREF_DECODE_AS_RANGE:
3827                 {
3828                         char *range_str = range_convert_range(NULL, prefs_get_range_value_real(pref, pref_current));
3829                         sharkd_json_value_string(FALSE, "r", range_str);
3830                         wmem_free(NULL, range_str);
3831                         break;
3832                 }
3833
3834                 case PREF_UAT:
3835                 {
3836                         uat_t *uat = prefs_get_uat_value(pref);
3837                         guint idx;
3838
3839                         sharkd_json_array_open(FALSE, "t");
3840                         for (idx = 0; idx < uat->raw_data->len; idx++)
3841                         {
3842                                 void *rec = UAT_INDEX_PTR(uat, idx);
3843                                 guint colnum;
3844
3845                                 sharkd_json_array_open(idx != 0, NULL);
3846                                 for (colnum = 0; colnum < uat->ncols; colnum++)
3847                                 {
3848                                         char *str = uat_fld_tostr(rec, &(uat->fields[colnum]));
3849
3850                                         sharkd_json_value_string(colnum != 0, NULL, str);
3851                                         g_free(str);
3852                                 }
3853
3854                                 sharkd_json_array_close();
3855                         }
3856
3857                         sharkd_json_array_close();
3858                         break;
3859                 }
3860
3861                 case PREF_COLOR:
3862                 case PREF_CUSTOM:
3863                 case PREF_STATIC_TEXT:
3864                 case PREF_OBSOLETE:
3865                         /* TODO */
3866                         break;
3867         }
3868
3869 #if 0
3870         sharkd_json_value_string(TRUE, "t", prefs_get_title(pref));
3871 #endif
3872
3873         sharkd_json_object_close();
3874         data->sepa = TRUE;
3875
3876         return 0; /* continue */
3877 }
3878
3879 static guint
3880 sharkd_session_process_dumpconf_mod_cb(module_t *module, gpointer d)
3881 {
3882         struct sharkd_session_process_dumpconf_data *data = (struct sharkd_session_process_dumpconf_data *) d;
3883
3884         data->module = module;
3885         prefs_pref_foreach(module, sharkd_session_process_dumpconf_cb, data);
3886
3887         return 0;
3888 }
3889
3890 /**
3891  * sharkd_session_process_dumpconf()
3892  *
3893  * Process dumpconf request
3894  *
3895  * Input:
3896  *   (o) pref - module, or preference, NULL for all
3897  *
3898  * Output object with attributes:
3899  *   (o) prefs   - object with module preferences
3900  *                  (m) [KEY] - preference name
3901  *                  (o) u - preference value (for PREF_UINT, PREF_DECODE_AS_UINT)
3902  *                  (o) ub - preference value suggested base for display (for PREF_UINT, PREF_DECODE_AS_UINT) and if different than 10
3903  *                  (o) b - preference value (only for PREF_BOOL) (1 true, 0 false)
3904  *                  (o) s - preference value (for PREF_STRING, PREF_SAVE_FILENAME, PREF_OPEN_FILENAME, PREF_DIRNAME)
3905  *                  (o) e - preference possible values (only for PREF_ENUM)
3906  *                  (o) r - preference value (for PREF_RANGE, PREF_DECODE_AS_RANGE)
3907  *                  (o) t - preference value (only for PREF_UAT)
3908  */
3909 static void
3910 sharkd_session_process_dumpconf(char *buf, const jsmntok_t *tokens, int count)
3911 {
3912         const char *tok_pref = json_find_attr(buf, tokens, count, "pref");
3913         module_t *pref_mod;
3914         char *dot_sepa;
3915
3916         if (!tok_pref)
3917         {
3918                 struct sharkd_session_process_dumpconf_data data;
3919
3920                 data.module = NULL;
3921                 data.sepa = FALSE;
3922
3923                 sharkd_json_object_open(FALSE);
3924
3925                 sharkd_json_value_anyf(FALSE, "prefs", NULL);
3926                 sharkd_json_object_open(FALSE);
3927                 prefs_modules_foreach(sharkd_session_process_dumpconf_mod_cb, &data);
3928                 sharkd_json_object_close();
3929
3930                 sharkd_json_object_close();
3931                 sharkd_json_finish();
3932                 return;
3933         }
3934
3935         if ((dot_sepa = strchr(tok_pref, '.')))
3936         {
3937                 pref_t *pref = NULL;
3938
3939                 *dot_sepa = '\0'; /* XXX, C abuse: discarding-const */
3940                 pref_mod = prefs_find_module(tok_pref);
3941                 if (pref_mod)
3942                         pref = prefs_find_preference(pref_mod, dot_sepa + 1);
3943                 *dot_sepa = '.';
3944
3945                 if (pref)
3946                 {
3947                         struct sharkd_session_process_dumpconf_data data;
3948
3949                         data.module = pref_mod;
3950                         data.sepa = FALSE;
3951
3952                         sharkd_json_object_open(FALSE);
3953
3954                         sharkd_json_value_anyf(FALSE, "prefs", NULL);
3955                         sharkd_json_object_open(FALSE);
3956                         sharkd_session_process_dumpconf_cb(pref, &data);
3957                         sharkd_json_object_close();
3958
3959                         sharkd_json_object_close();
3960                         sharkd_json_finish();
3961                 }
3962
3963                 return;
3964         }
3965
3966         pref_mod = prefs_find_module(tok_pref);
3967         if (pref_mod)
3968         {
3969                 struct sharkd_session_process_dumpconf_data data;
3970
3971                 data.module = pref_mod;
3972                 data.sepa = FALSE;
3973
3974                 sharkd_json_object_open(FALSE);
3975
3976                 sharkd_json_value_anyf(FALSE, "prefs", NULL);
3977                 sharkd_json_object_open(FALSE);
3978                 prefs_pref_foreach(pref_mod, sharkd_session_process_dumpconf_cb, &data);
3979                 sharkd_json_object_close();
3980
3981                 sharkd_json_object_close();
3982                 sharkd_json_finish();
3983         }
3984 }
3985
3986 struct sharkd_download_rtp
3987 {
3988         rtpstream_id_t id;
3989         GSList *packets;
3990         double start_time;
3991 };
3992
3993 static void
3994 sharkd_rtp_download_free_items(void *ptr)
3995 {
3996         rtp_packet_t *rtp_packet = (rtp_packet_t *) ptr;
3997
3998         g_free(rtp_packet->info);
3999         g_free(rtp_packet->payload_data);
4000         g_free(rtp_packet);
4001 }
4002
4003 static void
4004 sharkd_rtp_download_decode(struct sharkd_download_rtp *req)
4005 {
4006         /* based on RtpAudioStream::decode() 6e29d874f8b5e6ebc59f661a0bb0dab8e56f122a */
4007         /* TODO, for now only without silence (timing_mode_ = Uninterrupted) */
4008
4009         static const int sample_bytes_ = sizeof(SAMPLE) / sizeof(char);
4010
4011         guint32 audio_out_rate_ = 0;
4012         struct _GHashTable *decoders_hash_ = rtp_decoder_hash_table_new();
4013         struct SpeexResamplerState_ *audio_resampler_ = NULL;
4014
4015         gsize resample_buff_len = 0x1000;
4016         SAMPLE *resample_buff = (SAMPLE *) g_malloc(resample_buff_len);
4017         spx_uint32_t cur_in_rate = 0;
4018         char *write_buff = NULL;
4019         gint64 write_bytes = 0;
4020         unsigned channels = 0;
4021         unsigned sample_rate = 0;
4022
4023         int i;
4024         int base64_state1 = 0;
4025         int base64_state2 = 0;
4026
4027         GSList *l;
4028
4029         for (l = req->packets; l; l = l->next)
4030         {
4031                 rtp_packet_t *rtp_packet = (rtp_packet_t *) l->data;
4032
4033                 SAMPLE *decode_buff = NULL;
4034                 size_t decoded_bytes;
4035
4036                 decoded_bytes = decode_rtp_packet(rtp_packet, &decode_buff, decoders_hash_, &channels, &sample_rate);
4037                 if (decoded_bytes == 0 || sample_rate == 0)
4038                 {
4039                         /* We didn't decode anything. Clean up and prep for the next packet. */
4040                         g_free(decode_buff);
4041                         continue;
4042                 }
4043
4044                 if (audio_out_rate_ == 0)
4045                 {
4046                         guint32 tmp32;
4047                         guint16 tmp16;
4048                         char wav_hdr[44];
4049
4050                         /* First non-zero wins */
4051                         audio_out_rate_ = sample_rate;
4052
4053                         RTP_STREAM_DEBUG("Audio sample rate is %u", audio_out_rate_);
4054
4055                         /* write WAVE header */
4056                         memset(&wav_hdr, 0, sizeof(wav_hdr));
4057                         memcpy(&wav_hdr[0], "RIFF", 4);
4058                         memcpy(&wav_hdr[4], "\xFF\xFF\xFF\xFF", 4); /* XXX, unknown */
4059                         memcpy(&wav_hdr[8], "WAVE", 4);
4060
4061                         memcpy(&wav_hdr[12], "fmt ", 4);
4062                         memcpy(&wav_hdr[16], "\x10\x00\x00\x00", 4); /* PCM */
4063                         memcpy(&wav_hdr[20], "\x01\x00", 2);         /* PCM */
4064                         /* # channels */
4065                         tmp16 = channels;
4066                         memcpy(&wav_hdr[22], &tmp16, 2);
4067                         /* sample rate */
4068                         tmp32 = sample_rate;
4069                         memcpy(&wav_hdr[24], &tmp32, 4);
4070                         /* byte rate */
4071                         tmp32 = sample_rate * channels * sample_bytes_;
4072                         memcpy(&wav_hdr[28], &tmp32, 4);
4073                         /* block align */
4074                         tmp16 = channels * sample_bytes_;
4075                         memcpy(&wav_hdr[32], &tmp16, 2);
4076                         /* bits per sample */
4077                         tmp16 = 8 * sample_bytes_;
4078                         memcpy(&wav_hdr[34], &tmp16, 2);
4079
4080                         memcpy(&wav_hdr[36], "data", 4);
4081                         memcpy(&wav_hdr[40], "\xFF\xFF\xFF\xFF", 4); /* XXX, unknown */
4082
4083                         for (i = 0; i < (int) sizeof(wav_hdr); i++)
4084                                 json_print_base64_step(&wav_hdr[i], &base64_state1, &base64_state2);
4085                 }
4086
4087                 // Write samples to our file.
4088                 write_buff = (char *) decode_buff;
4089                 write_bytes = decoded_bytes;
4090
4091                 if (audio_out_rate_ != sample_rate)
4092                 {
4093                         spx_uint32_t in_len, out_len;
4094
4095                         /* Resample the audio to match our previous output rate. */
4096                         if (!audio_resampler_)
4097                         {
4098                                 audio_resampler_ = speex_resampler_init(1, sample_rate, audio_out_rate_, 10, NULL);
4099                                 speex_resampler_skip_zeros(audio_resampler_);
4100                                 RTP_STREAM_DEBUG("Started resampling from %u to (out) %u Hz.", sample_rate, audio_out_rate_);
4101                         }
4102                         else
4103                         {
4104                                 spx_uint32_t audio_out_rate;
4105                                 speex_resampler_get_rate(audio_resampler_, &cur_in_rate, &audio_out_rate);
4106
4107                                 if (sample_rate != cur_in_rate)
4108                                 {
4109                                         speex_resampler_set_rate(audio_resampler_, sample_rate, audio_out_rate);
4110                                         RTP_STREAM_DEBUG("Changed input rate from %u to %u Hz. Out is %u.", cur_in_rate, sample_rate, audio_out_rate_);
4111                                 }
4112                         }
4113                         in_len = (spx_uint32_t)rtp_packet->info->info_payload_len;
4114                         out_len = (audio_out_rate_ * (spx_uint32_t)rtp_packet->info->info_payload_len / sample_rate) + (audio_out_rate_ % sample_rate != 0);
4115                         if (out_len * sample_bytes_ > resample_buff_len)
4116                         {
4117                                 while ((out_len * sample_bytes_ > resample_buff_len))
4118                                         resample_buff_len *= 2;
4119                                 resample_buff = (SAMPLE *) g_realloc(resample_buff, resample_buff_len);
4120                         }
4121
4122                         speex_resampler_process_int(audio_resampler_, 0, decode_buff, &in_len, resample_buff, &out_len);
4123                         write_buff = (char *) resample_buff;
4124                         write_bytes = out_len * sample_bytes_;
4125                 }
4126
4127                 /* Write the decoded, possibly-resampled audio */
4128                 for (i = 0; i < write_bytes; i++)
4129                         json_print_base64_step(&write_buff[i], &base64_state1, &base64_state2);
4130
4131                 g_free(decode_buff);
4132         }
4133
4134         json_print_base64_step(NULL, &base64_state1, &base64_state2);
4135
4136         g_free(resample_buff);
4137         g_hash_table_destroy(decoders_hash_);
4138 }
4139
4140 static gboolean
4141 sharkd_session_packet_download_tap_rtp_cb(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_, const void *data)
4142 {
4143         const struct _rtp_info *rtp_info = (const struct _rtp_info *) data;
4144         struct sharkd_download_rtp *req_rtp = (struct sharkd_download_rtp *) tapdata;
4145
4146         /* do not consider RTP packets without a setup frame */
4147         if (rtp_info->info_setup_frame_num == 0)
4148                 return FALSE;
4149
4150         if (rtpstream_id_equal_pinfo_rtp_info(&req_rtp->id, pinfo, rtp_info))
4151         {
4152                 rtp_packet_t *rtp_packet;
4153
4154                 rtp_packet = g_new0(rtp_packet_t, 1);
4155                 rtp_packet->info = (struct _rtp_info *) g_memdup(rtp_info, sizeof(struct _rtp_info));
4156
4157                 if (rtp_info->info_all_data_present && rtp_info->info_payload_len != 0)
4158                         rtp_packet->payload_data = (guint8 *) g_memdup(&(rtp_info->info_data[rtp_info->info_payload_offset]), rtp_info->info_payload_len);
4159
4160                 if (!req_rtp->packets)
4161                         req_rtp->start_time = nstime_to_sec(&pinfo->abs_ts);
4162
4163                 rtp_packet->frame_num = pinfo->num;
4164                 rtp_packet->arrive_offset = nstime_to_sec(&pinfo->abs_ts) - req_rtp->start_time;
4165
4166                 /* XXX, O(n) optimize */
4167                 req_rtp->packets = g_slist_append(req_rtp->packets, rtp_packet);
4168         }
4169
4170         return FALSE;
4171 }
4172
4173 /**
4174  * sharkd_session_process_download()
4175  *
4176  * Process download request
4177  *
4178  * Input:
4179  *   (m) token  - token to download
4180  *
4181  * Output object with attributes:
4182  *   (o) file - suggested name of file
4183  *   (o) mime - suggested content type
4184  *   (o) data - payload base64 encoded
4185  */
4186 static void
4187 sharkd_session_process_download(char *buf, const jsmntok_t *tokens, int count)
4188 {
4189         const char *tok_token      = json_find_attr(buf, tokens, count, "token");
4190
4191         if (!tok_token)
4192                 return;
4193
4194         if (!strncmp(tok_token, "eo:", 3))
4195         {
4196                 struct sharkd_export_object_list *object_list;
4197                 const export_object_entry_t *eo_entry = NULL;
4198
4199                 for (object_list = sharkd_eo_list; object_list; object_list = object_list->next)
4200                 {
4201                         size_t eo_type_len = strlen(object_list->type);
4202
4203                         if (!strncmp(tok_token, object_list->type, eo_type_len) && tok_token[eo_type_len] == '_')
4204                         {
4205                                 int row;
4206
4207                                 if (sscanf(&tok_token[eo_type_len + 1], "%d", &row) != 1)
4208                                         break;
4209
4210                                 eo_entry = (export_object_entry_t *) g_slist_nth_data(object_list->entries, row);
4211                                 break;
4212                         }
4213                 }
4214
4215                 if (eo_entry)
4216                 {
4217                         const char *mime     = (eo_entry->content_type) ? eo_entry->content_type : "application/octet-stream";
4218                         const char *filename = (eo_entry->filename) ? eo_entry->filename : tok_token;
4219
4220                         sharkd_json_object_open(FALSE);
4221                         sharkd_json_value_string(FALSE, "file", filename);
4222                         sharkd_json_value_string(TRUE, "mime", mime);
4223                         sharkd_json_value_base64(TRUE, "data", eo_entry->payload_data, (size_t) eo_entry->payload_len);
4224                         sharkd_json_object_close();
4225                         sharkd_json_finish();
4226                 }
4227         }
4228         else if (!strcmp(tok_token, "ssl-secrets"))
4229         {
4230                 char *str = ssl_export_sessions();
4231
4232                 if (str)
4233                 {
4234                         const char *mime     = "text/plain";
4235                         const char *filename = "keylog.txt";
4236
4237                         sharkd_json_object_open(FALSE);
4238                         sharkd_json_value_string(FALSE, "file", filename);
4239                         sharkd_json_value_string(TRUE, "mime", mime);
4240                         sharkd_json_value_base64(TRUE, "data", str, strlen(str));
4241                         sharkd_json_object_close();
4242                         sharkd_json_finish();
4243                 }
4244                 g_free(str);
4245         }
4246         else if (!strncmp(tok_token, "rtp:", 4))
4247         {
4248                 struct sharkd_download_rtp rtp_req;
4249                 GString *tap_error;
4250
4251                 memset(&rtp_req, 0, sizeof(rtp_req));
4252                 if (!sharkd_rtp_match_init(&rtp_req.id, tok_token + 4))
4253                 {
4254                         fprintf(stderr, "sharkd_session_process_download() rtp tokenizing error %s\n", tok_token);
4255                         return;
4256                 }
4257
4258                 tap_error = register_tap_listener("rtp", &rtp_req, NULL, 0, NULL, sharkd_session_packet_download_tap_rtp_cb, NULL, NULL);
4259                 if (tap_error)
4260                 {
4261                         fprintf(stderr, "sharkd_session_process_download() rtp error=%s", tap_error->str);
4262                         g_string_free(tap_error, TRUE);
4263                         return;
4264                 }
4265
4266                 sharkd_retap();
4267                 remove_tap_listener(&rtp_req);
4268
4269                 if (rtp_req.packets)
4270                 {
4271                         const char *mime     = "audio/x-wav";
4272                         const char *filename = tok_token;
4273
4274                         sharkd_json_object_open(FALSE);
4275                         sharkd_json_value_string(FALSE, "file", filename);
4276                         sharkd_json_value_string(TRUE, "mime", mime);
4277
4278                         sharkd_json_value_anyf(TRUE, "data", NULL);
4279                         putchar('"');
4280                         sharkd_rtp_download_decode(&rtp_req);
4281                         putchar('"');
4282
4283                         sharkd_json_object_close();
4284                         sharkd_json_finish();
4285
4286                         g_slist_free_full(rtp_req.packets, sharkd_rtp_download_free_items);
4287                 }
4288         }
4289 }
4290
4291 static void
4292 sharkd_session_process(char *buf, const jsmntok_t *tokens, int count)
4293 {
4294         int i;
4295
4296         /* sanity check, and split strings */
4297         if (count < 1 || tokens[0].type != JSMN_OBJECT)
4298         {
4299                 fprintf(stderr, "sanity check(1): [0] not object\n");
4300                 return;
4301         }
4302
4303         /* don't need [0] token */
4304         tokens++;
4305         count--;
4306
4307         if (count & 1)
4308         {
4309                 fprintf(stderr, "sanity check(2): %d not even\n", count);
4310                 return;
4311         }
4312
4313         for (i = 0; i < count; i += 2)
4314         {
4315                 if (tokens[i].type != JSMN_STRING)
4316                 {
4317                         fprintf(stderr, "sanity check(3): [%d] not string\n", i);
4318                         return;
4319                 }
4320
4321                 if (tokens[i + 1].type != JSMN_STRING && tokens[i + 1].type != JSMN_PRIMITIVE)
4322                 {
4323                         fprintf(stderr, "sanity check(3a): [%d] wrong type\n", i + 1);
4324                         return;
4325                 }
4326
4327                 buf[tokens[i + 0].end] = '\0';
4328                 buf[tokens[i + 1].end] = '\0';
4329
4330                 /* unescape only value, as keys are simple strings */
4331                 if (tokens[i + 1].type == JSMN_STRING && !json_decode_string_inplace(&buf[tokens[i + 1].start]))
4332                 {
4333                         fprintf(stderr, "sanity check(3b): [%d] cannot unescape string\n", i + 1);
4334                         return;
4335                 }
4336         }
4337
4338         {
4339                 const char *tok_req = json_find_attr(buf, tokens, count, "req");
4340
4341                 if (!tok_req)
4342                 {
4343                         fprintf(stderr, "sanity check(4): no \"req\".\n");
4344                         return;
4345                 }
4346
4347                 if (!strcmp(tok_req, "load"))
4348                         sharkd_session_process_load(buf, tokens, count);
4349                 else if (!strcmp(tok_req, "status"))
4350                         sharkd_session_process_status();
4351                 else if (!strcmp(tok_req, "analyse"))
4352                         sharkd_session_process_analyse();
4353                 else if (!strcmp(tok_req, "info"))
4354                         sharkd_session_process_info();
4355                 else if (!strcmp(tok_req, "check"))
4356                         sharkd_session_process_check(buf, tokens, count);
4357                 else if (!strcmp(tok_req, "complete"))
4358                         sharkd_session_process_complete(buf, tokens, count);
4359                 else if (!strcmp(tok_req, "frames"))
4360                         sharkd_session_process_frames(buf, tokens, count);
4361                 else if (!strcmp(tok_req, "tap"))
4362                         sharkd_session_process_tap(buf, tokens, count);
4363                 else if (!strcmp(tok_req, "follow"))
4364                         sharkd_session_process_follow(buf, tokens, count);
4365                 else if (!strcmp(tok_req, "iograph"))
4366                         sharkd_session_process_iograph(buf, tokens, count);
4367                 else if (!strcmp(tok_req, "intervals"))
4368                         sharkd_session_process_intervals(buf, tokens, count);
4369                 else if (!strcmp(tok_req, "frame"))
4370                         sharkd_session_process_frame(buf, tokens, count);
4371                 else if (!strcmp(tok_req, "setcomment"))
4372                         sharkd_session_process_setcomment(buf, tokens, count);
4373                 else if (!strcmp(tok_req, "setconf"))
4374                         sharkd_session_process_setconf(buf, tokens, count);
4375                 else if (!strcmp(tok_req, "dumpconf"))
4376                         sharkd_session_process_dumpconf(buf, tokens, count);
4377                 else if (!strcmp(tok_req, "download"))
4378                         sharkd_session_process_download(buf, tokens, count);
4379                 else if (!strcmp(tok_req, "bye"))
4380                         exit(0);
4381                 else
4382                         fprintf(stderr, "::: req = %s\n", tok_req);
4383
4384                 /* reply for every command are 0+ lines of JSON reply (outputed above), finished by empty new line */
4385                 sharkd_json_finish();
4386
4387                 /*
4388                  * We do an explicit fflush after every line, because
4389                  * we want output to be written to the socket as soon
4390                  * as the line is complete.
4391                  *
4392                  * The stream is fully-buffered by default, so it's
4393                  * only flushed when the buffer fills or the FILE *
4394                  * is closed.  On UN*X, we could set it to be line
4395                  * buffered, but the MSVC standard I/O routines don't
4396                  * support line buffering - they only support *byte*
4397                  * buffering, doing a write for every byte written,
4398                  * which is too inefficient, and full buffering,
4399                  * which is what you get if you request line buffering.
4400                  */
4401                 fflush(stdout);
4402         }
4403 }
4404
4405 int
4406 sharkd_session_main(void)
4407 {
4408         char buf[2 * 1024];
4409         jsmntok_t *tokens = NULL;
4410         int tokens_max = -1;
4411
4412         fprintf(stderr, "Hello in child.\n");
4413
4414         filter_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, sharkd_session_filter_free);
4415
4416 #ifdef HAVE_MAXMINDDB
4417         /* mmdbresolve was stopped before fork(), force starting it */
4418         uat_get_table_by_name("MaxMind Database Paths")->post_update_cb();
4419 #endif
4420
4421         while (fgets(buf, sizeof(buf), stdin))
4422         {
4423                 /* every command is line seperated JSON */
4424                 int ret;
4425
4426                 ret = json_parse(buf, NULL, 0);
4427                 if (ret < 0)
4428                 {
4429                         fprintf(stderr, "invalid JSON -> closing\n");
4430                         return 1;
4431                 }
4432
4433                 /* fprintf(stderr, "JSON: %d tokens\n", ret); */
4434                 ret += 1;
4435
4436                 if (tokens == NULL || tokens_max < ret)
4437                 {
4438                         tokens_max = ret;
4439                         tokens = (jsmntok_t *) g_realloc(tokens, sizeof(jsmntok_t) * tokens_max);
4440                 }
4441
4442                 memset(tokens, 0, ret * sizeof(jsmntok_t));
4443
4444                 ret = json_parse(buf, tokens, ret);
4445                 if (ret < 0)
4446                 {
4447                         fprintf(stderr, "invalid JSON(2) -> closing\n");
4448                         return 2;
4449                 }
4450
4451 #if defined(HAVE_C_ARES) || defined(HAVE_MAXMINDDB)
4452                 host_name_lookup_process();
4453 #endif
4454
4455                 sharkd_session_process(buf, tokens, ret);
4456         }
4457
4458         g_hash_table_destroy(filter_table);
4459         g_free(tokens);
4460
4461         return 0;
4462 }
4463
4464 /*
4465  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
4466  *
4467  * Local variables:
4468  * c-basic-offset: 8
4469  * tab-width: 8
4470  * indent-tabs-mode: t
4471  * End:
4472  *
4473  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
4474  * :indentSize=8:tabSize=8:noTabs=false:
4475  */