From a829305aa207ddcda3936a0ffab082cb93359efc Mon Sep 17 00:00:00 2001 From: Henning Westerholt Date: Sat, 13 Apr 2019 19:52:03 +0200 Subject: [PATCH] uac: bug fix for uac module uac_replace* functions, register callbacks after start - bug fix for uac module uac_replace* functions, register callbacks after restart - only applies to the dialog tracking mode of the module - the uac module was not using the available dialog callbacks for a proxy (re-)start - because of this the uac module was not able to properly re-write in-dialog messages like BYEs after a proxy restart - As we don't have access to the uac_flag at the dialog on load callback, we just install a callback for both from and to rewriting cases. If only one of the functions is used in the cfg hen the uac module will obviously not find database variables for the other case, and will log an error. This is of course also a bit inefficient, but as it only applies to this (re-)start case it does not matter. (cherry picked from commit aa7dee1ab874aaac807c2166f38ec9da0fa0ccf6) --- src/modules/uac/replace.c | 75 ++++++++++++++++++++++++++++++++++++++- src/modules/uac/replace.h | 2 ++ src/modules/uac/uac.c | 4 +-- 3 files changed, 77 insertions(+), 4 deletions(-) diff --git a/src/modules/uac/replace.c b/src/modules/uac/replace.c index 46bd1c6965a..6231b5a7aeb 100644 --- a/src/modules/uac/replace.c +++ b/src/modules/uac/replace.c @@ -55,7 +55,7 @@ extern int_str restore_from_avp_name; extern unsigned short restore_to_avp_type; extern int_str restore_to_avp_name; -extern struct dlg_binds dlg_api; +struct dlg_binds dlg_api; static str from_dlgvar[] = {str_init("_uac_fu"), str_init("_uac_funew"), str_init("_uac_fdp"), str_init("_uac_fdpnew")}; static str to_dlgvar[] = {str_init("_uac_to"), str_init("_uac_tonew"), str_init("_uac_tdp"), str_init("_uac_tdpnew")}; @@ -1006,3 +1006,76 @@ static void replace_callback(struct dlg_cell *dlg, int type, free: pkg_free(p); } + + +/* helper function to avoid code duplication */ +static inline int uac_load_callback_helper(struct dlg_cell* dialog, unsigned int uac_flag) { + + if( dlg_api.register_dlgcb(dialog, DLGCB_REQ_WITHIN, + (void*)(unsigned long)replace_callback, (void*)(unsigned long)uac_flag, 0) != 0) { + LM_ERR("can't register create dialog REQ_WITHIN callback\n"); + return -1; + } + + if( dlg_api.register_dlgcb(dialog, DLGCB_CONFIRMED, + (void*)(unsigned long)replace_callback, (void*)(unsigned long)uac_flag, 0) != 0) { + LM_ERR("can't register create dialog CONFIRM callback\n"); + return -1; + } + + if( dlg_api.register_dlgcb(dialog, DLGCB_TERMINATED, + (void*)(unsigned long)replace_callback, (void*)(unsigned long)uac_flag, 0) != 0) { + LM_ERR("can't register create dialog TERMINATED callback\n"); + return -1; + } + return 0; +} + + +/* callback for loading a dialog from database */ +static void uac_on_load_callback(struct dlg_cell* dialog, int type, struct dlg_cb_params* params) { + + if(!dialog) { + LM_ERR("invalid values\n!"); + return; + } + + /* Note: + * We don't have a way to access the real uac flags from the uac_replace_* + * method call at this point in time anymore. Therefore we just install a + * callback for both FROM and TO replace cases. This might be a bit + * inefficient in cases where only one of the functions is used. But as + * this applies only e.g. to a proxy restart with runnning dialogs, it + * does not matter. The replace_callback function will just not find a + * an entry in the dialog variables table and log an error. + */ + if(uac_load_callback_helper(dialog, FL_USE_UAC_FROM) != 0) { + LM_ERR("can't register create callbacks for UAC FROM\n"); + return; + } + if(uac_load_callback_helper(dialog, FL_USE_UAC_TO) != 0) { + LM_ERR("can't register create callbacks for UAC TO\n"); + return; + } + + LM_DBG("dialog '%p' loaded and callbacks registered\n", dialog); +} + + +/* initialization of all necessary callbacks to track a dialog */ +int uac_init_dlg(void) { + + memset(&dlg_api, 0, sizeof(struct dlg_binds)); + + if( load_dlg_api(&dlg_api) != 0) { + LM_ERR("can't load dialog API\n"); + return -1; + } + + if( dlg_api.register_dlgcb( 0, DLGCB_LOADED, uac_on_load_callback, 0, 0) != 0) { + LM_ERR("can't register on load callback\n"); + return -1; + } + LM_DBG("loaded dialog API and registered on load callback\n"); + return 0; +} diff --git a/src/modules/uac/replace.h b/src/modules/uac/replace.h index c5b6639d4e8..f2fb6f8a4e3 100644 --- a/src/modules/uac/replace.h +++ b/src/modules/uac/replace.h @@ -41,5 +41,7 @@ int restore_uri( struct sip_msg *msg, str *rr_param, str* restore_avp, int check /* RR callback functions */ void rr_checker(struct sip_msg *msg, str *r_param, void *cb_param); +/* init dlg module */ +int uac_init_dlg(void); #endif diff --git a/src/modules/uac/uac.c b/src/modules/uac/uac.c index 8528027f7eb..5a99e0820b9 100644 --- a/src/modules/uac/uac.c +++ b/src/modules/uac/uac.c @@ -90,7 +90,6 @@ struct rr_binds uac_rrb; pv_spec_t auth_username_spec; pv_spec_t auth_realm_spec; pv_spec_t auth_password_spec; -struct dlg_binds dlg_api; static int w_replace_from(struct sip_msg* msg, char* p1, char* p2); static int w_restore_from(struct sip_msg* msg, char* p1, char* p2); @@ -294,7 +293,6 @@ static int mod_init(void) if (restore_mode==UAC_AUTO_RESTORE) { /* we need the append_fromtag on in RR */ - memset(&dlg_api, 0, sizeof(struct dlg_binds)); if (uac_restore_dlg==0) { if (!uac_rrb.append_fromtag) { LM_ERR("'append_fromtag' RR param is not enabled!" @@ -302,7 +300,7 @@ static int mod_init(void) goto error; } } else { - if (load_dlg_api(&dlg_api)!=0) { + if (uac_init_dlg()!=0) { LM_ERR("failed to find dialog API - is dialog module loaded?\n"); goto error; }