Browse code

modules_k/uac: uac_replace_from/to AUTO mode with dialog module

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.

Anca Vamanu authored on 19/07/2012 14:49:13
Showing 7 changed files
... ...
@@ -281,10 +281,11 @@ int cancel_branch( struct cell *t, int branch,
281 281
 		stop_rb_retr(irb); /* stop retransmissions */
282 282
 	}
283 283
 
284
-	if (cfg_get(tm, tm_cfg, reparse_invite)) {
284
+	if (cfg_get(tm, tm_cfg, reparse_invite) ||
285
+			(t->uas.request && t->uas.request->msg_flags&(FL_USE_UAC_FROM|FL_USE_UAC_TO))) {
285 286
 		/* build the CANCEL from the INVITE which was sent out */
286 287
 		cancel = build_local_reparse(t, branch, &len, CANCEL, CANCEL_LEN,
287
-									 &t->to
288
+									 (t->uas.request->msg_flags&FL_USE_UAC_TO)?0:&t->to
288 289
 	#ifdef CANCEL_REASON_SUPPORT
289 290
 									 , reason
290 291
 	#endif /* CANCEL_REASON_SUPPORT */
... ...
@@ -400,6 +400,8 @@ int load_dlg( struct dlg_binds *dlgb )
400 400
 	dlgb->terminate_dlg = dlg_bye_all;
401 401
 	dlgb->set_dlg_var = set_dlg_variable;
402 402
 	dlgb->get_dlg_var = get_dlg_variable;
403
+	dlgb->get_dlg = dlg_get_msg_dialog;
404
+	dlgb->release_dlg = dlg_release;
403 405
 	return 1;
404 406
 }
405 407
 
... ...
@@ -35,11 +35,17 @@
35 35
 /* terminate_dlg function prototype */
36 36
 typedef int (*terminate_dlg_f)(struct dlg_cell* dlg, str *hdrs);
37 37
 
38
+typedef struct dlg_cell *(*get_dlg_f)(struct sip_msg *msg);
39
+
40
+typedef void (*release_dlg_f)(struct dlg_cell *dlg);
41
+
38 42
 struct dlg_binds {
39 43
 	register_dlgcb_f  register_dlgcb;
40 44
 	terminate_dlg_f terminate_dlg;
41 45
     set_dlg_variable_f set_dlg_var;
42 46
 	get_dlg_variable_f get_dlg_var;
47
+	get_dlg_f          get_dlg;
48
+	release_dlg_f      release_dlg;
43 49
 };
44 50
 
45 51
 
... ...
@@ -14,9 +14,9 @@ Ramona-Elena Modroiu
14 14
 
15 15
    <ramona@rosdev.ro>
16 16
 
17
-   Copyright � 2009-2010 asipto.com
17
+   Copyright © 2009-2010 asipto.com
18 18
 
19
-   Copyright � 2005 Voice Sistem
19
+   Copyright © 2005 Voice Sistem
20 20
      __________________________________________________________________
21 21
 
22 22
    Table of Contents
... ...
@@ -158,7 +158,10 @@ Chapter 1. Admin Guide
158 158
    The following modules must be loaded before this module:
159 159
      * TM - Transaction Module
160 160
      * RR - Record-Route Module, but only if restore mode for FROM URI is
161
-       set to "auto".
161
+       set to “auto”.
162
+     * Dialog Module, but only if restore mode for FROM URI is set to
163
+       “auto” and you want uac_replace_from or uac_replace_to to store the
164
+       values of the URIs as dialog variables.
162 165
 
163 166
 2.2. External Libraries or Applications
164 167
 
... ...
@@ -186,7 +189,7 @@ Chapter 1. Admin Guide
186 186
    Name of Record-Route header parameter that will be used to store
187 187
    (encoded) the original FROM URI.
188 188
 
189
-   This parameter is optional, it's default value being "vsf".
189
+   This parameter is optional, it's default value being “vsf”.
190 190
 
191 191
    Example 1.1. Set rr_from_store_param parameter
192 192
 ...
... ...
@@ -198,7 +201,7 @@ modparam("uac","rr_from_store_param","my_param")
198 198
    Name of Record-Route header parameter that will be used to store
199 199
    (encoded) the original TO URI.
200 200
 
201
-   This parameter is optional, it's default value being "vst".
201
+   This parameter is optional, it's default value being “vst”.
202 202
 
203 203
    Example 1.2. Set rr_to_store_param parameter
204 204
 ...
... ...
@@ -209,15 +212,15 @@ modparam("uac","rr_to_store_param","my_param")
209 209
 
210 210
    There are 3 mode of restoring the original FROM URI and the original TO
211 211
    URI:
212
-     * "none" - no information about original URI is stored; restoration
212
+     * “none” - no information about original URI is stored; restoration
213 213
        is not possible.
214
-     * "manual" - all following replies will be restored, but not also the
214
+     * “manual” - all following replies will be restored, but not also the
215 215
        sequential requests - this must be manually updated based on
216 216
        original URI.
217
-     * "auto" - all sequential requests and replies will be automatically
217
+     * “auto” - all sequential requests and replies will be automatically
218 218
        updated based on stored original URI.
219 219
 
220
-   This parameter is optional, it's default value being "auto".
220
+   This parameter is optional, it's default value being “auto”.
221 221
 
222 222
    Example 1.3. Set restore_mode parameter
223 223
 ...
... ...
@@ -242,13 +245,17 @@ modparam("uac","restore_passwd","my_secret_passwd")
242 242
    the original from uri in order to be able to restore it in replies.
243 243
    That makes sense, if the original-uri can not be extracted from the
244 244
    original request, e.g. if msg_apply_changes() was used after calling
245
-   uac_replace_from()
245
+   uac_replace_from() or uac_replace_to().
246
+
247
+   If you create a dialog ( with dlg_manage() ) before calling
248
+   uac_replace_from(), this avp will not be needed. The values of the uris
249
+   will be stored as dialog variables.
246 250
 
247 251
    Default value of this parameter is empty.
248 252
 
249 253
    Example 1.5. Set restore_from_avp parameter
250 254
 ...
251
-modparam("uac","restore_from_avp","$avp(s:original_uri_from)")
255
+modparam("uac","restore_from_avp","$avp(original_uri_from)")
252 256
 ...
253 257
 
254 258
 3.6. restore_to_avp (string)
... ...
@@ -259,11 +266,15 @@ modparam("uac","restore_from_avp","$avp(s:original_uri_from)")
259 259
    request, e.g. if msg_apply_changes() was used after calling
260 260
    uac_replace_to()
261 261
 
262
+   If you create a dialog ( with dlg_manage() ) before calling or
263
+   uac_replace_to(), this avp will not be needed. The values of the uris
264
+   will be stored as dialog variables.
265
+
262 266
    Default value of this parameter is empty.
263 267
 
264 268
    Example 1.6. Set restore_to_avp parameter
265 269
 ...
266
-modparam("uac","restore_to_avp","$avp(s:original_uri_to)")
270
+modparam("uac","restore_to_avp","$avp(original_uri_to)")
267 271
 ...
268 272
 
269 273
 3.7. credential (string)
... ...
@@ -283,9 +294,9 @@ modparam("uac","credential","username:domain:password")
283 283
    The definition of an AVP that might contain the realm to be used to
284 284
    perform authentication.
285 285
 
286
-   If you define it, you also need to define "auth_username_avp"
287
-   (Section 3.9, "auth_username_avp (string)") and "auth_username_avp"
288
-   (Section 3.10, "auth_password_avp (string)").
286
+   If you define it, you also need to define “auth_username_avp”
287
+   (Section 3.9, “auth_username_avp (string)”) and “auth_username_avp”
288
+   (Section 3.10, “auth_password_avp (string)”).
289 289
 
290 290
    Example 1.8. Set auth_realm_avp parameter
291 291
 ...
... ...
@@ -297,9 +308,9 @@ modparam("uac","auth_realm_avp","$avp(i:10)")
297 297
    The definition of an AVP that might contain the username to be used to
298 298
    perform authentication.
299 299
 
300
-   If you define it, you also need to define "auth_realm_avp"
301
-   (Section 3.8, "auth_realm_avp (string)") and "auth_username_avp"
302
-   (Section 3.10, "auth_password_avp (string)").
300
+   If you define it, you also need to define “auth_realm_avp”
301
+   (Section 3.8, “auth_realm_avp (string)”) and “auth_username_avp”
302
+   (Section 3.10, “auth_password_avp (string)”).
303 303
 
304 304
    Example 1.9. Set auth_username_avp parameter
305 305
 ...
... ...
@@ -311,9 +322,9 @@ modparam("uac","auth_username_avp","$avp(i:11)")
311 311
    The definition of an AVP that might contain the password to be used to
312 312
    perform authentication.
313 313
 
314
-   If you define it, you also need to define "auth_password_avp"
315
-   (Section 3.10, "auth_password_avp (string)") and "auth_username_avp"
316
-   (Section 3.10, "auth_password_avp (string)").
314
+   If you define it, you also need to define “auth_password_avp”
315
+   (Section 3.10, “auth_password_avp (string)”) and “auth_username_avp”
316
+   (Section 3.10, “auth_password_avp (string)”).
317 317
 
318 318
    Example 1.10. Set auth_password_avp parameter
319 319
 ...
... ...
@@ -365,7 +376,7 @@ modparam("uac", "reg_contact_addr", "192.168.1.2:5080")
365 365
    5.9. uac_reg_lookup(uuid, dst)
366 366
    5.10. uac_reg_request_to(user, mode)
367 367
 
368
-5.1. uac_replace_from(display,uri)
368
+5.1.  uac_replace_from(display,uri)
369 369
 
370 370
    Replace in FROM header the display name and the URI part.
371 371
 
... ...
@@ -373,6 +384,24 @@ modparam("uac", "reg_contact_addr", "192.168.1.2:5080")
373 373
 
374 374
    This function can be used from REQUEST_ROUTE and from BRANCH_ROUTE.
375 375
 
376
+   If you set restore_mode to AUTO, the URI will be modified automatically
377
+   in all subsequent requests and replies in that dialog.
378
+
379
+   There are two ways in which the AUTO mode can be achieved.
380
+
381
+   One uses the rr module and appends to the Record-Route header a
382
+   parameter containing some strings from which the original and new URI
383
+   can be computed. The problem with this mode is that it relies on the
384
+   fact the parties will send the Route exactly as it was received. In
385
+   case there is a change, the resulting URIs will not be correct.
386
+
387
+   The other one uses the dialog module to store the original and new URI.
388
+   If you already use dialog module in your configuration, this is the
389
+   advisable mode. All you need to do to use this is to call dlg_manage()
390
+   before calling uac_replace_from(). It works by storing the URIs as
391
+   dialog variables and registering callbacks in dialog module for in
392
+   dialog requests.
393
+
376 394
    Example 1.14. uac_replace_from usage
377 395
 ...
378 396
 # replace both display and uri
... ...
@@ -385,7 +414,7 @@ uac_replace_from("","sip:robin@gotham.org");
385 385
 uac_replace_from("","");
386 386
 ...
387 387
 
388
-5.2. uac_replace_from(uri)
388
+5.2.  uac_replace_from(uri)
389 389
 
390 390
    Replace in FROM header the URI part without altering the display name.
391 391
 
... ...
@@ -398,7 +427,7 @@ uac_replace_from("","");
398 398
 uac_replace_from("sip:batman@gotham.org");
399 399
 ...
400 400
 
401
-5.3. uac_restore_from()
401
+5.3.  uac_restore_from()
402 402
 
403 403
    This function will check if the FROM URI was modified and will use the
404 404
    information stored in header parameter to restore the original FROM URI
... ...
@@ -411,7 +440,7 @@ uac_replace_from("sip:batman@gotham.org");
411 411
 uac_restore_from();
412 412
 ...
413 413
 
414
-5.4. uac_replace_to(display,uri)
414
+5.4.  uac_replace_to(display,uri)
415 415
 
416 416
    Replace in TO header the display name and the URI part.
417 417
 
... ...
@@ -422,7 +451,7 @@ uac_restore_from();
422 422
    Example 1.17. uac_replace_to usage
423 423
 ...
424 424
 # replace both display and uri
425
-uac_replace_to("$avp(s:display)","$avp(s:uri)");
425
+uac_replace_to("$avp(display)","$avp(uri)");
426 426
 # replace only display and do not touch uri
427 427
 uac_replace_to("batman","");
428 428
 # remove display and replace uri
... ...
@@ -431,7 +460,7 @@ uac_replace_to("","sip:robin@gotham.org");
431 431
 uac_replace_to("","");
432 432
 ...
433 433
 
434
-5.5. uac_replace_to(uri)
434
+5.5.  uac_replace_to(uri)
435 435
 
436 436
    Replace in TO header the URI part without altering the display name.
437 437
 
... ...
@@ -439,12 +468,30 @@ uac_replace_to("","");
439 439
 
440 440
    This function can be used from REQUEST_ROUTE and from BRANCH_ROUTE.
441 441
 
442
+   If you set restore_mode to AUTO, the URI will be modified automatically
443
+   in all subsequent requests and replies in that dialog.
444
+
445
+   There are two ways in which the AUTO mode can be achieved.
446
+
447
+   One uses the rr module and appends to the Record-Route header a
448
+   parameter containing some strings from which the original and new URI
449
+   can be computed. The problem with this mode is that it relies on the
450
+   fact the parties will send the Route exactly as it was received. In
451
+   case there is a change, the resulting URIs will not be correct.
452
+
453
+   The other one uses the dialog module to store the original and new URI.
454
+   If you already use dialog module in your configuration, this is the
455
+   advisable mode. All you need to do to use this is to call dlg_manage()
456
+   before calling uac_replace_to(). It works by storing the URIs as dialog
457
+   variables and registering callbacks in dialog module for in dialog
458
+   requests.
459
+
442 460
    Example 1.18. uac_replace_to usage
443 461
 ...
444 462
 uac_replace_to("sip:batman@gotham.org");
445 463
 ...
446 464
 
447
-5.6. uac_restore_to()
465
+5.6.  uac_restore_to()
448 466
 
449 467
    This function will check if the TO URI was modified and will use the
450 468
    information stored in header parameter to restore the original TO URI
... ...
@@ -457,7 +504,7 @@ uac_replace_to("sip:batman@gotham.org");
457 457
 uac_restore_to();
458 458
 ...
459 459
 
460
-5.7. uac_auth()
460
+5.7.  uac_auth()
461 461
 
462 462
    This function can be called only from failure route and will build the
463 463
    authentication response header and insert it into the request without
... ...
@@ -470,7 +517,7 @@ uac_restore_to();
470 470
 uac_auth();
471 471
 ...
472 472
 
473
-5.8. uac_req_send()
473
+5.8.  uac_req_send()
474 474
 
475 475
    This function sends a SIP message from the configuration file. The
476 476
    message is built out of $uac_req(...) pseudo-variable.
... ...
@@ -487,7 +534,7 @@ $uac_req(turi)="sip:kamailio.org";
487 487
 uac_req_send();
488 488
 ...
489 489
 
490
-5.9. uac_reg_lookup(uuid, dst)
490
+5.9.  uac_reg_lookup(uuid, dst)
491 491
 
492 492
    This function sets the PV dst to SIP URI that correspond to uuid in uac
493 493
    registations table. uuid and dst must be pseudo-variables.
... ...
@@ -503,7 +550,7 @@ if(uac_reg_lookup("$rU", "$ru"))
503 503
 }
504 504
 ...
505 505
 
506
-5.10. uac_reg_request_to(user, mode)
506
+5.10.  uac_reg_request_to(user, mode)
507 507
 
508 508
    This function can be used to send an authenticated request to a remote
509 509
    user in the uac registrations table. It sets the request-uri, dst-uri
... ...
@@ -67,6 +67,14 @@
67 67
 				restore mode for FROM URI is set to <quote>auto</quote>.
68 68
 			</para>
69 69
 			</listitem>
70
+			<listitem>
71
+			<para>
72
+				<emphasis>Dialog Module</emphasis>, but only if
73
+				restore mode for FROM URI is set to <quote>auto</quote> and
74
+				you want uac_replace_from or uac_replace_to to store the values
75
+				of the URIs as dialog variables.
76
+			</para>
77
+			</listitem>
70 78
 			</itemizedlist>
71 79
 			</para>
72 80
 		</section>
... ...
@@ -198,7 +206,12 @@ modparam("uac","restore_passwd","my_secret_passwd")
198 198
 			If defined and restore_mode is manual or auto, the avp is used to save
199 199
 			the original from uri in order to be able to restore it in replies.
200 200
 			That makes sense, if the original-uri can not be extracted from the original
201
-			request, e.g. if msg_apply_changes() was used after calling uac_replace_from()  
201
+			request, e.g. if msg_apply_changes() was used after calling uac_replace_from()
202
+			or uac_replace_to().
203
+			</para>
204
+			<para>
205
+				If you create a dialog ( with dlg_manage() ) before calling uac_replace_from(),
206
+			this avp will not be needed. The values of the uris will be stored as dialog variables.
202 207
 			</para>
203 208
 			<para><emphasis>
204 209
 					Default value of this parameter is empty.
... ...
@@ -208,7 +221,7 @@ modparam("uac","restore_passwd","my_secret_passwd")
208 208
 				<title>Set <varname>restore_from_avp</varname> parameter</title>
209 209
 				<programlisting format="linespecific">
210 210
 ...
211
-modparam("uac","restore_from_avp","$avp(s:original_uri_from)")
211
+modparam("uac","restore_from_avp","$avp(original_uri_from)")
212 212
 ...
213 213
 				</programlisting>
214 214
 			</example>
... ...
@@ -221,6 +234,10 @@ modparam("uac","restore_from_avp","$avp(s:original_uri_from)")
221 221
 			That makes sense, if the original-uri can not be extracted from the original
222 222
 			request, e.g. if msg_apply_changes() was used after calling uac_replace_to()  
223 223
 			</para>
224
+			<para>
225
+				If you create a dialog ( with dlg_manage() ) before calling or uac_replace_to(),
226
+				this avp will not be needed. The values of the uris will be stored as dialog variables.
227
+			</para>
224 228
 			<para><emphasis>
225 229
 					Default value of this parameter is empty.
226 230
 				</emphasis>
... ...
@@ -229,7 +246,7 @@ modparam("uac","restore_from_avp","$avp(s:original_uri_from)")
229 229
 				<title>Set <varname>restore_to_avp</varname> parameter</title>
230 230
 				<programlisting format="linespecific">
231 231
 ...
232
-modparam("uac","restore_to_avp","$avp(s:original_uri_to)")
232
+modparam("uac","restore_to_avp","$avp(original_uri_to)")
233 233
 ...
234 234
 				</programlisting>
235 235
 			</example>
... ...
@@ -394,6 +411,27 @@ modparam("uac", "reg_contact_addr", "192.168.1.2:5080")
394 394
 			<para>
395 395
 			This function can be used from REQUEST_ROUTE and from BRANCH_ROUTE.
396 396
 			</para>
397
+			<para>
398
+			If you set restore_mode to AUTO, the URI will be modified automatically in
399
+			all subsequent requests and replies in that dialog.
400
+			</para>
401
+			<para>
402
+				There are two ways in which the AUTO mode can be achieved.
403
+			</para>
404
+			<para>
405
+				One uses the rr module and appends to the Record-Route header a parameter
406
+				containing some strings from which the original and new URI can be computed.
407
+				The problem with this mode is that it relies on the fact the parties will
408
+				send the Route exactly as it was received. In case there is a change, the
409
+				resulting URIs will not be correct.
410
+			</para>
411
+			<para>
412
+				The other one uses the dialog module to store the original and new URI.
413
+				If you already use dialog module in your configuration, this is the advisable mode.
414
+				All you need to do to use this is to call dlg_manage() before calling uac_replace_from().
415
+				It works by storing the URIs as dialog variables and registering callbacks in dialog 
416
+				module for in dialog requests.
417
+			</para>
397 418
 			<example>
398 419
 				<title><function>uac_replace_from</function> usage</title>
399 420
 				<programlisting format="linespecific">
... ...
@@ -474,7 +512,7 @@ uac_restore_from();
474 474
 				<programlisting format="linespecific">
475 475
 ...
476 476
 # replace both display and uri
477
-uac_replace_to("$avp(s:display)","$avp(s:uri)");
477
+uac_replace_to("$avp(display)","$avp(uri)");
478 478
 # replace only display and do not touch uri
479 479
 uac_replace_to("batman","");
480 480
 # remove display and replace uri
... ...
@@ -499,6 +537,28 @@ uac_replace_to("","");
499 499
 			<para>
500 500
 			This function can be used from REQUEST_ROUTE and from BRANCH_ROUTE.
501 501
 			</para>
502
+			<para>
503
+			If you set restore_mode to AUTO, the URI will be modified automatically in
504
+			all subsequent requests and replies in that dialog.
505
+			</para>
506
+			<para>
507
+				There are two ways in which the AUTO mode can be achieved.
508
+			</para>
509
+			<para>
510
+				One uses the rr module and appends to the Record-Route header a parameter
511
+				containing some strings from which the original and new URI can be computed.
512
+				The problem with this mode is that it relies on the fact the parties will
513
+				send the Route exactly as it was received. In case there is a change, the
514
+				resulting URIs will not be correct.
515
+			</para>
516
+			<para>
517
+				The other one uses the dialog module to store the original and new URI.
518
+				If you already use dialog module in your configuration, this is the advisable mode.
519
+				All you need to do to use this is to call dlg_manage() before calling uac_replace_to().
520
+				It works by storing the URIs as dialog variables and registering callbacks in dialog 
521
+				module for in dialog requests.
522
+			</para>
523
+
502 524
 			<example>
503 525
 				<title><function>uac_replace_to</function> usage</title>
504 526
 				<programlisting format="linespecific">
... ...
@@ -42,6 +42,9 @@
42 42
 #include "../../modules/tm/h_table.h"
43 43
 #include "../../modules/tm/tm_load.h"
44 44
 #include "../rr/api.h"
45
+#include "../dialog/dlg_load.h"
46
+#include "../dialog/dlg_hash.h"
47
+
45 48
 
46 49
 #include "replace.h"
47 50
 
... ...
@@ -59,6 +62,9 @@ extern int_str restore_from_avp_name;
59 59
 extern unsigned short restore_to_avp_type;
60 60
 extern int_str restore_to_avp_name;
61 61
 
62
+extern struct dlg_binds dlg_api;
63
+static str from_dlgvar[] = {str_init("_uac_fu"), str_init("_uac_funew")};
64
+static str to_dlgvar[] = {str_init("_uac_to"), str_init("_uac_tonew") };
62 65
 
63 66
 static char enc_table64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
64 67
 		"abcdefghijklmnopqrstuvwxyz0123456789+/";
... ...
@@ -67,6 +73,9 @@ static int dec_table64[256];
67 67
 
68 68
 static void restore_uris_reply(struct cell* t, int type, struct tmcb_params *p);
69 69
 
70
+static void replace_callback(struct dlg_cell *dlg, int type,
71
+		struct dlg_cb_params *_params);
72
+
70 73
 #define text3B64_len(_l)   ( ( ((_l)+2)/3 ) << 2 )
71 74
 
72 75
 /* The reply, were the From-Line was replaced. */
... ...
@@ -235,9 +244,18 @@ int replace_uri( struct sip_msg *msg, str *display, str *uri,
235 235
 	char *p;
236 236
 	str param;
237 237
 	str buf;
238
-	int uac_flag;
238
+	unsigned int uac_flag;
239 239
 	int i;
240 240
 	int_str avp_value;
241
+	struct dlg_cell* dlg = 0;
242
+	str * dlgvar_names;
243
+
244
+	uac_flag = (hdr==msg->from)?FL_USE_UAC_FROM:FL_USE_UAC_TO;
245
+	if(msg->msg_flags & uac_flag)
246
+	{
247
+		LM_ERR("Called uac_replace multiple times on the message\n");
248
+		return -1;
249
+	}
241 250
 
242 251
 	/* consistency check! in AUTO mode, do NOT allow URI changing
243 252
 	 * in sequential request */
... ...
@@ -347,84 +365,133 @@ int replace_uri( struct sip_msg *msg, str *display, str *uri,
347 347
 	if (restore_mode==UAC_NO_RESTORE)
348 348
 		return 0;
349 349
 
350
-	/* build RR parameter */
351
-	buf.s = buf_s;
352
-	if ( body->uri.len>uri->len ) {
353
-		if (body->uri.len>MAX_URI_SIZE) {
354
-			 LM_ERR("old %.*s uri too long\n",hdr->name.len,hdr->name.s);
350
+	/* trying to get dialog */
351
+	if (dlg_api.get_dlg) {
352
+		dlg = dlg_api.get_dlg(msg);
353
+	}
354
+
355
+	if (dlg) {
356
+		dlgvar_names = (uac_flag==FL_USE_UAC_FROM)?from_dlgvar:to_dlgvar;
357
+		if(dlg_api.get_dlg_var(dlg, &dlgvar_names[0])) {
358
+
359
+			LM_INFO("Already called uac_replace for this dialog\n");
360
+			/* delete the from_new dlg var */
361
+
362
+			if (dlg_api.set_dlg_var(dlg, &dlgvar_names[1], 0) < 0) {
363
+				LM_ERR("cannot store new uri value\n");
364
+				dlg_api.release_dlg(dlg);
365
+				goto error;
366
+			}
367
+			LM_INFO("Deleted <%.*s> var in dialog\n",
368
+					dlgvar_names[1].len, dlgvar_names[1].s);
369
+		}
370
+		else {
371
+			/* the first time uac_replace is called for this dialog */
372
+
373
+			if (dlg_api.set_dlg_var(dlg, &dlgvar_names[0], &body->uri) < 0) {
374
+				LM_ERR("cannot store value\n");
375
+				dlg_api.release_dlg(dlg);
376
+				goto error;
377
+			}
378
+			LM_DBG("Stored <%.*s> var in dialog with value %.*s\n",
379
+					dlgvar_names[0].len, dlgvar_names[0].s, body->uri.len, body->uri.s);
380
+
381
+			if (dlg_api.register_dlgcb(dlg, DLGCB_REQ_WITHIN|DLGCB_CONFIRMED|DLGCB_TERMINATED,
382
+					(void*)(unsigned long)replace_callback, (void*)(unsigned long)uac_flag, 0) != 0) {
383
+				LM_ERR("cannot register callback\n");
384
+				dlg_api.release_dlg(dlg);
385
+				goto error;
386
+			}
387
+		}
388
+		if (dlg_api.set_dlg_var(dlg, &dlgvar_names[1], uri) < 0) {
389
+			LM_ERR("cannot store new uri value\n");
390
+			dlg_api.release_dlg(dlg);
355 391
 			goto error;
356 392
 		}
357
-		memcpy( buf.s, body->uri.s, body->uri.len);
358
-		for( i=0 ; i<uri->len ; i++ )
359
-			buf.s[i] ^=uri->s[i];
360
-		buf.len = body->uri.len;
393
+		LM_DBG("Stored <%.*s> var in dialog with value %.*s\n",
394
+				dlgvar_names[1].len, dlgvar_names[1].s, uri->len, uri->s);
395
+		dlg_api.release_dlg(dlg);
361 396
 	} else {
362
-		if (uri->len>MAX_URI_SIZE) {
363
-			LM_ERR("new %.*s uri too long\n",hdr->name.len,hdr->name.s);
397
+		if (!uac_rrb.append_fromtag) {
398
+			LM_ERR("'append_fromtag' RR param is not enabled!"
399
+			" - required by AUTO restore mode\n");
364 400
 			goto error;
365 401
 		}
366
-		memcpy( buf.s, uri->s, uri->len);
367
-		for( i=0 ; i<body->uri.len ; i++ )
368
-			buf.s[i] ^=body->uri.s[i];
369
-		buf.len = uri->len;
370
-	}
371 402
 
372
-	/* encrypt parameter ;) */
373
-	if (uac_passwd.len)
374
-		for( i=0 ; i<buf.len ; i++)
375
-			buf.s[i] ^= uac_passwd.s[i%uac_passwd.len];
403
+		/* build RR parameter */
404
+		buf.s = buf_s;
405
+		if ( body->uri.len>uri->len ) {
406
+			if (body->uri.len>MAX_URI_SIZE) {
407
+				 LM_ERR("old %.*s uri too long\n",hdr->name.len,hdr->name.s);
408
+				goto error;
409
+			}
410
+			memcpy( buf.s, body->uri.s, body->uri.len);
411
+			for( i=0 ; i<uri->len ; i++ )
412
+				buf.s[i] ^=uri->s[i];
413
+			buf.len = body->uri.len;
414
+		} else {
415
+			if (uri->len>MAX_URI_SIZE) {
416
+				LM_ERR("new %.*s uri too long\n",hdr->name.len,hdr->name.s);
417
+				goto error;
418
+			}
419
+			memcpy( buf.s, uri->s, uri->len);
420
+			for( i=0 ; i<body->uri.len ; i++ )
421
+				buf.s[i] ^=body->uri.s[i];
422
+			buf.len = uri->len;
423
+		}
376 424
 
377
-	/* encode the param */
378
-	if (encode_uri( &buf , &replace)<0 )
379
-	{
380
-		LM_ERR("failed to encode uris\n");
381
-		goto error;
382
-	}
383
-	LM_DBG("encode is=<%.*s> len=%d\n",replace.len,replace.s,replace.len);
425
+		/* encrypt parameter ;) */
426
+		if (uac_passwd.len)
427
+			for( i=0 ; i<buf.len ; i++)
428
+				buf.s[i] ^= uac_passwd.s[i%uac_passwd.len];
384 429
 
385
-	/* add RR parameter */
386
-	param.len = 1+rr_param->len+1+replace.len;
387
-	param.s = (char*)pkg_malloc(param.len);
388
-	if (param.s==0)
389
-	{
390
-		LM_ERR("no more pkg mem\n");
391
-		goto error;
392
-	}
393
-	p = param.s;
394
-	*(p++) = ';';
395
-	memcpy( p, rr_param->s, rr_param->len);
396
-	p += rr_param->len;
397
-	*(p++) = '=';
398
-	memcpy( p, replace.s, replace.len);
399
-	p += replace.len;
430
+		/* encode the param */
431
+		if (encode_uri( &buf , &replace)<0 )
432
+		{
433
+			LM_ERR("failed to encode uris\n");
434
+			goto error;
435
+		}
436
+		LM_DBG("encode is=<%.*s> len=%d\n",replace.len,replace.s,replace.len);
400 437
 
401
-	if (uac_rrb.add_rr_param( msg, &param)!=0)
402
-	{
403
-		LM_ERR("add_RR_param failed\n");
404
-		goto error1;
438
+		/* add RR parameter */
439
+		param.len = 1+rr_param->len+1+replace.len;
440
+		param.s = (char*)pkg_malloc(param.len);
441
+		if (param.s==0)
442
+		{
443
+			LM_ERR("no more pkg mem\n");
444
+			goto error;
445
+		}
446
+		p = param.s;
447
+		*(p++) = ';';
448
+		memcpy( p, rr_param->s, rr_param->len);
449
+		p += rr_param->len;
450
+		*(p++) = '=';
451
+		memcpy( p, replace.s, replace.len);
452
+		p += replace.len;
453
+
454
+		if (uac_rrb.add_rr_param( msg, &param)!=0)
455
+		{
456
+			LM_ERR("add_RR_param failed\n");
457
+			goto error1;
458
+		}
459
+		pkg_free(param.s);
405 460
 	}
406 461
 
462
+	if ((msg->msg_flags&(FL_USE_UAC_FROM|FL_USE_UAC_TO))==0) {
463
+		/* add TM callback to restore the FROM/TO hdr in reply */
464
+		if (uac_tmb.register_tmcb( msg, 0, TMCB_RESPONSE_IN,
465
+			restore_uris_reply,0,0)!=1) {
466
+			LM_ERR("failed to install TM callback\n");
467
+			goto error;
468
+		}
469
+	}
470
+	msg->msg_flags |= uac_flag;
407 471
 
408
-	uac_flag = (hdr==msg->from)?FL_USE_UAC_FROM:FL_USE_UAC_TO;
409
-
410
-	if ((msg->msg_flags&uac_flag)==0) {
411
-			/* first time here ? */
412
-			if ((msg->msg_flags&(FL_USE_UAC_FROM|FL_USE_UAC_TO))==0){
413
-					/* add TM callback to restore the FROM/TO hdr in reply */
414
-					if (uac_tmb.register_tmcb( msg, 0, TMCB_RESPONSE_IN,
415
-					restore_uris_reply,0,0)!=1) {
416
-							LM_ERR("failed to install TM callback\n");
417
-							goto error1;
418
-					}
419
-			}
420
-			/* set TO/ FROM specific flags */
421
-			msg->msg_flags |= uac_flag;
422
-			if ( (Trans=uac_tmb.t_gett())!=NULL && Trans!=T_UNDEFINED &&
423
-			Trans->uas.request)
424
-					Trans->uas.request->msg_flags |= uac_flag;
472
+	if ( (Trans=uac_tmb.t_gett())!=NULL && Trans!=T_UNDEFINED &&
473
+		Trans->uas.request) {
474
+		Trans->uas.request->msg_flags |= uac_flag;
425 475
 	}
426 476
 
427
-	pkg_free(param.s);
428 477
 	return 0;
429 478
 error1:
430 479
 	pkg_free(param.s);
... ...
@@ -705,3 +772,98 @@ void restore_uris_reply(struct cell* t, int type, struct tmcb_params *p)
705 705
 	}
706 706
 }
707 707
 
708
+/************************** DIALOG CB function ******************************/
709
+
710
+static void replace_callback(struct dlg_cell *dlg, int type,
711
+		struct dlg_cb_params *_params)
712
+{
713
+	struct lump* l;
714
+	struct sip_msg *msg;
715
+	str old_uri;
716
+	str* new_uri;
717
+	char *p;
718
+	unsigned int uac_flag;
719
+	int dlgvar_index = 0;
720
+	str* dlgvar_names;
721
+
722
+	if (!dlg || !_params || _params->direction == DLG_DIR_NONE || !_params->req)
723
+		return;
724
+
725
+	uac_flag = (unsigned int)(unsigned long)*(_params->param);
726
+
727
+	msg = _params->req;
728
+	if(msg->msg_flags & uac_flag)
729
+		return;
730
+
731
+	dlgvar_names = (uac_flag==FL_USE_UAC_FROM)?from_dlgvar:to_dlgvar;
732
+
733
+	/* check the request direction */
734
+	if ( ((uac_flag == FL_USE_UAC_TO) && _params->direction == DLG_DIR_DOWNSTREAM) ||
735
+		((uac_flag != FL_USE_UAC_TO) && _params->direction == DLG_DIR_UPSTREAM) ) {
736
+		/* replace the TO URI */
737
+		if ( msg->to==0 && (parse_headers(msg,HDR_TO_F,0)!=0 || msg->to==0) ) {
738
+			LM_ERR("failed to parse TO hdr\n");
739
+			return;
740
+		}
741
+		old_uri = ((struct to_body*)msg->to->parsed)->uri;
742
+	} else {
743
+		/* replace the FROM URI */
744
+		if ( parse_from_header(msg)<0 ) {
745
+			LM_ERR("failed to find/parse FROM hdr\n");
746
+			return;
747
+		}
748
+		old_uri = ((struct to_body*)msg->from->parsed)->uri;
749
+	}
750
+
751
+	if (_params->direction == DLG_DIR_DOWNSTREAM) {
752
+		dlgvar_index = 1;
753
+		LM_DBG("DOWNSTREAM direction detected - replacing uri"
754
+				" with the new uri\n");
755
+	} else {
756
+		LM_DBG("UPSTREAM direction detected - replacing uri"
757
+				" with the original uri\n");
758
+	}
759
+
760
+	if ((new_uri = dlg_api.get_dlg_var(dlg, &dlgvar_names[dlgvar_index])) == 0) {
761
+		LM_DBG("<%.*s> param not found\n", dlgvar_names[dlgvar_index].len,
762
+				dlgvar_names[dlgvar_index].s);
763
+		return;
764
+	}
765
+
766
+	LM_DBG("Replace [%.*s] eith [%.*s]\n", old_uri.len, old_uri.s,
767
+			new_uri->len, new_uri->s);
768
+
769
+	/* duplicate the decoded value */
770
+	p = pkg_malloc( new_uri->len);
771
+	if (!p) {
772
+		LM_ERR("no more pkg mem\n");
773
+		return;
774
+	}
775
+	memcpy( p, new_uri->s, new_uri->len);
776
+
777
+	/* build del/add lumps */
778
+	l = del_lump( msg, old_uri.s-msg->buf, old_uri.len, 0);
779
+	if (l==0) {
780
+		LM_ERR("del lump failed\n");
781
+		goto free;
782
+	}
783
+
784
+	if (insert_new_lump_after( l, p, new_uri->len, 0)==0) {
785
+		LM_ERR("insert new lump failed\n");
786
+		goto free;
787
+	}
788
+
789
+	/* register tm callback to change replies but only if not registered earlier */
790
+	if (!(msg->msg_flags & (FL_USE_UAC_FROM|FL_USE_UAC_TO)) &&
791
+			uac_tmb.register_tmcb( msg, 0, TMCB_RESPONSE_IN,
792
+			restore_uris_reply, 0, 0) != 1 ) {
793
+		LM_ERR("failed to install TM callback\n");
794
+		return;
795
+	}
796
+	msg->msg_flags |= uac_flag;
797
+
798
+	return;
799
+
800
+free:
801
+	pkg_free(p);
802
+}
... ...
@@ -51,6 +51,7 @@
51 51
 #include "../../rpc.h"
52 52
 #include "../../rpc_lookup.h"
53 53
 #include "../../cfg/cfg_struct.h"
54
+#include "../dialog/dlg_load.h"
54 55
 
55 56
 #include "../rr/api.h"
56 57
 
... ...
@@ -86,6 +87,7 @@ struct rr_binds uac_rrb;
86 86
 pv_spec_t auth_username_spec;
87 87
 pv_spec_t auth_realm_spec;
88 88
 pv_spec_t auth_password_spec;
89
+struct dlg_binds dlg_api;
89 90
 
90 91
 static int w_replace_from(struct sip_msg* msg, char* p1, char* p2);
91 92
 static int w_restore_from(struct sip_msg* msg);
... ...
@@ -286,12 +288,17 @@ static int mod_init(void)
286 286
 
287 287
 		if (restore_mode==UAC_AUTO_RESTORE) {
288 288
 			/* we need the append_fromtag on in RR */
289
-			if (!uac_rrb.append_fromtag) {
290
-				LM_ERR("'append_fromtag' RR param is not enabled"
291
-					" - required by AUTO restore mode!"
292
-					" Or you should set from_restore_mode param to 'none'\n");
293
-				goto error;
289
+
290
+			memset(&dlg_api, 0, sizeof(struct dlg_binds));
291
+			if (load_dlg_api(&dlg_api)!=0) {
292
+				if (!uac_rrb.append_fromtag) {
293
+					LM_ERR("'append_fromtag' RR param is not enabled!"
294
+						" - required by AUTO restore mode\n");
295
+					goto error;
296
+				}
297
+				LM_DBG("failed to find dialog API - is dialog module loaded?\n");
294 298
 			}
299
+
295 300
 			/* get all requests doing loose route */
296 301
 			if (uac_rrb.register_rrcb( rr_checker, 0)!=0) {
297 302
 				LM_ERR("failed to install RR callback\n");