MT#55283 introduce abstract parsing framework

Change-Id: I63ba6fc7e6278e989e87a3abdb66976084b403bc
pull/1848/head
Richard Fuchs 2 years ago
parent f7538d3ea6
commit 3f8f182119

@ -1300,9 +1300,8 @@ void call_ng_flags_init(sdp_ng_flags *out, enum call_opmode opmode) {
out->frequencies = g_array_new(false, false, sizeof(int)); out->frequencies = g_array_new(false, false, sizeof(int));
} }
static void call_ng_dict_iter(sdp_ng_flags *out, bencode_item_t *input, static void call_ng_dict_iter(ng_parser_ctx_t *ctx, bencode_item_t *input,
enum call_opmode opmode, void (*callback)(ng_parser_ctx_t *, str *key, bencode_item_t *value))
void (*callback)(sdp_ng_flags *, str *key, bencode_item_t *value, enum call_opmode _opmode))
{ {
if (input->type != BENCODE_DICTIONARY) if (input->type != BENCODE_DICTIONARY)
return; return;
@ -1317,8 +1316,7 @@ static void call_ng_dict_iter(sdp_ng_flags *out, bencode_item_t *input,
if (!bencode_get_str(key, &k)) if (!bencode_get_str(key, &k))
continue; continue;
callback(out, &k, value, opmode); callback(ctx, &k, value);
} }
} }
void call_ng_direction_flag(sdp_ng_flags *out, bencode_item_t *value) void call_ng_direction_flag(sdp_ng_flags *out, bencode_item_t *value)
@ -1329,9 +1327,8 @@ void call_ng_direction_flag(sdp_ng_flags *out, bencode_item_t *value)
for (bencode_item_t *cit = value->child; cit && diridx < 2; cit = cit->sibling) for (bencode_item_t *cit = value->child; cit && diridx < 2; cit = cit->sibling)
bencode_get_str(cit, &out->direction[diridx++]); bencode_get_str(cit, &out->direction[diridx++]);
} }
void call_ng_codec_flags(sdp_ng_flags *out, str *key, bencode_item_t *value, void call_ng_codec_flags(ng_parser_ctx_t *ctx, str *key, bencode_item_t *value) {
enum call_opmode opmode) sdp_ng_flags *out = ctx->flags;
{
switch (__csh_lookup(key)) { switch (__csh_lookup(key)) {
case CSH_LOOKUP("except"): case CSH_LOOKUP("except"):
call_ng_flags_str_list(out, value, call_ng_flags_str_ht, &out->codec_except); call_ng_flags_str_list(out, value, call_ng_flags_str_ht, &out->codec_except);
@ -1435,11 +1432,10 @@ static void call_ng_flags_freqs(sdp_ng_flags *out, bencode_item_t *value) {
} }
} }
void call_ng_main_flags(sdp_ng_flags *out, str *key, bencode_item_t *value, void call_ng_main_flags(ng_parser_ctx_t *ctx, str *key, bencode_item_t *value) {
enum call_opmode opmode)
{
str s = STR_NULL; str s = STR_NULL;
bencode_item_t *it; bencode_item_t *it;
sdp_ng_flags *out = ctx->flags;
bencode_get_str(value, &s); bencode_get_str(value, &s);
@ -1524,7 +1520,7 @@ void call_ng_main_flags(sdp_ng_flags *out, str *key, bencode_item_t *value,
out->digit = s.s[0]; out->digit = s.s[0];
break; break;
case CSH_LOOKUP("codec"): case CSH_LOOKUP("codec"):
call_ng_dict_iter(out, value, opmode, call_ng_codec_flags); call_ng_dict_iter(ctx, value, call_ng_codec_flags);
break; break;
case CSH_LOOKUP("command"): case CSH_LOOKUP("command"):
break; break;
@ -1868,7 +1864,7 @@ void call_ng_main_flags(sdp_ng_flags *out, str *key, bencode_item_t *value,
case CSH_LOOKUP("rtpp-flags"): case CSH_LOOKUP("rtpp-flags"):
case CSH_LOOKUP("rtpp_flags"):; case CSH_LOOKUP("rtpp_flags"):;
/* s - list of rtpp flags */ /* s - list of rtpp flags */
parse_rtpp_flags(&s, value->buffer, opmode, out); parse_rtpp_flags(&s, ctx);
break; break;
case CSH_LOOKUP("SDES"): case CSH_LOOKUP("SDES"):
case CSH_LOOKUP("sdes"): case CSH_LOOKUP("sdes"):
@ -2013,9 +2009,11 @@ void call_ng_main_flags(sdp_ng_flags *out, str *key, bencode_item_t *value,
} }
} }
static void call_ng_process_flags(sdp_ng_flags *out, bencode_item_t *input, enum call_opmode opmode) { static void call_ng_process_flags(sdp_ng_flags *out, ng_parser_ctx_t *ctx, enum call_opmode opmode) {
call_ng_flags_init(out, opmode); call_ng_flags_init(out, opmode);
call_ng_dict_iter(out, input, opmode, call_ng_main_flags); ctx->opmode = opmode;
ctx->flags = out;
call_ng_dict_iter(ctx, ctx->req, call_ng_main_flags);
} }
static void ng_sdp_attr_manipulations_free(struct sdp_manipulations * array[__MT_MAX]) { static void ng_sdp_attr_manipulations_free(struct sdp_manipulations * array[__MT_MAX]) {
@ -2134,8 +2132,7 @@ static enum basic_errors call_ng_basic_checks(sdp_ng_flags *flags, enum call_opm
return 0; return 0;
} }
static const char *call_offer_answer_ng(ng_buffer *ngbuf, bencode_item_t *input, static const char *call_offer_answer_ng(ng_parser_ctx_t *ctx, enum call_opmode opmode, const char* addr,
bencode_item_t *output, enum call_opmode opmode, const char* addr,
const endpoint_t *sin) const endpoint_t *sin)
{ {
const char *errstr; const char *errstr;
@ -2147,8 +2144,9 @@ static const char *call_offer_answer_ng(ng_buffer *ngbuf, bencode_item_t *input,
int ret; int ret;
g_auto(sdp_ng_flags) flags; g_auto(sdp_ng_flags) flags;
struct sdp_chopper *chopper; struct sdp_chopper *chopper;
bencode_item_t *output = ctx->resp;
call_ng_process_flags(&flags, input, opmode); call_ng_process_flags(&flags, ctx, opmode);
if ((ret = call_ng_basic_checks(&flags, opmode)) > 0) if ((ret = call_ng_basic_checks(&flags, opmode)) > 0)
return _ng_basic_errors[ret]; return _ng_basic_errors[ret];
@ -2178,7 +2176,7 @@ static const char *call_offer_answer_ng(ng_buffer *ngbuf, bencode_item_t *input,
call = call_get(&flags.call_id); call = call_get(&flags.call_id);
// SDP fragments for trickle ICE must always operate on an existing call // SDP fragments for trickle ICE must always operate on an existing call
if (opmode == OP_OFFER && trickle_ice_update(ngbuf, call, &flags, &streams)) { if (opmode == OP_OFFER && trickle_ice_update(ctx->ngbuf, call, &flags, &streams)) {
errstr = NULL; errstr = NULL;
// SDP fragments for trickle ICE are consumed with no replacement returned // SDP fragments for trickle ICE are consumed with no replacement returned
goto out; goto out;
@ -2298,23 +2296,25 @@ out:
return errstr; return errstr;
} }
const char *call_offer_ng(ng_buffer *ngbuf, bencode_item_t *input, bencode_item_t *output, const char *call_offer_ng(ng_parser_ctx_t *ctx,
const char* addr, const char* addr,
const endpoint_t *sin) const endpoint_t *sin)
{ {
return call_offer_answer_ng(ngbuf, input, output, OP_OFFER, addr, sin); return call_offer_answer_ng(ctx, OP_OFFER, addr, sin);
} }
const char *call_answer_ng(ng_buffer *ngbuf, bencode_item_t *input, bencode_item_t *output) { const char *call_answer_ng(ng_parser_ctx_t *ctx) {
return call_offer_answer_ng(ngbuf, input, output, OP_ANSWER, NULL, NULL); return call_offer_answer_ng(ctx, OP_ANSWER, NULL, NULL);
} }
const char *call_delete_ng(bencode_item_t *input, bencode_item_t *output) { const char *call_delete_ng(ng_parser_ctx_t *ctx) {
str fromtag, totag, viabranch, callid; str fromtag, totag, viabranch, callid;
bencode_item_t *flags, *it; bencode_item_t *flags, *it;
bool fatal = false; bool fatal = false;
bool discard = false; bool discard = false;
int delete_delay; int delete_delay;
bencode_item_t *input = ctx->req;
bencode_item_t *output = ctx->resp;
if (!bencode_dictionary_get_str(input, "call-id", &callid)) if (!bencode_dictionary_get_str(input, "call-id", &callid))
return "No call-id in message"; return "No call-id in message";
@ -2773,9 +2773,11 @@ static void ng_list_calls(bencode_item_t *output, long long int limit) {
const char *call_query_ng(bencode_item_t *input, bencode_item_t *output) { const char *call_query_ng(ng_parser_ctx_t *ctx) {
str callid, fromtag, totag; str callid, fromtag, totag;
call_t *call; call_t *call;
bencode_item_t *input = ctx->req;
bencode_item_t *output = ctx->resp;
if (!bencode_dictionary_get_str(input, "call-id", &callid)) if (!bencode_dictionary_get_str(input, "call-id", &callid))
return "No call-id in message"; return "No call-id in message";
@ -2793,9 +2795,11 @@ const char *call_query_ng(bencode_item_t *input, bencode_item_t *output) {
} }
const char *call_list_ng(bencode_item_t *input, bencode_item_t *output) { const char *call_list_ng(ng_parser_ctx_t *ctx) {
bencode_item_t *calls = NULL; bencode_item_t *calls = NULL;
long long int limit; long long int limit;
bencode_item_t *input = ctx->req;
bencode_item_t *output = ctx->resp;
limit = bencode_dictionary_get_int_str(input, "limit", 32); limit = bencode_dictionary_get_int_str(input, "limit", 32);
@ -2810,14 +2814,15 @@ const char *call_list_ng(bencode_item_t *input, bencode_item_t *output) {
} }
static const char *call_recording_common_ng(bencode_item_t *input, bencode_item_t *output, static const char *call_recording_common_ng(ng_parser_ctx_t *ctx,
enum call_opmode opmode, enum call_opmode opmode,
void (*fn)(bencode_item_t *input, call_t *call)) void (*fn)(bencode_item_t *input, call_t *call))
{ {
g_auto(sdp_ng_flags) flags; g_auto(sdp_ng_flags) flags;
g_autoptr(call_t) call = NULL; g_autoptr(call_t) call = NULL;
bencode_item_t *input = ctx->req;
call_ng_process_flags(&flags, input, opmode); call_ng_process_flags(&flags, ctx, opmode);
if (!bencode_dictionary_get_str(input, "call-id", &flags.call_id)) if (!bencode_dictionary_get_str(input, "call-id", &flags.call_id))
return "No call-id in message"; return "No call-id in message";
@ -2850,16 +2855,16 @@ static const char *call_recording_common_ng(bencode_item_t *input, bencode_item_
static void start_recording_fn(bencode_item_t *input, call_t *call) { static void start_recording_fn(bencode_item_t *input, call_t *call) {
recording_start(call); recording_start(call);
} }
const char *call_start_recording_ng(bencode_item_t *input, bencode_item_t *output) { const char *call_start_recording_ng(ng_parser_ctx_t *ctx) {
return call_recording_common_ng(input, output, OP_START_RECORDING, start_recording_fn); return call_recording_common_ng(ctx, OP_START_RECORDING, start_recording_fn);
} }
static void pause_recording_fn(bencode_item_t *input, call_t *call) { static void pause_recording_fn(bencode_item_t *input, call_t *call) {
recording_pause(call); recording_pause(call);
} }
const char *call_pause_recording_ng(bencode_item_t *input, bencode_item_t *output) { const char *call_pause_recording_ng(ng_parser_ctx_t *ctx) {
return call_recording_common_ng(input, output, OP_PAUSE_RECORDING, pause_recording_fn); return call_recording_common_ng(ctx, OP_PAUSE_RECORDING, pause_recording_fn);
} }
@ -2889,8 +2894,8 @@ static void stop_recording_fn(bencode_item_t *input, call_t *call) {
recording_stop(call); recording_stop(call);
} }
const char *call_stop_recording_ng(bencode_item_t *input, bencode_item_t *output) { const char *call_stop_recording_ng(ng_parser_ctx_t *ctx) {
return call_recording_common_ng(input, output, OP_STOP_RECORDING, stop_recording_fn); return call_recording_common_ng(ctx, OP_STOP_RECORDING, stop_recording_fn);
} }
@ -2940,12 +2945,12 @@ found:
return NULL; return NULL;
} }
static const char *media_block_match(call_t **call, struct call_monologue **monologue, static const char *media_block_match(call_t **call, struct call_monologue **monologue,
sdp_ng_flags *flags, bencode_item_t *input, enum call_opmode opmode) sdp_ng_flags *flags, ng_parser_ctx_t *ctx, enum call_opmode opmode)
{ {
*call = NULL; *call = NULL;
*monologue = NULL; *monologue = NULL;
call_ng_process_flags(flags, input, opmode); call_ng_process_flags(flags, ctx, opmode);
if (!flags->call_id.s) if (!flags->call_id.s)
return "No call-id in message"; return "No call-id in message";
@ -2976,9 +2981,9 @@ void add_media_to_sub_list(subscription_q *q, struct call_media *media, struct c
t_queue_push_tail(q, ms); t_queue_push_tail(q, ms);
} }
static const char *media_block_match_mult(call_t **call, subscription_q *medias, static const char *media_block_match_mult(call_t **call, subscription_q *medias,
sdp_ng_flags *flags, bencode_item_t *input, enum call_opmode opmode) sdp_ng_flags *flags, ng_parser_ctx_t *ctx, enum call_opmode opmode)
{ {
call_ng_process_flags(flags, input, opmode); call_ng_process_flags(flags, ctx, opmode);
if (!flags->call_id.s) if (!flags->call_id.s)
return "No call-id in message"; return "No call-id in message";
@ -3040,13 +3045,13 @@ 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 // XXX these are all identical - unify and use a flags int and/or callback
const char *call_start_forwarding_ng(bencode_item_t *input, bencode_item_t *output) { const char *call_start_forwarding_ng(ng_parser_ctx_t *ctx) {
g_autoptr(call_t) call = NULL; g_autoptr(call_t) call = NULL;
struct call_monologue *monologue; struct call_monologue *monologue;
const char *errstr = NULL; const char *errstr = NULL;
g_auto(sdp_ng_flags) flags; g_auto(sdp_ng_flags) flags;
errstr = media_block_match(&call, &monologue, &flags, input, OP_START_FORWARDING); errstr = media_block_match(&call, &monologue, &flags, ctx, OP_START_FORWARDING);
if (errstr) if (errstr)
return errstr; return errstr;
@ -3069,13 +3074,13 @@ const char *call_start_forwarding_ng(bencode_item_t *input, bencode_item_t *outp
return NULL; return NULL;
} }
const char *call_stop_forwarding_ng(bencode_item_t *input, bencode_item_t *output) { const char *call_stop_forwarding_ng(ng_parser_ctx_t *ctx) {
g_autoptr(call_t) call = NULL; g_autoptr(call_t) call = NULL;
struct call_monologue *monologue; struct call_monologue *monologue;
const char *errstr = NULL; const char *errstr = NULL;
g_auto(sdp_ng_flags) flags; g_auto(sdp_ng_flags) flags;
errstr = media_block_match(&call, &monologue, &flags, input, OP_STOP_FORWARDING); errstr = media_block_match(&call, &monologue, &flags, ctx, OP_STOP_FORWARDING);
if (errstr) if (errstr)
return errstr; return errstr;
@ -3177,13 +3182,13 @@ static void call_set_dtmf_block(call_t *call, struct call_monologue *monologue,
} }
} }
const char *call_block_dtmf_ng(bencode_item_t *input, bencode_item_t *output) { const char *call_block_dtmf_ng(ng_parser_ctx_t *ctx) {
g_autoptr(call_t) call = NULL; g_autoptr(call_t) call = NULL;
struct call_monologue *monologue; struct call_monologue *monologue;
const char *errstr = NULL; const char *errstr = NULL;
g_auto(sdp_ng_flags) flags; g_auto(sdp_ng_flags) flags;
errstr = media_block_match(&call, &monologue, &flags, input, OP_BLOCK_DTMF); errstr = media_block_match(&call, &monologue, &flags, ctx, OP_BLOCK_DTMF);
if (errstr) if (errstr)
return errstr; return errstr;
@ -3192,13 +3197,13 @@ const char *call_block_dtmf_ng(bencode_item_t *input, bencode_item_t *output) {
return NULL; return NULL;
} }
const char *call_unblock_dtmf_ng(bencode_item_t *input, bencode_item_t *output) { const char *call_unblock_dtmf_ng(ng_parser_ctx_t *ctx) {
g_autoptr(call_t) call = NULL; g_autoptr(call_t) call = NULL;
struct call_monologue *monologue; struct call_monologue *monologue;
const char *errstr = NULL; const char *errstr = NULL;
g_auto(sdp_ng_flags) flags; g_auto(sdp_ng_flags) flags;
errstr = media_block_match(&call, &monologue, &flags, input, OP_UNBLOCK_DTMF); errstr = media_block_match(&call, &monologue, &flags, ctx, OP_UNBLOCK_DTMF);
if (errstr) if (errstr)
return errstr; return errstr;
@ -3251,7 +3256,7 @@ const char *call_unblock_dtmf_ng(bencode_item_t *input, bencode_item_t *output)
return NULL; return NULL;
} }
static const char *call_block_silence_media(bencode_item_t *input, bool on_off, const char *ucase_verb, static const char *call_block_silence_media(ng_parser_ctx_t *ctx, bool on_off, const char *ucase_verb,
const char *lcase_verb, const char *lcase_verb,
unsigned int call_flag, unsigned int ml_flag, size_t attr_offset) unsigned int call_flag, unsigned int ml_flag, size_t attr_offset)
{ {
@ -3261,7 +3266,7 @@ static const char *call_block_silence_media(bencode_item_t *input, bool on_off,
g_auto(sdp_ng_flags) flags; g_auto(sdp_ng_flags) flags;
bool found_subscriptions = false; bool found_subscriptions = false;
errstr = media_block_match(&call, &monologue, &flags, input, OP_BLOCK_SILENCE_MEDIA); errstr = media_block_match(&call, &monologue, &flags, ctx, OP_BLOCK_SILENCE_MEDIA);
if (errstr) if (errstr)
return errstr; return errstr;
@ -3410,35 +3415,35 @@ static const char *call_block_silence_media(bencode_item_t *input, bool on_off,
return NULL; return NULL;
} }
#define CALL_BLOCK_SILENCE_MEDIA(input, on_off, ucase_verb, lcase_verb, member_name, flag) \ #define CALL_BLOCK_SILENCE_MEDIA(ctx, on_off, ucase_verb, lcase_verb, member_name, flag) \
call_block_silence_media(input, on_off, ucase_verb, lcase_verb, \ call_block_silence_media(ctx, on_off, ucase_verb, lcase_verb, \
CALL_FLAG_ ## flag, \ CALL_FLAG_ ## flag, \
ML_FLAG_ ## flag, \ ML_FLAG_ ## flag, \
G_STRUCT_OFFSET(struct sink_attrs, member_name)) G_STRUCT_OFFSET(struct sink_attrs, member_name))
const char *call_block_media_ng(bencode_item_t *input, bencode_item_t *output) { const char *call_block_media_ng(ng_parser_ctx_t *ctx) {
return CALL_BLOCK_SILENCE_MEDIA(input, true, "Blocking", "blocking", block_media, BLOCK_MEDIA); return CALL_BLOCK_SILENCE_MEDIA(ctx, true, "Blocking", "blocking", block_media, BLOCK_MEDIA);
} }
const char *call_unblock_media_ng(bencode_item_t *input, bencode_item_t *output) { const char *call_unblock_media_ng(ng_parser_ctx_t *ctx) {
return CALL_BLOCK_SILENCE_MEDIA(input, false, "Unblocking", "unblocking", block_media, BLOCK_MEDIA); return CALL_BLOCK_SILENCE_MEDIA(ctx, false, "Unblocking", "unblocking", block_media, BLOCK_MEDIA);
} }
const char *call_silence_media_ng(bencode_item_t *input, bencode_item_t *output) { const char *call_silence_media_ng(ng_parser_ctx_t *ctx) {
return CALL_BLOCK_SILENCE_MEDIA(input, true, "Silencing", "silencing", silence_media, SILENCE_MEDIA); return CALL_BLOCK_SILENCE_MEDIA(ctx, true, "Silencing", "silencing", silence_media, SILENCE_MEDIA);
} }
const char *call_unsilence_media_ng(bencode_item_t *input, bencode_item_t *output) { const char *call_unsilence_media_ng(ng_parser_ctx_t *ctx) {
return CALL_BLOCK_SILENCE_MEDIA(input, false, "Unsilencing", "unsilencing", silence_media, SILENCE_MEDIA); return CALL_BLOCK_SILENCE_MEDIA(ctx, false, "Unsilencing", "unsilencing", silence_media, SILENCE_MEDIA);
} }
#ifdef WITH_TRANSCODING #ifdef WITH_TRANSCODING
static const char *play_media_select_party(call_t **call, monologues_q *monologues, static const char *play_media_select_party(call_t **call, monologues_q *monologues,
bencode_item_t *input, sdp_ng_flags *flags) ng_parser_ctx_t *ctx, sdp_ng_flags *flags)
{ {
struct call_monologue *monologue; struct call_monologue *monologue;
t_queue_init(monologues); t_queue_init(monologues);
const char *err = media_block_match(call, &monologue, flags, input, OP_PLAY_MEDIA); const char *err = media_block_match(call, &monologue, flags, ctx, OP_PLAY_MEDIA);
if (err) if (err)
return err; return err;
if (flags->all == ALL_ALL) if (flags->all == ALL_ALL)
@ -3452,14 +3457,14 @@ static const char *play_media_select_party(call_t **call, monologues_q *monologu
#endif #endif
const char *call_play_media_ng(bencode_item_t *input, bencode_item_t *output) { const char *call_play_media_ng(ng_parser_ctx_t *ctx) {
#ifdef WITH_TRANSCODING #ifdef WITH_TRANSCODING
g_autoptr(call_t) call = NULL; g_autoptr(call_t) call = NULL;
g_auto(monologues_q) monologues; g_auto(monologues_q) monologues;
const char *err = NULL; const char *err = NULL;
g_auto(sdp_ng_flags) flags; g_auto(sdp_ng_flags) flags;
err = play_media_select_party(&call, &monologues, input, &flags); err = play_media_select_party(&call, &monologues, ctx, &flags);
if (err) if (err)
return err; return err;
@ -3499,7 +3504,7 @@ const char *call_play_media_ng(bencode_item_t *input, bencode_item_t *output) {
return "No media file specified"; return "No media file specified";
if (l == monologues.head && monologue->player->coder.duration) if (l == monologues.head && monologue->player->coder.duration)
bencode_dictionary_add_integer(output, "duration", monologue->player->coder.duration); bencode_dictionary_add_integer(ctx->resp, "duration", monologue->player->coder.duration);
} }
@ -3510,7 +3515,7 @@ const char *call_play_media_ng(bencode_item_t *input, bencode_item_t *output) {
} }
const char *call_stop_media_ng(bencode_item_t *input, bencode_item_t *output) { const char *call_stop_media_ng(ng_parser_ctx_t *ctx) {
#ifdef WITH_TRANSCODING #ifdef WITH_TRANSCODING
g_autoptr(call_t) call = NULL; g_autoptr(call_t) call = NULL;
g_auto(monologues_q) monologues; g_auto(monologues_q) monologues;
@ -3518,7 +3523,7 @@ const char *call_stop_media_ng(bencode_item_t *input, bencode_item_t *output) {
long long last_frame_pos = 0; long long last_frame_pos = 0;
g_auto(sdp_ng_flags) flags; g_auto(sdp_ng_flags) flags;
err = play_media_select_party(&call, &monologues, input, &flags); err = play_media_select_party(&call, &monologues, ctx, &flags);
if (err) if (err)
return err; return err;
@ -3534,7 +3539,7 @@ const char *call_stop_media_ng(bencode_item_t *input, bencode_item_t *output) {
codec_update_all_source_handlers(monologue, NULL); codec_update_all_source_handlers(monologue, NULL);
update_init_subscribers(monologue, OP_STOP_MEDIA); update_init_subscribers(monologue, OP_STOP_MEDIA);
} }
bencode_dictionary_add_integer(output, "last-frame-pos", last_frame_pos); bencode_dictionary_add_integer(ctx->resp, "last-frame-pos", last_frame_pos);
return NULL; return NULL;
#else #else
@ -3543,14 +3548,14 @@ const char *call_stop_media_ng(bencode_item_t *input, bencode_item_t *output) {
} }
const char *call_play_dtmf_ng(bencode_item_t *input, bencode_item_t *output) { const char *call_play_dtmf_ng(ng_parser_ctx_t *ctx) {
#ifdef WITH_TRANSCODING #ifdef WITH_TRANSCODING
g_autoptr(call_t) call = NULL; g_autoptr(call_t) call = NULL;
g_auto(monologues_q) monologues; g_auto(monologues_q) monologues;
const char *err = NULL; const char *err = NULL;
g_auto(sdp_ng_flags) flags; g_auto(sdp_ng_flags) flags;
err = play_media_select_party(&call, &monologues, input, &flags); err = play_media_select_party(&call, &monologues, ctx, &flags);
if (err) if (err)
return err; return err;
@ -3645,7 +3650,7 @@ found_sink:
} }
const char *call_publish_ng(ng_buffer *ngbuf, bencode_item_t *input, bencode_item_t *output, const char *call_publish_ng(ng_parser_ctx_t *ctx,
const char *addr, const char *addr,
const endpoint_t *sin) const endpoint_t *sin)
{ {
@ -3657,7 +3662,7 @@ const char *call_publish_ng(ng_buffer *ngbuf, bencode_item_t *input, bencode_ite
g_autoptr(call_t) call = NULL; g_autoptr(call_t) call = NULL;
int ret; int ret;
call_ng_process_flags(&flags, input, OP_PUBLISH); call_ng_process_flags(&flags, ctx, OP_PUBLISH);
if ((ret = call_ng_basic_checks(&flags, OP_PUBLISH)) > 0) if ((ret = call_ng_basic_checks(&flags, OP_PUBLISH)) > 0)
return _ng_basic_errors[ret]; return _ng_basic_errors[ret];
@ -3671,7 +3676,7 @@ const char *call_publish_ng(ng_buffer *ngbuf, bencode_item_t *input, bencode_ite
call = call_get_or_create(&flags.call_id, false); call = call_get_or_create(&flags.call_id, false);
if (trickle_ice_update(ngbuf, call, &flags, &streams)) if (trickle_ice_update(ctx->ngbuf, call, &flags, &streams))
return NULL; return NULL;
updated_created_from(call, addr, sin); updated_created_from(call, addr, sin);
@ -3684,8 +3689,8 @@ const char *call_publish_ng(ng_buffer *ngbuf, bencode_item_t *input, bencode_ite
ret = sdp_create(&sdp_out, ml, &flags); ret = sdp_create(&sdp_out, ml, &flags);
if (!ret) { if (!ret) {
save_last_sdp(ml, &sdp_in, &parsed, &streams); save_last_sdp(ml, &sdp_in, &parsed, &streams);
bencode_buffer_destroy_add(output->buffer, g_free, sdp_out.s); bencode_buffer_destroy_add(ctx->resp->buffer, g_free, sdp_out.s);
bencode_dictionary_add_str(output, "sdp", &sdp_out); bencode_dictionary_add_str(ctx->resp, "sdp", &sdp_out);
sdp_out = STR_NULL; // ownership passed to output sdp_out = STR_NULL; // ownership passed to output
} }
@ -3700,16 +3705,17 @@ const char *call_publish_ng(ng_buffer *ngbuf, bencode_item_t *input, bencode_ite
} }
const char *call_subscribe_request_ng(bencode_item_t *input, bencode_item_t *output) { const char *call_subscribe_request_ng(ng_parser_ctx_t *ctx) {
const char *err = NULL; const char *err = NULL;
g_auto(sdp_ng_flags) flags; g_auto(sdp_ng_flags) flags;
char rand_buf[65]; char rand_buf[65];
g_autoptr(call_t) call = NULL; g_autoptr(call_t) call = NULL;
g_auto(subscription_q) srms = TYPED_GQUEUE_INIT; g_auto(subscription_q) srms = TYPED_GQUEUE_INIT;
g_auto(str) sdp_out = STR_NULL; g_auto(str) sdp_out = STR_NULL;
bencode_item_t *output = ctx->resp;
/* get source monologue */ /* get source monologue */
err = media_block_match_mult(&call, &srms, &flags, input, OP_REQUEST); err = media_block_match_mult(&call, &srms, &flags, ctx, OP_REQUEST);
if (err) if (err)
return err; return err;
@ -3809,13 +3815,13 @@ const char *call_subscribe_request_ng(bencode_item_t *input, bencode_item_t *out
} }
const char *call_subscribe_answer_ng(ng_buffer *ngbuf, bencode_item_t *input, bencode_item_t *output) { const char *call_subscribe_answer_ng(ng_parser_ctx_t *ctx) {
g_auto(sdp_ng_flags) flags; g_auto(sdp_ng_flags) flags;
g_auto(sdp_sessions_q) parsed = TYPED_GQUEUE_INIT; g_auto(sdp_sessions_q) parsed = TYPED_GQUEUE_INIT;
g_auto(sdp_streams_q) streams = TYPED_GQUEUE_INIT; g_auto(sdp_streams_q) streams = TYPED_GQUEUE_INIT;
g_autoptr(call_t) call = NULL; g_autoptr(call_t) call = NULL;
call_ng_process_flags(&flags, input, OP_REQ_ANSWER); call_ng_process_flags(&flags, ctx, OP_REQ_ANSWER);
if (!flags.call_id.s) if (!flags.call_id.s)
return "No call-id in message"; return "No call-id in message";
@ -3823,7 +3829,7 @@ const char *call_subscribe_answer_ng(ng_buffer *ngbuf, bencode_item_t *input, be
if (!call) if (!call)
return "Unknown call-ID"; return "Unknown call-ID";
if (trickle_ice_update(ngbuf, call, &flags, &streams)) if (trickle_ice_update(ctx->ngbuf, call, &flags, &streams))
return NULL; return NULL;
if (!flags.to_tag.s) if (!flags.to_tag.s)
@ -3851,11 +3857,11 @@ const char *call_subscribe_answer_ng(ng_buffer *ngbuf, bencode_item_t *input, be
} }
const char *call_unsubscribe_ng(bencode_item_t *input, bencode_item_t *output) { const char *call_unsubscribe_ng(ng_parser_ctx_t *ctx) {
g_auto(sdp_ng_flags) flags; g_auto(sdp_ng_flags) flags;
g_autoptr(call_t) call = NULL; g_autoptr(call_t) call = NULL;
call_ng_process_flags(&flags, input, OP_REQ_ANSWER); call_ng_process_flags(&flags, ctx, OP_REQ_ANSWER);
if (!flags.call_id.s) if (!flags.call_id.s)
return "No call-id in message"; return "No call-id in message";

@ -78,6 +78,15 @@ typedef struct ng_ctx {
func( __VA_ARGS__); \ func( __VA_ARGS__); \
} while (0) } while (0)
const ng_parser_t ng_parser_native = {
.collapse = bencode_collapse_str,
};
const ng_parser_t ng_parser_json = {
.collapse = bencode_collapse_str_json,
};
void init_ng_tracing(void) { void init_ng_tracing(void) {
if (rtpe_config.homer_ng_on && has_homer()) if (rtpe_config.homer_ng_on && has_homer())
trace_ng = true; trace_ng = true;
@ -214,7 +223,6 @@ ng_buffer *ng_buffer_new(struct obj *ref) {
static void control_ng_process_payload(ng_ctx *hctx, str *reply, str *data, const endpoint_t *sin, char *addr, struct obj *ref, static void control_ng_process_payload(ng_ctx *hctx, str *reply, str *data, const endpoint_t *sin, char *addr, struct obj *ref,
struct ng_buffer **ngbufp) struct ng_buffer **ngbufp)
{ {
bencode_item_t *dict, *resp;
str cmd = STR_NULL, callid; str cmd = STR_NULL, callid;
const char *errstr, *resultstr; const char *errstr, *resultstr;
GString *log_str; GString *log_str;
@ -222,12 +230,14 @@ 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); struct control_ng_stats* cur = get_control_ng_stats(&sin->address);
enum ng_command command = -1; enum ng_command command = -1;
struct ng_buffer *ngbuf = *ngbufp = ng_buffer_new(ref); ng_parser_ctx_t parser_ctx = {
.parser = &ng_parser_native,
};
resp = bencode_dictionary(&ngbuf->buffer); parser_ctx.ngbuf = *ngbufp = ng_buffer_new(ref);
assert(resp != NULL);
str *(*collapse_func)(bencode_item_t *root, str *out) = bencode_collapse_str; parser_ctx.resp = bencode_dictionary(&parser_ctx.ngbuf->buffer);
assert(parser_ctx.resp != NULL);
errstr = "Invalid data (no payload)"; errstr = "Invalid data (no payload)";
if (data->len <= 0) if (data->len <= 0)
@ -235,23 +245,23 @@ static void control_ng_process_payload(ng_ctx *hctx, str *reply, str *data, cons
/* Bencode dictionary */ /* Bencode dictionary */
if (data->s[0] == 'd') { if (data->s[0] == 'd') {
dict = bencode_decode_expect_str(&ngbuf->buffer, data, BENCODE_DICTIONARY); parser_ctx.req = bencode_decode_expect_str(&parser_ctx.ngbuf->buffer, data, BENCODE_DICTIONARY);
errstr = "Could not decode bencode dictionary"; errstr = "Could not decode bencode dictionary";
if (!dict) if (!parser_ctx.req)
goto err_send; goto err_send;
} }
/* JSON */ /* JSON */
else if (data->s[0] == '{') { else if (data->s[0] == '{') {
collapse_func = bencode_collapse_str_json; parser_ctx.parser = &ng_parser_json;
JsonParser *json = json_parser_new(); JsonParser *json = json_parser_new();
bencode_buffer_destroy_add(&ngbuf->buffer, g_object_unref, json); bencode_buffer_destroy_add(&parser_ctx.ngbuf->buffer, g_object_unref, json);
errstr = "Failed to parse JSON document"; errstr = "Failed to parse JSON document";
if (!json_parser_load_from_data(json, data->s, data->len, NULL)) if (!json_parser_load_from_data(json, data->s, data->len, NULL))
goto err_send; goto err_send;
dict = bencode_convert_json(&ngbuf->buffer, json); parser_ctx.req = bencode_convert_json(&parser_ctx.ngbuf->buffer, json);
errstr = "Could not decode bencode dictionary"; errstr = "Could not decode bencode dictionary";
if (!dict || dict->type != BENCODE_DICTIONARY) if (!parser_ctx.req || parser_ctx.req->type != BENCODE_DICTIONARY)
goto err_send; goto err_send;
} }
@ -260,12 +270,12 @@ static void control_ng_process_payload(ng_ctx *hctx, str *reply, str *data, cons
goto err_send; goto err_send;
} }
bencode_dictionary_get_str(dict, "command", &cmd); bencode_dictionary_get_str(parser_ctx.req, "command", &cmd);
errstr = "Dictionary contains no key \"command\""; errstr = "Dictionary contains no key \"command\"";
if (!cmd.s) if (!cmd.s)
goto err_send; goto err_send;
bencode_dictionary_get_str(dict, "call-id", &callid); bencode_dictionary_get_str(parser_ctx.req, "call-id", &callid);
log_info_str(&callid); log_info_str(&callid);
ilogs(control, LOG_INFO, "Received command '"STR_FORMAT"' from %s", STR_FMT(&cmd), addr); ilogs(control, LOG_INFO, "Received command '"STR_FORMAT"' from %s", STR_FMT(&cmd), addr);
@ -274,7 +284,7 @@ static void control_ng_process_payload(ng_ctx *hctx, str *reply, str *data, cons
log_str = g_string_sized_new(256); log_str = g_string_sized_new(256);
g_string_append_printf(log_str, "Dump for '"STR_FORMAT"' from %s: %s", STR_FMT(&cmd), addr, g_string_append_printf(log_str, "Dump for '"STR_FORMAT"' from %s: %s", STR_FMT(&cmd), addr,
rtpe_config.common.log_mark_prefix); rtpe_config.common.log_mark_prefix);
pretty_print(dict, log_str); pretty_print(parser_ctx.req, log_str);
g_string_append(log_str, rtpe_config.common.log_mark_suffix); g_string_append(log_str, rtpe_config.common.log_mark_suffix);
ilogs(control, LOG_DEBUG, "%.*s", (int) log_str->len, log_str->str); ilogs(control, LOG_DEBUG, "%.*s", (int) log_str->len, log_str->str);
g_string_free(log_str, TRUE); g_string_free(log_str, TRUE);
@ -292,99 +302,99 @@ static void control_ng_process_payload(ng_ctx *hctx, str *reply, str *data, cons
command = NGC_PING; command = NGC_PING;
break; break;
case CSH_LOOKUP("offer"): case CSH_LOOKUP("offer"):
errstr = call_offer_ng(ngbuf, dict, resp, addr, sin); errstr = call_offer_ng(&parser_ctx, addr, sin);
command = NGC_OFFER; command = NGC_OFFER;
break; break;
case CSH_LOOKUP("answer"): case CSH_LOOKUP("answer"):
errstr = call_answer_ng(ngbuf, dict, resp); errstr = call_answer_ng(&parser_ctx);
command = NGC_ANSWER; command = NGC_ANSWER;
break; break;
case CSH_LOOKUP("delete"): case CSH_LOOKUP("delete"):
errstr = call_delete_ng(dict, resp); errstr = call_delete_ng(&parser_ctx);
command = NGC_DELETE; command = NGC_DELETE;
break; break;
case CSH_LOOKUP("query"): case CSH_LOOKUP("query"):
errstr = call_query_ng(dict, resp); errstr = call_query_ng(&parser_ctx);
command = NGC_QUERY; command = NGC_QUERY;
break; break;
case CSH_LOOKUP("list"): case CSH_LOOKUP("list"):
errstr = call_list_ng(dict, resp); errstr = call_list_ng(&parser_ctx);
command = NGC_LIST; command = NGC_LIST;
break; break;
case CSH_LOOKUP("start recording"): case CSH_LOOKUP("start recording"):
errstr = call_start_recording_ng(dict, resp); errstr = call_start_recording_ng(&parser_ctx);
command = NGC_START_RECORDING; command = NGC_START_RECORDING;
break; break;
case CSH_LOOKUP("stop recording"): case CSH_LOOKUP("stop recording"):
errstr = call_stop_recording_ng(dict, resp); errstr = call_stop_recording_ng(&parser_ctx);
command = NGC_STOP_RECORDING; command = NGC_STOP_RECORDING;
break; break;
case CSH_LOOKUP("pause recording"): case CSH_LOOKUP("pause recording"):
errstr = call_pause_recording_ng(dict, resp); errstr = call_pause_recording_ng(&parser_ctx);
command = NGC_PAUSE_RECORDING; command = NGC_PAUSE_RECORDING;
break; break;
case CSH_LOOKUP("start forwarding"): case CSH_LOOKUP("start forwarding"):
errstr = call_start_forwarding_ng(dict, resp); errstr = call_start_forwarding_ng(&parser_ctx);
command = NGC_START_FORWARDING; command = NGC_START_FORWARDING;
break; break;
case CSH_LOOKUP("stop forwarding"): case CSH_LOOKUP("stop forwarding"):
errstr = call_stop_forwarding_ng(dict, resp); errstr = call_stop_forwarding_ng(&parser_ctx);
command = NGC_STOP_FORWARDING; command = NGC_STOP_FORWARDING;
break; break;
case CSH_LOOKUP("block DTMF"): case CSH_LOOKUP("block DTMF"):
errstr = call_block_dtmf_ng(dict, resp); errstr = call_block_dtmf_ng(&parser_ctx);
command = NGC_BLOCK_DTMF; command = NGC_BLOCK_DTMF;
break; break;
case CSH_LOOKUP("unblock DTMF"): case CSH_LOOKUP("unblock DTMF"):
errstr = call_unblock_dtmf_ng(dict, resp); errstr = call_unblock_dtmf_ng(&parser_ctx);
command = NGC_UNBLOCK_DTMF; command = NGC_UNBLOCK_DTMF;
break; break;
case CSH_LOOKUP("block media"): case CSH_LOOKUP("block media"):
errstr = call_block_media_ng(dict, resp); errstr = call_block_media_ng(&parser_ctx);
command = NGC_BLOCK_MEDIA; command = NGC_BLOCK_MEDIA;
break; break;
case CSH_LOOKUP("unblock media"): case CSH_LOOKUP("unblock media"):
errstr = call_unblock_media_ng(dict, resp); errstr = call_unblock_media_ng(&parser_ctx);
command = NGC_UNBLOCK_MEDIA; command = NGC_UNBLOCK_MEDIA;
break; break;
case CSH_LOOKUP("silence media"): case CSH_LOOKUP("silence media"):
errstr = call_silence_media_ng(dict, resp); errstr = call_silence_media_ng(&parser_ctx);
command = NGC_SILENCE_MEDIA; command = NGC_SILENCE_MEDIA;
break; break;
case CSH_LOOKUP("unsilence media"): case CSH_LOOKUP("unsilence media"):
errstr = call_unsilence_media_ng(dict, resp); errstr = call_unsilence_media_ng(&parser_ctx);
command = NGC_UNSILENCE_MEDIA; command = NGC_UNSILENCE_MEDIA;
break; break;
case CSH_LOOKUP("play media"): case CSH_LOOKUP("play media"):
errstr = call_play_media_ng(dict, resp); errstr = call_play_media_ng(&parser_ctx);
command = NGC_PLAY_MEDIA; command = NGC_PLAY_MEDIA;
break; break;
case CSH_LOOKUP("stop media"): case CSH_LOOKUP("stop media"):
errstr = call_stop_media_ng(dict, resp); errstr = call_stop_media_ng(&parser_ctx);
command = NGC_STOP_MEDIA; command = NGC_STOP_MEDIA;
break; break;
case CSH_LOOKUP("play DTMF"): case CSH_LOOKUP("play DTMF"):
errstr = call_play_dtmf_ng(dict, resp); errstr = call_play_dtmf_ng(&parser_ctx);
command = NGC_PLAY_DTMF; command = NGC_PLAY_DTMF;
break; break;
case CSH_LOOKUP("statistics"): case CSH_LOOKUP("statistics"):
errstr = statistics_ng(dict, resp); errstr = statistics_ng(&parser_ctx);
command = NGC_STATISTICS; command = NGC_STATISTICS;
break; break;
case CSH_LOOKUP("publish"): case CSH_LOOKUP("publish"):
errstr = call_publish_ng(ngbuf, dict, resp, addr, sin); errstr = call_publish_ng(&parser_ctx, addr, sin);
command = NGC_PUBLISH; command = NGC_PUBLISH;
break; break;
case CSH_LOOKUP("subscribe request"): case CSH_LOOKUP("subscribe request"):
errstr = call_subscribe_request_ng(dict, resp); errstr = call_subscribe_request_ng(&parser_ctx);
command = NGC_SUBSCRIBE_REQ; command = NGC_SUBSCRIBE_REQ;
break; break;
case CSH_LOOKUP("subscribe answer"): case CSH_LOOKUP("subscribe answer"):
errstr = call_subscribe_answer_ng(ngbuf, dict, resp); errstr = call_subscribe_answer_ng(&parser_ctx);
command = NGC_SUBSCRIBE_ANS; command = NGC_SUBSCRIBE_ANS;
break; break;
case CSH_LOOKUP("unsubscribe"): case CSH_LOOKUP("unsubscribe"):
errstr = call_unsubscribe_ng(dict, resp); errstr = call_unsubscribe_ng(&parser_ctx);
command = NGC_UNSUBSCRIBE; command = NGC_UNSUBSCRIBE;
break; break;
default: default:
@ -409,7 +419,7 @@ static void control_ng_process_payload(ng_ctx *hctx, str *reply, str *data, cons
if (errstr) if (errstr)
goto err_send; goto err_send;
bencode_dictionary_add_string(resp, "result", resultstr); bencode_dictionary_add_string(parser_ctx.resp, "result", resultstr);
// update interval statistics // update interval statistics
RTPE_STATS_INC(ng_commands[command]); RTPE_STATS_INC(ng_commands[command]);
@ -422,30 +432,31 @@ err_send:
if (errstr < magic_load_limit_strings[0] || errstr > magic_load_limit_strings[__LOAD_LIMIT_MAX-1]) { 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 "]", ilogs(control, LOG_WARNING, "Protocol error in packet from %s: %s [" STR_FORMAT_M "]",
addr, errstr, STR_FMT_M(data)); addr, errstr, STR_FMT_M(data));
bencode_dictionary_add_string(resp, "result", "error"); bencode_dictionary_add_string(parser_ctx.resp, "result", "error");
bencode_dictionary_add_string(resp, "error-reason", errstr); bencode_dictionary_add_string(parser_ctx.resp, "error-reason", errstr);
g_atomic_int_inc(&cur->errors); g_atomic_int_inc(&cur->errors);
cmd = STR_NULL; cmd = STR_NULL;
} }
else { else {
bencode_dictionary_add_string(resp, "result", "load limit"); bencode_dictionary_add_string(parser_ctx.resp, "result", "load limit");
bencode_dictionary_add_string(resp, "message", errstr); bencode_dictionary_add_string(parser_ctx.resp, "message", errstr);
} }
send_resp: send_resp:
collapse_func(resp, reply); parser_ctx.parser->collapse(parser_ctx.resp, reply);
if (cmd.s) { 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); 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) { if (get_log_level(control) >= LOG_DEBUG) {
dict = bencode_decode_expect_str(&ngbuf->buffer, reply, BENCODE_DICTIONARY); parser_ctx.req = bencode_decode_expect_str(&parser_ctx.ngbuf->buffer,
if (dict) { reply, BENCODE_DICTIONARY);
if (parser_ctx.req) {
log_str = g_string_sized_new(256); log_str = g_string_sized_new(256);
g_string_append_printf(log_str, "Response dump for '"STR_FORMAT"' to %s: %s", g_string_append_printf(log_str, "Response dump for '"STR_FORMAT"' to %s: %s",
STR_FMT(&cmd), addr, STR_FMT(&cmd), addr,
rtpe_config.common.log_mark_prefix); rtpe_config.common.log_mark_prefix);
pretty_print(dict, log_str); pretty_print(parser_ctx.req, log_str);
g_string_append(log_str, rtpe_config.common.log_mark_suffix); g_string_append(log_str, rtpe_config.common.log_mark_suffix);
ilogs(control, LOG_DEBUG, "%.*s", (int) log_str->len, log_str->str); ilogs(control, LOG_DEBUG, "%.*s", (int) log_str->len, log_str->str);
g_string_free(log_str, TRUE); g_string_free(log_str, TRUE);

@ -102,7 +102,7 @@ static bool str_key_val_prefix(const str * p, const char * q,
/* parse `received-from` */ /* parse `received-from` */
static bool parse_received_from(str * key, str * val, bencode_buffer_t * buf, static bool parse_received_from(str * key, str * val, bencode_buffer_t * buf,
sdp_ng_flags * out, enum call_opmode opmode) ng_parser_ctx_t *ctx)
{ {
bencode_item_t * item; bencode_item_t * item;
int ip_af = AF_UNSPEC; int ip_af = AF_UNSPEC;
@ -117,15 +117,14 @@ static bool parse_received_from(str * key, str * val, bencode_buffer_t * buf,
bencode_list_add_str(item, &ipfamily); bencode_list_add_str(item, &ipfamily);
bencode_list_add_str(item, &s); bencode_list_add_str(item, &s);
call_ng_main_flags(out, &STR_CONST("received-from"), item, opmode); call_ng_main_flags(ctx, &STR_CONST("received-from"), item);
return true; return true;
} }
return false; return false;
} }
static bool parse_codec_to_dict(str * key, str * val, const char *cmp1, const char *cmp2, static bool parse_codec_to_dict(str * key, str * val, const char *cmp1, const char *cmp2,
const char * dictstr, sdp_ng_flags * out, bencode_buffer_t * buf, const char * dictstr, ng_parser_ctx_t *ctx, bencode_buffer_t * buf)
enum call_opmode opmode)
{ {
str s; str s;
@ -136,29 +135,29 @@ static bool parse_codec_to_dict(str * key, str * val, const char *cmp1, const ch
return false; return false;
} }
call_ng_codec_flags(out, &STR(dictstr), bencode_str(buf, &s), opmode); call_ng_codec_flags(ctx, &STR(dictstr), bencode_str(buf, &s));
return true; return true;
} }
/* parse codec related flags */ /* parse codec related flags */
static bool parse_codecs(enum call_opmode opmode, sdp_ng_flags * out, static bool parse_codecs(ng_parser_ctx_t *ctx,
bencode_buffer_t * buf, str * key, str * val) bencode_buffer_t * buf, str * key, str * val)
{ {
if (parse_codec_to_dict(key, val, "transcode", if (parse_codec_to_dict(key, val, "transcode",
"codec-transcode", "transcode", out, buf, opmode) || "codec-transcode", "transcode", ctx, buf) ||
parse_codec_to_dict(key, val, "codec-strip", parse_codec_to_dict(key, val, "codec-strip",
NULL, "strip", out, buf, opmode) || NULL, "strip", ctx, buf) ||
parse_codec_to_dict(key, val, "codec-offer", parse_codec_to_dict(key, val, "codec-offer",
NULL, "offer", out, buf, opmode) || NULL, "offer", ctx, buf) ||
parse_codec_to_dict(key, val, "codec-mask", parse_codec_to_dict(key, val, "codec-mask",
NULL, "mask", out, buf, opmode) || NULL, "mask", ctx, buf) ||
parse_codec_to_dict(key, val, "codec-set", parse_codec_to_dict(key, val, "codec-set",
NULL, "set", out, buf, opmode) || NULL, "set", ctx, buf) ||
parse_codec_to_dict(key, val, "codec-accept", parse_codec_to_dict(key, val, "codec-accept",
NULL, "accept", out, buf, opmode) || NULL, "accept", ctx, buf) ||
parse_codec_to_dict(key, val, "codec-except", parse_codec_to_dict(key, val, "codec-except",
NULL, "except", out, buf, opmode)) NULL, "except", ctx, buf))
{ {
return true; return true;
} }
@ -167,13 +166,13 @@ static bool parse_codecs(enum call_opmode opmode, sdp_ng_flags * out,
} }
/* prase transport, such as for example RTP/AVP */ /* prase transport, such as for example RTP/AVP */
static void parse_transports(sdp_ng_flags *out, bencode_buffer_t *buf, static void parse_transports(ng_parser_ctx_t *ctx, bencode_buffer_t *buf,
enum call_opmode opmode, unsigned int transport) unsigned int transport)
{ {
const char * val = transports[transport & 0x007]; const char * val = transports[transport & 0x007];
if (!val) if (!val)
return; return;
call_ng_main_flags(out, &STR_CONST("transport-protocol"), bencode_string(buf, val), opmode); call_ng_main_flags(ctx, &STR_CONST("transport-protocol"), bencode_string(buf, val));
} }
#if 0 #if 0
@ -197,12 +196,12 @@ static bool parse_str_flag(str * key, str * val, const char * name,
* @param rtpp_flags - raw str rtpp_flags * @param rtpp_flags - raw str rtpp_flags
* @param dict - root dict to store encoded flags * @param dict - root dict to store encoded flags
*/ */
void parse_rtpp_flags(const str * rtpp_flags, bencode_buffer_t * buf, void parse_rtpp_flags(const str * rtpp_flags, ng_parser_ctx_t *ctx)
enum call_opmode opmode, sdp_ng_flags * out)
{ {
str remainder, key, val; str remainder, key, val;
bencode_item_t * direction; bencode_item_t * direction;
unsigned int transport = 0; unsigned int transport = 0;
bencode_buffer_t *buf = &ctx->ngbuf->buffer;
if (!rtpp_flags->s) if (!rtpp_flags->s)
return; return;
@ -222,11 +221,11 @@ void parse_rtpp_flags(const str * rtpp_flags, bencode_buffer_t * buf,
break; break;
/* specific received-from parsing */ /* specific received-from parsing */
if (parse_received_from(&key, &val, buf, out, opmode)) if (parse_received_from(&key, &val, buf, ctx))
goto next; goto next;
/* codecs have own specific parsing as well */ /* codecs have own specific parsing as well */
if (parse_codecs(opmode, out, buf, &key, &val)) if (parse_codecs(ctx, buf, &key, &val))
goto next; goto next;
/* parse other generic flags */ /* parse other generic flags */
@ -273,7 +272,7 @@ void parse_rtpp_flags(const str * rtpp_flags, bencode_buffer_t * buf,
transport = 0x101; transport = 0x101;
/* from-tag can be overriden, but originally has to be provided */ /* from-tag can be overriden, but originally has to be provided */
else if (val.s && str_eq(&key, "from-tag")) { else if (val.s && str_eq(&key, "from-tag")) {
out->directional = 1; /* explicitly add directional for this case */ ctx->flags->directional = 1; /* explicitly add directional for this case */
goto generic; goto generic;
} }
/* direction */ /* direction */
@ -316,19 +315,19 @@ void parse_rtpp_flags(const str * rtpp_flags, bencode_buffer_t * buf,
generic: generic:
/* generic one key flags */ /* generic one key flags */
if (!val.s) if (!val.s)
call_ng_flags_flags(out, &key, NULL); call_ng_flags_flags(ctx->flags, &key, NULL);
/* generic flags with value, but no particular processing */ /* generic flags with value, but no particular processing */
else else
call_ng_main_flags(out, &key, bencode_str(buf, &val), opmode); call_ng_main_flags(ctx, &key, bencode_str(buf, &val));
next:; next:;
} }
/* define transport */ /* define transport */
if (transport) if (transport)
parse_transports(out, buf, opmode, transport); parse_transports(ctx, buf, transport);
/* add directions to the root dict */ /* add directions to the root dict */
if (direction && direction->child) if (direction && direction->child)
call_ng_direction_flag(out, direction); call_ng_direction_flag(ctx->flags, direction);
} }

@ -952,13 +952,13 @@ void statistics_init(void) {
rtpe_codec_stats = codec_stats_ht_new(); rtpe_codec_stats = codec_stats_ht_new();
} }
const char *statistics_ng(bencode_item_t *input, bencode_item_t *output) { const char *statistics_ng(ng_parser_ctx_t *ctx) {
g_autoptr(stats_metric_q) metrics = statistics_gather_metrics(NULL); g_autoptr(stats_metric_q) metrics = statistics_gather_metrics(NULL);
g_auto(GQueue) bstack = G_QUEUE_INIT; g_auto(GQueue) bstack = G_QUEUE_INIT;
bencode_item_t *dict = output; bencode_item_t *dict = ctx->resp;
const char *sub_label = "statistics"; // top level const char *sub_label = "statistics"; // top level
bencode_buffer_t *buf = output->buffer; bencode_buffer_t *buf = &ctx->ngbuf->buffer;
for (__auto_type l = metrics->head; l; l = l->next) { for (__auto_type l = metrics->head; l; l = l->next) {
stats_metric *m = l->data; stats_metric *m = l->data;

@ -59,39 +59,6 @@ enum message_type {
SIP_REPLY, SIP_REPLY,
}; };
enum call_opmode {
OP_OFFER = 0,
OP_ANSWER = 1,
OP_REQUEST,
OP_REQ_ANSWER,
OP_PUBLISH,
OP_DELETE,
OP_QUERY,
OP_LIST,
OP_PING,
OP_STATISTICS,
OP_PLAY_DTMF,
OP_BLOCK_DTMF,
OP_UNBLOCK_DTMF,
OP_BLOCK_MEDIA,
OP_UNBLOCK_MEDIA,
OP_SILENCE_MEDIA,
OP_UNSILENCE_MEDIA,
OP_BLOCK_SILENCE_MEDIA,
OP_UNBLOCK_SILENCE_MEDIA,
OP_PLAY_MEDIA,
OP_STOP_MEDIA,
OP_START_FORWARDING,
OP_STOP_FORWARDING,
OP_SUBSCRIBER_REQ,
OP_SUBSCRIBER_ANS,
OP_UNSUBSCRIBE,
OP_START_RECORDING,
OP_STOP_RECORDING,
OP_PAUSE_RECORDING,
OP_OTHER,
};
#define IS_OP_OTHER(opmode) \ #define IS_OP_OTHER(opmode) \
((opmode == OP_DELETE || opmode == OP_QUERY) \ ((opmode == OP_DELETE || opmode == OP_QUERY) \
|| (opmode == OP_LIST || opmode == OP_PING) \ || (opmode == OP_LIST || opmode == OP_PING) \

@ -251,33 +251,33 @@ str *call_lookup_udp(char **);
str *call_delete_udp(char **); str *call_delete_udp(char **);
str *call_query_udp(char **); str *call_query_udp(char **);
const char *call_offer_ng(ng_buffer *, bencode_item_t *, bencode_item_t *, const char*, const char *call_offer_ng(ng_parser_ctx_t *, const char*,
const endpoint_t *); const endpoint_t *);
const char *call_answer_ng(ng_buffer *, bencode_item_t *, bencode_item_t *); const char *call_answer_ng(ng_parser_ctx_t *);
const char *call_delete_ng(bencode_item_t *, bencode_item_t *); const char *call_delete_ng(ng_parser_ctx_t *);
const char *call_query_ng(bencode_item_t *, bencode_item_t *); const char *call_query_ng(ng_parser_ctx_t *);
const char *call_list_ng(bencode_item_t *, bencode_item_t *); const char *call_list_ng(ng_parser_ctx_t *);
const char *call_start_recording_ng(bencode_item_t *, bencode_item_t *); const char *call_start_recording_ng(ng_parser_ctx_t *);
const char *call_stop_recording_ng(bencode_item_t *, bencode_item_t *); const char *call_stop_recording_ng(ng_parser_ctx_t *);
const char *call_pause_recording_ng(bencode_item_t *, bencode_item_t *); const char *call_pause_recording_ng(ng_parser_ctx_t *);
const char *call_start_forwarding_ng(bencode_item_t *, bencode_item_t *); const char *call_start_forwarding_ng(ng_parser_ctx_t *);
const char *call_stop_forwarding_ng(bencode_item_t *, bencode_item_t *); const char *call_stop_forwarding_ng(ng_parser_ctx_t *);
const char *call_block_dtmf_ng(bencode_item_t *, bencode_item_t *); const char *call_block_dtmf_ng(ng_parser_ctx_t *);
const char *call_unblock_dtmf_ng(bencode_item_t *, bencode_item_t *); const char *call_unblock_dtmf_ng(ng_parser_ctx_t *);
const char *call_block_media_ng(bencode_item_t *, bencode_item_t *); const char *call_block_media_ng(ng_parser_ctx_t *);
const char *call_unblock_media_ng(bencode_item_t *, bencode_item_t *); const char *call_unblock_media_ng(ng_parser_ctx_t *);
const char *call_silence_media_ng(bencode_item_t *, bencode_item_t *); const char *call_silence_media_ng(ng_parser_ctx_t *);
const char *call_unsilence_media_ng(bencode_item_t *, bencode_item_t *); const char *call_unsilence_media_ng(ng_parser_ctx_t *);
const char *call_play_media_ng(bencode_item_t *, bencode_item_t *); const char *call_play_media_ng(ng_parser_ctx_t *);
const char *call_stop_media_ng(bencode_item_t *, bencode_item_t *); const char *call_stop_media_ng(ng_parser_ctx_t *);
const char *call_play_dtmf_ng(bencode_item_t *, bencode_item_t *); const char *call_play_dtmf_ng(ng_parser_ctx_t *);
void ng_call_stats(call_t *call, const str *fromtag, const str *totag, bencode_item_t *output, void ng_call_stats(call_t *call, const str *fromtag, const str *totag, bencode_item_t *output,
struct call_stats *totals); struct call_stats *totals);
const char *call_publish_ng(ng_buffer *, bencode_item_t *, bencode_item_t *, const char *, const char *call_publish_ng(ng_parser_ctx_t *, const char *,
const endpoint_t *); const endpoint_t *);
const char *call_subscribe_request_ng(bencode_item_t *, bencode_item_t *); const char *call_subscribe_request_ng(ng_parser_ctx_t *);
const char *call_subscribe_answer_ng(ng_buffer *, bencode_item_t *, bencode_item_t *); const char *call_subscribe_answer_ng(ng_parser_ctx_t *);
const char *call_unsubscribe_ng(bencode_item_t *, bencode_item_t *); const char *call_unsubscribe_ng(ng_parser_ctx_t *);
void add_media_to_sub_list(subscription_q *q, struct call_media *media, struct call_monologue *ml); void add_media_to_sub_list(subscription_q *q, struct call_media *media, struct call_monologue *ml);
@ -294,10 +294,8 @@ void call_interfaces_free(void);
void call_interfaces_timer(void); void call_interfaces_timer(void);
void call_ng_flags_flags(sdp_ng_flags *out, str *s, helper_arg dummy); void call_ng_flags_flags(sdp_ng_flags *out, str *s, helper_arg dummy);
void call_ng_main_flags(sdp_ng_flags *out, str *key, bencode_item_t *value, void call_ng_main_flags(ng_parser_ctx_t *, str *key, bencode_item_t *value);
enum call_opmode opmode); void call_ng_codec_flags(ng_parser_ctx_t *, str *key, bencode_item_t *value);
void call_ng_codec_flags(sdp_ng_flags *out, str *key, bencode_item_t *value,
enum call_opmode opmode);
void call_ng_direction_flag(sdp_ng_flags *out, bencode_item_t *value); void call_ng_direction_flag(sdp_ng_flags *out, bencode_item_t *value);
INLINE struct sdp_manipulations *sdp_manipulations_get_by_id(const sdp_ng_flags *f, enum media_type id) { INLINE struct sdp_manipulations *sdp_manipulations_get_by_id(const sdp_ng_flags *f, enum media_type id) {

@ -63,6 +63,57 @@ struct ng_buffer {
struct obj *ref; struct obj *ref;
}; };
enum call_opmode {
OP_OFFER = 0,
OP_ANSWER = 1,
OP_REQUEST,
OP_REQ_ANSWER,
OP_PUBLISH,
OP_DELETE,
OP_QUERY,
OP_LIST,
OP_PING,
OP_STATISTICS,
OP_PLAY_DTMF,
OP_BLOCK_DTMF,
OP_UNBLOCK_DTMF,
OP_BLOCK_MEDIA,
OP_UNBLOCK_MEDIA,
OP_SILENCE_MEDIA,
OP_UNSILENCE_MEDIA,
OP_BLOCK_SILENCE_MEDIA,
OP_UNBLOCK_SILENCE_MEDIA,
OP_PLAY_MEDIA,
OP_STOP_MEDIA,
OP_START_FORWARDING,
OP_STOP_FORWARDING,
OP_SUBSCRIBER_REQ,
OP_SUBSCRIBER_ANS,
OP_UNSUBSCRIBE,
OP_START_RECORDING,
OP_STOP_RECORDING,
OP_PAUSE_RECORDING,
OP_OTHER,
};
struct ng_parser {
str *(*collapse)(bencode_item_t *root, str *out);
};
struct ng_parser_ctx {
const ng_parser_t *parser;
struct ng_buffer *ngbuf;
bencode_item_t *req;
bencode_item_t *resp;
sdp_ng_flags *flags;
enum call_opmode opmode;
};
extern const ng_parser_t ng_parser_native;
extern const ng_parser_t ng_parser_json;
extern const char *ng_command_strings[NGC_COUNT]; extern const char *ng_command_strings[NGC_COUNT];
extern const char *ng_command_strings_esc[NGC_COUNT]; extern const char *ng_command_strings_esc[NGC_COUNT];
extern const char *ng_command_strings_short[NGC_COUNT]; extern const char *ng_command_strings_short[NGC_COUNT];

@ -14,7 +14,6 @@
* Syntax: * Syntax:
* rtpp_flags: flag1=<value>, flag2-<value> ... * rtpp_flags: flag1=<value>, flag2-<value> ...
*/ */
void parse_rtpp_flags(const str * rtpp_flags, bencode_buffer_t * buf, void parse_rtpp_flags(const str * rtpp_flags, ng_parser_ctx_t *);
enum call_opmode opmode, sdp_ng_flags * out);
#endif #endif

@ -173,7 +173,7 @@ void statistics_update_foreignown_inc(call_t * c);
stats_metric_q *statistics_gather_metrics(struct interface_sampled_rate_stats *); stats_metric_q *statistics_gather_metrics(struct interface_sampled_rate_stats *);
void statistics_free_metrics(stats_metric_q *); void statistics_free_metrics(stats_metric_q *);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(stats_metric_q, statistics_free_metrics) G_DEFINE_AUTOPTR_CLEANUP_FUNC(stats_metric_q, statistics_free_metrics)
const char *statistics_ng(bencode_item_t *input, bencode_item_t *output); const char *statistics_ng(ng_parser_ctx_t *);
enum thread_looper_action call_rate_stats_updater(void); enum thread_looper_action call_rate_stats_updater(void);
/** /**

@ -36,6 +36,9 @@ union sdp_attr_print_arg {
} __attribute__ ((__transparent_union__)); } __attribute__ ((__transparent_union__));
typedef void sdp_attr_print_f(GString *, union sdp_attr_print_arg, const sdp_ng_flags *flags); typedef void sdp_attr_print_f(GString *, union sdp_attr_print_arg, const sdp_ng_flags *flags);
typedef struct ng_parser ng_parser_t;
typedef struct ng_parser_ctx ng_parser_ctx_t;
#include "containers.h" #include "containers.h"
struct sdp_session; struct sdp_session;

Loading…
Cancel
Save