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