diff --git a/modules/media_exchange/media_sessions.c b/modules/media_exchange/media_sessions.c index b2508187dd..7bf12daaf3 100644 --- a/modules/media_exchange/media_sessions.c +++ b/modules/media_exchange/media_sessions.c @@ -19,6 +19,7 @@ */ #include "media_sessions.h" +#include "media_utils.h" static int media_session_dlg_idx; @@ -110,6 +111,26 @@ struct media_session *media_session_get(struct dlg_cell *dlg) return media_dlg.dlg_ctx_get_ptr(dlg, media_session_dlg_idx); } +static void media_session_end(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params) +{ + /* dialog has terminated - we need to terminate all ongoing legs */ + struct media_session_leg *msl, *msln; + struct media_session *ms = media_session_get(dlg); + + /* media server no longer exists, so it's been already handled */ + if (!ms) + return; + + MEDIA_SESSION_LOCK(ms); + for (msl = ms->legs; msl; msl = msln) { + media_session_b2b_end(msl); + msln = msl->next; + /* leg might dissapear here */ + MSL_UNREF_NORELEASE(msl); + } + media_session_release(ms, 1/* unlock */); +} + struct media_session *media_session_create(struct dlg_cell *dlg) { struct media_session *ms; @@ -126,6 +147,15 @@ struct media_session *media_session_create(struct dlg_cell *dlg) media_dlg.dlg_ref(dlg, 1); media_dlg.dlg_ctx_put_ptr(dlg, media_session_dlg_idx, ms); + if (media_dlg.register_dlgcb(dlg, DLGCB_TERMINATED|DLGCB_EXPIRED, + media_session_end, NULL, NULL) < 0) { + /* we are not storing media session in the dialog, as it might + * dissapear along the way, if the playback ends */ + LM_ERR("could not register media_session_termination!\n"); + media_session_free(ms); + return NULL; + } + LM_DBG(" creating media_session=%p\n", ms); return ms; } diff --git a/modules/media_exchange/media_sessions.h b/modules/media_exchange/media_sessions.h index 060fa6e325..a078db772e 100644 --- a/modules/media_exchange/media_sessions.h +++ b/modules/media_exchange/media_sessions.h @@ -79,7 +79,6 @@ struct media_session { (_msl)->ref--; \ if ((_msl)->ref == 0) { \ struct media_session *__tmp_ms = _msl->ms; \ - LM_DBG("destroying media session leg=%p\n", _msl); \ media_session_leg_free(_msl); \ media_session_release(__tmp_ms, 1/* release ms lock */); \ } else { \ @@ -95,13 +94,21 @@ struct media_session { (_msl)->ref--; \ if ((_msl)->ref == 0) { \ struct media_session *__tmp_ms = _msl->ms; \ - LM_DBG("destroying media session leg=%p\n", _msl); \ media_session_leg_free(_msl); \ media_session_release(__tmp_ms, 0); \ } else if ((_msl)->ref < 0) \ LM_BUG("invalid ref for media session leg=%p ref=%d (%s:%d)\n", \ (_msl), (_msl)->ref, __func__, __LINE__); \ - } \ + } while(0) + +#define MSL_UNREF_NORELEASE(_msl) \ + do { \ + (_msl)->ref--; \ + if ((_msl)->ref == 0) \ + media_session_leg_free(_msl); \ + else if ((_msl)->ref < 0) \ + LM_BUG("invalid ref for media session leg=%p ref=%d (%s:%d)\n", \ + (_msl), (_msl)->ref, __func__, __LINE__); \ } while(0) int init_media_sessions(void); diff --git a/modules/media_exchange/media_utils.c b/modules/media_exchange/media_utils.c index 462f830d27..1158577db8 100644 --- a/modules/media_exchange/media_utils.c +++ b/modules/media_exchange/media_utils.c @@ -102,3 +102,22 @@ int media_session_reinvite(struct media_session_leg *msl, int leg, str *pbody) return media_dlg.send_indialog_request(msl->ms->dlg, &inv, leg, &body, &ct_sdp, NULL, NULL); } + +int media_session_b2b_end(struct media_session_leg *msl) +{ + struct b2b_req_data req; + str bye = str_init(BYE); + + memset(&req, 0, sizeof(req)); + req.et = msl->b2b_entity; + req.b2b_key = &msl->b2b_key; + req.method = &bye; + req.no_cb = 1; /* do not call callback */ + + if (media_b2b.send_request(&req) < 0) { + LM_ERR("Cannot end recording session for key %.*s\n", + req.b2b_key->len, req.b2b_key->s); + return -1; + } + return 0; +} diff --git a/modules/media_exchange/media_utils.h b/modules/media_exchange/media_utils.h index a3213f920d..a8cea95389 100644 --- a/modules/media_exchange/media_utils.h +++ b/modules/media_exchange/media_utils.h @@ -27,4 +27,6 @@ int media_session_resume_dlg(struct media_session_leg *msl); int media_session_reinvite(struct media_session_leg *msl, int leg, str *pbody); +int media_session_b2b_end(struct media_session_leg *msl); + #endif /* _MEDIA_UTILS_H_ */