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