diff --git a/core/AmB2BSession.cpp b/core/AmB2BSession.cpp index 83354eab..58baae92 100644 --- a/core/AmB2BSession.cpp +++ b/core/AmB2BSession.cpp @@ -276,6 +276,15 @@ void AmB2BSession::createFakeReply(const AmMimeBody *sdp, AmMimeBody& reply_bo ILOG_DLG(L_DBG, "created pending INVITE reply body: %s\n", body_str.c_str()); } +static void sdp2body(const AmSdp &sdp, AmMimeBody &body) +{ + string body_str; + sdp.print(body_str); + AmMimeBody *s = body.hasContentType(SIP_APPLICATION_SDP); + if (s) s->parse(SIP_APPLICATION_SDP, (const unsigned char*)body_str.c_str(), body_str.length()); + else body.parse(SIP_APPLICATION_SDP, (const unsigned char*)body_str.c_str(), body_str.length()); +} + void AmB2BSession::acceptPendingInvite(AmSipRequest *invite) { // reply the INVITE with fake 200 reply @@ -292,9 +301,44 @@ void AmB2BSession::acceptPendingInvite(AmSipRequest *invite) void AmB2BSession::acceptPendingInviteB2B(const AmSipRequest& invite) { const AmMimeBody *sdp = invite.body.hasContentType(SIP_APPLICATION_SDP); - AmSipReply n_reply; - createFakeReply(sdp, n_reply.body); + + /* local sdp, which was already learned before */ + AmSdp remote_sdp = dlg->getRemoteSdp(); + + unsigned int remote_port = 0; + + if (dlg->getRemoteMediaPort() > 0) { + ILOG_DLG(L_DBG, "Using remotely seen SDP port for faking this reply: '%d'\n", dlg->getRemoteMediaPort()); + remote_port = dlg->getRemoteMediaPort(); + } + else if (!remote_sdp.media.empty()) { + /* take first possible media and re-use its port */ + SdpMedia remote_sdp_media = remote_sdp.media.front(); + if (remote_sdp_media.port > 0) { + ILOG_DLG(L_DBG, "Using remotely seen SDP port for faking this reply: '%d'\n", remote_sdp_media.port); + remote_port = remote_sdp_media.port; + } + } + + if (remote_port > 0) { + /* create fake AmSdp from AmMimeBody */ + AmSdp fake_sdp; + AmMimeBody fake_mimebody; + fake_sdp.parse((const char *)sdp->getPayload()); + + ILOG_DLG(L_DBG, "Using local SDP port for faking this reply: '%d'\n", remote_port); + for (auto it = fake_sdp.media.begin(); it != fake_sdp.media.end(); ++it) + { + it->port = remote_port; + } + + sdp2body(fake_sdp, fake_mimebody); + createFakeReply(&fake_mimebody, n_reply.body); + } + else { + createFakeReply(sdp, n_reply.body); + } n_reply.code = 200; n_reply.reason = "OK"; diff --git a/core/AmOfferAnswer.cpp b/core/AmOfferAnswer.cpp index 28797b29..e20b2ad1 100644 --- a/core/AmOfferAnswer.cpp +++ b/core/AmOfferAnswer.cpp @@ -58,7 +58,8 @@ AmOfferAnswer::AmOfferAnswer(AmSipDialog* dlg) sdp_remote(), sdp_local(), dlg(dlg), - force_sdp(true) + force_sdp(true), + remote_port_seen(0) { } @@ -85,6 +86,11 @@ const AmSdp& AmOfferAnswer::getRemoteSdp() const return sdp_remote; } +const unsigned int& AmOfferAnswer::getRemoteMediaPort() const +{ + return remote_port_seen; +} + /** State maintenance */ void AmOfferAnswer::saveState() { @@ -225,6 +231,12 @@ int AmOfferAnswer::onReplyIn(const AmSipReply& reply) dlg->onSdpReceived(true); } + if (!sdp_remote.media.empty()) + { + SdpMedia remote = sdp_remote.media.front(); + remote_port_seen = remote.port; + } + } else { bool is_reliable = reply.code >= 200 || key_in_list(getHeader(reply.hdrs, SIP_HDR_REQUIRE), SIP_EXT_100REL); saveState(); @@ -274,6 +286,12 @@ int AmOfferAnswer::onRxSdp(unsigned int m_cseq, const string& m_remote_tag, sdp_remote.clear(); } + if (!sdp_remote.media.empty()) + { + SdpMedia remote = sdp_remote.media.front(); + remote_port_seen = remote.port; + } + if(err_code == 0) { switch(state) { diff --git a/core/AmOfferAnswer.h b/core/AmOfferAnswer.h index f0c19254..eea096a5 100644 --- a/core/AmOfferAnswer.h +++ b/core/AmOfferAnswer.h @@ -53,6 +53,9 @@ private: AmSdp sdp_remote; AmSdp sdp_local; + /* saved remote port */ + unsigned int remote_port_seen; + AmSipDialog* dlg; /** Should SDP generation be forced when not required by standards? */ @@ -79,6 +82,7 @@ public: void setState(OAState n_st); const AmSdp& getLocalSdp() const; const AmSdp& getRemoteSdp() const; + const unsigned int& getRemoteMediaPort() const; void clear(); void clearTransitionalState(); diff --git a/core/AmSipDialog.h b/core/AmSipDialog.h index 16d7c1c9..56e01fa7 100644 --- a/core/AmSipDialog.h +++ b/core/AmSipDialog.h @@ -134,6 +134,7 @@ protected: const AmSdp& getLocalSdp() { return oa.getLocalSdp(); } const AmSdp& getRemoteSdp() { return oa.getRemoteSdp(); } + const unsigned int& getRemoteMediaPort() { return oa.getRemoteMediaPort(); } /** * Reliable provisional replies