diff --git a/core/AmB2BSession.cpp b/core/AmB2BSession.cpp index 9bea175f..ff7af7ad 100644 --- a/core/AmB2BSession.cpp +++ b/core/AmB2BSession.cpp @@ -100,7 +100,9 @@ AmB2BSession::AmB2BSession(const string& other_local_tag, AmSipDialog* p_dlg, enable_dtmf_rtp_detection(false), rtp_relay_transparent_seqno(true), rtp_relay_transparent_ssrc(true), est_invite_cseq(0),est_invite_other_cseq(0), - media_session(NULL) + media_session(NULL), + previous_origin_sessId(0), + previous_origin_sessV(0) { if(!subs) subs = new AmSipSubscription(dlg,this); } @@ -515,6 +517,56 @@ void AmB2BSession::updateLocalSdp(AmSdp &sdp) media_session->replaceConnectionAddress(sdp, a_leg, localMediaIP(), advertisedIP()); } +void AmB2BSession::updateLocalSdpOrigin(AmSdp& sdp) { + // fix SDP origin + if (sdp_origin.conn.address.empty()) { + // remember this origin for whole dialog lifetime + sdp_origin = sdp.origin; + previous_sdp = sdp; + previous_origin_sessId = sdp.origin.sessId; + previous_origin_sessV = sdp.origin.sessV; + DBG("Remembering initial SDP Origin (Id %s V %s)\n", + longlong2str(sdp.origin.sessId).c_str(), longlong2str(sdp.origin.sessV).c_str()); + } + else { + bool sdp_changed = false; + // check if Origin Id/Version has changed + if ((sdp.origin.sessV != previous_origin_sessV) || + (sdp.origin.sessId != previous_origin_sessId)){ + sdp_changed = true; + // remember for next time + previous_origin_sessId = sdp.origin.sessId; + previous_origin_sessV = sdp.origin.sessV; + } + // use remembered SDP origin + sdp.origin = sdp_origin; + // check if SDP has changed (apart from origin) + if (!sdp_changed) { + // comparing the AmSdp objects may be unsafe (intialized members...), + // so comparing resulting SDP string + string s_sdp; string s_previous_sdp; + sdp.print(s_sdp); previous_sdp.print(s_previous_sdp); + if (!(s_sdp == s_previous_sdp)) { + sdp_changed = true; + } + } + // ...and increase version if changed + if (sdp_changed) { + // increase version + sdp_origin.sessV++; + // update origin + sdp.origin = sdp_origin; + // remember the current SDP for the next time + previous_sdp = sdp; + DBG("SDP changed; updating Origin (Id %s V %s)\n", + longlong2str(sdp.origin.sessId).c_str(), longlong2str(sdp.origin.sessV).c_str()); + } else { + DBG("SDP unchanged; keeping Origin (Id %s V %s)\n", + longlong2str(sdp.origin.sessId).c_str(), longlong2str(sdp.origin.sessV).c_str()); + } + } +} + void AmB2BSession::updateLocalBody(AmMimeBody& body) { AmMimeBody *sdp = body.hasContentType(SIP_APPLICATION_SDP); @@ -527,6 +579,7 @@ void AmB2BSession::updateLocalBody(AmMimeBody& body) } updateLocalSdp(parser_sdp); + updateLocalSdpOrigin(parser_sdp); // regenerate SDP string n_body; diff --git a/core/AmB2BSession.h b/core/AmB2BSession.h index 55d17b8a..11da28be 100644 --- a/core/AmB2BSession.h +++ b/core/AmB2BSession.h @@ -158,6 +158,12 @@ private: /** CSeq map for REFER subscriptions */ map refer_id_map; + // we have to use the same "o=" line with potentially increasing session version in SDP + SdpOrigin sdp_origin; + AmSdp previous_sdp; + unsigned long long previous_origin_sessId; + unsigned long long previous_origin_sessV; + protected: /** Tell if the session should * process SIP request itself @@ -300,6 +306,11 @@ private: void updateRelayStreams(const AmMimeBody& body, AmSdp& parser_sdp); + /** set locally used SDP origin */ + void setSdpOrigin(const SdpOrigin &o) { sdp_origin = o; } + /** set SDP origin in local body */ + void updateLocalSdpOrigin(AmSdp& sdp); + /** replace connection with our address */ void updateLocalBody(AmMimeBody& body); diff --git a/core/AmSdp.h b/core/AmSdp.h index ee873204..68a95d19 100644 --- a/core/AmSdp.h +++ b/core/AmSdp.h @@ -70,7 +70,7 @@ struct SdpConnection /** IP address */ string address; - SdpConnection() : network(0), addrType(0), address(), ipv4{}, ipv6{} {} + SdpConnection() : network(NT_IN), addrType(AT_NONE), address(), ipv4{}, ipv6{} {} bool operator == (const SdpConnection& other) const; /** pretty print */