MT#60476 sdp_create: add support of sdp_version_check

Add support of origin version manipulations via
`sdp_version_check()`.

Change-Id: I36a5c196242c29f12ceed97abc920ca9b868fb05
pull/1848/head
Donat Zenichev 1 year ago
parent 2be41a41e8
commit 7308a88b34

@ -2040,6 +2040,9 @@ INLINE void chopper_append_c(struct sdp_chopper *c, const char *s) {
INLINE void chopper_append_str(struct sdp_chopper *c, const str *s) {
chopper_append(c, s->s, s->len);
}
/**
* TODO: deprecate as soon as sdp_replace is discontinued.
*/
static void chopper_replace(struct sdp_chopper *c, str *old, size_t *old_pos,
const char *repl, size_t repl_len)
{
@ -2900,36 +2903,84 @@ static void insert_rtcp_attr(GString *s, struct packet_stream *ps, const sdp_ng_
append_attr_to_gstring(s, "rtcp", &STR_GS(s_dst), flags, (sdp_media ? sdp_media->media_type_id : MT_UNKNOWN));
}
static void sdp_version_replace(struct sdp_chopper *chop, sdp_sessions_q *sessions,
sdp_origin *orig)
/**
* chop - used by sdp_replace
* s - used by sdp_create
*
* TODO: deprecate chop-based handling, as soon as sdp_replace is gone.
*/
static void sdp_version_replace(struct sdp_chopper *chop, GString *s,
sdp_sessions_q *sessions,
sdp_origin *src_orig,
sdp_origin *other_orig)
{
char version_str[64];
snprintf(version_str, sizeof(version_str), "%llu", orig->version_num);
snprintf(version_str, sizeof(version_str), "%llu", src_orig->version_num);
size_t version_len = strlen(version_str);
chop->offset = 0; // start from the top
for (__auto_type l = sessions->head; l; l = l->next) {
struct sdp_session *session = l->data;
sdp_origin *origin = &session->origin;
// update string unconditionally to keep position tracking intact
chopper_replace(chop, &origin->version_str, &origin->version_output_pos, version_str, version_len);
/* for sdp_replace */
if (chop) {
/* start from the top */
chop->offset = 0;
for (__auto_type l = sessions->head; l; l = l->next)
{
struct sdp_session *session = l->data;
sdp_origin *origin = &session->origin;
/* update string unconditionally to keep position tracking intact */
chopper_replace(chop, &origin->version_str, &origin->version_output_pos, version_str, version_len);
}
}
/* for sdp_create */
else {
if (!other_orig || !src_orig)
return;
other_orig->version_num = src_orig->version_num;
/* is our new value longer? */
if (version_len > other_orig->version_str.len) {
/* overwrite + insert */
g_string_overwrite_len(s, other_orig->version_output_pos, version_str, other_orig->version_str.len);
g_string_insert(s, other_orig->version_output_pos + other_orig->version_str.len, version_str + other_orig->version_str.len);
other_orig->version_str.len = version_len;
}
else {
/* overwrite + optional erase */
g_string_overwrite(s, other_orig->version_output_pos, version_str);
if (version_len < other_orig->version_str.len) {
g_string_erase(s, other_orig->version_output_pos + version_len, other_orig->version_str.len - version_len);
other_orig->version_str.len = version_len;
}
}
}
}
static void sdp_version_check(struct sdp_chopper *chop, sdp_sessions_q *sessions,
/**
* `chop` - used by sdp_replace (in this case `s` is NULL)
* `s` - used by sdp_create (in this case `chop` is NULL)
*
* TODO: deprecate chop-based handling, as soon as sdp_replace is gone.
*/
static void sdp_version_check(struct sdp_chopper *chop, GString *s,
sdp_sessions_q *sessions,
struct call_monologue *monologue,
bool force_increase)
{
/* We really expect only a single session here, but we treat all the same regardless,
* and use the same version number on all of them */
if (!monologue->session_last_sdp_orig)
return;
sdp_origin *origin = monologue->session_last_sdp_orig;
sdp_origin *other_origin = NULL;
struct media_subscription *ms = call_get_top_media_subscription(monologue);
if (ms && ms->monologue && ms->monologue->session_sdp_orig)
other_origin = ms->monologue->session_sdp_orig;
/* We really expect only a single session here, but we treat all the same regardless,
* and use the same version number on all of them */
/* First update all versions to match our single version */
sdp_version_replace(chop, sessions, origin);
sdp_version_replace(chop, s, sessions, origin, other_origin);
/* Now check if we need to change the version actually.
* The version change will be forced with the 'force_increase',
@ -2939,17 +2990,17 @@ static void sdp_version_check(struct sdp_chopper *chop, sdp_sessions_q *sessions
if (!force_increase) {
if (!monologue->last_out_sdp)
goto dup;
if (g_string_equal(monologue->last_out_sdp, chop->output))
if (g_string_equal(monologue->last_out_sdp, (chop ? chop->output : s)))
return;
}
/* mismatch detected. increment version, update again, and store copy */
origin->version_num++;
sdp_version_replace(chop, sessions, origin);
sdp_version_replace(chop, s, sessions, origin, other_origin);
if (monologue->last_out_sdp)
g_string_free(monologue->last_out_sdp, TRUE);
dup:
monologue->last_out_sdp = g_string_new_len(chop->output->str, chop->output->len);
monologue->last_out_sdp = g_string_new_len((chop ? chop->output->str : s->str), (chop ? chop->output->len : s->len));
}
const char *sdp_get_sendrecv(struct call_media *media) {
@ -3442,7 +3493,7 @@ int sdp_replace(struct sdp_chopper *chop, sdp_sessions_q *sessions,
* which forces version increase regardless changes in the SDP information.
*/
if (flags->force_inc_sdp_ver || flags->replace_sdp_version || flags->replace_origin_full)
sdp_version_check(chop, sessions, monologue, !!flags->force_inc_sdp_ver);
sdp_version_check(chop, NULL, sessions, monologue, !!flags->force_inc_sdp_ver);
return 0;
@ -3472,10 +3523,12 @@ static void sdp_out_add_origin(GString *out, struct call_monologue *monologue,
str * orig_session_id = (ml->session_last_sdp_orig && flags->replace_origin_full) ?
&ml->session_last_sdp_orig->session_id : &ml->session_sdp_orig->session_id;
/* orig session ver */
/* TODO: add support of `sdp_version_check()` */
unsigned long long orig_session_version = (ml->session_last_sdp_orig && flags->replace_origin_full) ?
ml->session_last_sdp_orig->version_num : ml->session_sdp_orig->version_num;
/* orig session ver
* replacement is handled later in sdp_create() based on SDP changes */
unsigned long long orig_session_version = ml->session_sdp_orig->version_num;
/* record origin version position for replacements
* + 4 - means: `o=` + 2 spaces between username and version / version and id */
ml->session_sdp_orig->version_output_pos = out->len + orig_username->len + orig_session_id->len + 4;
/* orig IP family and address */
str orig_address_type;
@ -3489,6 +3542,7 @@ static void sdp_out_add_origin(GString *out, struct call_monologue *monologue,
orig_address = ml->session_sdp_orig->address.address;
}
/* print it to the output sdp */
g_string_append_printf(out,
"o="STR_FORMAT" "STR_FORMAT" %llu IN "STR_FORMAT" "STR_FORMAT"\r\n",
STR_FMT(orig_username),
@ -3680,6 +3734,14 @@ int sdp_create(str *out, struct call_monologue *monologue, sdp_ng_flags *flags)
print_sdp_media_section(s, media, NULL, flags, rtp_ps_link, true, false);
}
/* The SDP version gets increased in case:
* - if replace_sdp_version (sdp-version) or replace_origin_full flag is set and SDP information has been updated, or
* - if the force_inc_sdp_ver (force-increment-sdp-ver) flag is set additionally to replace_sdp_version,
* which forces version increase regardless changes in the SDP information.
*/
if (flags->force_inc_sdp_ver || flags->replace_sdp_version || flags->replace_origin_full)
sdp_version_check(NULL, s, NULL, monologue, !!flags->force_inc_sdp_ver);
out->len = s->len;
out->s = g_string_free(s, FALSE);
return 0;

Loading…
Cancel
Save