diff --git a/daemon/redis.c b/daemon/redis.c index 0facd61f8..50fa40ff1 100644 --- a/daemon/redis.c +++ b/daemon/redis.c @@ -2693,430 +2693,438 @@ static void json_update_detected_endpoints(const ng_parser_t *parser, parser_arg ? endpoint_print_buf(&ps->detected_endpoints[i]) : ""); } -/** - * encodes the few (k,v) pairs for one call under one json structure - */ +static void redis_encode_ml_basic(struct call_monologue *ml, const ng_parser_t *parser, parser_arg root) { + char tmp[128]; + + snprintf(tmp, sizeof(tmp), "tag-%u", ml->unique_id); + parser_arg inner = parser->dict_add_dict_dup(root, tmp); + + JSON_SET_SIMPLE("created", "%" PRId64, ml->created_us); + JSON_SET_SIMPLE("deleted", "%" PRId64, ml->deleted_us); + JSON_SET_SIMPLE("block_dtmf", "%i", ml->block_dtmf); + JSON_SET_SIMPLE("ml_flags", "%" PRIu64, atomic64_get_na(&ml->ml_flags)); + JSON_SET_SIMPLE_CSTR("desired_family", ml->desired_family ? ml->desired_family->rfc_name : ""); + if (ml->logical_intf) + JSON_SET_SIMPLE_STR("logical_intf", &ml->logical_intf->name); + + if (ml->tag.s) + JSON_SET_SIMPLE_STR("tag", &ml->tag); + if (ml->call_id.s) + JSON_SET_SIMPLE_STR("call_id", &ml->tag); + if (ml->viabranch.s) + JSON_SET_SIMPLE_STR("via-branch", &ml->viabranch); + if (ml->label.s) + JSON_SET_SIMPLE_STR("label", &ml->label); + if (ml->metadata.s) + JSON_SET_SIMPLE_STR("metadata", &ml->metadata); + + JSON_SET_SIMPLE_STR("sdp_session_name", &ml->sdp_session_name); + JSON_SET_SIMPLE_STR("sdp_session_timing", &ml->sdp_session_timing); + + if (ml->sdp_orig_in.parsed) { + JSON_SET_SIMPLE_STR("sdp_orig_username", &ml->sdp_orig_in.username); + JSON_SET_SIMPLE_STR("sdp_orig_session_id", &ml->sdp_orig_in.session_id); + JSON_SET_SIMPLE("sdp_orig_version_num", "%llu", ml->sdp_orig_in.version_num); + JSON_SET_SIMPLE("sdp_orig_parsed", "%u", ml->sdp_orig_in.parsed); + JSON_SET_SIMPLE_STR("sdp_orig_address_network_type", &ml->sdp_orig_in.address.network_type); + JSON_SET_SIMPLE_STR("sdp_orig_address_address_type", &ml->sdp_orig_in.address.address_type); + JSON_SET_SIMPLE_STR("sdp_orig_address_address", &ml->sdp_orig_in.address.address); + } + if (ml->sdp_orig_out.parsed) { + JSON_SET_SIMPLE_STR("last_sdp_orig_username", &ml->sdp_orig_out.username); + JSON_SET_SIMPLE_STR("last_sdp_orig_session_id", &ml->sdp_orig_out.session_id); + JSON_SET_SIMPLE("last_sdp_orig_version_num", "%llu", ml->sdp_orig_out.version_num); + JSON_SET_SIMPLE("last_sdp_orig_parsed", "%u", ml->sdp_orig_out.parsed); + JSON_SET_SIMPLE_STR("last_sdp_orig_address_network_type", &ml->sdp_orig_out.address.network_type); + JSON_SET_SIMPLE_STR("last_sdp_orig_address_address_type", &ml->sdp_orig_out.address.address_type); + JSON_SET_SIMPLE_STR("last_sdp_orig_address_address", &ml->sdp_orig_out.address.address); + } + + if (ml->sdp_session_bandwidth.as >= 0) + JSON_SET_SIMPLE("sdp_session_as", "%ld", ml->sdp_session_bandwidth.as); + if (ml->sdp_session_bandwidth.ct >= 0) + JSON_SET_SIMPLE("sdp_session_ct", "%ld", ml->sdp_session_bandwidth.ct); + if (ml->sdp_session_bandwidth.rr >= 0) + JSON_SET_SIMPLE("sdp_session_rr", "%ld", ml->sdp_session_bandwidth.rr); + if (ml->sdp_session_bandwidth.rs >= 0) + JSON_SET_SIMPLE("sdp_session_rs", "%ld", ml->sdp_session_bandwidth.rs); + if (ml->sdp_session_bandwidth.tias >= 0) + JSON_SET_SIMPLE("sdp_session_tias", "%ld", ml->sdp_session_bandwidth.tias); + if (ml->last_out_sdp && ml->last_out_sdp->len) + JSON_SET_SIMPLE_LEN("last_out_sdp", ml->last_out_sdp->len, + ml->last_out_sdp->str); + + snprintf(tmp, sizeof(tmp), "medias-%u", ml->unique_id); + inner = parser->dict_add_list_dup(root, tmp); + for (unsigned int j = 0; j < ml->medias->len; j++) { + struct call_media *media = ml->medias->pdata[j]; + JSON_ADD_LIST_STRING("%u", media ? media->unique_id : -1); + } -// scope = write only these monologues' state, plus the state only a rollback -// reads. NULL writes the whole call, which is what the Redis record wants. -static bool ml_in_scope(struct call_monologue * const *scope, const struct call_monologue *ml) { - return !scope || ml == scope[0] || ml == scope[1]; } -static str redis_encode_json(ng_parser_ctx_t *ctx, call_t *c, void **to_free, - struct call_monologue * const *scope) -{ +static parser_arg redis_encode_media_basic(struct call_media *media, const ng_parser_t *parser, parser_arg root) { + char tmp[128]; + + snprintf(tmp, sizeof(tmp), "payload_types-%u", media->unique_id); + parser_arg inner = parser->dict_add_list_dup(root, tmp); + redis_encode_codec_store(parser, inner, &media->codecs); + + // SSRC table dump + // XXX needs fixing + LOCK(&media->ssrc_hash_in.lock); + snprintf(tmp, sizeof(tmp), "ssrc_table-%u", media->unique_id); + parser_arg list = parser->dict_add_list_dup(root, tmp); + for (GList *m = media->ssrc_hash_in.nq.head; m; m = m->next) { + struct ssrc_entry_call *se = m->data; + inner = parser->list_add_dict(list); + + JSON_SET_SIMPLE("ssrc", "%" PRIu32, se->h.ssrc); + // XXX use function for in/out + JSON_SET_SIMPLE("in_srtp_index", "%u", atomic_get_na(&se->stats->ext_seq)); + JSON_SET_SIMPLE("in_srtcp_index", "%u", atomic_get_na(&se->stats->rtcp_seq)); + JSON_SET_SIMPLE("in_payload_type", "%i", se->tracker.most[0]); + //JSON_SET_SIMPLE("out_srtp_index", "%u", atomic_get_na(&se->output_ctx.stats->ext_seq)); + //JSON_SET_SIMPLE("out_srtcp_index", "%u", atomic_get_na(&se->output_ctx.stats->rtcp_seq)); + //JSON_SET_SIMPLE("out_payload_type", "%i", se->output_ctx.tracker.most[0]); + // XXX add rest of info + } + + snprintf(tmp, sizeof(tmp), "media-%u", media->unique_id); + inner = parser->dict_add_dict_dup(root, tmp); + + JSON_SET_SIMPLE("tag","%u", media->monologue->unique_id); + JSON_SET_SIMPLE("index","%u", media->index); + JSON_SET_SIMPLE_STR("type", &media->type); + if (media->format_str.s) + JSON_SET_SIMPLE_STR("format_str", &media->format_str); + if (media->media_id.s) + JSON_SET_SIMPLE_STR("media_id", &media->media_id); + if (media->label.s) + JSON_SET_SIMPLE_STR("label", &media->label); + JSON_SET_SIMPLE_CSTR("protocol", media->protocol ? media->protocol->name : ""); + JSON_SET_SIMPLE_CSTR("desired_family", media->desired_family ? media->desired_family->rfc_name : ""); + if (media->logical_intf) + JSON_SET_SIMPLE_STR("logical_intf", &media->logical_intf->name); + JSON_SET_SIMPLE("ptime","%i", media->ptime); + JSON_SET_SIMPLE("maxptime","%i", media->maxptime); + JSON_SET_SIMPLE("media_flags", "%" PRIu64, atomic64_get_na(&media->media_flags)); + + if (media->sdp_media_bandwidth.as >= 0) + JSON_SET_SIMPLE("bandwidth_as","%ld", media->sdp_media_bandwidth.as); + if (media->sdp_media_bandwidth.rr >= 0) + JSON_SET_SIMPLE("bandwidth_rr","%ld", media->sdp_media_bandwidth.rr); + if (media->sdp_media_bandwidth.rs >= 0) + JSON_SET_SIMPLE("bandwidth_rs","%ld", media->sdp_media_bandwidth.rs); + if (media->sdp_media_bandwidth.ct >= 0) + JSON_SET_SIMPLE("bandwidth_ct","%ld", media->sdp_media_bandwidth.ct); + if (media->sdp_media_bandwidth.tias >= 0) + JSON_SET_SIMPLE("bandwidth_tias","%ld", media->sdp_media_bandwidth.tias); + + redis_encode_sdes_params(parser, inner, "sdes_in", &media->sdes_in); + redis_encode_sdes_params(parser, inner, "sdes_out", &media->sdes_out); + redis_encode_dtls_fingerprint(parser, inner, &media->fingerprint); + + return inner; +} + + +static parser_arg redis_encode_stream_basic(struct packet_stream *ps, const ng_parser_t *parser, parser_arg root) { + char tmp[128]; + + snprintf(tmp, sizeof(tmp), "stream_sfds-%u", ps->unique_id); + parser_arg inner = parser->dict_add_list_dup(root, tmp); + for (__auto_type k = ps->sfds.head; k; k = k->next) { + stream_fd *sfd = k->data; + JSON_ADD_LIST_STRING("%u", sfd->unique_id); + } + + snprintf(tmp, sizeof(tmp), "stream-%u", ps->unique_id); + inner = parser->dict_add_dict_dup(root, tmp); + + JSON_SET_SIMPLE("media","%u",ps->media->unique_id); + JSON_SET_SIMPLE("sfd","%u",ps->selected_sfd ? ps->selected_sfd->unique_id : -1); + JSON_SET_SIMPLE("rtcp_sibling","%u",ps->rtcp_sibling ? ps->rtcp_sibling->unique_id : -1); + JSON_SET_SIMPLE("ps_flags", "%" PRIu64, atomic64_get_na(&ps->ps_flags)); + JSON_SET_SIMPLE("component","%u",ps->component); + JSON_SET_SIMPLE_CSTR("endpoint",endpoint_print_buf(&ps->endpoint)); + JSON_SET_SIMPLE_CSTR("advertised_endpoint",endpoint_print_buf(&ps->advertised_endpoint)); + + JSON_SET_SIMPLE("stats-packets","%" PRIu64, atomic64_get_na(&ps->stats_in->packets)); + JSON_SET_SIMPLE("stats-bytes","%" PRIu64, atomic64_get_na(&ps->stats_in->bytes)); + JSON_SET_SIMPLE("stats-errors","%" PRIu64, atomic64_get_na(&ps->stats_in->errors)); + + json_update_crypto_params(parser, inner, "", &ps->crypto.params); + + return inner; +} + + +static str redis_encode_json_ml(ng_parser_ctx_t *ctx, call_t *c, void **to_free, + struct call_monologue *ml) +{ char tmp[128]; const ng_parser_t *parser = ctx->parser; parser_arg root = parser->dict(ctx); - { - parser_arg inner = {0}; - - if (!scope) { - inner = parser->dict_add_dict(root, "json"); - JSON_SET_SIMPLE("created","%" PRId64, c->created); - JSON_SET_SIMPLE("destroyed","%" PRId64, c->destroyed); - JSON_SET_SIMPLE("last_signal","%" PRId64, c->last_signal_us); - JSON_SET_SIMPLE("tos","%u", (int) c->tos); - JSON_SET_SIMPLE("deleted","%" PRId64, c->deleted_us); - JSON_SET_SIMPLE("num_sfds","%u", t_queue_get_length(&c->stream_fds)); - JSON_SET_SIMPLE("num_streams","%u", t_queue_get_length(&c->streams)); - JSON_SET_SIMPLE("num_medias","%u", t_queue_get_length(&c->medias)); - JSON_SET_SIMPLE("num_tags","%u", t_queue_get_length(&c->monologues)); - JSON_SET_SIMPLE("num_maps","%u", t_queue_get_length(&c->endpoint_maps)); - JSON_SET_SIMPLE("ml_deleted","%" PRId64, c->ml_deleted_us); - JSON_SET_SIMPLE("redis_hosted_db","%u", c->redis_hosted_db); - JSON_SET_SIMPLE_STR("recording_metadata", &c->metadata); - JSON_SET_SIMPLE("block_dtmf","%i", c->block_dtmf); - JSON_SET_SIMPLE("call_flags", "%" PRIu64, atomic64_get_na(&c->call_flags)); - - if (c->created_from.len) - JSON_SET_SIMPLE_STR("created_from", &c->created_from); - if (c->recording_meta_prefix.len) - JSON_SET_SIMPLE_STR("recording_meta_prefix", &c->recording_meta_prefix); - if (c->recording_file.len) - JSON_SET_SIMPLE_STR("recording_file", &c->recording_file); - if (c->recording_path.len) - JSON_SET_SIMPLE_STR("recording_path", &c->recording_path); - if (c->recording_pattern.len) - JSON_SET_SIMPLE_STR("recording_pattern", &c->recording_pattern); - if (c->recording_random_tag.len) - JSON_SET_SIMPLE_STR("recording_random_tag", &c->recording_random_tag); + parser_arg inner; + + redis_encode_ml_basic(ml, parser, root); + + for (unsigned int i = 0; i < ml->medias->len; i++) { + __auto_type media = ml->medias->pdata[i]; + if (!media) + continue; + + inner = redis_encode_media_basic(media, parser, root); + + if (media->tls_id.s) + JSON_SET_SIMPLE_STR("tls_id", &media->tls_id); + if (media->fp_hash_func) + JSON_SET_SIMPLE_CSTR("preferred_hash_func", + media->fp_hash_func->name); + if (media->endpoint_map) + JSON_SET_SIMPLE("endpoint_map", "%u", + media->endpoint_map->unique_id); + + unsigned int num_cands = 0; + for (__auto_type m = media->ice_candidates.head; m; m = m->next) + num_cands++; + JSON_SET_SIMPLE("num_ice_candidates", "%u", num_cands); + JSON_SET_SIMPLE("had_ice", "%i", media->ice_agent ? 1 : 0); + if (media->ice_agent) { + JSON_SET_SIMPLE_STR("ice_ufrag_local", &media->ice_agent->ufrag[0]); + JSON_SET_SIMPLE_STR("ice_ufrag_remote", &media->ice_agent->ufrag[1]); + JSON_SET_SIMPLE_STR("ice_pwd_local", &media->ice_agent->pwd[0]); + JSON_SET_SIMPLE_STR("ice_pwd_remote", &media->ice_agent->pwd[1]); } - for (__auto_type l = scope ? NULL : c->monologues.head; l; l = l->next) { - const struct call_monologue *ml = l->data; - if (!ml->checkpoint) - continue; - snprintf(tmp, sizeof(tmp), "checkpoint-%u", ml->unique_id); + unsigned int ci = 0; + for (__auto_type m = media->ice_candidates.head; m; m = m->next, ci++) { + const struct ice_candidate *cand = m->data; + snprintf(tmp, sizeof(tmp), "ice_candidate-%u-%u", media->unique_id, ci); inner = parser->dict_add_dict_dup(root, tmp); - JSON_SET_SIMPLE("pending", "%i", ml->checkpoint->pending ? 1 : 0); - if (ml->checkpoint->snapshot.len) { - /* nested as a string; heap buffer rather than a VLA, as escape() can - * need up to 3x the input */ - char *enc = g_malloc_n(ml->checkpoint->snapshot.len + 1, 3); - str encs = parser->escape(enc, ml->checkpoint->snapshot.s, - ml->checkpoint->snapshot.len); - parser->dict_add_str_dup(inner, "snapshot", &encs); - g_free(enc); - } + JSON_SET_SIMPLE_STR("foundation", &cand->foundation); + JSON_SET_SIMPLE("component", "%lu", (unsigned long) cand->component_id); + JSON_SET_SIMPLE_CSTR("transport", + cand->transport ? cand->transport->name : ""); + JSON_SET_SIMPLE("priority", "%lu", (unsigned long) cand->priority); + JSON_SET_SIMPLE("type", "%u", cand->type); + JSON_SET_SIMPLE_STR("ufrag", &cand->ufrag); + JSON_SET_SIMPLE_CSTR("endpoint", + cand->endpoint.address.family + ? endpoint_print_buf(&cand->endpoint) : ""); + JSON_SET_SIMPLE_CSTR("related", + cand->related.address.family + ? endpoint_print_buf(&cand->related) : ""); } - for (__auto_type l = scope ? NULL : c->stream_fds.head; l; l = l->next) { - stream_fd *sfd = l->data; + snprintf(tmp, sizeof(tmp), "offered_payload_types-%u", media->unique_id); + inner = parser->dict_add_list_dup(root, tmp); + redis_encode_codec_store(parser, inner, &media->offered_codecs); - snprintf(tmp, sizeof(tmp), "sfd-%u", sfd->unique_id); - inner = parser->dict_add_dict_dup(root, tmp); + IQUEUE_FOREACH(&media->streams, ps) { + if (!ps->media) + continue; - { - JSON_SET_SIMPLE_CSTR("pref_family", sfd->local_intf->logical->preferred_family->rfc_name); - JSON_SET_SIMPLE("localport","%u", sfd->socket.local.port); - JSON_SET_SIMPLE("fd", "%i", sfd->socket.fd); - JSON_SET_SIMPLE_STR("logical_intf", &sfd->local_intf->logical->name); - JSON_SET_SIMPLE("local_intf_uid","%u", sfd->local_intf->unique_id); - JSON_SET_SIMPLE("stream","%u", sfd->stream->unique_id); + LOCK(&ps->lock); - json_update_crypto_params(parser, inner, "", &sfd->crypto.params); - } + inner = redis_encode_stream_basic(ps, parser, root); + + JSON_SET_SIMPLE_CSTR("learned_endpoint", + ps->learned_endpoint.address.family + ? endpoint_print_buf(&ps->learned_endpoint) : ""); + JSON_SET_SIMPLE_CSTR("last_local_endpoint", + ps->last_local_endpoint.address.family + ? endpoint_print_buf(&ps->last_local_endpoint) : ""); + JSON_SET_SIMPLE("ep_detect_signal", "%" PRId64, ps->ep_detect_signal); + JSON_SET_SIMPLE("el_flags", "%u", ps->el_flags); + json_update_detected_endpoints(parser, inner, ps); + } + } - } // --- for + return parser->collapse(ctx, root, to_free); +} - IQUEUE_FOREACH(&c->streams, ps) { - if (!ps->media || !ml_in_scope(scope, ps->media->monologue)) - continue; - LOCK(&ps->lock); +static str redis_encode_json(ng_parser_ctx_t *ctx, call_t *c, void **to_free) +{ + char tmp[128]; + const ng_parser_t *parser = ctx->parser; - snprintf(tmp, sizeof(tmp), "stream-%u", ps->unique_id); - inner = parser->dict_add_dict_dup(root, tmp); + parser_arg root = parser->dict(ctx); - { - JSON_SET_SIMPLE("media","%u",ps->media->unique_id); - JSON_SET_SIMPLE("sfd","%u",ps->selected_sfd ? ps->selected_sfd->unique_id : -1); - JSON_SET_SIMPLE("rtcp_sibling","%u",ps->rtcp_sibling ? ps->rtcp_sibling->unique_id : -1); - JSON_SET_SIMPLE("ps_flags", "%" PRIu64, atomic64_get_na(&ps->ps_flags)); - JSON_SET_SIMPLE("component","%u",ps->component); - JSON_SET_SIMPLE_CSTR("endpoint",endpoint_print_buf(&ps->endpoint)); - JSON_SET_SIMPLE_CSTR("advertised_endpoint",endpoint_print_buf(&ps->advertised_endpoint)); - if (scope) { - JSON_SET_SIMPLE_CSTR("learned_endpoint", - ps->learned_endpoint.address.family - ? endpoint_print_buf(&ps->learned_endpoint) : ""); - JSON_SET_SIMPLE_CSTR("last_local_endpoint", - ps->last_local_endpoint.address.family - ? endpoint_print_buf(&ps->last_local_endpoint) : ""); - JSON_SET_SIMPLE("ep_detect_signal", "%" PRId64, ps->ep_detect_signal); - JSON_SET_SIMPLE("el_flags", "%u", ps->el_flags); - json_update_detected_endpoints(parser, inner, ps); - } - JSON_SET_SIMPLE("stats-packets","%" PRIu64, atomic64_get_na(&ps->stats_in->packets)); - JSON_SET_SIMPLE("stats-bytes","%" PRIu64, atomic64_get_na(&ps->stats_in->bytes)); - JSON_SET_SIMPLE("stats-errors","%" PRIu64, atomic64_get_na(&ps->stats_in->errors)); - - json_update_crypto_params(parser, inner, "", &ps->crypto.params); - } + parser_arg inner; + + inner = parser->dict_add_dict(root, "json"); + JSON_SET_SIMPLE("created","%" PRId64, c->created); + JSON_SET_SIMPLE("destroyed","%" PRId64, c->destroyed); + JSON_SET_SIMPLE("last_signal","%" PRId64, c->last_signal_us); + JSON_SET_SIMPLE("tos","%u", (int) c->tos); + JSON_SET_SIMPLE("deleted","%" PRId64, c->deleted_us); + JSON_SET_SIMPLE("num_sfds","%u", t_queue_get_length(&c->stream_fds)); + JSON_SET_SIMPLE("num_streams","%u", t_queue_get_length(&c->streams)); + JSON_SET_SIMPLE("num_medias","%u", t_queue_get_length(&c->medias)); + JSON_SET_SIMPLE("num_tags","%u", t_queue_get_length(&c->monologues)); + JSON_SET_SIMPLE("num_maps","%u", t_queue_get_length(&c->endpoint_maps)); + JSON_SET_SIMPLE("ml_deleted","%" PRId64, c->ml_deleted_us); + JSON_SET_SIMPLE("redis_hosted_db","%u", c->redis_hosted_db); + JSON_SET_SIMPLE_STR("recording_metadata", &c->metadata); + JSON_SET_SIMPLE("block_dtmf","%i", c->block_dtmf); + JSON_SET_SIMPLE("call_flags", "%" PRIu64, atomic64_get_na(&c->call_flags)); + + if (c->created_from.len) + JSON_SET_SIMPLE_STR("created_from", &c->created_from); + if (c->recording_meta_prefix.len) + JSON_SET_SIMPLE_STR("recording_meta_prefix", &c->recording_meta_prefix); + if (c->recording_file.len) + JSON_SET_SIMPLE_STR("recording_file", &c->recording_file); + if (c->recording_path.len) + JSON_SET_SIMPLE_STR("recording_path", &c->recording_path); + if (c->recording_pattern.len) + JSON_SET_SIMPLE_STR("recording_pattern", &c->recording_pattern); + if (c->recording_random_tag.len) + JSON_SET_SIMPLE_STR("recording_random_tag", &c->recording_random_tag); - snprintf(tmp, sizeof(tmp), "stream_sfds-%u", ps->unique_id); - inner = parser->dict_add_list_dup(root, tmp); - for (__auto_type k = ps->sfds.head; k; k = k->next) { - stream_fd *sfd = k->data; - JSON_ADD_LIST_STRING("%u", sfd->unique_id); - } + for (__auto_type l = c->monologues.head; l; l = l->next) { + const struct call_monologue *ml = l->data; + if (!ml->checkpoint) + continue; + snprintf(tmp, sizeof(tmp), "checkpoint-%u", ml->unique_id); + inner = parser->dict_add_dict_dup(root, tmp); + JSON_SET_SIMPLE("pending", "%i", ml->checkpoint->pending ? 1 : 0); + if (ml->checkpoint->snapshot.len) { + /* nested as a string; heap buffer rather than a VLA, as escape() can + * need up to 3x the input */ + char *enc = g_malloc_n(ml->checkpoint->snapshot.len + 1, 3); + str encs = parser->escape(enc, ml->checkpoint->snapshot.s, + ml->checkpoint->snapshot.len); + parser->dict_add_str_dup(inner, "snapshot", &encs); + g_free(enc); + } + } - if (!scope) { - snprintf(tmp, sizeof(tmp), "rtp_sinks-%u", ps->unique_id); - inner = parser->dict_add_list_dup(root, tmp); - for (__auto_type k = ps->rtp_sinks.head; k; k = k->next) { - struct sink_handler *sh = k->data; - struct packet_stream *sink = sh->sink; - JSON_ADD_LIST_STRING("%u", sink->unique_id); - } - } + for (__auto_type l = c->stream_fds.head; l; l = l->next) { + stream_fd *sfd = l->data; - if (!scope) { - snprintf(tmp, sizeof(tmp), "rtcp_sinks-%u", ps->unique_id); - inner = parser->dict_add_list_dup(root, tmp); - for (__auto_type k = ps->rtcp_sinks.head; k; k = k->next) { - struct sink_handler *sh = k->data; - struct packet_stream *sink = sh->sink; - JSON_ADD_LIST_STRING("%u", sink->unique_id); - } - } - } // --- for streams.head + snprintf(tmp, sizeof(tmp), "sfd-%u", sfd->unique_id); + inner = parser->dict_add_dict_dup(root, tmp); - for (__auto_type l = c->monologues.head; l; l = l->next) { - struct call_monologue *ml = l->data; + JSON_SET_SIMPLE_CSTR("pref_family", sfd->local_intf->logical->preferred_family->rfc_name); + JSON_SET_SIMPLE("localport","%u", sfd->socket.local.port); + JSON_SET_SIMPLE("fd", "%i", sfd->socket.fd); + JSON_SET_SIMPLE_STR("logical_intf", &sfd->local_intf->logical->name); + JSON_SET_SIMPLE("local_intf_uid","%u", sfd->local_intf->unique_id); + JSON_SET_SIMPLE("stream","%u", sfd->stream->unique_id); - if (!ml_in_scope(scope, ml)) - continue; + json_update_crypto_params(parser, inner, "", &sfd->crypto.params); - snprintf(tmp, sizeof(tmp), "tag-%u", ml->unique_id); - inner = parser->dict_add_dict_dup(root, tmp); + } // --- for - { - - JSON_SET_SIMPLE("created", "%" PRId64, ml->created_us); - JSON_SET_SIMPLE("deleted", "%" PRId64, ml->deleted_us); - JSON_SET_SIMPLE("block_dtmf", "%i", ml->block_dtmf); - JSON_SET_SIMPLE("ml_flags", "%" PRIu64, atomic64_get_na(&ml->ml_flags)); - JSON_SET_SIMPLE_CSTR("desired_family", ml->desired_family ? ml->desired_family->rfc_name : ""); - if (ml->logical_intf) - JSON_SET_SIMPLE_STR("logical_intf", &ml->logical_intf->name); - - if (ml->tag.s) - JSON_SET_SIMPLE_STR("tag", &ml->tag); - if (ml->call_id.s) - JSON_SET_SIMPLE_STR("call_id", &ml->tag); - if (ml->viabranch.s) - JSON_SET_SIMPLE_STR("via-branch", &ml->viabranch); - if (ml->label.s) - JSON_SET_SIMPLE_STR("label", &ml->label); - if (ml->metadata.s) - JSON_SET_SIMPLE_STR("metadata", &ml->metadata); - - JSON_SET_SIMPLE_STR("sdp_session_name", &ml->sdp_session_name); - JSON_SET_SIMPLE_STR("sdp_session_timing", &ml->sdp_session_timing); - - if (ml->sdp_orig_in.parsed) { - JSON_SET_SIMPLE_STR("sdp_orig_username", &ml->sdp_orig_in.username); - JSON_SET_SIMPLE_STR("sdp_orig_session_id", &ml->sdp_orig_in.session_id); - JSON_SET_SIMPLE("sdp_orig_version_num", "%llu", ml->sdp_orig_in.version_num); - JSON_SET_SIMPLE("sdp_orig_parsed", "%u", ml->sdp_orig_in.parsed); - JSON_SET_SIMPLE_STR("sdp_orig_address_network_type", &ml->sdp_orig_in.address.network_type); - JSON_SET_SIMPLE_STR("sdp_orig_address_address_type", &ml->sdp_orig_in.address.address_type); - JSON_SET_SIMPLE_STR("sdp_orig_address_address", &ml->sdp_orig_in.address.address); - } - if (ml->sdp_orig_out.parsed) { - JSON_SET_SIMPLE_STR("last_sdp_orig_username", &ml->sdp_orig_out.username); - JSON_SET_SIMPLE_STR("last_sdp_orig_session_id", &ml->sdp_orig_out.session_id); - JSON_SET_SIMPLE("last_sdp_orig_version_num", "%llu", ml->sdp_orig_out.version_num); - JSON_SET_SIMPLE("last_sdp_orig_parsed", "%u", ml->sdp_orig_out.parsed); - JSON_SET_SIMPLE_STR("last_sdp_orig_address_network_type", &ml->sdp_orig_out.address.network_type); - JSON_SET_SIMPLE_STR("last_sdp_orig_address_address_type", &ml->sdp_orig_out.address.address_type); - JSON_SET_SIMPLE_STR("last_sdp_orig_address_address", &ml->sdp_orig_out.address.address); - } - - if (ml->sdp_session_bandwidth.as >= 0) - JSON_SET_SIMPLE("sdp_session_as", "%ld", ml->sdp_session_bandwidth.as); - if (ml->sdp_session_bandwidth.ct >= 0) - JSON_SET_SIMPLE("sdp_session_ct", "%ld", ml->sdp_session_bandwidth.ct); - if (ml->sdp_session_bandwidth.rr >= 0) - JSON_SET_SIMPLE("sdp_session_rr", "%ld", ml->sdp_session_bandwidth.rr); - if (ml->sdp_session_bandwidth.rs >= 0) - JSON_SET_SIMPLE("sdp_session_rs", "%ld", ml->sdp_session_bandwidth.rs); - if (ml->sdp_session_bandwidth.tias >= 0) - JSON_SET_SIMPLE("sdp_session_tias", "%ld", ml->sdp_session_bandwidth.tias); - if (ml->last_out_sdp && ml->last_out_sdp->len) - JSON_SET_SIMPLE_LEN("last_out_sdp", ml->last_out_sdp->len, - ml->last_out_sdp->str); - } + IQUEUE_FOREACH(&c->streams, ps) { + if (!ps->media) + continue; - GList *k = g_hash_table_get_values(ml->associated_tags); - if (!scope) { - snprintf(tmp, sizeof(tmp), "associated_tags-%u", ml->unique_id); - inner = parser->dict_add_list_dup(root, tmp); - for (GList *m = k; m; m = m->next) { - struct call_monologue *ml2 = m->data; - JSON_ADD_LIST_STRING("%u", ml2->unique_id); - } - } + LOCK(&ps->lock); - g_list_free(k); + redis_encode_stream_basic(ps, parser, root); - if (!scope) { - snprintf(tmp, sizeof(tmp), "tag_aliases-%u", ml->unique_id); - inner = parser->dict_add_list_dup(root, tmp); - for (__auto_type alias = ml->tag_aliases.head; alias; alias = alias->next) - JSON_ADD_LIST_STRING(STR_FORMAT, STR_FMT(alias->data)); - } + snprintf(tmp, sizeof(tmp), "rtp_sinks-%u", ps->unique_id); + inner = parser->dict_add_list_dup(root, tmp); + for (__auto_type k = ps->rtp_sinks.head; k; k = k->next) { + struct sink_handler *sh = k->data; + struct packet_stream *sink = sh->sink; + JSON_ADD_LIST_STRING("%u", sink->unique_id); + } - snprintf(tmp, sizeof(tmp), "medias-%u", ml->unique_id); - inner = parser->dict_add_list_dup(root, tmp); - for (unsigned int j = 0; j < ml->medias->len; j++) { - struct call_media *media = ml->medias->pdata[j]; - JSON_ADD_LIST_STRING("%u", media ? media->unique_id : -1); - } - } // --- for monologues.head + snprintf(tmp, sizeof(tmp), "rtcp_sinks-%u", ps->unique_id); + inner = parser->dict_add_list_dup(root, tmp); + for (__auto_type k = ps->rtcp_sinks.head; k; k = k->next) { + struct sink_handler *sh = k->data; + struct packet_stream *sink = sh->sink; + JSON_ADD_LIST_STRING("%u", sink->unique_id); + } + } // --- for streams.head - for (__auto_type l = c->medias.head; l; l = l->next) { - struct call_media *media = l->data; + for (__auto_type l = c->monologues.head; l; l = l->next) { + struct call_monologue *ml = l->data; - if (!media || !ml_in_scope(scope, media->monologue)) - continue; + redis_encode_ml_basic(ml, parser, root); - if (!scope) { - /* store media subscriptions */ - snprintf(tmp, sizeof(tmp), "media-subscriptions-%u", media->unique_id); - inner = parser->dict_add_list_dup(root, tmp); - - IQUEUE_FOREACH(&media->media_subscriptions, ms) { - JSON_ADD_LIST_STRING("%u/%u/%u/%u/%u", - ms->media->unique_id, - ms->attrs.offer_answer, - ms->attrs.rtcp_only, - ms->attrs.egress, - ms->attrs.inject); - } - } + GList *k = g_hash_table_get_values(ml->associated_tags); + snprintf(tmp, sizeof(tmp), "associated_tags-%u", ml->unique_id); + inner = parser->dict_add_list_dup(root, tmp); + for (GList *m = k; m; m = m->next) { + struct call_monologue *ml2 = m->data; + JSON_ADD_LIST_STRING("%u", ml2->unique_id); + } + g_list_free(k); - snprintf(tmp, sizeof(tmp), "media-%u", media->unique_id); - inner = parser->dict_add_dict_dup(root, tmp); + snprintf(tmp, sizeof(tmp), "tag_aliases-%u", ml->unique_id); + inner = parser->dict_add_list_dup(root, tmp); + for (__auto_type alias = ml->tag_aliases.head; alias; alias = alias->next) + JSON_ADD_LIST_STRING(STR_FORMAT, STR_FMT(alias->data)); + } // --- for monologues.head - { - JSON_SET_SIMPLE("tag","%u", media->monologue->unique_id); - JSON_SET_SIMPLE("index","%u", media->index); - JSON_SET_SIMPLE_STR("type", &media->type); - if (media->format_str.s) - JSON_SET_SIMPLE_STR("format_str", &media->format_str); - if (media->media_id.s) - JSON_SET_SIMPLE_STR("media_id", &media->media_id); - if (media->label.s) - JSON_SET_SIMPLE_STR("label", &media->label); - JSON_SET_SIMPLE_CSTR("protocol", media->protocol ? media->protocol->name : ""); - JSON_SET_SIMPLE_CSTR("desired_family", media->desired_family ? media->desired_family->rfc_name : ""); - if (media->logical_intf) - JSON_SET_SIMPLE_STR("logical_intf", &media->logical_intf->name); - JSON_SET_SIMPLE("ptime","%i", media->ptime); - JSON_SET_SIMPLE("maxptime","%i", media->maxptime); - JSON_SET_SIMPLE("media_flags", "%" PRIu64, atomic64_get_na(&media->media_flags)); - - if (media->sdp_media_bandwidth.as >= 0) - JSON_SET_SIMPLE("bandwidth_as","%ld", media->sdp_media_bandwidth.as); - if (media->sdp_media_bandwidth.rr >= 0) - JSON_SET_SIMPLE("bandwidth_rr","%ld", media->sdp_media_bandwidth.rr); - if (media->sdp_media_bandwidth.rs >= 0) - JSON_SET_SIMPLE("bandwidth_rs","%ld", media->sdp_media_bandwidth.rs); - if (media->sdp_media_bandwidth.ct >= 0) - JSON_SET_SIMPLE("bandwidth_ct","%ld", media->sdp_media_bandwidth.ct); - if (media->sdp_media_bandwidth.tias >= 0) - JSON_SET_SIMPLE("bandwidth_tias","%ld", media->sdp_media_bandwidth.tias); - - if (scope) { - if (media->tls_id.s) - JSON_SET_SIMPLE_STR("tls_id", &media->tls_id); - if (media->fp_hash_func) - JSON_SET_SIMPLE_CSTR("preferred_hash_func", - media->fp_hash_func->name); - if (media->endpoint_map) - JSON_SET_SIMPLE("endpoint_map", "%u", - media->endpoint_map->unique_id); - - unsigned int num_cands = 0; - for (__auto_type m = media->ice_candidates.head; m; m = m->next) - num_cands++; - JSON_SET_SIMPLE("num_ice_candidates", "%u", num_cands); - JSON_SET_SIMPLE("had_ice", "%i", media->ice_agent ? 1 : 0); - if (media->ice_agent) { - JSON_SET_SIMPLE_STR("ice_ufrag_local", &media->ice_agent->ufrag[0]); - JSON_SET_SIMPLE_STR("ice_ufrag_remote", &media->ice_agent->ufrag[1]); - JSON_SET_SIMPLE_STR("ice_pwd_local", &media->ice_agent->pwd[0]); - JSON_SET_SIMPLE_STR("ice_pwd_remote", &media->ice_agent->pwd[1]); - } - } - - redis_encode_sdes_params(parser, inner, "sdes_in", &media->sdes_in); - redis_encode_sdes_params(parser, inner, "sdes_out", &media->sdes_out); - redis_encode_dtls_fingerprint(parser, inner, &media->fingerprint); - } + for (__auto_type l = c->medias.head; l; l = l->next) { + struct call_media *media = l->data; - if (scope) { - unsigned int ci = 0; - for (__auto_type m = media->ice_candidates.head; m; m = m->next, ci++) { - const struct ice_candidate *cand = m->data; - snprintf(tmp, sizeof(tmp), "ice_candidate-%u-%u", media->unique_id, ci); - inner = parser->dict_add_dict_dup(root, tmp); - JSON_SET_SIMPLE_STR("foundation", &cand->foundation); - JSON_SET_SIMPLE("component", "%lu", (unsigned long) cand->component_id); - JSON_SET_SIMPLE_CSTR("transport", - cand->transport ? cand->transport->name : ""); - JSON_SET_SIMPLE("priority", "%lu", (unsigned long) cand->priority); - JSON_SET_SIMPLE("type", "%u", cand->type); - JSON_SET_SIMPLE_STR("ufrag", &cand->ufrag); - JSON_SET_SIMPLE_CSTR("endpoint", - cand->endpoint.address.family - ? endpoint_print_buf(&cand->endpoint) : ""); - JSON_SET_SIMPLE_CSTR("related", - cand->related.address.family - ? endpoint_print_buf(&cand->related) : ""); - } - } + if (!media) + continue; - if (!scope) { - snprintf(tmp, sizeof(tmp), "streams-%u", media->unique_id); - inner = parser->dict_add_list_dup(root, tmp); - IQUEUE_FOREACH(&media->streams, ps) - JSON_ADD_LIST_STRING("%u", ps->unique_id); - } + /* store media subscriptions */ + snprintf(tmp, sizeof(tmp), "media-subscriptions-%u", media->unique_id); + inner = parser->dict_add_list_dup(root, tmp); + + IQUEUE_FOREACH(&media->media_subscriptions, ms) { + JSON_ADD_LIST_STRING("%u/%u/%u/%u/%u", + ms->media->unique_id, + ms->attrs.offer_answer, + ms->attrs.rtcp_only, + ms->attrs.egress, + ms->attrs.inject); + } - if (!scope) { - snprintf(tmp, sizeof(tmp), "maps-%u", media->unique_id); - inner = parser->dict_add_list_dup(root, tmp); - IQUEUE_FOREACH(&media->endpoint_maps, ep) - JSON_ADD_LIST_STRING("%u", ep->unique_id); - } + redis_encode_media_basic(media, parser, root); - snprintf(tmp, sizeof(tmp), "payload_types-%u", media->unique_id); - inner = parser->dict_add_list_dup(root, tmp); - redis_encode_codec_store(parser, inner, &media->codecs); + snprintf(tmp, sizeof(tmp), "streams-%u", media->unique_id); + inner = parser->dict_add_list_dup(root, tmp); + IQUEUE_FOREACH(&media->streams, ps) + JSON_ADD_LIST_STRING("%u", ps->unique_id); - if (scope) { - snprintf(tmp, sizeof(tmp), "offered_payload_types-%u", media->unique_id); - inner = parser->dict_add_list_dup(root, tmp); - redis_encode_codec_store(parser, inner, &media->offered_codecs); - } + snprintf(tmp, sizeof(tmp), "maps-%u", media->unique_id); + inner = parser->dict_add_list_dup(root, tmp); + IQUEUE_FOREACH(&media->endpoint_maps, ep) + JSON_ADD_LIST_STRING("%u", ep->unique_id); - // SSRC table dump - // XXX needs fixing - LOCK(&media->ssrc_hash_in.lock); - snprintf(tmp, sizeof(tmp), "ssrc_table-%u", media->unique_id); - parser_arg list = parser->dict_add_list_dup(root, tmp); - for (GList *m = media->ssrc_hash_in.nq.head; m; m = m->next) { - struct ssrc_entry_call *se = m->data; - inner = parser->list_add_dict(list); - - JSON_SET_SIMPLE("ssrc", "%" PRIu32, se->h.ssrc); - // XXX use function for in/out - JSON_SET_SIMPLE("in_srtp_index", "%u", atomic_get_na(&se->stats->ext_seq)); - JSON_SET_SIMPLE("in_srtcp_index", "%u", atomic_get_na(&se->stats->rtcp_seq)); - JSON_SET_SIMPLE("in_payload_type", "%i", se->tracker.most[0]); - //JSON_SET_SIMPLE("out_srtp_index", "%u", atomic_get_na(&se->output_ctx.stats->ext_seq)); - //JSON_SET_SIMPLE("out_srtcp_index", "%u", atomic_get_na(&se->output_ctx.stats->rtcp_seq)); - //JSON_SET_SIMPLE("out_payload_type", "%i", se->output_ctx.tracker.most[0]); - // XXX add rest of info - } - } // --- for medias.head - - if (!scope) { - IQUEUE_FOREACH(&c->endpoint_maps, ep) { - snprintf(tmp, sizeof(tmp), "map-%u", ep->unique_id); - inner = parser->dict_add_dict_dup(root, tmp); - - { - JSON_SET_SIMPLE("wildcard","%i", ep->wildcard); - JSON_SET_SIMPLE("num_ports","%u", ep->num_ports); - JSON_SET_SIMPLE_CSTR("intf_preferred_family", ep->logical_intf->preferred_family->rfc_name); - JSON_SET_SIMPLE_STR("logical_intf", &ep->logical_intf->name); - JSON_SET_SIMPLE_CSTR("endpoint", endpoint_print_buf(&ep->endpoint)); - - } - - snprintf(tmp, sizeof(tmp), "map_sfds-%u", ep->unique_id); - inner = parser->dict_add_list_dup(root, tmp); - for (__auto_type m = ep->intf_sfds.head; m; m = m->next) { - struct sfd_intf_list *il = m->data; - JSON_ADD_LIST_STRING("loc-%u", il->local_intf->unique_id); - for (__auto_type n = il->list.head; n; n = n->next) { - stream_fd *sfd = n->data; - JSON_ADD_LIST_STRING("%u", sfd->unique_id); - } - } - } - } // --- for c->endpoint_maps.head + } // --- for medias.head + + IQUEUE_FOREACH(&c->endpoint_maps, ep) { + snprintf(tmp, sizeof(tmp), "map-%u", ep->unique_id); + inner = parser->dict_add_dict_dup(root, tmp); + + { + JSON_SET_SIMPLE("wildcard","%i", ep->wildcard); + JSON_SET_SIMPLE("num_ports","%u", ep->num_ports); + JSON_SET_SIMPLE_CSTR("intf_preferred_family", ep->logical_intf->preferred_family->rfc_name); + JSON_SET_SIMPLE_STR("logical_intf", &ep->logical_intf->name); + JSON_SET_SIMPLE_CSTR("endpoint", endpoint_print_buf(&ep->endpoint)); + } + + snprintf(tmp, sizeof(tmp), "map_sfds-%u", ep->unique_id); + inner = parser->dict_add_list_dup(root, tmp); + for (__auto_type m = ep->intf_sfds.head; m; m = m->next) { + struct sfd_intf_list *il = m->data; + JSON_ADD_LIST_STRING("loc-%u", il->local_intf->unique_id); + for (__auto_type n = il->list.head; n; n = n->next) { + stream_fd *sfd = n->data; + JSON_ADD_LIST_STRING("%u", sfd->unique_id); + } + } } return parser->collapse(ctx, root, to_free); @@ -3124,14 +3132,13 @@ static str redis_encode_json(ng_parser_ctx_t *ctx, call_t *c, void **to_free, str redis_snapshot_encode(call_t *c, struct call_monologue *ml) { - struct call_monologue *scope[2] = { ml, ml }; ng_parser_ctx_t ctx; arena_t bbuf; // never leaves the daemon, so the format is ours to pick ng_parser_native.init(&ctx, &bbuf); void *to_free = NULL; - str encoded = redis_encode_json(&ctx, c, &to_free, scope); + str encoded = redis_encode_json_ml(&ctx, c, &to_free, ml); str out = STR_NULL; if (encoded.len) out = str_dup_str(&encoded); @@ -3560,7 +3567,7 @@ void redis_update_onekey(call_t *c, struct redis *r) { redis_format_parsers[rtpe_config.redis_format]->init(&ctx, &bbuf); void *to_free = NULL; - str result = redis_encode_json(&ctx, c, &to_free, NULL); + str result = redis_encode_json(&ctx, c, &to_free); if (!result.len) goto err;