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