diff --git a/README.md b/README.md index 9c5b37cd9..f6a4e9762 100644 --- a/README.md +++ b/README.md @@ -1100,6 +1100,10 @@ Optionally included keys are: Additional options that can be appended to the codec string with additional slashes are ptime and the `fmtp` string, for example `iLBC/8000/1///mode=30`. + If a literal `=` cannot be used due to parsing constraints (i.e. being wrongly + interpreted as a key-value pair), it can be escaped by using two dashes instead, + e.g. `iLBC/8000/1///mode--30`. + As a special case, if the `strip=all` option has been used and the `transcode` option is used on a codec that was originally present in the offer, then *rtpengine* will treat this codec the same as if it had been used with the `offer` diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index 242b4ee0b..bd45429b7 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -704,25 +704,35 @@ static void call_ng_flags_supports(struct sdp_ng_flags *out, str *s, void *dummy if (!str_cmp(s, "load limit")) out->supports_load_limit = 1; } +static str *str_dup_escape(const str *s) { + str *ret = str_dup(s); + int i; + while ((i = str_str(ret, "--")) >= 0) { + ret->s[i] = '='; + memmove(&ret->s[i + 1], &ret->s[i + 2], ret->len - i - 2); + ret->len--; + } + return ret; +} static void call_ng_flags_codec_list(struct sdp_ng_flags *out, str *s, void *qp) { - str *s_copy = str_slice_dup(s); + str *s_copy = str_dup_escape(s); g_queue_push_tail((GQueue *) qp, s_copy); } static void call_ng_flags_str_ht(struct sdp_ng_flags *out, str *s, void *htp) { - str *s_copy = str_slice_dup(s); + str *s_copy = str_dup_escape(s); GHashTable **ht = htp; if (!*ht) - *ht = g_hash_table_new_full(str_case_hash, str_case_equal, str_slice_free, NULL); + *ht = g_hash_table_new_full(str_case_hash, str_case_equal, free, NULL); g_hash_table_replace(*ht, s_copy, s_copy); } #ifdef WITH_TRANSCODING static void call_ng_flags_str_ht_split(struct sdp_ng_flags *out, str *s, void *htp) { GHashTable **ht = htp; if (!*ht) - *ht = g_hash_table_new_full(str_case_hash, str_case_equal, str_slice_free, str_slice_free); + *ht = g_hash_table_new_full(str_case_hash, str_case_equal, free, free); str splitter = *s; while (1) { - g_hash_table_replace(*ht, str_slice_dup(&splitter), str_slice_dup(s)); + g_hash_table_replace(*ht, str_dup_escape(&splitter), str_dup_escape(s)); char *c = memrchr(splitter.s, '/', splitter.len); if (!c) break; @@ -1009,8 +1019,8 @@ static void call_ng_free_flags(struct sdp_ng_flags *flags) { g_hash_table_destroy(flags->codec_set); if (flags->sdes_no) g_hash_table_destroy(flags->sdes_no); - g_queue_clear_full(&flags->codec_offer, str_slice_free); - g_queue_clear_full(&flags->codec_transcode, str_slice_free); + g_queue_clear_full(&flags->codec_offer, free); + g_queue_clear_full(&flags->codec_transcode, free); } static enum load_limit_reasons call_offer_session_limit(void) { diff --git a/daemon/codec.c b/daemon/codec.c index fef965222..db1eff722 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -2129,7 +2129,6 @@ static int __codec_synth_transcode_options(struct rtp_payload_type *pt, struct s if (pt->clock_rate != 1) return 0; - struct call *call = media->call; GHashTable *clockrates = g_hash_table_new(g_direct_hash, g_direct_equal); // special handling - add one instance for each clock rate that is present @@ -2137,17 +2136,13 @@ static int __codec_synth_transcode_options(struct rtp_payload_type *pt, struct s struct rtp_payload_type *pt_r = k->data; if (g_hash_table_lookup(clockrates, GUINT_TO_POINTER(pt_r->clock_rate))) continue; - char *pt_s; - if (asprintf(&pt_s, STR_FORMAT "/%u", STR_FMT(&pt->encoding), pt_r->clock_rate) < 0) - continue; - pt_s = call_strdup(call, pt_s); - // XXX optimise this -^ call buffer can probably be replaced with a gstringchunk - // and made lock free + char *pt_s = g_strdup_printf(STR_FORMAT "/%u", STR_FMT(&pt->encoding), pt_r->clock_rate); g_hash_table_insert(clockrates, GUINT_TO_POINTER(pt_r->clock_rate), (void *) 1); str pt_str; str_init(&pt_str, pt_s); ilog(LOG_DEBUG, "Synthesised transcoding option for '%s'", pt_s); - g_queue_push_tail(&flags->codec_transcode, str_slice_dup(&pt_str)); + g_queue_push_tail(&flags->codec_transcode, str_dup(&pt_str)); + g_free(pt_s); } payload_type_free(pt);