uac: bug fix for uac module uac_replace* functions, register callbacks after start
authorHenning Westerholt <hw@skalatan.de>
Sat, 13 Apr 2019 17:52:03 +0000 (19:52 +0200)
committerHenning Westerholt <hw@skalatan.de>
Sat, 13 Apr 2019 17:52:03 +0000 (19:52 +0200)
- 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.

src/modules/uac/replace.c
src/modules/uac/replace.h
src/modules/uac/uac.c

index 46bd1c6..6231b5a 100644 (file)
@@ -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 @@ free2:
 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;
+}
index c5b6639..f2fb6f8 100644 (file)
@@ -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
index 8528027..5a99e08 100644 (file)
@@ -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;
                                }