diff --git a/apps/dsm/mods/mod_dlg/ModDlg.cpp b/apps/dsm/mods/mod_dlg/ModDlg.cpp index 2257abf9..16b7223e 100644 --- a/apps/dsm/mods/mod_dlg/ModDlg.cpp +++ b/apps/dsm/mods/mod_dlg/ModDlg.cpp @@ -182,14 +182,22 @@ EXEC_ACTION_START(DLGAcceptInviteAction) { try { AmMimeBody sdp_body; - if(sess->dlg->reply(*sc_sess->last_req.get(),code_i, reason, - sdp_body.addPart(SIP_APPLICATION_SDP), hdrs) != 0) + /* save generated SDP body for this session as `established_body` */ + if(sess->dlg->reply(*sc_sess->last_req.get(), + code_i, + reason, + sdp_body.addPart(SIP_APPLICATION_SDP), + hdrs, + SIP_FLAGS_SAVE_ESTB_SDP) != 0) + { throw AmSession::Exception(500,"could not send response"); + } }catch(const AmSession::Exception& e){ ERROR("%i %s\n",e.code,e.reason.c_str()); sess->setStopped(); + sess->dlg->reply(*sc_sess->last_req.get(),e.code,e.reason); sc_sess->SET_ERRNO(DSM_ERRNO_DLG); diff --git a/core/AmBasicSipDialog.h b/core/AmBasicSipDialog.h index 03d84f23..5e50cbcb 100644 --- a/core/AmBasicSipDialog.h +++ b/core/AmBasicSipDialog.h @@ -45,6 +45,8 @@ using std::string; #define SIP_FLAGS_NOBL 1<<4 // do not use destination blacklist +#define SIP_FLAGS_SAVE_ESTB_SDP 1<<10 // save established SDP body when processing in OA, see `AmOfferAnswer::onReplyOut()` + /** \brief SIP transaction representation */ struct AmSipTransaction { diff --git a/core/AmOfferAnswer.cpp b/core/AmOfferAnswer.cpp index 0ae9a3b3..784f768d 100644 --- a/core/AmOfferAnswer.cpp +++ b/core/AmOfferAnswer.cpp @@ -361,7 +361,7 @@ int AmOfferAnswer::onRequestOut(AmSipRequest& req) return 0; } -int AmOfferAnswer::onReplyOut(AmSipReply& reply, bool no_sdp_generation) +int AmOfferAnswer::onReplyOut(AmSipReply& reply, int &flags, AmMimeBody &ret_body, bool no_sdp_generation) { AmMimeBody* sdp_body = reply.body.hasContentType(SIP_APPLICATION_SDP); AmMimeBody* csta_body = reply.body.hasContentType(SIP_APPLICATION_CSTA_XML); @@ -409,7 +409,6 @@ int AmOfferAnswer::onReplyOut(AmSipReply& reply, bool no_sdp_generation) } sdp_body->setPayload((const unsigned char*)existing_sdp.c_str(), existing_sdp.length()); - has_sdp = true; DBG("Now has_sdp has been reset to true.\n"); @@ -469,6 +468,14 @@ int AmOfferAnswer::onReplyOut(AmSipReply& reply, bool no_sdp_generation) sdp_body->setPayload((const unsigned char*)sdp_buf.c_str(), sdp_buf.length()); has_sdp = true; + + /* some of sessions want generated body to be kept for the future, e.g. for the case + * when we want to reinvite the other side, before this side got actual SDP answer. + * e.g. this happens in DSM, when we generate faked SDP in some cases. */ + if (flags & SIP_FLAGS_SAVE_ESTB_SDP) { + DBG("Saving established_body based on newly generated SDP.\n"); + ret_body = *sdp_body; + } } } else if (sdp_body && has_sdp) { diff --git a/core/AmOfferAnswer.h b/core/AmOfferAnswer.h index b5d6763e..e646fda4 100644 --- a/core/AmOfferAnswer.h +++ b/core/AmOfferAnswer.h @@ -86,7 +86,7 @@ public: int onReplyIn(const AmSipReply& reply); int onRequestOut(AmSipRequest& req); /* `no_sdp_generation` - can be used for cases like absent SDP in coming INVITE */ - int onReplyOut(AmSipReply& reply, bool no_sdp_generation = false); + int onReplyOut(AmSipReply& reply, int &flags, AmMimeBody &ret_body, bool no_sdp_generation = false); int onRequestSent(const AmSipRequest& req); int onReplySent(const AmSipReply& reply); void onNoAck(unsigned int ack_cseq); diff --git a/core/AmSipDialog.cpp b/core/AmSipDialog.cpp index 3339615c..3e6685db 100644 --- a/core/AmSipDialog.cpp +++ b/core/AmSipDialog.cpp @@ -271,8 +271,15 @@ int AmSipDialog::onTxRequest(AmSipRequest& req, int& flags) int AmSipDialog::onTxReply(const AmSipRequest& req, AmSipReply& reply, int& flags) { if (offeranswer_enabled) { - if(oa.onReplyOut(reply, req.body.empty()) < 0) + AmMimeBody sdp_body; + if(oa.onReplyOut(reply, flags, sdp_body, req.body.empty()) < 0) return -1; + + /* if generated by OA, save it */ + if (!sdp_body.empty()) { + DBG("OA generated an SDP body, saving as established_body.\n"); + established_body = sdp_body; + } } rel100.onReplyOut(reply);