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