diff --git a/apps/sbc/CallLeg.cpp b/apps/sbc/CallLeg.cpp index 9fb55ab8..6e5ab876 100644 --- a/apps/sbc/CallLeg.cpp +++ b/apps/sbc/CallLeg.cpp @@ -535,9 +535,34 @@ void CallLeg::b2bInitial2xx(AmSipReply& reply, bool forward) void CallLeg::onInitialReply(B2BSipReplyEvent *e) { - if (e->reply.code < 200) b2bInitial1xx(e->reply, e->forward); - else if (e->reply.code < 300) b2bInitial2xx(e->reply, e->forward); - else b2bInitialErr(e->reply, e->forward); + /* 100-199 */ + if (e->reply.code < 200) { + string announce = getHeader(e->reply.hdrs, SIP_HDR_P_EARLY_ANNOUNCE); + dlg->setForcedEarlyAnnounce(announce.find("force") != std::string::npos); + + /* exceptionally treat 183 with the 'P-Early-Announce: force', + similarly to the 200OK response, this will properly update the caller + with the late SDP capabilities (an early announcement), + which has been put on hold during the transfer + + DSM applications using it: + - early_dbprompt (early_announce) */ + if (e->reply.code == 183 && !announce.empty() && dlg->getForcedEarlyAnnounce()) { + b2bInitial2xx(e->reply, e->forward); + } else { + b2bInitial1xx(e->reply, e->forward); + } + } + + /* 200-299 */ + else if (e->reply.code < 300) { + b2bInitial2xx(e->reply, e->forward); + } + + /* 300-699 */ + else { + b2bInitialErr(e->reply, e->forward); + } } void CallLeg::b2bInitialErr(AmSipReply& reply, bool forward) diff --git a/core/AmB2BMedia.cpp b/core/AmB2BMedia.cpp index 5df69085..f1296876 100644 --- a/core/AmB2BMedia.cpp +++ b/core/AmB2BMedia.cpp @@ -874,14 +874,18 @@ void AmB2BMedia::updateStreamPair(AudioStreamPair &pair) TRACE("updating stream in A leg\n"); pair.a.setDtmfSink(b); + if (pair.b.getInput()) pair.a.setRelayStream(NULL); // don't mix relayed RTP into the other's input else pair.a.setRelayStream(pair.b.getStream()); + if (have_a) pair.a.initStream(playout_type, a_leg_local_sdp, a_leg_remote_sdp, pair.media_idx); TRACE("updating stream in B leg\n"); pair.b.setDtmfSink(a); + if (pair.a.getInput()) pair.b.setRelayStream(NULL); // don't mix relayed RTP into the other's input else pair.b.setRelayStream(pair.a.getStream()); + if (have_b) pair.b.initStream(playout_type, b_leg_local_sdp, b_leg_remote_sdp, pair.media_idx); TRACE("audio streams updated\n"); diff --git a/core/AmSipDialog.cpp b/core/AmSipDialog.cpp index bec06024..168340cf 100644 --- a/core/AmSipDialog.cpp +++ b/core/AmSipDialog.cpp @@ -65,7 +65,7 @@ AmSipDialog::AmSipDialog(AmSipDialogEventHandler* h) offeranswer_enabled(true), early_session_started(false),session_started(false), pending_invites(0), - sdp_local(), sdp_remote() + sdp_local(), sdp_remote(), force_early_announce(false) { } diff --git a/core/AmSipDialog.h b/core/AmSipDialog.h index 79d732c8..2cfb8e42 100644 --- a/core/AmSipDialog.h +++ b/core/AmSipDialog.h @@ -59,6 +59,9 @@ protected: // Reliable provisional reply support Am100rel rel100; + /* dialog variables needed to properly handle 183->200OK faking */ + bool force_early_announce; + int onTxReply(const AmSipRequest& req, AmSipReply& reply, int& flags); int onTxRequest(AmSipRequest& req, int& flags); @@ -99,6 +102,10 @@ protected: void setOAForceSDP(bool force) { oa.setForceSDP(force); } bool getOAForceSDP() const { return oa.getForceSDP(); } + /* getter/setter for faked 183 as 200OK responses, TT#187351 */ + void setForcedEarlyAnnounce(bool value) { force_early_announce = value; } + bool getForcedEarlyAnnounce() { return force_early_announce; } + const AmSdp& getLocalSdp() { return oa.getLocalSdp(); } const AmSdp& getRemoteSdp() { return oa.getRemoteSdp(); } diff --git a/core/sip/defs.h b/core/sip/defs.h index 9b3ecfb9..4d8746df 100644 --- a/core/sip/defs.h +++ b/core/sip/defs.h @@ -54,6 +54,7 @@ #define SIP_HDR_EVENT "Event" #define SIP_HDR_SUBSCRIPTION_STATE "Subscription-State" #define SIP_HDR_REPLACES "Replaces" +#define SIP_HDR_P_EARLY_ANNOUNCE "P-Early-Announce" #define SIP_HDR_COL(_hdr) _hdr ":" #define SIP_HDR_COLSP(_hdr) SIP_HDR_COL(_hdr) " "