diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index 328c4d8ac..808c2a04f 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -935,6 +935,39 @@ static void call_ng_flags_str_ht_split(struct sdp_ng_flags *out, str *s, void *h } } #endif + +struct sdp_attr_helper { + void (*fn)(struct sdp_ng_flags *out, str *s, void *); + size_t offset; +}; + +static const struct sdp_attr_helper sdp_attr_helper_add = { + .fn = call_ng_flags_esc_str_list, + .offset = G_STRUCT_OFFSET(struct sdp_manipulations, add_commands), +}; +static const struct sdp_attr_helper sdp_attr_helper_remove = { + .fn = call_ng_flags_str_ht, + .offset = G_STRUCT_OFFSET(struct sdp_manipulations, rem_commands), +}; +static const struct sdp_attr_helper sdp_attr_helper_substitute = { + .fn = call_ng_flags_str_pair_ht, + .offset = G_STRUCT_OFFSET(struct sdp_manipulations, subst_commands), +}; + +static void call_ng_flags_sdp_attr_helper(struct sdp_ng_flags *out, str *s, void *helper) { + // get media type + str token; + if (str_token(&token, s, '-')) + return; + struct sdp_manipulations *sm = sdp_manipulations_get_by_name(out, &token); + if (!sm) { + ilog(LOG_WARN, "SDP manipulations: unsupported SDP section '" STR_FORMAT "' targeted.", + STR_FMT(&token)); + } + struct sdp_attr_helper *h = helper; + h->fn(out, s, &G_STRUCT_MEMBER(void *, sm, h->offset)); +} + // helper to alias values from other dictionaries into the "flags" dictionary INLINE int call_ng_flags_prefix(struct sdp_ng_flags *out, str *s_ori, const char *prefix, void (*cb)(struct sdp_ng_flags *, str *, void *), void *ptr) @@ -1146,6 +1179,12 @@ static void call_ng_flags_flags(struct sdp_ng_flags *out, str *s, void *dummy) { return; if (call_ng_flags_prefix(out, s, "replace-", call_ng_flags_replace, NULL)) return; + if (call_ng_flags_prefix(out, s, "sdp-attr-add-", call_ng_flags_sdp_attr_helper, (void *) &sdp_attr_helper_add)) + return; + if (call_ng_flags_prefix(out, s, "sdp-attr-remove-", call_ng_flags_sdp_attr_helper, (void *) &sdp_attr_helper_remove)) + return; + if (call_ng_flags_prefix(out, s, "sdp-attr-substitute-", call_ng_flags_sdp_attr_helper, (void *) &sdp_attr_helper_substitute)) + return; #ifdef WITH_TRANSCODING if (out->opmode == OP_OFFER || out->opmode == OP_REQUEST || out->opmode == OP_PUBLISH) { if (call_ng_flags_prefix(out, s, "transcode-", call_ng_flags_esc_str_list, diff --git a/docs/ng_control_protocol.md b/docs/ng_control_protocol.md index 016f0048b..936ec0a80 100644 --- a/docs/ng_control_protocol.md +++ b/docs/ng_control_protocol.md @@ -1372,6 +1372,8 @@ Examples: }, } +* As an alternative syntax these can be listed in the `flags` list, using a syntax of e.g. `sdp-attr-remove-audio-ssrc:` or `sdp-attr-substitude-none-sendrecv>sendonly`. Equals signs (`=`) can be escaped as double dashes (`--`) and spaces can be escaped as double periods (`..`). + An example of a complete `offer` request dictionary could be (SDP body abbreviated): { "command": "offer", "call-id": "cfBXzDSZqhYNcXM", "from-tag": "mS9rSAn0Cr", diff --git a/t/auto-daemon-tests.pl b/t/auto-daemon-tests.pl index 1817cf473..902671675 100755 --- a/t/auto-daemon-tests.pl +++ b/t/auto-daemon-tests.pl @@ -15982,6 +15982,7 @@ a=rtcp:PORT a=crypto:3 AES_256_CM_HMAC_SHA1_80 inline:CRYPTO256 SDP + # Arbitrary SDP manipulations new_call; @@ -16424,6 +16425,450 @@ a=sendrecv a=rtcp:PORT SDP + +# Arbitrary SDP manipulations via `flags` + +new_call; + +offer('SDP attr manipulations - remove a= line on media audio', { ICE => 'remove', DTLS => 'off', SDES => [ 'nonew' ], flags => ['sdp-attr-remove-audio-test'] }, < 'remove' }, < 'remove', DTLS => 'off', SDES => [ 'nonew' ], flags => ['sdp-attr-remove-none-test'] }, < 'remove' }, < 'remove', DTLS => 'off', SDES => [ 'nonew' ], flags => ['sdp-attr-remove-audio-test2', 'sdp-attr-remove-none-test1'] }, < 'remove' }, < 'remove', DTLS => 'off', SDES => [ 'nonew' ], flags => ['sdp-attr-add-audio-test1', 'sdp-attr-add-none-test2'], }, < 'remove' }, < 'remove', DTLS => 'off', SDES => [ 'nonew' ], flags => ['sdp-attr-add-audio-test1', 'sdp-attr-add-audio-test2'] }, < 'remove' }, < 'remove', DTLS => 'off', SDES => [ 'nonew' ], flags => ['sdp-attr-add-audio-test1', 'sdp-attr-remove-audio-test2'] }, < 'remove' }, < 'remove', DTLS => 'off', SDES => [ 'nonew' ], flags => ['sdp-attr-remove-none-test1', 'sdp-attr-remove-none-test2'] }, < 'remove' }, < 'remove', DTLS => 'off', SDES => [ 'nonew' ], flags => ['sdp-attr-substitute-audio-test1>test2'] }, < 'remove' }, < 'remove', DTLS => 'off', SDES => [ 'nonew' ], flags => ['sdp-attr-substitute-none-test1>test2'] }, < 'remove' }, < 'remove', DTLS => 'off', SDES => [ 'nonew' ], flags => ['sdp-attr-substitute-audio-test1>test2', 'sdp-attr-substitute-audio-test5>test6'] }, < 'remove' }, <