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