diff --git a/include/asterisk/res_pjsip_session.h b/include/asterisk/res_pjsip_session.h index ccee8c96d107d2a670db884fe179232e43822424..34f4783541ec090594d2731bf19e271f7f070fb5 100644 --- a/include/asterisk/res_pjsip_session.h +++ b/include/asterisk/res_pjsip_session.h @@ -258,6 +258,8 @@ enum ast_sip_session_response_priority { * processing to incoming and outgoing SIP requests and responses */ struct ast_sip_session_supplement { + /*! Reference module info */ + struct ast_module *module; /*! Method on which to call the callbacks. If NULL, call on all methods */ const char *method; /*! Priority for this supplement. Lower numbers are visited before higher numbers */ @@ -580,9 +582,13 @@ void ast_sip_session_unregister_sdp_handler(struct ast_sip_session_sdp_handler * * set channel data based on headers in an incoming message. Similarly, * a module could reject an incoming request if desired. * + * \param module Referenced module(NULL safe) * \param supplement The supplement to register */ -void ast_sip_session_register_supplement(struct ast_sip_session_supplement *supplement); +void ast_sip_session_register_supplement_with_module(struct ast_module *module, struct ast_sip_session_supplement *supplement); + +#define ast_sip_session_register_supplement(supplement) \ + ast_sip_session_register_supplement_with_module(AST_MODULE_SELF, supplement) /*! * \brief Unregister a an supplement to SIP session processing @@ -598,6 +604,13 @@ void ast_sip_session_unregister_supplement(struct ast_sip_session_supplement *su */ int ast_sip_session_add_supplements(struct ast_sip_session *session); +/*! + * \brief Remove supplements from a SIP session + * + * \param session The session to remove + */ +void ast_sip_session_remove_supplements(struct ast_sip_session *session); + /*! * \brief Alternative for ast_datastore_alloc() * diff --git a/res/res_pjsip/pjsip_message_filter.c b/res/res_pjsip/pjsip_message_filter.c index f948c4449cc155fc3a23daf63165df16d569ff12..4b0f60dfc9e671c9a82ab4783678261933229466 100644 --- a/res/res_pjsip/pjsip_message_filter.c +++ b/res/res_pjsip/pjsip_message_filter.c @@ -24,6 +24,7 @@ #include "asterisk/res_pjsip.h" #include "asterisk/res_pjsip_session.h" #include "include/res_pjsip_private.h" +#include "asterisk/module.h" #define MOD_DATA_RESTRICTIONS "restrictions" diff --git a/res/res_pjsip/pjsip_session.c b/res/res_pjsip/pjsip_session.c index f3f3a4d8782bb401da7a14acc9c8d028b6e3a2fd..7dc622170341f1d4d1612eea85d12cd6e55e950a 100644 --- a/res/res_pjsip/pjsip_session.c +++ b/res/res_pjsip/pjsip_session.c @@ -32,12 +32,16 @@ AST_RWLIST_HEAD_STATIC(session_supplements, ast_sip_session_supplement); -void ast_sip_session_register_supplement(struct ast_sip_session_supplement *supplement) +void ast_sip_session_register_supplement_with_module(struct ast_module *module, struct ast_sip_session_supplement *supplement) { struct ast_sip_session_supplement *iter; int inserted = 0; SCOPED_LOCK(lock, &session_supplements, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK); + ast_assert(supplement != NULL); + + supplement->module = module; + if (!supplement->response_priority) { supplement->response_priority = AST_SIP_SESSION_BEFORE_MEDIA; } @@ -94,8 +98,34 @@ int ast_sip_session_add_supplements(struct ast_sip_session *session) if (!copy) { return -1; } + + /* referenced session created. increasing module reference. */ + ast_module_ref(copy->module); + AST_LIST_INSERT_TAIL(&session->supplements, copy, next); } return 0; } + +void ast_sip_session_remove_supplements(struct ast_sip_session *session) +{ + struct ast_sip_session_supplement *iter; + + if (!session) { + return; + } + + /* free the supplements */ + while ((iter = AST_LIST_REMOVE_HEAD(&session->supplements, next))) { + if (iter->module) { + /* referenced session closed. decreasing modue reference. */ + ast_module_unref(iter->module); + } + + ast_free(iter); + } + + return; +} + diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c index 94240d392541ed53ba4b4b84479e61c5affb9fc0..99e0ca4ff574107de745f1c595045afb356a530f 100644 --- a/res/res_pjsip_session.c +++ b/res/res_pjsip_session.c @@ -58,6 +58,9 @@ #define DEFAULT_NUM_SESSION_MEDIA 2 /* Some forward declarations */ +static void handle_session_begin(struct ast_sip_session *session); +static void handle_session_end(struct ast_sip_session *session); +static void handle_session_destroy(struct ast_sip_session *session); static void handle_incoming_request(struct ast_sip_session *session, pjsip_rx_data *rdata); static void handle_incoming_response(struct ast_sip_session *session, pjsip_rx_data *rdata, enum ast_sip_session_response_priority response_priority); @@ -2088,7 +2091,6 @@ static int datastore_cmp(void *obj, void *arg, int flags) static void session_destructor(void *obj) { struct ast_sip_session *session = obj; - struct ast_sip_session_supplement *supplement; struct ast_sip_session_delayed_request *delay; const char *endpoint_name = session->endpoint ? ast_sorcery_object_get_id(session->endpoint) : "<none>"; @@ -2104,19 +2106,18 @@ static void session_destructor(void *obj) , session->contact ? ast_sorcery_object_get_id(session->contact) : "<none>" ); - while ((supplement = AST_LIST_REMOVE_HEAD(&session->supplements, next))) { - if (supplement->session_destroy) { - supplement->session_destroy(session); - } - ast_free(supplement); - } + /* fire session destroy handler */ + handle_session_destroy(session); + + /* remove all registered supplements */ + ast_sip_session_remove_supplements(session); + AST_LIST_HEAD_DESTROY(&session->supplements); ast_taskprocessor_unreference(session->serializer); ao2_cleanup(session->datastores); ast_sip_session_media_state_free(session->active_media_state); ast_sip_session_media_state_free(session->pending_media_state); - AST_LIST_HEAD_DESTROY(&session->supplements); while ((delay = AST_LIST_REMOVE_HEAD(&session->delayed_requests, next))) { delayed_request_free(delay); } @@ -2165,7 +2166,6 @@ struct ast_sip_session *ast_sip_session_alloc(struct ast_sip_endpoint *endpoint, { RAII_VAR(struct ast_sip_session *, session, NULL, ao2_cleanup); struct ast_sip_session *ret_session; - struct ast_sip_session_supplement *iter; int dsp_features = 0; session = ao2_alloc(sizeof(*session), session_destructor); @@ -2247,11 +2247,9 @@ struct ast_sip_session *ast_sip_session_alloc(struct ast_sip_endpoint *endpoint, ao2_ref(session, -1); return NULL; } - AST_LIST_TRAVERSE(&session->supplements, iter, next) { - if (iter->session_begin) { - iter->session_begin(session); - } - } + + /* Fire seesion begin handlers */ + handle_session_begin(session); /* Avoid unnecessary ref manipulation to return a session */ ret_session = session; @@ -3316,6 +3314,40 @@ static void handle_incoming_request(struct ast_sip_session *session, pjsip_rx_da } } +static void handle_session_begin(struct ast_sip_session *session) +{ + struct ast_sip_session_supplement *iter; + + AST_LIST_TRAVERSE(&session->supplements, iter, next) { + if (iter->session_begin) { + iter->session_begin(session); + } + } +} + +static void handle_session_destroy(struct ast_sip_session *session) +{ + struct ast_sip_session_supplement *iter; + + AST_LIST_TRAVERSE(&session->supplements, iter, next) { + if (iter->session_destroy) { + iter->session_destroy(session); + } + } +} + +static void handle_session_end(struct ast_sip_session *session) +{ + struct ast_sip_session_supplement *iter; + + /* Session is dead. Notify the supplements. */ + AST_LIST_TRAVERSE(&session->supplements, iter, next) { + if (iter->session_end) { + iter->session_end(session); + } + } +} + static void handle_incoming_response(struct ast_sip_session *session, pjsip_rx_data *rdata, enum ast_sip_session_response_priority response_priority) { @@ -3393,17 +3425,13 @@ static void handle_outgoing_response(struct ast_sip_session *session, pjsip_tx_d static int session_end(void *vsession) { struct ast_sip_session *session = vsession; - struct ast_sip_session_supplement *iter; /* Stop the scheduled termination */ sip_session_defer_termination_stop_timer(session); /* Session is dead. Notify the supplements. */ - AST_LIST_TRAVERSE(&session->supplements, iter, next) { - if (iter->session_end) { - iter->session_end(session); - } - } + handle_session_end(session); + return 0; }