From 3cc3b6d56c7d91a70c7314964b3cf89b79894701 Mon Sep 17 00:00:00 2001 From: Donat Zenichev Date: Thu, 2 Jan 2025 10:26:30 +0100 Subject: [PATCH] MT#61630 moh: add support of zero-connection flag Zero-connection flag controls whether the connection address offered in the SDP body going towards recipient (the one who will receive the MoH media), is set to all zeroes. Is declared as: moh=[connection=zero] Can be useful for older client implementations, who want to see zeroed media when receiving sendonly and getting put on hold. Must be advertised once during the session origination, and then will affect the SDP body as soon as SDP sendonly body is received (from the behalf of one, who advertised MoH capabilities). SDP body recovers to the real IP addresses being inserted into recipient's SDP, as soon as the media gets unheld. Backwards compatibility: doesn't affect non-MoH calls. And doesn't affect offer/answer exchanges within MoH calls, which do not put the remote side on hold. Additionally: previously existing MoH test adopted. Additionally: new test introduced to check the SDP content, when using zero-connection flag. Change-Id: If0c38a3d294e6d5fe3886bee19ff2382e5705f9a --- daemon/call_interfaces.c | 10 ++- daemon/media_player.c | 34 ++++++++++ include/media_player.h | 1 + t/auto-daemon-tests.pl | 141 ++++++++++++++++++++++++++++++++++++++- 4 files changed, 183 insertions(+), 3 deletions(-) diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index f0a6d5859..54cb436ae 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -168,6 +168,9 @@ static void updated_created_from(call_t *c, const char *addr, const endpoint_t * } } +/** + * TODO: probably makes sense to move to the call.c + */ static const char* call_check_moh(struct call_monologue *from_ml, struct call_monologue *to_ml, sdp_ng_flags *flags) { @@ -189,7 +192,12 @@ static const char* call_check_moh(struct call_monologue *from_ml, struct call_mo errstr = call_play_media_for_ml(to_ml, opts, NULL); if (errstr) return errstr; - to_ml->player->moh = true; /* mark player as used for MoH */ + /* mark player as used for MoH */ + to_ml->player->moh = true; + /* check if originator wants to advertise zero address during moh */ + if (ML_ISSET(from_ml, MOH_ZEROCONN)) { + call_ml_moh_set_zeroconn(from_ml); + } } else if (call_ml_stops_moh(from_ml, to_ml, flags->opmode)) { /* whom to stop the moh audio */ diff --git a/daemon/media_player.c b/daemon/media_player.c index e3eb70fa1..9236f4640 100644 --- a/daemon/media_player.c +++ b/daemon/media_player.c @@ -1227,6 +1227,40 @@ bool call_ml_stops_moh(struct call_monologue *from_ml, struct call_monologue *to return false; } +/** + * Sets zero-connection for the first found subscription media with sendonly state + * and audio type. + */ +void call_ml_moh_set_zeroconn(struct call_monologue *from_ml) { + for (int i = 0; i < from_ml->medias->len; i++) + { + struct call_media * media = from_ml->medias->pdata[i]; + if (!media || media->type_id != MT_AUDIO) + continue; + if (!MEDIA_ISSET(media, SEND) && MEDIA_ISSET(media, RECV)) + { + if (media->media_subscriptions.head) { + struct media_subscription * ms = media->media_subscriptions.head->data; + if (ms->media) { + struct packet_stream *ps; + __auto_type msl = ms->media->streams.head; + while (msl) + { + ps = msl->data; + if (PS_ISSET(ps, RTP)) { + ilog(LOG_DEBUG, "Forced packet stream of '"STR_FORMAT"' (media index: '%d') to zero_addr due to MoH zero-connection.", + STR_FMT(&ms->media->monologue->tag), ms->media->index); + PS_SET(ps, ZERO_ADDR); + return; /* stop */ + } + msl = msl->next; + } + } + } + } + } +} + const char * call_play_media_for_ml(struct call_monologue *ml, media_player_opts_t opts, sdp_ng_flags *flags) { diff --git a/include/media_player.h b/include/media_player.h index 279a4461e..128ee37bf 100644 --- a/include/media_player.h +++ b/include/media_player.h @@ -141,6 +141,7 @@ long long call_stop_media_for_ml(struct call_monologue *ml); bool call_ml_wants_moh(struct call_monologue *ml, enum ng_opmode opmode); bool call_ml_stops_moh(struct call_monologue *from_ml, struct call_monologue *to_ml, enum ng_opmode opmode); +void call_ml_moh_set_zeroconn(struct call_monologue *from_ml); void media_player_init(void); void media_player_free(void); diff --git a/t/auto-daemon-tests.pl b/t/auto-daemon-tests.pl index 651b3dcca..214c18818 100755 --- a/t/auto-daemon-tests.pl +++ b/t/auto-daemon-tests.pl @@ -26226,7 +26226,7 @@ $resp = rtpe_req('statistics', 'statistics'); ($sock_a, $sock_b) = new_call([qw(198.51.100.1 33041)], [qw(198.51.100.3 33042)]); # declare that offerer is capable of moh -offer('Music on hold - sendrecv', { ICE => 'remove', DTLS => 'off', moh => { blob => $wav_file, connection => 'zero', mode => 'sendrecv' } }, < 'remove', DTLS => 'off', moh => { blob => $wav_file, mode => 'sendrecv' } }, < 'remove', moh => { 'db-id' => '123', connection => 'zero', mode => 'sendrecv' } }, < 'remove', moh => { 'db-id' => '123', mode => 'sendrecv' } }, < 'remove', DTLS => 'off', moh => { blob => $wav_file, connection => 'zero', mode => 'sendrecv' } }, < 'remove', moh => { 'db-id' => '123', connection => 'zero', mode => 'sendrecv' } }, < 'remove', DTLS => 'off' }, < 'remove' }, < 'remove', DTLS => 'off' }, < 'remove' }, <