diff --git a/daemon/bencode.c b/daemon/bencode.c index 3b8880eb7..9a0de8876 100644 --- a/daemon/bencode.c +++ b/daemon/bencode.c @@ -137,6 +137,9 @@ alloc: void bencode_buffer_free(bencode_buffer_t *buf) { struct __bencode_buffer_piece *piece, *next; + if (!buf) + return; + for (piece = buf->pieces; piece; piece = next) { next = piece->next; BENCODE_FREE(piece); diff --git a/daemon/call.c b/daemon/call.c index 4c33a2805..363c3bd47 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -4766,7 +4766,7 @@ static void monologue_stop(struct call_monologue *ml, bool stop_media_subsribers // call must be locked in W. // unlocks the call and releases the reference prior to returning, even on error. int call_delete_branch(call_t *c, const str *branch, - const str *fromtag, const str *totag, ng_parser_ctx_t *ctx, int delete_delay) + const str *fromtag, const str *totag, ng_command_ctx_t *ctx, int delete_delay) { struct call_monologue *ml; int ret; @@ -4894,7 +4894,7 @@ out: int call_delete_branch_by_id(const str *callid, const str *branch, - const str *fromtag, const str *totag, ng_parser_ctx_t *ctx, int delete_delay) + const str *fromtag, const str *totag, ng_command_ctx_t *ctx, int delete_delay) { call_t *c = call_get(callid); if (!c) { diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index c8d6e6e5e..d6479a873 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -1986,11 +1986,12 @@ void call_ng_main_flags(const ng_parser_t *parser, str *key, parser_arg value, h } } -static void call_ng_process_flags(sdp_ng_flags *out, ng_parser_ctx_t *ctx, enum call_opmode opmode) { +static void call_ng_process_flags(sdp_ng_flags *out, ng_command_ctx_t *ctx, enum call_opmode opmode) { + const ng_parser_t *parser = ctx->parser_ctx.parser; call_ng_flags_init(out, opmode); ctx->opmode = opmode; ctx->flags = out; - ctx->parser->dict_iter(ctx->parser, ctx->req, call_ng_main_flags, out); + parser->dict_iter(parser, ctx->req, call_ng_main_flags, out); } static void ng_sdp_attr_manipulations_free(struct sdp_manipulations * array[__MT_MAX]) { @@ -2109,7 +2110,7 @@ static enum basic_errors call_ng_basic_checks(sdp_ng_flags *flags, enum call_opm return 0; } -static const char *call_offer_answer_ng(ng_parser_ctx_t *ctx, enum call_opmode opmode, const char* addr, +static const char *call_offer_answer_ng(ng_command_ctx_t *ctx, enum call_opmode opmode, const char* addr, const endpoint_t *sin) { const char *errstr; @@ -2121,6 +2122,7 @@ static const char *call_offer_answer_ng(ng_parser_ctx_t *ctx, enum call_opmode o int ret; g_auto(sdp_ng_flags) flags; parser_arg output = ctx->resp; + const ng_parser_t *parser = ctx->parser_ctx.parser; call_ng_process_flags(&flags, ctx, opmode); @@ -2139,7 +2141,7 @@ static const char *call_offer_answer_ng(ng_parser_ctx_t *ctx, enum call_opmode o if (flags.loop_protect && sdp_is_duplicate(&parsed)) { ilog(LOG_INFO, "Ignoring message as SDP has already been processed by us"); - ctx->parser->dict_add_str(output, "sdp", &flags.sdp); + parser->dict_add_str(output, "sdp", &flags.sdp); errstr = NULL; goto out; } @@ -2236,7 +2238,7 @@ static const char *call_offer_answer_ng(ng_parser_ctx_t *ctx, enum call_opmode o meta_write_sdp_after(recording, chopper->output, from_ml, opmode); - recording_response(recording, ctx->parser, output); + recording_response(recording, ctx->parser_ctx.parser, output); } dequeue_sdp_fragments(from_ml); @@ -2264,21 +2266,21 @@ static const char *call_offer_answer_ng(ng_parser_ctx_t *ctx, enum call_opmode o goto out; if (chopper->output->len) - ctx->parser->dict_add_str(output, "sdp", &STR_LEN(chopper->output->str, chopper->output->len)); + ctx->parser_ctx.parser->dict_add_str(output, "sdp", &STR_LEN(chopper->output->str, chopper->output->len)); errstr = NULL; out: return errstr; } -const char *call_offer_ng(ng_parser_ctx_t *ctx, +const char *call_offer_ng(ng_command_ctx_t *ctx, const char* addr, const endpoint_t *sin) { return call_offer_answer_ng(ctx, OP_OFFER, addr, sin); } -const char *call_answer_ng(ng_parser_ctx_t *ctx) { +const char *call_answer_ng(ng_command_ctx_t *ctx) { return call_offer_answer_ng(ctx, OP_ANSWER, NULL, NULL); } @@ -2289,26 +2291,27 @@ static void call_delete_flags(str *key, unsigned int idx, helper_arg arg) { else if (!str_cmp(key, "discard-recording")) fatal_discard[1] = true; } -const char *call_delete_ng(ng_parser_ctx_t *ctx) { +const char *call_delete_ng(ng_command_ctx_t *ctx) { str fromtag, totag, viabranch, callid; parser_arg flags; bool fatal_discard[2] = {0}; int delete_delay; parser_arg input = ctx->req; parser_arg output = ctx->resp; + const ng_parser_t *parser = ctx->parser_ctx.parser; - if (!ctx->parser->dict_get_str(input, "call-id", &callid)) + if (!parser->dict_get_str(input, "call-id", &callid)) return "No call-id in message"; - ctx->parser->dict_get_str(input, "from-tag", &fromtag); - ctx->parser->dict_get_str(input, "to-tag", &totag); - ctx->parser->dict_get_str(input, "via-branch", &viabranch); + parser->dict_get_str(input, "from-tag", &fromtag); + parser->dict_get_str(input, "to-tag", &totag); + parser->dict_get_str(input, "via-branch", &viabranch); - flags = ctx->parser->dict_get_expect(input, "flags", BENCODE_LIST); + flags = parser->dict_get_expect(input, "flags", BENCODE_LIST); if (flags.gen) - ctx->parser->list_iter(ctx->parser, flags, call_delete_flags, NULL, fatal_discard); - delete_delay = ctx->parser->dict_get_int_str(input, "delete-delay", -1); + parser->list_iter(parser, flags, call_delete_flags, NULL, fatal_discard); + delete_delay = parser->dict_get_int_str(input, "delete-delay", -1); if (delete_delay == -1) - delete_delay = ctx->parser->dict_get_int_str(input, "delete delay", -1); + delete_delay = parser->dict_get_int_str(input, "delete delay", -1); call_t *c = call_get(&callid); if (!c) @@ -2325,19 +2328,20 @@ const char *call_delete_ng(ng_parser_ctx_t *ctx) { err: if (fatal_discard[0]) return "Call-ID not found or tags didn't match"; - ctx->parser->dict_add_string(output, "warning", "Call-ID not found or tags didn't match"); + parser->dict_add_string(output, "warning", "Call-ID not found or tags didn't match"); return NULL; } -static void ng_stats(ng_parser_ctx_t *ctx, parser_arg dict, const char *dict_name, +static void ng_stats(ng_command_ctx_t *ctx, parser_arg dict, const char *dict_name, const struct stream_stats *s, struct stream_stats *totals) { if (ctx) { - parser_arg d = ctx->parser->dict_add_dict(dict, dict_name); - ctx->parser->dict_add_int(d, "packets", atomic64_get_na(&s->packets)); - ctx->parser->dict_add_int(d, "bytes", atomic64_get_na(&s->bytes)); - ctx->parser->dict_add_int(d, "errors", atomic64_get_na(&s->errors)); + const ng_parser_t *parser = ctx->parser_ctx.parser; + parser_arg d = parser->dict_add_dict(dict, dict_name); + parser->dict_add_int(d, "packets", atomic64_get_na(&s->packets)); + parser->dict_add_int(d, "bytes", atomic64_get_na(&s->bytes)); + parser->dict_add_int(d, "errors", atomic64_get_na(&s->errors)); } if (!totals) return; @@ -2377,7 +2381,7 @@ static void ng_stats_stream_ssrc(const ng_parser_t *parser, parser_arg dict, #define BF_PS(k, f) if (PS_ISSET(ps, f)) parser->list_add_string(flags, k) -static void ng_stats_stream(ng_parser_ctx_t *ctx, parser_arg list, const struct packet_stream *ps, +static void ng_stats_stream(ng_command_ctx_t *ctx, parser_arg list, const struct packet_stream *ps, struct call_stats *totals) { parser_arg dict = {0}, flags; @@ -2386,7 +2390,7 @@ static void ng_stats_stream(ng_parser_ctx_t *ctx, parser_arg list, const struct if (!ctx) goto stats; - const ng_parser_t *parser = ctx->parser; + const ng_parser_t *parser = ctx->parser_ctx.parser; dict = parser->list_add_dict(list); @@ -2437,7 +2441,7 @@ stats: #define BF_M(k, f) if (MEDIA_ISSET(m, f)) parser->list_add_string(flags, k) -static void ng_stats_media(ng_parser_ctx_t *ctx, parser_arg list, const struct call_media *m, +static void ng_stats_media(ng_command_ctx_t *ctx, parser_arg list, const struct call_media *m, struct call_stats *totals) { parser_arg dict, streams = {0}, flags; @@ -2447,7 +2451,7 @@ static void ng_stats_media(ng_parser_ctx_t *ctx, parser_arg list, const struct c if (!ctx) goto stats; - const ng_parser_t *parser = ctx->parser; + const ng_parser_t *parser = ctx->parser_ctx.parser; rtp_pt = __rtp_stats_codec((struct call_media *)m); @@ -2501,7 +2505,7 @@ stats: } } -static void ng_stats_monologue(ng_parser_ctx_t *ctx, parser_arg dict, const struct call_monologue *ml, +static void ng_stats_monologue(ng_command_ctx_t *ctx, parser_arg dict, const struct call_monologue *ml, struct call_stats *totals, parser_arg ssrc) { parser_arg sub, medias = {0}; @@ -2515,7 +2519,7 @@ static void ng_stats_monologue(ng_parser_ctx_t *ctx, parser_arg dict, const stru if (!ctx) goto stats; - const ng_parser_t *parser = ctx->parser; + const ng_parser_t *parser = ctx->parser_ctx.parser; if (ml->tag.len) sub = parser->dict_add_dict(dict, ml->tag.s); @@ -2677,7 +2681,7 @@ static void ng_stats_ssrc(const ng_parser_t *parser, parser_arg dict, struct ssr } /* call must be locked */ -void ng_call_stats(ng_parser_ctx_t *ctx, call_t *call, const str *fromtag, const str *totag, +void ng_call_stats(ng_command_ctx_t *ctx, call_t *call, const str *fromtag, const str *totag, struct call_stats *totals) { parser_arg tags = {0}, dict; @@ -2685,6 +2689,7 @@ void ng_call_stats(ng_parser_ctx_t *ctx, call_t *call, const str *fromtag, const struct call_monologue *ml; struct call_stats t_b; parser_arg ssrc = {0}; + const ng_parser_t *parser = ctx->parser_ctx.parser; if (!totals) totals = &t_b; @@ -2695,13 +2700,13 @@ void ng_call_stats(ng_parser_ctx_t *ctx, call_t *call, const str *fromtag, const call_ngb_hold_ref(call, ctx->ngbuf); - ctx->parser->dict_add_int(ctx->resp, "created", call->created.tv_sec); - ctx->parser->dict_add_int(ctx->resp, "created_us", call->created.tv_usec); - ctx->parser->dict_add_int(ctx->resp, "last signal", call->last_signal); - ctx->parser->dict_add_int(ctx->resp, "last redis update", atomic64_get_na(&call->last_redis_update)); + parser->dict_add_int(ctx->resp, "created", call->created.tv_sec); + parser->dict_add_int(ctx->resp, "created_us", call->created.tv_usec); + parser->dict_add_int(ctx->resp, "last signal", call->last_signal); + parser->dict_add_int(ctx->resp, "last redis update", atomic64_get_na(&call->last_redis_update)); - ssrc = ctx->parser->dict_add_dict(ctx->resp, "SSRC"); - tags = ctx->parser->dict_add_dict(ctx->resp, "tags"); + ssrc = parser->dict_add_dict(ctx->resp, "SSRC"); + tags = parser->dict_add_dict(ctx->resp, "tags"); stats: match_tag = (totag && totag->s && totag->len) ? totag : fromtag; @@ -2740,26 +2745,27 @@ stats: if (!ctx) return; - dict = ctx->parser->dict_add_dict(ctx->resp, "totals"); + dict = parser->dict_add_dict(ctx->resp, "totals"); ng_stats(ctx, dict, "RTP", &totals->totals[0], NULL); ng_stats(ctx, dict, "RTCP", &totals->totals[1], NULL); if (call->recording) { - parser_arg rec = ctx->parser->dict_add_dict(ctx->resp, "recording"); - ctx->parser->dict_add_int(rec, "call recording", !!CALL_ISSET(call, RECORDING_ON)); - ctx->parser->dict_add_int(rec, "forwarding", !!CALL_ISSET(call, REC_FORWARDING)); + parser_arg rec = parser->dict_add_dict(ctx->resp, "recording"); + parser->dict_add_int(rec, "call recording", !!CALL_ISSET(call, RECORDING_ON)); + parser->dict_add_int(rec, "forwarding", !!CALL_ISSET(call, REC_FORWARDING)); } } -static void ng_list_calls(ng_parser_ctx_t *ctx, parser_arg output, long long int limit) { +static void ng_list_calls(ng_command_ctx_t *ctx, parser_arg output, long long int limit) { rtpe_calls_ht_iter iter; + const ng_parser_t *parser = ctx->parser_ctx.parser; rwlock_lock_r(&rtpe_callhash_lock); t_hash_table_iter_init (&iter, rtpe_callhash); str *key; while (limit-- && t_hash_table_iter_next (&iter, &key, NULL)) { - ctx->parser->list_add_str_dup(output, key); + parser->list_add_str_dup(output, key); } rwlock_unlock_r(&rtpe_callhash_lock); @@ -2767,18 +2773,19 @@ static void ng_list_calls(ng_parser_ctx_t *ctx, parser_arg output, long long int -const char *call_query_ng(ng_parser_ctx_t *ctx) { +const char *call_query_ng(ng_command_ctx_t *ctx) { str callid, fromtag, totag; call_t *call; parser_arg input = ctx->req; + const ng_parser_t *parser = ctx->parser_ctx.parser; - if (!ctx->parser->dict_get_str(input, "call-id", &callid)) + if (!parser->dict_get_str(input, "call-id", &callid)) return "No call-id in message"; call = call_get_opmode(&callid, OP_QUERY); if (!call) return "Unknown call-id"; - ctx->parser->dict_get_str(input, "from-tag", &fromtag); - ctx->parser->dict_get_str(input, "to-tag", &totag); + parser->dict_get_str(input, "from-tag", &fromtag); + parser->dict_get_str(input, "to-tag", &totag); ng_call_stats(ctx, call, &fromtag, &totag, NULL); rwlock_unlock_w(&call->master_lock); @@ -2788,18 +2795,19 @@ const char *call_query_ng(ng_parser_ctx_t *ctx) { } -const char *call_list_ng(ng_parser_ctx_t *ctx) { +const char *call_list_ng(ng_command_ctx_t *ctx) { parser_arg calls; long long int limit; parser_arg input = ctx->req; parser_arg output = ctx->resp; + const ng_parser_t *parser = ctx->parser_ctx.parser; - limit = ctx->parser->dict_get_int_str(input, "limit", 32); + limit = parser->dict_get_int_str(input, "limit", 32); if (limit < 0) { return "invalid limit, must be >= 0"; } - calls = ctx->parser->dict_add_list(output, "calls"); + calls = parser->dict_add_list(output, "calls"); ng_list_calls(ctx, calls, limit); @@ -2807,17 +2815,18 @@ const char *call_list_ng(ng_parser_ctx_t *ctx) { } -static const char *call_recording_common_ng(ng_parser_ctx_t *ctx, +static const char *call_recording_common_ng(ng_command_ctx_t *ctx, enum call_opmode opmode, - void (*fn)(ng_parser_ctx_t *, call_t *call)) + void (*fn)(ng_command_ctx_t *, call_t *call)) { g_auto(sdp_ng_flags) flags; g_autoptr(call_t) call = NULL; parser_arg input = ctx->req; + const ng_parser_t *parser = ctx->parser_ctx.parser; call_ng_process_flags(&flags, ctx, opmode); - if (!ctx->parser->dict_get_str(input, "call-id", &flags.call_id)) + if (!parser->dict_get_str(input, "call-id", &flags.call_id)) return "No call-id in message"; call = call_get_opmode(&flags.call_id, opmode); if (!call) @@ -2825,7 +2834,7 @@ static const char *call_recording_common_ng(ng_parser_ctx_t *ctx, struct call_monologue *ml = NULL; - if (ctx->parser->dict_get_str(input, "from-tag", &flags.from_tag)) { + if (parser->dict_get_str(input, "from-tag", &flags.from_tag)) { if (flags.from_tag.s) { ml = call_get_monologue(call, &flags.from_tag); if (!ml) @@ -2845,18 +2854,18 @@ static const char *call_recording_common_ng(ng_parser_ctx_t *ctx, } -static void start_recording_fn(ng_parser_ctx_t *ctx, call_t *call) { +static void start_recording_fn(ng_command_ctx_t *ctx, call_t *call) { recording_start(call); } -const char *call_start_recording_ng(ng_parser_ctx_t *ctx) { +const char *call_start_recording_ng(ng_command_ctx_t *ctx) { return call_recording_common_ng(ctx, OP_START_RECORDING, start_recording_fn); } -static void pause_recording_fn(ng_parser_ctx_t *ctx, call_t *call) { +static void pause_recording_fn(ng_command_ctx_t *ctx, call_t *call) { recording_pause(call); } -const char *call_pause_recording_ng(ng_parser_ctx_t *ctx) { +const char *call_pause_recording_ng(ng_command_ctx_t *ctx) { return call_recording_common_ng(ctx, OP_PAUSE_RECORDING, pause_recording_fn); } @@ -2867,25 +2876,26 @@ static void stop_recording_iter(str *key, unsigned int idx, helper_arg arg) { else if (str_cmp(key, "discard-recording") == 0) *arg.call_fn = recording_discard; } -static void stop_recording_fn(ng_parser_ctx_t *ctx, call_t *call) { +static void stop_recording_fn(ng_command_ctx_t *ctx, call_t *call) { // support alternative usage for "pause" call: either `pause=yes` ... parser_arg input = ctx->req; + const ng_parser_t *parser = ctx->parser_ctx.parser; str pause; - if (ctx->parser->dict_get_str(input, "pause", &pause)) { + if (parser->dict_get_str(input, "pause", &pause)) { if (!str_cmp(&pause, "yes") || !str_cmp(&pause, "on") || !str_cmp(&pause, "true")) { pause_recording_fn(ctx, call); return; } } // ... or `flags=[pause]` - parser_arg item = ctx->parser->dict_get_expect(input, "flags", BENCODE_LIST); + parser_arg item = parser->dict_get_expect(input, "flags", BENCODE_LIST); void (*fn)(call_t *) = recording_stop; if (item.gen) - ctx->parser->list_iter(ctx->parser, item, stop_recording_iter, NULL, &fn); + parser->list_iter(parser, item, stop_recording_iter, NULL, &fn); fn(call); } -const char *call_stop_recording_ng(ng_parser_ctx_t *ctx) { +const char *call_stop_recording_ng(ng_command_ctx_t *ctx) { return call_recording_common_ng(ctx, OP_STOP_RECORDING, stop_recording_fn); } @@ -2936,7 +2946,7 @@ found: return NULL; } static const char *media_block_match(call_t **call, struct call_monologue **monologue, - sdp_ng_flags *flags, ng_parser_ctx_t *ctx, enum call_opmode opmode) + sdp_ng_flags *flags, ng_command_ctx_t *ctx, enum call_opmode opmode) { *call = NULL; *monologue = NULL; @@ -2972,7 +2982,7 @@ void add_media_to_sub_list(subscription_q *q, struct call_media *media, struct c t_queue_push_tail(q, ms); } static const char *media_block_match_mult(call_t **call, subscription_q *medias, - sdp_ng_flags *flags, ng_parser_ctx_t *ctx, enum call_opmode opmode) + sdp_ng_flags *flags, ng_command_ctx_t *ctx, enum call_opmode opmode) { call_ng_process_flags(flags, ctx, opmode); @@ -3036,7 +3046,7 @@ static const char *media_block_match_mult(call_t **call, subscription_q *medias, } // XXX these are all identical - unify and use a flags int and/or callback -const char *call_start_forwarding_ng(ng_parser_ctx_t *ctx) { +const char *call_start_forwarding_ng(ng_command_ctx_t *ctx) { g_autoptr(call_t) call = NULL; struct call_monologue *monologue; const char *errstr = NULL; @@ -3065,7 +3075,7 @@ const char *call_start_forwarding_ng(ng_parser_ctx_t *ctx) { return NULL; } -const char *call_stop_forwarding_ng(ng_parser_ctx_t *ctx) { +const char *call_stop_forwarding_ng(ng_command_ctx_t *ctx) { g_autoptr(call_t) call = NULL; struct call_monologue *monologue; const char *errstr = NULL; @@ -3173,7 +3183,7 @@ static void call_set_dtmf_block(call_t *call, struct call_monologue *monologue, } } -const char *call_block_dtmf_ng(ng_parser_ctx_t *ctx) { +const char *call_block_dtmf_ng(ng_command_ctx_t *ctx) { g_autoptr(call_t) call = NULL; struct call_monologue *monologue; const char *errstr = NULL; @@ -3188,7 +3198,7 @@ const char *call_block_dtmf_ng(ng_parser_ctx_t *ctx) { return NULL; } -const char *call_unblock_dtmf_ng(ng_parser_ctx_t *ctx) { +const char *call_unblock_dtmf_ng(ng_command_ctx_t *ctx) { g_autoptr(call_t) call = NULL; struct call_monologue *monologue; const char *errstr = NULL; @@ -3247,7 +3257,7 @@ const char *call_unblock_dtmf_ng(ng_parser_ctx_t *ctx) { return NULL; } -static const char *call_block_silence_media(ng_parser_ctx_t *ctx, bool on_off, const char *ucase_verb, +static const char *call_block_silence_media(ng_command_ctx_t *ctx, bool on_off, const char *ucase_verb, const char *lcase_verb, unsigned int call_flag, unsigned int ml_flag, size_t attr_offset) { @@ -3412,23 +3422,23 @@ static const char *call_block_silence_media(ng_parser_ctx_t *ctx, bool on_off, c ML_FLAG_ ## flag, \ G_STRUCT_OFFSET(struct sink_attrs, member_name)) -const char *call_block_media_ng(ng_parser_ctx_t *ctx) { +const char *call_block_media_ng(ng_command_ctx_t *ctx) { return CALL_BLOCK_SILENCE_MEDIA(ctx, true, "Blocking", "blocking", block_media, BLOCK_MEDIA); } -const char *call_unblock_media_ng(ng_parser_ctx_t *ctx) { +const char *call_unblock_media_ng(ng_command_ctx_t *ctx) { return CALL_BLOCK_SILENCE_MEDIA(ctx, false, "Unblocking", "unblocking", block_media, BLOCK_MEDIA); } -const char *call_silence_media_ng(ng_parser_ctx_t *ctx) { +const char *call_silence_media_ng(ng_command_ctx_t *ctx) { return CALL_BLOCK_SILENCE_MEDIA(ctx, true, "Silencing", "silencing", silence_media, SILENCE_MEDIA); } -const char *call_unsilence_media_ng(ng_parser_ctx_t *ctx) { +const char *call_unsilence_media_ng(ng_command_ctx_t *ctx) { return CALL_BLOCK_SILENCE_MEDIA(ctx, false, "Unsilencing", "unsilencing", silence_media, SILENCE_MEDIA); } #ifdef WITH_TRANSCODING static const char *play_media_select_party(call_t **call, monologues_q *monologues, - ng_parser_ctx_t *ctx, sdp_ng_flags *flags) + ng_command_ctx_t *ctx, sdp_ng_flags *flags) { struct call_monologue *monologue; @@ -3448,12 +3458,13 @@ static const char *play_media_select_party(call_t **call, monologues_q *monologu #endif -const char *call_play_media_ng(ng_parser_ctx_t *ctx) { +const char *call_play_media_ng(ng_command_ctx_t *ctx) { #ifdef WITH_TRANSCODING g_autoptr(call_t) call = NULL; g_auto(monologues_q) monologues; const char *err = NULL; g_auto(sdp_ng_flags) flags; + const ng_parser_t *parser = ctx->parser_ctx.parser; err = play_media_select_party(&call, &monologues, ctx, &flags); if (err) @@ -3496,7 +3507,7 @@ const char *call_play_media_ng(ng_parser_ctx_t *ctx) { return "No media file specified"; if (l == monologues.head && monologue->player->coder.duration) - ctx->parser->dict_add_int(ctx->resp, "duration", monologue->player->coder.duration); + parser->dict_add_int(ctx->resp, "duration", monologue->player->coder.duration); } @@ -3507,13 +3518,14 @@ const char *call_play_media_ng(ng_parser_ctx_t *ctx) { } -const char *call_stop_media_ng(ng_parser_ctx_t *ctx) { +const char *call_stop_media_ng(ng_command_ctx_t *ctx) { #ifdef WITH_TRANSCODING g_autoptr(call_t) call = NULL; g_auto(monologues_q) monologues; const char *err = NULL; long long last_frame_pos = 0; g_auto(sdp_ng_flags) flags; + const ng_parser_t *parser = ctx->parser_ctx.parser; err = play_media_select_party(&call, &monologues, ctx, &flags); if (err) @@ -3531,7 +3543,7 @@ const char *call_stop_media_ng(ng_parser_ctx_t *ctx) { codec_update_all_source_handlers(monologue, NULL); update_init_subscribers(monologue, OP_STOP_MEDIA); } - ctx->parser->dict_add_int(ctx->resp, "last-frame-pos", last_frame_pos); + parser->dict_add_int(ctx->resp, "last-frame-pos", last_frame_pos); return NULL; #else @@ -3540,7 +3552,7 @@ const char *call_stop_media_ng(ng_parser_ctx_t *ctx) { } -const char *call_play_dtmf_ng(ng_parser_ctx_t *ctx) { +const char *call_play_dtmf_ng(ng_command_ctx_t *ctx) { #ifdef WITH_TRANSCODING g_autoptr(call_t) call = NULL; g_auto(monologues_q) monologues; @@ -3642,7 +3654,7 @@ found_sink: } -const char *call_publish_ng(ng_parser_ctx_t *ctx, +const char *call_publish_ng(ng_command_ctx_t *ctx, const char *addr, const endpoint_t *sin) { @@ -3653,6 +3665,7 @@ const char *call_publish_ng(ng_parser_ctx_t *ctx, g_auto(str) sdp_out = STR_NULL; g_autoptr(call_t) call = NULL; int ret; + const ng_parser_t *parser = ctx->parser_ctx.parser; call_ng_process_flags(&flags, ctx, OP_PUBLISH); @@ -3682,7 +3695,7 @@ const char *call_publish_ng(ng_parser_ctx_t *ctx, if (!ret) { save_last_sdp(ml, &sdp_in, &parsed, &streams); ctx->ngbuf->sdp_out = sdp_out.s; - ctx->parser->dict_add_str(ctx->resp, "sdp", &sdp_out); + parser->dict_add_str(ctx->resp, "sdp", &sdp_out); sdp_out = STR_NULL; // ownership passed to output } @@ -3697,7 +3710,7 @@ const char *call_publish_ng(ng_parser_ctx_t *ctx, } -const char *call_subscribe_request_ng(ng_parser_ctx_t *ctx) { +const char *call_subscribe_request_ng(ng_command_ctx_t *ctx) { const char *err = NULL; g_auto(sdp_ng_flags) flags; char rand_buf[65]; @@ -3705,6 +3718,7 @@ const char *call_subscribe_request_ng(ng_parser_ctx_t *ctx) { g_auto(subscription_q) srms = TYPED_GQUEUE_INIT; g_auto(str) sdp_out = STR_NULL; parser_arg output = ctx->resp; + const ng_parser_t *parser = ctx->parser_ctx.parser; /* get source monologue */ err = media_block_match_mult(&call, &srms, &flags, ctx, OP_REQUEST); @@ -3745,7 +3759,7 @@ const char *call_subscribe_request_ng(ng_parser_ctx_t *ctx) { /* place return output SDP */ if (sdp_out.len) { ctx->ngbuf->sdp_out = sdp_out.s; - ctx->parser->dict_add_str(output, "sdp", &sdp_out); + parser->dict_add_str(output, "sdp", &sdp_out); sdp_out = STR_NULL; /* ownership passed to output */ } @@ -3755,49 +3769,49 @@ const char *call_subscribe_request_ng(ng_parser_ctx_t *ctx) { if (srms.length == 1) { struct media_subscription *ms = srms.head->data; struct call_monologue *source_ml = ms->monologue; - ctx->parser->dict_add_str_dup(output, "from-tag", &source_ml->tag); + parser->dict_add_str_dup(output, "from-tag", &source_ml->tag); } parser_arg tag_medias = {0}, media_labels = {0}; if (flags.siprec) { - tag_medias = ctx->parser->dict_add_list(output, "tag-medias"); - media_labels = ctx->parser->dict_add_dict(output, "media-labels"); + tag_medias = parser->dict_add_list(output, "tag-medias"); + media_labels = parser->dict_add_dict(output, "media-labels"); } - parser_arg from_list = ctx->parser->dict_add_list(output, "from-tags"); + parser_arg from_list = parser->dict_add_list(output, "from-tags"); for (__auto_type l = srms.head; l; l = l->next) { struct media_subscription *ms = l->data; struct call_monologue *source_ml = ms->monologue; - ctx->parser->list_add_str_dup(from_list, &source_ml->tag); + parser->list_add_str_dup(from_list, &source_ml->tag); if (tag_medias.gen) { - parser_arg tag_label = ctx->parser->list_add_dict(tag_medias); - ctx->parser->dict_add_str(tag_label, "tag", &source_ml->tag); + parser_arg tag_label = parser->list_add_dict(tag_medias); + parser->dict_add_str(tag_label, "tag", &source_ml->tag); if (source_ml->label.len) - ctx->parser->dict_add_str(tag_label, "label", &source_ml->label); - parser_arg medias = ctx->parser->dict_add_list(tag_label, "medias"); + parser->dict_add_str(tag_label, "label", &source_ml->label); + parser_arg medias = parser->dict_add_list(tag_label, "medias"); for (unsigned int i = 0; i < source_ml->medias->len; i++) { struct call_media *media = source_ml->medias->pdata[i]; if (!media) continue; - parser_arg med_ent = ctx->parser->list_add_dict(medias); - ctx->parser->dict_add_int(med_ent, "index", media->index); - ctx->parser->dict_add_str(med_ent, "type", &media->type); - ctx->parser->dict_add_str(med_ent, "label", &media->label); - ctx->parser->dict_add_string(med_ent, "mode", sdp_get_sendrecv(media)); + parser_arg med_ent = parser->list_add_dict(medias); + parser->dict_add_int(med_ent, "index", media->index); + parser->dict_add_str(med_ent, "type", &media->type); + parser->dict_add_str(med_ent, "label", &media->label); + parser->dict_add_string(med_ent, "mode", sdp_get_sendrecv(media)); if (media_labels.gen) { parser_arg label = - ctx->parser->dict_add_dict(media_labels, media->label.s); - ctx->parser->dict_add_str(label, "tag", &source_ml->tag); - ctx->parser->dict_add_int(label, "index", media->index); - ctx->parser->dict_add_str(label, "type", &media->type); + parser->dict_add_dict(media_labels, media->label.s); + parser->dict_add_str(label, "tag", &source_ml->tag); + parser->dict_add_int(label, "index", media->index); + parser->dict_add_str(label, "type", &media->type); if (source_ml->label.len) - ctx->parser->dict_add_str(label, "label", &source_ml->label); - ctx->parser->dict_add_string(label, "mode", sdp_get_sendrecv(media)); + parser->dict_add_str(label, "label", &source_ml->label); + parser->dict_add_string(label, "mode", sdp_get_sendrecv(media)); } } } } - ctx->parser->dict_add_str_dup(output, "to-tag", &dest_ml->tag); + parser->dict_add_str_dup(output, "to-tag", &dest_ml->tag); dequeue_sdp_fragments(dest_ml); @@ -3807,7 +3821,7 @@ const char *call_subscribe_request_ng(ng_parser_ctx_t *ctx) { } -const char *call_subscribe_answer_ng(ng_parser_ctx_t *ctx) { +const char *call_subscribe_answer_ng(ng_command_ctx_t *ctx) { g_auto(sdp_ng_flags) flags; g_auto(sdp_sessions_q) parsed = TYPED_GQUEUE_INIT; g_auto(sdp_streams_q) streams = TYPED_GQUEUE_INIT; @@ -3849,7 +3863,7 @@ const char *call_subscribe_answer_ng(ng_parser_ctx_t *ctx) { } -const char *call_unsubscribe_ng(ng_parser_ctx_t *ctx) { +const char *call_unsubscribe_ng(ng_command_ctx_t *ctx) { g_auto(sdp_ng_flags) flags; g_autoptr(call_t) call = NULL; diff --git a/daemon/control_ng.c b/daemon/control_ng.c index 74ab15b58..0080c071b 100644 --- a/daemon/control_ng.c +++ b/daemon/control_ng.c @@ -133,10 +133,10 @@ static long long bencode_get_int(bencode_item_t *arg) { return arg->value; } static parser_arg __bencode_dict(ng_parser_ctx_t *ctx) { - return (parser_arg) bencode_dictionary(&ctx->ngbuf->buffer); + return (parser_arg) bencode_dictionary(ctx->buffer); } static parser_arg __bencode_list(ng_parser_ctx_t *ctx) { - return (parser_arg) bencode_list(&ctx->ngbuf->buffer); + return (parser_arg) bencode_list(ctx->buffer); } static void bencode_pretty_print(bencode_item_t *el, GString *s); @@ -174,11 +174,15 @@ static parser_arg __bencode_list_add(bencode_item_t *l, bencode_item_t *e) { static parser_arg __bencode_list_add_dictionary(bencode_item_t *l) { return (parser_arg) bencode_list_add_dictionary(l); } -static str *__bencode_collapse_str(ng_parser_ctx_t *ctx, bencode_item_t *a, str *out) { - return bencode_collapse_str(a, out); +static str __bencode_collapse_str(ng_parser_ctx_t *ctx, bencode_item_t *a, void **to_free) { + return bencode_collapse_str(a); } static const char *__bencode_strdup(ng_parser_ctx_t *ctx, const char *s) { - return bencode_strdup(&ctx->ngbuf->buffer, s); + return bencode_strdup(ctx->buffer, s); +} +static void __bencode_ctx_init(ng_parser_ctx_t *ctx, bencode_buffer_t *buf) { + bencode_buffer_init(buf); + *ctx = (ng_parser_ctx_t) { .parser = &ng_parser_native, .buffer = buf }; } static bool json_is_dict(JsonNode *n) { @@ -422,19 +426,23 @@ static void json_list_add_str(JsonNode *n, const str *v) { static void json_list_add_string(JsonNode *n, const char *s) { json_array_add_string_element(json_node_get_array(n), s); } -static str *json_collapse(ng_parser_ctx_t *ctx, JsonNode *a, str *out) { +static str json_collapse(ng_parser_ctx_t *ctx, JsonNode *a, void **to_free) { JsonGenerator *g = json_generator_new(); json_generator_set_root(g, a); size_t len; char *s = json_generator_to_data(g, &len); + *to_free = s; g_object_unref(g); - *out = STR_LEN(s, len); - ctx->ngbuf->collapsed = s; + str out = STR_LEN(s, len); json_node_unref(a); return out; } +static void json_ctx_init(ng_parser_ctx_t *ctx, bencode_buffer_t *buf) { + *ctx = (ng_parser_ctx_t) { .parser = &ng_parser_json }; +} const ng_parser_t ng_parser_native = { + .init = __bencode_ctx_init, .collapse = __bencode_collapse_str, .dict_iter = bencode_dict_iter, .is_list = bencode_is_list, @@ -468,6 +476,7 @@ const ng_parser_t ng_parser_native = { .pretty_print = bencode_pretty_print, }; const ng_parser_t ng_parser_json = { + .init = json_ctx_init, .collapse = json_collapse, .dict_iter = json_dict_iter, .is_list = json_is_list, @@ -649,11 +658,10 @@ static void control_ng_process_payload(ng_ctx *hctx, str *reply, str *data, cons struct control_ng_stats* cur = get_control_ng_stats(&sin->address); enum ng_command command = -1; - ng_parser_ctx_t parser_ctx = { - .parser = &ng_parser_native, - }; + ng_command_ctx_t command_ctx = {0}; + const ng_parser_t *parser = &ng_parser_native; - parser_ctx.ngbuf = *ngbufp = ng_buffer_new(ref); + command_ctx.ngbuf = *ngbufp = ng_buffer_new(ref); errstr = "Invalid data (no payload)"; if (data->len <= 0) @@ -661,26 +669,24 @@ static void control_ng_process_payload(ng_ctx *hctx, str *reply, str *data, cons /* Bencode dictionary */ if (data->s[0] == 'd') { - int ret = bencode_buffer_init(&parser_ctx.ngbuf->buffer); - assert(ret == 0); - (void) ret; + ng_parser_native.init(&command_ctx.parser_ctx, &command_ctx.ngbuf->buffer); - parser_ctx.req.benc = bencode_decode_expect_str(&parser_ctx.ngbuf->buffer, data, BENCODE_DICTIONARY); + command_ctx.req.benc = bencode_decode_expect_str(&command_ctx.ngbuf->buffer, data, BENCODE_DICTIONARY); errstr = "Could not decode bencode dictionary"; - if (!parser_ctx.req.benc) + if (!command_ctx.req.benc) goto err_send; } /* JSON */ else if (data->s[0] == '{') { - parser_ctx.parser = &ng_parser_json; - parser_ctx.ngbuf->json = json_parser_new(); + ng_parser_json.init(&command_ctx.parser_ctx, &command_ctx.ngbuf->buffer); + command_ctx.ngbuf->json = json_parser_new(); errstr = "Failed to parse JSON document"; - if (!json_parser_load_from_data(parser_ctx.ngbuf->json, data->s, data->len, NULL)) + if (!json_parser_load_from_data(command_ctx.ngbuf->json, data->s, data->len, NULL)) goto err_send; - parser_ctx.req.json = json_parser_get_root(parser_ctx.ngbuf->json); + command_ctx.req.json = json_parser_get_root(command_ctx.ngbuf->json); errstr = "Could not decode bencode dictionary"; - if (!parser_ctx.req.json || !parser_ctx.parser->is_dict(parser_ctx.req)) + if (!command_ctx.req.json || !ng_parser_json.is_dict(command_ctx.req)) goto err_send; } @@ -689,15 +695,17 @@ static void control_ng_process_payload(ng_ctx *hctx, str *reply, str *data, cons goto err_send; } - parser_ctx.resp = parser_ctx.parser->dict(&parser_ctx); - assert(parser_ctx.resp.gen != NULL); + parser = command_ctx.parser_ctx.parser; + + command_ctx.resp = parser->dict(&command_ctx.parser_ctx); + assert(command_ctx.resp.gen != NULL); - parser_ctx.parser->dict_get_str(parser_ctx.req, "command", &cmd); + parser->dict_get_str(command_ctx.req, "command", &cmd); errstr = "Dictionary contains no key \"command\""; if (!cmd.s) goto err_send; - parser_ctx.parser->dict_get_str(parser_ctx.req, "call-id", &callid); + parser->dict_get_str(command_ctx.req, "call-id", &callid); log_info_str(&callid); ilogs(control, LOG_INFO, "Received command '"STR_FORMAT"' from %s", STR_FMT(&cmd), addr); @@ -706,7 +714,7 @@ static void control_ng_process_payload(ng_ctx *hctx, str *reply, str *data, cons log_str = g_string_sized_new(256); g_string_append_printf(log_str, "Dump for '"STR_FORMAT"' from %s: %s", STR_FMT(&cmd), addr, rtpe_config.common.log_mark_prefix); - parser_ctx.parser->pretty_print(parser_ctx.req, log_str); + parser->pretty_print(command_ctx.req, log_str); g_string_append(log_str, rtpe_config.common.log_mark_suffix); ilogs(control, LOG_DEBUG, "%.*s", (int) log_str->len, log_str->str); g_string_free(log_str, TRUE); @@ -724,99 +732,99 @@ static void control_ng_process_payload(ng_ctx *hctx, str *reply, str *data, cons command = NGC_PING; break; case CSH_LOOKUP("offer"): - errstr = call_offer_ng(&parser_ctx, addr, sin); + errstr = call_offer_ng(&command_ctx, addr, sin); command = NGC_OFFER; break; case CSH_LOOKUP("answer"): - errstr = call_answer_ng(&parser_ctx); + errstr = call_answer_ng(&command_ctx); command = NGC_ANSWER; break; case CSH_LOOKUP("delete"): - errstr = call_delete_ng(&parser_ctx); + errstr = call_delete_ng(&command_ctx); command = NGC_DELETE; break; case CSH_LOOKUP("query"): - errstr = call_query_ng(&parser_ctx); + errstr = call_query_ng(&command_ctx); command = NGC_QUERY; break; case CSH_LOOKUP("list"): - errstr = call_list_ng(&parser_ctx); + errstr = call_list_ng(&command_ctx); command = NGC_LIST; break; case CSH_LOOKUP("start recording"): - errstr = call_start_recording_ng(&parser_ctx); + errstr = call_start_recording_ng(&command_ctx); command = NGC_START_RECORDING; break; case CSH_LOOKUP("stop recording"): - errstr = call_stop_recording_ng(&parser_ctx); + errstr = call_stop_recording_ng(&command_ctx); command = NGC_STOP_RECORDING; break; case CSH_LOOKUP("pause recording"): - errstr = call_pause_recording_ng(&parser_ctx); + errstr = call_pause_recording_ng(&command_ctx); command = NGC_PAUSE_RECORDING; break; case CSH_LOOKUP("start forwarding"): - errstr = call_start_forwarding_ng(&parser_ctx); + errstr = call_start_forwarding_ng(&command_ctx); command = NGC_START_FORWARDING; break; case CSH_LOOKUP("stop forwarding"): - errstr = call_stop_forwarding_ng(&parser_ctx); + errstr = call_stop_forwarding_ng(&command_ctx); command = NGC_STOP_FORWARDING; break; case CSH_LOOKUP("block DTMF"): - errstr = call_block_dtmf_ng(&parser_ctx); + errstr = call_block_dtmf_ng(&command_ctx); command = NGC_BLOCK_DTMF; break; case CSH_LOOKUP("unblock DTMF"): - errstr = call_unblock_dtmf_ng(&parser_ctx); + errstr = call_unblock_dtmf_ng(&command_ctx); command = NGC_UNBLOCK_DTMF; break; case CSH_LOOKUP("block media"): - errstr = call_block_media_ng(&parser_ctx); + errstr = call_block_media_ng(&command_ctx); command = NGC_BLOCK_MEDIA; break; case CSH_LOOKUP("unblock media"): - errstr = call_unblock_media_ng(&parser_ctx); + errstr = call_unblock_media_ng(&command_ctx); command = NGC_UNBLOCK_MEDIA; break; case CSH_LOOKUP("silence media"): - errstr = call_silence_media_ng(&parser_ctx); + errstr = call_silence_media_ng(&command_ctx); command = NGC_SILENCE_MEDIA; break; case CSH_LOOKUP("unsilence media"): - errstr = call_unsilence_media_ng(&parser_ctx); + errstr = call_unsilence_media_ng(&command_ctx); command = NGC_UNSILENCE_MEDIA; break; case CSH_LOOKUP("play media"): - errstr = call_play_media_ng(&parser_ctx); + errstr = call_play_media_ng(&command_ctx); command = NGC_PLAY_MEDIA; break; case CSH_LOOKUP("stop media"): - errstr = call_stop_media_ng(&parser_ctx); + errstr = call_stop_media_ng(&command_ctx); command = NGC_STOP_MEDIA; break; case CSH_LOOKUP("play DTMF"): - errstr = call_play_dtmf_ng(&parser_ctx); + errstr = call_play_dtmf_ng(&command_ctx); command = NGC_PLAY_DTMF; break; case CSH_LOOKUP("statistics"): - errstr = statistics_ng(&parser_ctx); + errstr = statistics_ng(&command_ctx); command = NGC_STATISTICS; break; case CSH_LOOKUP("publish"): - errstr = call_publish_ng(&parser_ctx, addr, sin); + errstr = call_publish_ng(&command_ctx, addr, sin); command = NGC_PUBLISH; break; case CSH_LOOKUP("subscribe request"): - errstr = call_subscribe_request_ng(&parser_ctx); + errstr = call_subscribe_request_ng(&command_ctx); command = NGC_SUBSCRIBE_REQ; break; case CSH_LOOKUP("subscribe answer"): - errstr = call_subscribe_answer_ng(&parser_ctx); + errstr = call_subscribe_answer_ng(&command_ctx); command = NGC_SUBSCRIBE_ANS; break; case CSH_LOOKUP("unsubscribe"): - errstr = call_unsubscribe_ng(&parser_ctx); + errstr = call_unsubscribe_ng(&command_ctx); command = NGC_UNSUBSCRIBE; break; default: @@ -841,7 +849,7 @@ static void control_ng_process_payload(ng_ctx *hctx, str *reply, str *data, cons if (errstr) goto err_send; - parser_ctx.parser->dict_add_string(parser_ctx.resp, "result", resultstr); + parser->dict_add_string(command_ctx.resp, "result", resultstr); // update interval statistics RTPE_STATS_INC(ng_commands[command]); @@ -854,38 +862,34 @@ err_send: if (errstr < magic_load_limit_strings[0] || errstr > magic_load_limit_strings[__LOAD_LIMIT_MAX-1]) { ilogs(control, LOG_WARNING, "Protocol error in packet from %s: %s [" STR_FORMAT_M "]", addr, errstr, STR_FMT_M(data)); - parser_ctx.parser->dict_add_string(parser_ctx.resp, "result", "error"); - parser_ctx.parser->dict_add_string(parser_ctx.resp, "error-reason", errstr); + parser->dict_add_string(command_ctx.resp, "result", "error"); + parser->dict_add_string(command_ctx.resp, "error-reason", errstr); g_atomic_int_inc(&cur->errors); cmd = STR_NULL; } else { - parser_ctx.parser->dict_add_string(parser_ctx.resp, "result", "load limit"); - parser_ctx.parser->dict_add_string(parser_ctx.resp, "message", errstr); + parser->dict_add_string(command_ctx.resp, "result", "load limit"); + parser->dict_add_string(command_ctx.resp, "message", errstr); } send_resp: - parser_ctx.parser->collapse(&parser_ctx, parser_ctx.resp, reply); - if (cmd.s) { ilogs(control, LOG_INFO, "Replying to '"STR_FORMAT"' from %s (elapsed time %llu.%06llu sec)", STR_FMT(&cmd), addr, (unsigned long long)cmd_process_time.tv_sec, (unsigned long long)cmd_process_time.tv_usec); if (get_log_level(control) >= LOG_DEBUG) { - parser_ctx.req.benc = bencode_decode_expect_str(&parser_ctx.ngbuf->buffer, - reply, BENCODE_DICTIONARY); - if (parser_ctx.req.benc) { - log_str = g_string_sized_new(256); - g_string_append_printf(log_str, "Response dump for '"STR_FORMAT"' to %s: %s", - STR_FMT(&cmd), addr, - rtpe_config.common.log_mark_prefix); - parser_ctx.parser->pretty_print(parser_ctx.req, log_str); - g_string_append(log_str, rtpe_config.common.log_mark_suffix); - ilogs(control, LOG_DEBUG, "%.*s", (int) log_str->len, log_str->str); - g_string_free(log_str, TRUE); - } + log_str = g_string_sized_new(256); + g_string_append_printf(log_str, "Response dump for '"STR_FORMAT"' to %s: %s", + STR_FMT(&cmd), addr, + rtpe_config.common.log_mark_prefix); + parser->pretty_print(command_ctx.resp, log_str); + g_string_append(log_str, rtpe_config.common.log_mark_suffix); + ilogs(control, LOG_DEBUG, "%.*s", (int) log_str->len, log_str->str); + g_string_free(log_str, TRUE); } } + *reply = parser->collapse(&command_ctx.parser_ctx, command_ctx.resp, &command_ctx.ngbuf->collapsed); + release_closed_sockets(); log_info_pop_until(&callid); CH(homer_trace_msg_out ,hctx, reply); diff --git a/daemon/dtmf.c b/daemon/dtmf.c index 40445ff79..40e3a8053 100644 --- a/daemon/dtmf.c +++ b/daemon/dtmf.c @@ -136,7 +136,7 @@ static void dtmf_bencode_and_notify(struct call_media *media, unsigned int event bencode_dictionary_add_integer(data, "duration", ((long long) duration * (1000000LL / clockrate)) / 1000LL); bencode_dictionary_add_integer(data, "volume", volume); - bencode_collapse_str(notify, &encoded_data); + encoded_data = bencode_collapse_str(notify); notify_ng_tcp_clients(&encoded_data); bencode_buffer_free(&bencbuf); } diff --git a/daemon/redis.c b/daemon/redis.c index e5cfeed78..b10186ff1 100644 --- a/daemon/redis.c +++ b/daemon/redis.c @@ -2405,7 +2405,7 @@ static void json_update_dtls_fingerprint(const ng_parser_t *parser, parser_arg i * encodes the few (k,v) pairs for one call under one json structure */ -static str redis_encode_json(ng_parser_ctx_t *ctx, call_t *c) { +static str redis_encode_json(ng_parser_ctx_t *ctx, call_t *c, void **to_free) { char tmp[2048]; const ng_parser_t *parser = ctx->parser; @@ -2749,9 +2749,7 @@ static str redis_encode_json(ng_parser_ctx_t *ctx, call_t *c) { } - str ret; - parser->collapse(ctx, root, &ret); - return ret; + return parser->collapse(ctx, root, to_free); } @@ -2780,13 +2778,12 @@ void redis_update_onekey(call_t *c, struct redis *r) { goto err; } - ng_parser_ctx_t ctx = {.parser = redis_format_parsers[rtpe_config.redis_format]}; - ctx.ngbuf = ng_buffer_new(NULL); // XXX make conditional - int ret = bencode_buffer_init(&ctx.ngbuf->buffer); // XXX make conditional and/or optimise - if (ret) - goto err; + ng_parser_ctx_t ctx; + bencode_buffer_t bbuf; + redis_format_parsers[rtpe_config.redis_format]->init(&ctx, &bbuf); - str result = redis_encode_json(&ctx, c); + void *to_free = NULL; + str result = redis_encode_json(&ctx, c, &to_free); if (!result.len) goto err; @@ -2796,7 +2793,8 @@ void redis_update_onekey(call_t *c, struct redis *r) { rwlock_unlock_r(&c->master_lock); - obj_put(ctx.ngbuf); + g_free(to_free); + bencode_buffer_free(ctx.buffer); return; err: diff --git a/daemon/statistics.c b/daemon/statistics.c index be8454103..fc0a53558 100644 --- a/daemon/statistics.c +++ b/daemon/statistics.c @@ -952,11 +952,13 @@ void statistics_init(void) { rtpe_codec_stats = codec_stats_ht_new(); } -const char *statistics_ng(ng_parser_ctx_t *ctx) { +const char *statistics_ng(ng_command_ctx_t *ctx) { g_autoptr(stats_metric_q) metrics = statistics_gather_metrics(NULL); g_auto(GQueue) bstack = G_QUEUE_INIT; parser_arg dict = ctx->resp; + ng_parser_ctx_t *parser_ctx = &ctx->parser_ctx; + const ng_parser_t *parser = parser_ctx->parser; const char *sub_label = "statistics"; // top level for (__auto_type l = metrics->head; l; l = l->next) { @@ -967,13 +969,13 @@ const char *statistics_ng(ng_parser_ctx_t *ctx) { // key:value entry? if (m->value_short) { if (m->is_int) - ctx->parser->dict_add_int(dict, ctx->parser->strdup(ctx, m->label), + parser->dict_add_int(dict, parser->strdup(parser_ctx, m->label), m->int_value); else if (m->value_raw) - ctx->parser->dict_add_str_dup(dict, ctx->parser->strdup(ctx, m->label), + parser->dict_add_str_dup(dict, parser->strdup(parser_ctx, m->label), &STR(m->value_raw)); else - ctx->parser->dict_add_str_dup(dict, ctx->parser->strdup(ctx, m->label), + parser->dict_add_str_dup(dict, parser->strdup(parser_ctx, m->label), &STR(m->value_short)); continue; } @@ -995,19 +997,19 @@ const char *statistics_ng(ng_parser_ctx_t *ctx) { // open bracket of some sort - new sub-entry follows parser_arg sub = {0}; if (m->is_brace) - sub = ctx->parser->dict(ctx); + sub = parser->dict(parser_ctx); else - sub = ctx->parser->list(ctx); + sub = parser->list(parser_ctx); assert(sub.gen != NULL); // is this a dictionary? - if (ctx->parser->is_dict(dict)) { + if (parser->is_dict(dict)) { assert(sub_label != NULL); - ctx->parser->dict_add(dict, ctx->parser->strdup(ctx, sub_label), sub); + parser->dict_add(dict, parser->strdup(parser_ctx, sub_label), sub); } - else if (ctx->parser->is_list(dict)) - ctx->parser->list_add(dict, sub); + else if (parser->is_list(dict)) + parser->list_add(dict, sub); else abort(); diff --git a/include/bencode.h b/include/bencode.h index 6b041a935..33c375c0e 100644 --- a/include/bencode.h +++ b/include/bencode.h @@ -216,8 +216,8 @@ struct iovec *bencode_iovec(bencode_item_t *root, int *cnt, unsigned int head, u * bencode_buffer_t object is destroyed. */ char *bencode_collapse(bencode_item_t *root, size_t *len); -/* Identical to bencode_collapse() but fills in a "str" object. Returns "out". */ -INLINE str *bencode_collapse_str(bencode_item_t *root, str *out); +/* Identical to bencode_collapse() but returns a "str" object. */ +INLINE str bencode_collapse_str(bencode_item_t *root); /* Identical to bencode_collapse(), but the memory for the returned string is not allocated from * a bencode_buffer_t object, but instead using the function defined as BENCODE_MALLOC (normally @@ -532,8 +532,9 @@ INLINE bencode_item_t *bencode_dictionary_get_expect(bencode_item_t *dict, const return NULL; return ret; } -INLINE str *bencode_collapse_str(bencode_item_t *root, str *out) { - out->s = bencode_collapse(root, &out->len); +INLINE str bencode_collapse_str(bencode_item_t *root) { + str out = STR_NULL; + out.s = bencode_collapse(root, &out.len); return out; } INLINE int bencode_strcmp(bencode_item_t *a, const char *b) { diff --git a/include/call.h b/include/call.h index 22a0569a9..bcd885862 100644 --- a/include/call.h +++ b/include/call.h @@ -811,9 +811,9 @@ int monologue_subscribe_answer(struct call_monologue *dst, sdp_ng_flags *flags, int monologue_unsubscribe(struct call_monologue *dst, sdp_ng_flags *); void monologue_destroy(struct call_monologue *ml); int call_delete_branch_by_id(const str *callid, const str *branch, - const str *fromtag, const str *totag, ng_parser_ctx_t *, int delete_delay); + const str *fromtag, const str *totag, ng_command_ctx_t *, int delete_delay); int call_delete_branch(call_t *, const str *branch, - const str *fromtag, const str *totag, ng_parser_ctx_t *, int delete_delay); + const str *fromtag, const str *totag, ng_command_ctx_t *, int delete_delay); void call_destroy(call_t *); struct call_media *call_media_new(call_t *call); void call_media_free(struct call_media **mdp); diff --git a/include/call_interfaces.h b/include/call_interfaces.h index 66622790b..c491622d9 100644 --- a/include/call_interfaces.h +++ b/include/call_interfaces.h @@ -242,33 +242,33 @@ str *call_lookup_udp(char **); str *call_delete_udp(char **); str *call_query_udp(char **); -const char *call_offer_ng(ng_parser_ctx_t *, const char*, +const char *call_offer_ng(ng_command_ctx_t *, const char*, const endpoint_t *); -const char *call_answer_ng(ng_parser_ctx_t *); -const char *call_delete_ng(ng_parser_ctx_t *); -const char *call_query_ng(ng_parser_ctx_t *); -const char *call_list_ng(ng_parser_ctx_t *); -const char *call_start_recording_ng(ng_parser_ctx_t *); -const char *call_stop_recording_ng(ng_parser_ctx_t *); -const char *call_pause_recording_ng(ng_parser_ctx_t *); -const char *call_start_forwarding_ng(ng_parser_ctx_t *); -const char *call_stop_forwarding_ng(ng_parser_ctx_t *); -const char *call_block_dtmf_ng(ng_parser_ctx_t *); -const char *call_unblock_dtmf_ng(ng_parser_ctx_t *); -const char *call_block_media_ng(ng_parser_ctx_t *); -const char *call_unblock_media_ng(ng_parser_ctx_t *); -const char *call_silence_media_ng(ng_parser_ctx_t *); -const char *call_unsilence_media_ng(ng_parser_ctx_t *); -const char *call_play_media_ng(ng_parser_ctx_t *); -const char *call_stop_media_ng(ng_parser_ctx_t *); -const char *call_play_dtmf_ng(ng_parser_ctx_t *); -void ng_call_stats(ng_parser_ctx_t *, call_t *call, const str *fromtag, const str *totag, +const char *call_answer_ng(ng_command_ctx_t *); +const char *call_delete_ng(ng_command_ctx_t *); +const char *call_query_ng(ng_command_ctx_t *); +const char *call_list_ng(ng_command_ctx_t *); +const char *call_start_recording_ng(ng_command_ctx_t *); +const char *call_stop_recording_ng(ng_command_ctx_t *); +const char *call_pause_recording_ng(ng_command_ctx_t *); +const char *call_start_forwarding_ng(ng_command_ctx_t *); +const char *call_stop_forwarding_ng(ng_command_ctx_t *); +const char *call_block_dtmf_ng(ng_command_ctx_t *); +const char *call_unblock_dtmf_ng(ng_command_ctx_t *); +const char *call_block_media_ng(ng_command_ctx_t *); +const char *call_unblock_media_ng(ng_command_ctx_t *); +const char *call_silence_media_ng(ng_command_ctx_t *); +const char *call_unsilence_media_ng(ng_command_ctx_t *); +const char *call_play_media_ng(ng_command_ctx_t *); +const char *call_stop_media_ng(ng_command_ctx_t *); +const char *call_play_dtmf_ng(ng_command_ctx_t *); +void ng_call_stats(ng_command_ctx_t *, call_t *call, const str *fromtag, const str *totag, struct call_stats *totals); -const char *call_publish_ng(ng_parser_ctx_t *, const char *, +const char *call_publish_ng(ng_command_ctx_t *, const char *, const endpoint_t *); -const char *call_subscribe_request_ng(ng_parser_ctx_t *); -const char *call_subscribe_answer_ng(ng_parser_ctx_t *); -const char *call_unsubscribe_ng(ng_parser_ctx_t *); +const char *call_subscribe_request_ng(ng_command_ctx_t *); +const char *call_subscribe_answer_ng(ng_command_ctx_t *); +const char *call_unsubscribe_ng(ng_command_ctx_t *); void add_media_to_sub_list(subscription_q *q, struct call_media *media, struct call_monologue *ml); diff --git a/include/control_ng.h b/include/control_ng.h index f37f7ac8e..579049cc6 100644 --- a/include/control_ng.h +++ b/include/control_ng.h @@ -65,7 +65,7 @@ struct ng_buffer { struct sdp_chopper *chopper; char *sdp_out; struct call *call; - char *collapsed; + void *collapsed; }; @@ -118,7 +118,8 @@ typedef union { } helper_arg __attribute__ ((__transparent_union__)); struct ng_parser { - str *(*collapse)(ng_parser_ctx_t *, parser_arg, str *out); + void (*init)(ng_parser_ctx_t *, bencode_buffer_t *); + str (*collapse)(ng_parser_ctx_t *, parser_arg, void **); bool (*dict_iter)(const ng_parser_t *, parser_arg, void (*callback)(const ng_parser_t *, str *, parser_arg, helper_arg), helper_arg); @@ -157,6 +158,10 @@ struct ng_parser { }; struct ng_parser_ctx { const ng_parser_t *parser; + bencode_buffer_t *buffer; +}; +struct ng_command_ctx { + ng_parser_ctx_t parser_ctx; struct ng_buffer *ngbuf; parser_arg req; parser_arg resp; diff --git a/include/statistics.h b/include/statistics.h index c0a09521a..c221fd00e 100644 --- a/include/statistics.h +++ b/include/statistics.h @@ -173,7 +173,7 @@ void statistics_update_foreignown_inc(call_t * c); stats_metric_q *statistics_gather_metrics(struct interface_sampled_rate_stats *); void statistics_free_metrics(stats_metric_q *); G_DEFINE_AUTOPTR_CLEANUP_FUNC(stats_metric_q, statistics_free_metrics) -const char *statistics_ng(ng_parser_ctx_t *); +const char *statistics_ng(ng_command_ctx_t *); enum thread_looper_action call_rate_stats_updater(void); /** diff --git a/include/types.h b/include/types.h index 4d92f77fd..c89c96b74 100644 --- a/include/types.h +++ b/include/types.h @@ -39,6 +39,7 @@ typedef void sdp_attr_print_f(GString *, union sdp_attr_print_arg, const sdp_ng_ typedef struct ng_parser ng_parser_t; typedef struct ng_parser_ctx ng_parser_ctx_t; +typedef struct ng_command_ctx ng_command_ctx_t; typedef struct bencode_item bencode_item_t;