MT#55283 rework parser framework

Change-Id: Ia837916ec2123afe03e63c62bfb7058173f05fad
pull/1853/head
Richard Fuchs 9 months ago
parent 68ff069adc
commit 7dd2235df1

@ -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);

@ -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) {

@ -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;

@ -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);

@ -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);
}

@ -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:

@ -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();

@ -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) {

@ -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);

@ -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);

@ -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;

@ -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);
/**

@ -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;

Loading…
Cancel
Save