modules_k/uac: uac_replace_from/to AUTO mode with dialog module
authorAnca Vamanu <anca.vamanu@1and1.ro>
Thu, 19 Jul 2012 14:49:13 +0000 (17:49 +0300)
committerAnca Vamanu <anca.vamanu@1and1.ro>
Thu, 19 Jul 2012 14:49:13 +0000 (17:49 +0300)
Added a implementation for uac_replace_from/to() that uses the dialog
module for AUTO mode. In this mode the URIs are stored as dialog
variables.

The change in tm module fixes a bug: if uac_replace_to() was called, the
URI was not changed accordingly in Cancel.

modules/tm/t_cancel.c
modules_k/dialog/dialog.c
modules_k/dialog/dlg_load.h
modules_k/uac/README
modules_k/uac/doc/uac_admin.xml
modules_k/uac/replace.c
modules_k/uac/uac.c

index 1a37213..ccd2212 100644 (file)
@@ -281,10 +281,11 @@ int cancel_branch( struct cell *t, int branch,
                stop_rb_retr(irb); /* stop retransmissions */
        }
 
-       if (cfg_get(tm, tm_cfg, reparse_invite)) {
+       if (cfg_get(tm, tm_cfg, reparse_invite) ||
+                       (t->uas.request && t->uas.request->msg_flags&(FL_USE_UAC_FROM|FL_USE_UAC_TO))) {
                /* build the CANCEL from the INVITE which was sent out */
                cancel = build_local_reparse(t, branch, &len, CANCEL, CANCEL_LEN,
-                                                                        &t->to
+                                                                        (t->uas.request->msg_flags&FL_USE_UAC_TO)?0:&t->to
        #ifdef CANCEL_REASON_SUPPORT
                                                                         , reason
        #endif /* CANCEL_REASON_SUPPORT */
index 3a404d1..4d7af53 100644 (file)
@@ -400,6 +400,8 @@ int load_dlg( struct dlg_binds *dlgb )
        dlgb->terminate_dlg = dlg_bye_all;
        dlgb->set_dlg_var = set_dlg_variable;
        dlgb->get_dlg_var = get_dlg_variable;
+       dlgb->get_dlg = dlg_get_msg_dialog;
+       dlgb->release_dlg = dlg_release;
        return 1;
 }
 
index f26115f..298af4f 100644 (file)
 /* terminate_dlg function prototype */
 typedef int (*terminate_dlg_f)(struct dlg_cell* dlg, str *hdrs);
 
+typedef struct dlg_cell *(*get_dlg_f)(struct sip_msg *msg);
+
+typedef void (*release_dlg_f)(struct dlg_cell *dlg);
+
 struct dlg_binds {
        register_dlgcb_f  register_dlgcb;
        terminate_dlg_f terminate_dlg;
     set_dlg_variable_f set_dlg_var;
        get_dlg_variable_f get_dlg_var;
+       get_dlg_f          get_dlg;
+       release_dlg_f      release_dlg;
 };
 
 
index e14b721..db83d3d 100644 (file)
@@ -14,9 +14,9 @@ Ramona-Elena Modroiu
 
    <ramona@rosdev.ro>
 
-   Copyright © 2009-2010 asipto.com
+   Copyright Â© 2009-2010 asipto.com
 
-   Copyright © 2005 Voice Sistem
+   Copyright Â© 2005 Voice Sistem
      __________________________________________________________________
 
    Table of Contents
@@ -158,7 +158,10 @@ Chapter 1. Admin Guide
    The following modules must be loaded before this module:
      * TM - Transaction Module
      * RR - Record-Route Module, but only if restore mode for FROM URI is
-       set to "auto".
+       set to “auto”.
+     * Dialog Module, but only if restore mode for FROM URI is set to
+       “auto” and you want uac_replace_from or uac_replace_to to store the
+       values of the URIs as dialog variables.
 
 2.2. External Libraries or Applications
 
@@ -186,7 +189,7 @@ Chapter 1. Admin Guide
    Name of Record-Route header parameter that will be used to store
    (encoded) the original FROM URI.
 
-   This parameter is optional, it's default value being "vsf".
+   This parameter is optional, it's default value being “vsf”.
 
    Example 1.1. Set rr_from_store_param parameter
 ...
@@ -198,7 +201,7 @@ modparam("uac","rr_from_store_param","my_param")
    Name of Record-Route header parameter that will be used to store
    (encoded) the original TO URI.
 
-   This parameter is optional, it's default value being "vst".
+   This parameter is optional, it's default value being “vst”.
 
    Example 1.2. Set rr_to_store_param parameter
 ...
@@ -209,15 +212,15 @@ modparam("uac","rr_to_store_param","my_param")
 
    There are 3 mode of restoring the original FROM URI and the original TO
    URI:
-     * "none" - no information about original URI is stored; restoration
+     * “none” - no information about original URI is stored; restoration
        is not possible.
-     * "manual" - all following replies will be restored, but not also the
+     * “manual” - all following replies will be restored, but not also the
        sequential requests - this must be manually updated based on
        original URI.
-     * "auto" - all sequential requests and replies will be automatically
+     * “auto” - all sequential requests and replies will be automatically
        updated based on stored original URI.
 
-   This parameter is optional, it's default value being "auto".
+   This parameter is optional, it's default value being “auto”.
 
    Example 1.3. Set restore_mode parameter
 ...
@@ -242,13 +245,17 @@ modparam("uac","restore_passwd","my_secret_passwd")
    the original from uri in order to be able to restore it in replies.
    That makes sense, if the original-uri can not be extracted from the
    original request, e.g. if msg_apply_changes() was used after calling
-   uac_replace_from()
+   uac_replace_from() or uac_replace_to().
+
+   If you create a dialog ( with dlg_manage() ) before calling
+   uac_replace_from(), this avp will not be needed. The values of the uris
+   will be stored as dialog variables.
 
    Default value of this parameter is empty.
 
    Example 1.5. Set restore_from_avp parameter
 ...
-modparam("uac","restore_from_avp","$avp(s:original_uri_from)")
+modparam("uac","restore_from_avp","$avp(original_uri_from)")
 ...
 
 3.6. restore_to_avp (string)
@@ -259,11 +266,15 @@ modparam("uac","restore_from_avp","$avp(s:original_uri_from)")
    request, e.g. if msg_apply_changes() was used after calling
    uac_replace_to()
 
+   If you create a dialog ( with dlg_manage() ) before calling or
+   uac_replace_to(), this avp will not be needed. The values of the uris
+   will be stored as dialog variables.
+
    Default value of this parameter is empty.
 
    Example 1.6. Set restore_to_avp parameter
 ...
-modparam("uac","restore_to_avp","$avp(s:original_uri_to)")
+modparam("uac","restore_to_avp","$avp(original_uri_to)")
 ...
 
 3.7. credential (string)
@@ -283,9 +294,9 @@ modparam("uac","credential","username:domain:password")
    The definition of an AVP that might contain the realm to be used to
    perform authentication.
 
-   If you define it, you also need to define "auth_username_avp"
-   (Section 3.9, "auth_username_avp (string)") and "auth_username_avp"
-   (Section 3.10, "auth_password_avp (string)").
+   If you define it, you also need to define “auth_username_avp”
+   (Section 3.9, “auth_username_avp (string)”) and “auth_username_avp”
+   (Section 3.10, “auth_password_avp (string)”).
 
    Example 1.8. Set auth_realm_avp parameter
 ...
@@ -297,9 +308,9 @@ modparam("uac","auth_realm_avp","$avp(i:10)")
    The definition of an AVP that might contain the username to be used to
    perform authentication.
 
-   If you define it, you also need to define "auth_realm_avp"
-   (Section 3.8, "auth_realm_avp (string)") and "auth_username_avp"
-   (Section 3.10, "auth_password_avp (string)").
+   If you define it, you also need to define “auth_realm_avp”
+   (Section 3.8, “auth_realm_avp (string)”) and “auth_username_avp”
+   (Section 3.10, “auth_password_avp (string)”).
 
    Example 1.9. Set auth_username_avp parameter
 ...
@@ -311,9 +322,9 @@ modparam("uac","auth_username_avp","$avp(i:11)")
    The definition of an AVP that might contain the password to be used to
    perform authentication.
 
-   If you define it, you also need to define "auth_password_avp"
-   (Section 3.10, "auth_password_avp (string)") and "auth_username_avp"
-   (Section 3.10, "auth_password_avp (string)").
+   If you define it, you also need to define “auth_password_avp”
+   (Section 3.10, “auth_password_avp (string)”) and “auth_username_avp”
+   (Section 3.10, “auth_password_avp (string)”).
 
    Example 1.10. Set auth_password_avp parameter
 ...
@@ -365,7 +376,7 @@ modparam("uac", "reg_contact_addr", "192.168.1.2:5080")
    5.9. uac_reg_lookup(uuid, dst)
    5.10. uac_reg_request_to(user, mode)
 
-5.1. uac_replace_from(display,uri)
+5.1.  uac_replace_from(display,uri)
 
    Replace in FROM header the display name and the URI part.
 
@@ -373,6 +384,24 @@ modparam("uac", "reg_contact_addr", "192.168.1.2:5080")
 
    This function can be used from REQUEST_ROUTE and from BRANCH_ROUTE.
 
+   If you set restore_mode to AUTO, the URI will be modified automatically
+   in all subsequent requests and replies in that dialog.
+
+   There are two ways in which the AUTO mode can be achieved.
+
+   One uses the rr module and appends to the Record-Route header a
+   parameter containing some strings from which the original and new URI
+   can be computed. The problem with this mode is that it relies on the
+   fact the parties will send the Route exactly as it was received. In
+   case there is a change, the resulting URIs will not be correct.
+
+   The other one uses the dialog module to store the original and new URI.
+   If you already use dialog module in your configuration, this is the
+   advisable mode. All you need to do to use this is to call dlg_manage()
+   before calling uac_replace_from(). It works by storing the URIs as
+   dialog variables and registering callbacks in dialog module for in
+   dialog requests.
+
    Example 1.14. uac_replace_from usage
 ...
 # replace both display and uri
@@ -385,7 +414,7 @@ uac_replace_from("","sip:robin@gotham.org");
 uac_replace_from("","");
 ...
 
-5.2. uac_replace_from(uri)
+5.2.  uac_replace_from(uri)
 
    Replace in FROM header the URI part without altering the display name.
 
@@ -398,7 +427,7 @@ uac_replace_from("","");
 uac_replace_from("sip:batman@gotham.org");
 ...
 
-5.3. uac_restore_from()
+5.3.  uac_restore_from()
 
    This function will check if the FROM URI was modified and will use the
    information stored in header parameter to restore the original FROM URI
@@ -411,7 +440,7 @@ uac_replace_from("sip:batman@gotham.org");
 uac_restore_from();
 ...
 
-5.4. uac_replace_to(display,uri)
+5.4.  uac_replace_to(display,uri)
 
    Replace in TO header the display name and the URI part.
 
@@ -422,7 +451,7 @@ uac_restore_from();
    Example 1.17. uac_replace_to usage
 ...
 # replace both display and uri
-uac_replace_to("$avp(s:display)","$avp(s:uri)");
+uac_replace_to("$avp(display)","$avp(uri)");
 # replace only display and do not touch uri
 uac_replace_to("batman","");
 # remove display and replace uri
@@ -431,7 +460,7 @@ uac_replace_to("","sip:robin@gotham.org");
 uac_replace_to("","");
 ...
 
-5.5. uac_replace_to(uri)
+5.5.  uac_replace_to(uri)
 
    Replace in TO header the URI part without altering the display name.
 
@@ -439,12 +468,30 @@ uac_replace_to("","");
 
    This function can be used from REQUEST_ROUTE and from BRANCH_ROUTE.
 
+   If you set restore_mode to AUTO, the URI will be modified automatically
+   in all subsequent requests and replies in that dialog.
+
+   There are two ways in which the AUTO mode can be achieved.
+
+   One uses the rr module and appends to the Record-Route header a
+   parameter containing some strings from which the original and new URI
+   can be computed. The problem with this mode is that it relies on the
+   fact the parties will send the Route exactly as it was received. In
+   case there is a change, the resulting URIs will not be correct.
+
+   The other one uses the dialog module to store the original and new URI.
+   If you already use dialog module in your configuration, this is the
+   advisable mode. All you need to do to use this is to call dlg_manage()
+   before calling uac_replace_to(). It works by storing the URIs as dialog
+   variables and registering callbacks in dialog module for in dialog
+   requests.
+
    Example 1.18. uac_replace_to usage
 ...
 uac_replace_to("sip:batman@gotham.org");
 ...
 
-5.6. uac_restore_to()
+5.6.  uac_restore_to()
 
    This function will check if the TO URI was modified and will use the
    information stored in header parameter to restore the original TO URI
@@ -457,7 +504,7 @@ uac_replace_to("sip:batman@gotham.org");
 uac_restore_to();
 ...
 
-5.7. uac_auth()
+5.7.  uac_auth()
 
    This function can be called only from failure route and will build the
    authentication response header and insert it into the request without
@@ -470,7 +517,7 @@ uac_restore_to();
 uac_auth();
 ...
 
-5.8. uac_req_send()
+5.8.  uac_req_send()
 
    This function sends a SIP message from the configuration file. The
    message is built out of $uac_req(...) pseudo-variable.
@@ -487,7 +534,7 @@ $uac_req(turi)="sip:kamailio.org";
 uac_req_send();
 ...
 
-5.9. uac_reg_lookup(uuid, dst)
+5.9.  uac_reg_lookup(uuid, dst)
 
    This function sets the PV dst to SIP URI that correspond to uuid in uac
    registations table. uuid and dst must be pseudo-variables.
@@ -503,7 +550,7 @@ if(uac_reg_lookup("$rU", "$ru"))
 }
 ...
 
-5.10. uac_reg_request_to(user, mode)
+5.10.  uac_reg_request_to(user, mode)
 
    This function can be used to send an authenticated request to a remote
    user in the uac registrations table. It sets the request-uri, dst-uri
index 734a5f0..d194ad7 100644 (file)
                                restore mode for FROM URI is set to <quote>auto</quote>.
                        </para>
                        </listitem>
+                       <listitem>
+                       <para>
+                               <emphasis>Dialog Module</emphasis>, but only if
+                               restore mode for FROM URI is set to <quote>auto</quote> and
+                               you want uac_replace_from or uac_replace_to to store the values
+                               of the URIs as dialog variables.
+                       </para>
+                       </listitem>
                        </itemizedlist>
                        </para>
                </section>
@@ -198,7 +206,12 @@ modparam("uac","restore_passwd","my_secret_passwd")
                        If defined and restore_mode is manual or auto, the avp is used to save
                        the original from uri in order to be able to restore it in replies.
                        That makes sense, if the original-uri can not be extracted from the original
-                       request, e.g. if msg_apply_changes() was used after calling uac_replace_from()  
+                       request, e.g. if msg_apply_changes() was used after calling uac_replace_from()
+                       or uac_replace_to().
+                       </para>
+                       <para>
+                               If you create a dialog ( with dlg_manage() ) before calling uac_replace_from(),
+                       this avp will not be needed. The values of the uris will be stored as dialog variables.
                        </para>
                        <para><emphasis>
                                        Default value of this parameter is empty.
@@ -208,7 +221,7 @@ modparam("uac","restore_passwd","my_secret_passwd")
                                <title>Set <varname>restore_from_avp</varname> parameter</title>
                                <programlisting format="linespecific">
 ...
-modparam("uac","restore_from_avp","$avp(s:original_uri_from)")
+modparam("uac","restore_from_avp","$avp(original_uri_from)")
 ...
                                </programlisting>
                        </example>
@@ -221,6 +234,10 @@ modparam("uac","restore_from_avp","$avp(s:original_uri_from)")
                        That makes sense, if the original-uri can not be extracted from the original
                        request, e.g. if msg_apply_changes() was used after calling uac_replace_to()  
                        </para>
+                       <para>
+                               If you create a dialog ( with dlg_manage() ) before calling or uac_replace_to(),
+                               this avp will not be needed. The values of the uris will be stored as dialog variables.
+                       </para>
                        <para><emphasis>
                                        Default value of this parameter is empty.
                                </emphasis>
@@ -229,7 +246,7 @@ modparam("uac","restore_from_avp","$avp(s:original_uri_from)")
                                <title>Set <varname>restore_to_avp</varname> parameter</title>
                                <programlisting format="linespecific">
 ...
-modparam("uac","restore_to_avp","$avp(s:original_uri_to)")
+modparam("uac","restore_to_avp","$avp(original_uri_to)")
 ...
                                </programlisting>
                        </example>
@@ -394,6 +411,27 @@ modparam("uac", "reg_contact_addr", "192.168.1.2:5080")
                        <para>
                        This function can be used from REQUEST_ROUTE and from BRANCH_ROUTE.
                        </para>
+                       <para>
+                       If you set restore_mode to AUTO, the URI will be modified automatically in
+                       all subsequent requests and replies in that dialog.
+                       </para>
+                       <para>
+                               There are two ways in which the AUTO mode can be achieved.
+                       </para>
+                       <para>
+                               One uses the rr module and appends to the Record-Route header a parameter
+                               containing some strings from which the original and new URI can be computed.
+                               The problem with this mode is that it relies on the fact the parties will
+                               send the Route exactly as it was received. In case there is a change, the
+                               resulting URIs will not be correct.
+                       </para>
+                       <para>
+                               The other one uses the dialog module to store the original and new URI.
+                               If you already use dialog module in your configuration, this is the advisable mode.
+                               All you need to do to use this is to call dlg_manage() before calling uac_replace_from().
+                               It works by storing the URIs as dialog variables and registering callbacks in dialog 
+                               module for in dialog requests.
+                       </para>
                        <example>
                                <title><function>uac_replace_from</function> usage</title>
                                <programlisting format="linespecific">
@@ -474,7 +512,7 @@ uac_restore_from();
                                <programlisting format="linespecific">
 ...
 # replace both display and uri
-uac_replace_to("$avp(s:display)","$avp(s:uri)");
+uac_replace_to("$avp(display)","$avp(uri)");
 # replace only display and do not touch uri
 uac_replace_to("batman","");
 # remove display and replace uri
@@ -499,6 +537,28 @@ uac_replace_to("","");
                        <para>
                        This function can be used from REQUEST_ROUTE and from BRANCH_ROUTE.
                        </para>
+                       <para>
+                       If you set restore_mode to AUTO, the URI will be modified automatically in
+                       all subsequent requests and replies in that dialog.
+                       </para>
+                       <para>
+                               There are two ways in which the AUTO mode can be achieved.
+                       </para>
+                       <para>
+                               One uses the rr module and appends to the Record-Route header a parameter
+                               containing some strings from which the original and new URI can be computed.
+                               The problem with this mode is that it relies on the fact the parties will
+                               send the Route exactly as it was received. In case there is a change, the
+                               resulting URIs will not be correct.
+                       </para>
+                       <para>
+                               The other one uses the dialog module to store the original and new URI.
+                               If you already use dialog module in your configuration, this is the advisable mode.
+                               All you need to do to use this is to call dlg_manage() before calling uac_replace_to().
+                               It works by storing the URIs as dialog variables and registering callbacks in dialog 
+                               module for in dialog requests.
+                       </para>
+
                        <example>
                                <title><function>uac_replace_to</function> usage</title>
                                <programlisting format="linespecific">
index 487c498..791d69b 100644 (file)
@@ -42,6 +42,9 @@
 #include "../../modules/tm/h_table.h"
 #include "../../modules/tm/tm_load.h"
 #include "../rr/api.h"
+#include "../dialog/dlg_load.h"
+#include "../dialog/dlg_hash.h"
+
 
 #include "replace.h"
 
@@ -59,6 +62,9 @@ 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;
+static str from_dlgvar[] = {str_init("_uac_fu"), str_init("_uac_funew")};
+static str to_dlgvar[] = {str_init("_uac_to"), str_init("_uac_tonew") };
 
 static char enc_table64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                "abcdefghijklmnopqrstuvwxyz0123456789+/";
@@ -67,6 +73,9 @@ static int dec_table64[256];
 
 static void restore_uris_reply(struct cell* t, int type, struct tmcb_params *p);
 
+static void replace_callback(struct dlg_cell *dlg, int type,
+               struct dlg_cb_params *_params);
+
 #define text3B64_len(_l)   ( ( ((_l)+2)/3 ) << 2 )
 
 /* The reply, were the From-Line was replaced. */
@@ -235,9 +244,18 @@ int replace_uri( struct sip_msg *msg, str *display, str *uri,
        char *p;
        str param;
        str buf;
-       int uac_flag;
+       unsigned int uac_flag;
        int i;
        int_str avp_value;
+       struct dlg_cell* dlg = 0;
+       str * dlgvar_names;
+
+       uac_flag = (hdr==msg->from)?FL_USE_UAC_FROM:FL_USE_UAC_TO;
+       if(msg->msg_flags & uac_flag)
+       {
+               LM_ERR("Called uac_replace multiple times on the message\n");
+               return -1;
+       }
 
        /* consistency check! in AUTO mode, do NOT allow URI changing
         * in sequential request */
@@ -347,84 +365,133 @@ int replace_uri( struct sip_msg *msg, str *display, str *uri,
        if (restore_mode==UAC_NO_RESTORE)
                return 0;
 
-       /* build RR parameter */
-       buf.s = buf_s;
-       if ( body->uri.len>uri->len ) {
-               if (body->uri.len>MAX_URI_SIZE) {
-                        LM_ERR("old %.*s uri too long\n",hdr->name.len,hdr->name.s);
+       /* trying to get dialog */
+       if (dlg_api.get_dlg) {
+               dlg = dlg_api.get_dlg(msg);
+       }
+
+       if (dlg) {
+               dlgvar_names = (uac_flag==FL_USE_UAC_FROM)?from_dlgvar:to_dlgvar;
+               if(dlg_api.get_dlg_var(dlg, &dlgvar_names[0])) {
+
+                       LM_INFO("Already called uac_replace for this dialog\n");
+                       /* delete the from_new dlg var */
+
+                       if (dlg_api.set_dlg_var(dlg, &dlgvar_names[1], 0) < 0) {
+                               LM_ERR("cannot store new uri value\n");
+                               dlg_api.release_dlg(dlg);
+                               goto error;
+                       }
+                       LM_INFO("Deleted <%.*s> var in dialog\n",
+                                       dlgvar_names[1].len, dlgvar_names[1].s);
+               }
+               else {
+                       /* the first time uac_replace is called for this dialog */
+
+                       if (dlg_api.set_dlg_var(dlg, &dlgvar_names[0], &body->uri) < 0) {
+                               LM_ERR("cannot store value\n");
+                               dlg_api.release_dlg(dlg);
+                               goto error;
+                       }
+                       LM_DBG("Stored <%.*s> var in dialog with value %.*s\n",
+                                       dlgvar_names[0].len, dlgvar_names[0].s, body->uri.len, body->uri.s);
+
+                       if (dlg_api.register_dlgcb(dlg, DLGCB_REQ_WITHIN|DLGCB_CONFIRMED|DLGCB_TERMINATED,
+                                       (void*)(unsigned long)replace_callback, (void*)(unsigned long)uac_flag, 0) != 0) {
+                               LM_ERR("cannot register callback\n");
+                               dlg_api.release_dlg(dlg);
+                               goto error;
+                       }
+               }
+               if (dlg_api.set_dlg_var(dlg, &dlgvar_names[1], uri) < 0) {
+                       LM_ERR("cannot store new uri value\n");
+                       dlg_api.release_dlg(dlg);
                        goto error;
                }
-               memcpy( buf.s, body->uri.s, body->uri.len);
-               for( i=0 ; i<uri->len ; i++ )
-                       buf.s[i] ^=uri->s[i];
-               buf.len = body->uri.len;
+               LM_DBG("Stored <%.*s> var in dialog with value %.*s\n",
+                               dlgvar_names[1].len, dlgvar_names[1].s, uri->len, uri->s);
+               dlg_api.release_dlg(dlg);
        } else {
-               if (uri->len>MAX_URI_SIZE) {
-                       LM_ERR("new %.*s uri too long\n",hdr->name.len,hdr->name.s);
+               if (!uac_rrb.append_fromtag) {
+                       LM_ERR("'append_fromtag' RR param is not enabled!"
+                       " - required by AUTO restore mode\n");
                        goto error;
                }
-               memcpy( buf.s, uri->s, uri->len);
-               for( i=0 ; i<body->uri.len ; i++ )
-                       buf.s[i] ^=body->uri.s[i];
-               buf.len = uri->len;
-       }
 
-       /* encrypt parameter ;) */
-       if (uac_passwd.len)
-               for( i=0 ; i<buf.len ; i++)
-                       buf.s[i] ^= uac_passwd.s[i%uac_passwd.len];
+               /* build RR parameter */
+               buf.s = buf_s;
+               if ( body->uri.len>uri->len ) {
+                       if (body->uri.len>MAX_URI_SIZE) {
+                                LM_ERR("old %.*s uri too long\n",hdr->name.len,hdr->name.s);
+                               goto error;
+                       }
+                       memcpy( buf.s, body->uri.s, body->uri.len);
+                       for( i=0 ; i<uri->len ; i++ )
+                               buf.s[i] ^=uri->s[i];
+                       buf.len = body->uri.len;
+               } else {
+                       if (uri->len>MAX_URI_SIZE) {
+                               LM_ERR("new %.*s uri too long\n",hdr->name.len,hdr->name.s);
+                               goto error;
+                       }
+                       memcpy( buf.s, uri->s, uri->len);
+                       for( i=0 ; i<body->uri.len ; i++ )
+                               buf.s[i] ^=body->uri.s[i];
+                       buf.len = uri->len;
+               }
 
-       /* encode the param */
-       if (encode_uri( &buf , &replace)<0 )
-       {
-               LM_ERR("failed to encode uris\n");
-               goto error;
-       }
-       LM_DBG("encode is=<%.*s> len=%d\n",replace.len,replace.s,replace.len);
+               /* encrypt parameter ;) */
+               if (uac_passwd.len)
+                       for( i=0 ; i<buf.len ; i++)
+                               buf.s[i] ^= uac_passwd.s[i%uac_passwd.len];
 
-       /* add RR parameter */
-       param.len = 1+rr_param->len+1+replace.len;
-       param.s = (char*)pkg_malloc(param.len);
-       if (param.s==0)
-       {
-               LM_ERR("no more pkg mem\n");
-               goto error;
-       }
-       p = param.s;
-       *(p++) = ';';
-       memcpy( p, rr_param->s, rr_param->len);
-       p += rr_param->len;
-       *(p++) = '=';
-       memcpy( p, replace.s, replace.len);
-       p += replace.len;
+               /* encode the param */
+               if (encode_uri( &buf , &replace)<0 )
+               {
+                       LM_ERR("failed to encode uris\n");
+                       goto error;
+               }
+               LM_DBG("encode is=<%.*s> len=%d\n",replace.len,replace.s,replace.len);
 
-       if (uac_rrb.add_rr_param( msg, &param)!=0)
-       {
-               LM_ERR("add_RR_param failed\n");
-               goto error1;
+               /* add RR parameter */
+               param.len = 1+rr_param->len+1+replace.len;
+               param.s = (char*)pkg_malloc(param.len);
+               if (param.s==0)
+               {
+                       LM_ERR("no more pkg mem\n");
+                       goto error;
+               }
+               p = param.s;
+               *(p++) = ';';
+               memcpy( p, rr_param->s, rr_param->len);
+               p += rr_param->len;
+               *(p++) = '=';
+               memcpy( p, replace.s, replace.len);
+               p += replace.len;
+
+               if (uac_rrb.add_rr_param( msg, &param)!=0)
+               {
+                       LM_ERR("add_RR_param failed\n");
+                       goto error1;
+               }
+               pkg_free(param.s);
        }
 
+       if ((msg->msg_flags&(FL_USE_UAC_FROM|FL_USE_UAC_TO))==0) {
+               /* add TM callback to restore the FROM/TO hdr in reply */
+               if (uac_tmb.register_tmcb( msg, 0, TMCB_RESPONSE_IN,
+                       restore_uris_reply,0,0)!=1) {
+                       LM_ERR("failed to install TM callback\n");
+                       goto error;
+               }
+       }
+       msg->msg_flags |= uac_flag;
 
-       uac_flag = (hdr==msg->from)?FL_USE_UAC_FROM:FL_USE_UAC_TO;
-
-       if ((msg->msg_flags&uac_flag)==0) {
-                       /* first time here ? */
-                       if ((msg->msg_flags&(FL_USE_UAC_FROM|FL_USE_UAC_TO))==0){
-                                       /* add TM callback to restore the FROM/TO hdr in reply */
-                                       if (uac_tmb.register_tmcb( msg, 0, TMCB_RESPONSE_IN,
-                                       restore_uris_reply,0,0)!=1) {
-                                                       LM_ERR("failed to install TM callback\n");
-                                                       goto error1;
-                                       }
-                       }
-                       /* set TO/ FROM specific flags */
-                       msg->msg_flags |= uac_flag;
-                       if ( (Trans=uac_tmb.t_gett())!=NULL && Trans!=T_UNDEFINED &&
-                       Trans->uas.request)
-                                       Trans->uas.request->msg_flags |= uac_flag;
+       if ( (Trans=uac_tmb.t_gett())!=NULL && Trans!=T_UNDEFINED &&
+               Trans->uas.request) {
+               Trans->uas.request->msg_flags |= uac_flag;
        }
 
-       pkg_free(param.s);
        return 0;
 error1:
        pkg_free(param.s);
@@ -705,3 +772,98 @@ void restore_uris_reply(struct cell* t, int type, struct tmcb_params *p)
        }
 }
 
+/************************** DIALOG CB function ******************************/
+
+static void replace_callback(struct dlg_cell *dlg, int type,
+               struct dlg_cb_params *_params)
+{
+       struct lump* l;
+       struct sip_msg *msg;
+       str old_uri;
+       str* new_uri;
+       char *p;
+       unsigned int uac_flag;
+       int dlgvar_index = 0;
+       str* dlgvar_names;
+
+       if (!dlg || !_params || _params->direction == DLG_DIR_NONE || !_params->req)
+               return;
+
+       uac_flag = (unsigned int)(unsigned long)*(_params->param);
+
+       msg = _params->req;
+       if(msg->msg_flags & uac_flag)
+               return;
+
+       dlgvar_names = (uac_flag==FL_USE_UAC_FROM)?from_dlgvar:to_dlgvar;
+
+       /* check the request direction */
+       if ( ((uac_flag == FL_USE_UAC_TO) && _params->direction == DLG_DIR_DOWNSTREAM) ||
+               ((uac_flag != FL_USE_UAC_TO) && _params->direction == DLG_DIR_UPSTREAM) ) {
+               /* replace the TO URI */
+               if ( msg->to==0 && (parse_headers(msg,HDR_TO_F,0)!=0 || msg->to==0) ) {
+                       LM_ERR("failed to parse TO hdr\n");
+                       return;
+               }
+               old_uri = ((struct to_body*)msg->to->parsed)->uri;
+       } else {
+               /* replace the FROM URI */
+               if ( parse_from_header(msg)<0 ) {
+                       LM_ERR("failed to find/parse FROM hdr\n");
+                       return;
+               }
+               old_uri = ((struct to_body*)msg->from->parsed)->uri;
+       }
+
+       if (_params->direction == DLG_DIR_DOWNSTREAM) {
+               dlgvar_index = 1;
+               LM_DBG("DOWNSTREAM direction detected - replacing uri"
+                               " with the new uri\n");
+       } else {
+               LM_DBG("UPSTREAM direction detected - replacing uri"
+                               " with the original uri\n");
+       }
+
+       if ((new_uri = dlg_api.get_dlg_var(dlg, &dlgvar_names[dlgvar_index])) == 0) {
+               LM_DBG("<%.*s> param not found\n", dlgvar_names[dlgvar_index].len,
+                               dlgvar_names[dlgvar_index].s);
+               return;
+       }
+
+       LM_DBG("Replace [%.*s] eith [%.*s]\n", old_uri.len, old_uri.s,
+                       new_uri->len, new_uri->s);
+
+       /* duplicate the decoded value */
+       p = pkg_malloc( new_uri->len);
+       if (!p) {
+               LM_ERR("no more pkg mem\n");
+               return;
+       }
+       memcpy( p, new_uri->s, new_uri->len);
+
+       /* build del/add lumps */
+       l = del_lump( msg, old_uri.s-msg->buf, old_uri.len, 0);
+       if (l==0) {
+               LM_ERR("del lump failed\n");
+               goto free;
+       }
+
+       if (insert_new_lump_after( l, p, new_uri->len, 0)==0) {
+               LM_ERR("insert new lump failed\n");
+               goto free;
+       }
+
+       /* register tm callback to change replies but only if not registered earlier */
+       if (!(msg->msg_flags & (FL_USE_UAC_FROM|FL_USE_UAC_TO)) &&
+                       uac_tmb.register_tmcb( msg, 0, TMCB_RESPONSE_IN,
+                       restore_uris_reply, 0, 0) != 1 ) {
+               LM_ERR("failed to install TM callback\n");
+               return;
+       }
+       msg->msg_flags |= uac_flag;
+
+       return;
+
+free:
+       pkg_free(p);
+}
index 763dd5a..63282a1 100644 (file)
@@ -51,6 +51,7 @@
 #include "../../rpc.h"
 #include "../../rpc_lookup.h"
 #include "../../cfg/cfg_struct.h"
+#include "../dialog/dlg_load.h"
 
 #include "../rr/api.h"
 
@@ -86,6 +87,7 @@ 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);
@@ -286,12 +288,17 @@ static int mod_init(void)
 
                if (restore_mode==UAC_AUTO_RESTORE) {
                        /* we need the append_fromtag on in RR */
-                       if (!uac_rrb.append_fromtag) {
-                               LM_ERR("'append_fromtag' RR param is not enabled"
-                                       " - required by AUTO restore mode!"
-                                       " Or you should set from_restore_mode param to 'none'\n");
-                               goto error;
+
+                       memset(&dlg_api, 0, sizeof(struct dlg_binds));
+                       if (load_dlg_api(&dlg_api)!=0) {
+                               if (!uac_rrb.append_fromtag) {
+                                       LM_ERR("'append_fromtag' RR param is not enabled!"
+                                               " - required by AUTO restore mode\n");
+                                       goto error;
+                               }
+                               LM_DBG("failed to find dialog API - is dialog module loaded?\n");
                        }
+
                        /* get all requests doing loose route */
                        if (uac_rrb.register_rrcb( rr_checker, 0)!=0) {
                                LM_ERR("failed to install RR callback\n");