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 189
    Name of Record-Route header parameter that will be used to store
187 190
    (encoded) the original FROM URI.
188 191
 
189
-   This parameter is optional, it's default value being "vsf".
192
+   This parameter is optional, it's default value being “vsf”.
190 193
 
191 194
    Example 1.1. Set rr_from_store_param parameter
192 195
 ...
... ...
@@ -198,7 +201,7 @@ modparam("uac","rr_from_store_param","my_param")
198 201
    Name of Record-Route header parameter that will be used to store
199 202
    (encoded) the original TO URI.
200 203
 
201
-   This parameter is optional, it's default value being "vst".
204
+   This parameter is optional, it's default value being “vst”.
202 205
 
203 206
    Example 1.2. Set rr_to_store_param parameter
204 207
 ...
... ...
@@ -209,15 +212,15 @@ modparam("uac","rr_to_store_param","my_param")
209 212
 
210 213
    There are 3 mode of restoring the original FROM URI and the original TO
211 214
    URI:
212
-     * "none" - no information about original URI is stored; restoration
215
+     * “none” - no information about original URI is stored; restoration
213 216
        is not possible.
214
-     * "manual" - all following replies will be restored, but not also the
217
+     * “manual” - all following replies will be restored, but not also the
215 218
        sequential requests - this must be manually updated based on
216 219
        original URI.
217
-     * "auto" - all sequential requests and replies will be automatically
220
+     * “auto” - all sequential requests and replies will be automatically
218 221
        updated based on stored original URI.
219 222
 
220
-   This parameter is optional, it's default value being "auto".
223
+   This parameter is optional, it's default value being “auto”.
221 224
 
222 225
    Example 1.3. Set restore_mode parameter
223 226
 ...
... ...
@@ -242,13 +245,17 @@ modparam("uac","restore_passwd","my_secret_passwd")
242 245
    the original from uri in order to be able to restore it in replies.
243 246
    That makes sense, if the original-uri can not be extracted from the
244 247
    original request, e.g. if msg_apply_changes() was used after calling
245
-   uac_replace_from()
248
+   uac_replace_from() or uac_replace_to().
249
+
250
+   If you create a dialog ( with dlg_manage() ) before calling
251
+   uac_replace_from(), this avp will not be needed. The values of the uris
252
+   will be stored as dialog variables.
246 253
 
247 254
    Default value of this parameter is empty.
248 255
 
249 256
    Example 1.5. Set restore_from_avp parameter
250 257
 ...
251
-modparam("uac","restore_from_avp","$avp(s:original_uri_from)")
258
+modparam("uac","restore_from_avp","$avp(original_uri_from)")
252 259
 ...
253 260
 
254 261
 3.6. restore_to_avp (string)
... ...
@@ -259,11 +266,15 @@ modparam("uac","restore_from_avp","$avp(s:original_uri_from)")
259 266
    request, e.g. if msg_apply_changes() was used after calling
260 267
    uac_replace_to()
261 268
 
269
+   If you create a dialog ( with dlg_manage() ) before calling or
270
+   uac_replace_to(), this avp will not be needed. The values of the uris
271
+   will be stored as dialog variables.
272
+
262 273
    Default value of this parameter is empty.
263 274
 
264 275
    Example 1.6. Set restore_to_avp parameter
265 276
 ...
266
-modparam("uac","restore_to_avp","$avp(s:original_uri_to)")
277
+modparam("uac","restore_to_avp","$avp(original_uri_to)")
267 278
 ...
268 279
 
269 280
 3.7. credential (string)
... ...
@@ -283,9 +294,9 @@ modparam("uac","credential","username:domain:password")
283 294
    The definition of an AVP that might contain the realm to be used to
284 295
    perform authentication.
285 296
 
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)").
297
+   If you define it, you also need to define “auth_username_avp”
298
+   (Section 3.9, “auth_username_avp (string)”) and “auth_username_avp”
299
+   (Section 3.10, “auth_password_avp (string)”).
289 300
 
290 301
    Example 1.8. Set auth_realm_avp parameter
291 302
 ...
... ...
@@ -297,9 +308,9 @@ modparam("uac","auth_realm_avp","$avp(i:10)")
297 308
    The definition of an AVP that might contain the username to be used to
298 309
    perform authentication.
299 310
 
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)").
311
+   If you define it, you also need to define “auth_realm_avp”
312
+   (Section 3.8, “auth_realm_avp (string)”) and “auth_username_avp”
313
+   (Section 3.10, “auth_password_avp (string)”).
303 314
 
304 315
    Example 1.9. Set auth_username_avp parameter
305 316
 ...
... ...
@@ -311,9 +322,9 @@ modparam("uac","auth_username_avp","$avp(i:11)")
311 322
    The definition of an AVP that might contain the password to be used to
312 323
    perform authentication.
313 324
 
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)").
325
+   If you define it, you also need to define “auth_password_avp”
326
+   (Section 3.10, “auth_password_avp (string)”) and “auth_username_avp”
327
+   (Section 3.10, “auth_password_avp (string)”).
317 328
 
318 329
    Example 1.10. Set auth_password_avp parameter
319 330
 ...
... ...
@@ -365,7 +376,7 @@ modparam("uac", "reg_contact_addr", "192.168.1.2:5080")
365 376
    5.9. uac_reg_lookup(uuid, dst)
366 377
    5.10. uac_reg_request_to(user, mode)
367 378
 
368
-5.1. uac_replace_from(display,uri)
379
+5.1.  uac_replace_from(display,uri)
369 380
 
370 381
    Replace in FROM header the display name and the URI part.
371 382
 
... ...
@@ -373,6 +384,24 @@ modparam("uac", "reg_contact_addr", "192.168.1.2:5080")
373 384
 
374 385
    This function can be used from REQUEST_ROUTE and from BRANCH_ROUTE.
375 386
 
387
+   If you set restore_mode to AUTO, the URI will be modified automatically
388
+   in all subsequent requests and replies in that dialog.
389
+
390
+   There are two ways in which the AUTO mode can be achieved.
391
+
392
+   One uses the rr module and appends to the Record-Route header a
393
+   parameter containing some strings from which the original and new URI
394
+   can be computed. The problem with this mode is that it relies on the
395
+   fact the parties will send the Route exactly as it was received. In
396
+   case there is a change, the resulting URIs will not be correct.
397
+
398
+   The other one uses the dialog module to store the original and new URI.
399
+   If you already use dialog module in your configuration, this is the
400
+   advisable mode. All you need to do to use this is to call dlg_manage()
401
+   before calling uac_replace_from(). It works by storing the URIs as
402
+   dialog variables and registering callbacks in dialog module for in
403
+   dialog requests.
404
+
376 405
    Example 1.14. uac_replace_from usage
377 406
 ...
378 407
 # replace both display and uri
... ...
@@ -385,7 +414,7 @@ uac_replace_from("","sip:robin@gotham.org");
385 414
 uac_replace_from("","");
386 415
 ...
387 416
 
388
-5.2. uac_replace_from(uri)
417
+5.2.  uac_replace_from(uri)
389 418
 
390 419
    Replace in FROM header the URI part without altering the display name.
391 420
 
... ...
@@ -398,7 +427,7 @@ uac_replace_from("","");
398 427
 uac_replace_from("sip:batman@gotham.org");
399 428
 ...
400 429
 
401
-5.3. uac_restore_from()
430
+5.3.  uac_restore_from()
402 431
 
403 432
    This function will check if the FROM URI was modified and will use the
404 433
    information stored in header parameter to restore the original FROM URI
... ...
@@ -411,7 +440,7 @@ uac_replace_from("sip:batman@gotham.org");
411 440
 uac_restore_from();
412 441
 ...
413 442
 
414
-5.4. uac_replace_to(display,uri)
443
+5.4.  uac_replace_to(display,uri)
415 444
 
416 445
    Replace in TO header the display name and the URI part.
417 446
 
... ...
@@ -422,7 +451,7 @@ uac_restore_from();
422 451
    Example 1.17. uac_replace_to usage
423 452
 ...
424 453
 # replace both display and uri
425
-uac_replace_to("$avp(s:display)","$avp(s:uri)");
454
+uac_replace_to("$avp(display)","$avp(uri)");
426 455
 # replace only display and do not touch uri
427 456
 uac_replace_to("batman","");
428 457
 # remove display and replace uri
... ...
@@ -431,7 +460,7 @@ uac_replace_to("","sip:robin@gotham.org");
431 460
 uac_replace_to("","");
432 461
 ...
433 462
 
434
-5.5. uac_replace_to(uri)
463
+5.5.  uac_replace_to(uri)
435 464
 
436 465
    Replace in TO header the URI part without altering the display name.
437 466
 
... ...
@@ -439,12 +468,30 @@ uac_replace_to("","");
439 468
 
440 469
    This function can be used from REQUEST_ROUTE and from BRANCH_ROUTE.
441 470
 
471
+   If you set restore_mode to AUTO, the URI will be modified automatically
472
+   in all subsequent requests and replies in that dialog.
473
+
474
+   There are two ways in which the AUTO mode can be achieved.
475
+
476
+   One uses the rr module and appends to the Record-Route header a
477
+   parameter containing some strings from which the original and new URI
478
+   can be computed. The problem with this mode is that it relies on the
479
+   fact the parties will send the Route exactly as it was received. In
480
+   case there is a change, the resulting URIs will not be correct.
481
+
482
+   The other one uses the dialog module to store the original and new URI.
483
+   If you already use dialog module in your configuration, this is the
484
+   advisable mode. All you need to do to use this is to call dlg_manage()
485
+   before calling uac_replace_to(). It works by storing the URIs as dialog
486
+   variables and registering callbacks in dialog module for in dialog
487
+   requests.
488
+
442 489
    Example 1.18. uac_replace_to usage
443 490
 ...
444 491
 uac_replace_to("sip:batman@gotham.org");
445 492
 ...
446 493
 
447
-5.6. uac_restore_to()
494
+5.6.  uac_restore_to()
448 495
 
449 496
    This function will check if the TO URI was modified and will use the
450 497
    information stored in header parameter to restore the original TO URI
... ...
@@ -457,7 +504,7 @@ uac_replace_to("sip:batman@gotham.org");
457 504
 uac_restore_to();
458 505
 ...
459 506
 
460
-5.7. uac_auth()
507
+5.7.  uac_auth()
461 508
 
462 509
    This function can be called only from failure route and will build the
463 510
    authentication response header and insert it into the request without
... ...
@@ -470,7 +517,7 @@ uac_restore_to();
470 517
 uac_auth();
471 518
 ...
472 519
 
473
-5.8. uac_req_send()
520
+5.8.  uac_req_send()
474 521
 
475 522
    This function sends a SIP message from the configuration file. The
476 523
    message is built out of $uac_req(...) pseudo-variable.
... ...
@@ -487,7 +534,7 @@ $uac_req(turi)="sip:kamailio.org";
487 534
 uac_req_send();
488 535
 ...
489 536
 
490
-5.9. uac_reg_lookup(uuid, dst)
537
+5.9.  uac_reg_lookup(uuid, dst)
491 538
 
492 539
    This function sets the PV dst to SIP URI that correspond to uuid in uac
493 540
    registations table. uuid and dst must be pseudo-variables.
... ...
@@ -503,7 +550,7 @@ if(uac_reg_lookup("$rU", "$ru"))
503 550
 }
504 551
 ...
505 552
 
506
-5.10. uac_reg_request_to(user, mode)
553
+5.10.  uac_reg_request_to(user, mode)
507 554
 
508 555
    This function can be used to send an authenticated request to a remote
509 556
    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 206
 			If defined and restore_mode is manual or auto, the avp is used to save
199 207
 			the original from uri in order to be able to restore it in replies.
200 208
 			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()  
209
+			request, e.g. if msg_apply_changes() was used after calling uac_replace_from()
210
+			or uac_replace_to().
211
+			</para>
212
+			<para>
213
+				If you create a dialog ( with dlg_manage() ) before calling uac_replace_from(),
214
+			this avp will not be needed. The values of the uris will be stored as dialog variables.
202 215
 			</para>
203 216
 			<para><emphasis>
204 217
 					Default value of this parameter is empty.
... ...
@@ -208,7 +221,7 @@ modparam("uac","restore_passwd","my_secret_passwd")
208 221
 				<title>Set <varname>restore_from_avp</varname> parameter</title>
209 222
 				<programlisting format="linespecific">
210 223
 ...
211
-modparam("uac","restore_from_avp","$avp(s:original_uri_from)")
224
+modparam("uac","restore_from_avp","$avp(original_uri_from)")
212 225
 ...
213 226
 				</programlisting>
214 227
 			</example>
... ...
@@ -221,6 +234,10 @@ modparam("uac","restore_from_avp","$avp(s:original_uri_from)")
221 234
 			That makes sense, if the original-uri can not be extracted from the original
222 235
 			request, e.g. if msg_apply_changes() was used after calling uac_replace_to()  
223 236
 			</para>
237
+			<para>
238
+				If you create a dialog ( with dlg_manage() ) before calling or uac_replace_to(),
239
+				this avp will not be needed. The values of the uris will be stored as dialog variables.
240
+			</para>
224 241
 			<para><emphasis>
225 242
 					Default value of this parameter is empty.
226 243
 				</emphasis>
... ...
@@ -229,7 +246,7 @@ modparam("uac","restore_from_avp","$avp(s:original_uri_from)")
229 246
 				<title>Set <varname>restore_to_avp</varname> parameter</title>
230 247
 				<programlisting format="linespecific">
231 248
 ...
232
-modparam("uac","restore_to_avp","$avp(s:original_uri_to)")
249
+modparam("uac","restore_to_avp","$avp(original_uri_to)")
233 250
 ...
234 251
 				</programlisting>
235 252
 			</example>
... ...
@@ -394,6 +411,27 @@ modparam("uac", "reg_contact_addr", "192.168.1.2:5080")
394 411
 			<para>
395 412
 			This function can be used from REQUEST_ROUTE and from BRANCH_ROUTE.
396 413
 			</para>
414
+			<para>
415
+			If you set restore_mode to AUTO, the URI will be modified automatically in
416
+			all subsequent requests and replies in that dialog.
417
+			</para>
418
+			<para>
419
+				There are two ways in which the AUTO mode can be achieved.
420
+			</para>
421
+			<para>
422
+				One uses the rr module and appends to the Record-Route header a parameter
423
+				containing some strings from which the original and new URI can be computed.
424
+				The problem with this mode is that it relies on the fact the parties will
425
+				send the Route exactly as it was received. In case there is a change, the
426
+				resulting URIs will not be correct.
427
+			</para>
428
+			<para>
429
+				The other one uses the dialog module to store the original and new URI.
430
+				If you already use dialog module in your configuration, this is the advisable mode.
431
+				All you need to do to use this is to call dlg_manage() before calling uac_replace_from().
432
+				It works by storing the URIs as dialog variables and registering callbacks in dialog 
433
+				module for in dialog requests.
434
+			</para>
397 435
 			<example>
398 436
 				<title><function>uac_replace_from</function> usage</title>
399 437
 				<programlisting format="linespecific">
... ...
@@ -474,7 +512,7 @@ uac_restore_from();
474 512
 				<programlisting format="linespecific">
475 513
 ...
476 514
 # replace both display and uri
477
-uac_replace_to("$avp(s:display)","$avp(s:uri)");
515
+uac_replace_to("$avp(display)","$avp(uri)");
478 516
 # replace only display and do not touch uri
479 517
 uac_replace_to("batman","");
480 518
 # remove display and replace uri
... ...
@@ -499,6 +537,28 @@ uac_replace_to("","");
499 537
 			<para>
500 538
 			This function can be used from REQUEST_ROUTE and from BRANCH_ROUTE.
501 539
 			</para>
540
+			<para>
541
+			If you set restore_mode to AUTO, the URI will be modified automatically in
542
+			all subsequent requests and replies in that dialog.
543
+			</para>
544
+			<para>
545
+				There are two ways in which the AUTO mode can be achieved.
546
+			</para>
547
+			<para>
548
+				One uses the rr module and appends to the Record-Route header a parameter
549
+				containing some strings from which the original and new URI can be computed.
550
+				The problem with this mode is that it relies on the fact the parties will
551
+				send the Route exactly as it was received. In case there is a change, the
552
+				resulting URIs will not be correct.
553
+			</para>
554
+			<para>
555
+				The other one uses the dialog module to store the original and new URI.
556
+				If you already use dialog module in your configuration, this is the advisable mode.
557
+				All you need to do to use this is to call dlg_manage() before calling uac_replace_to().
558
+				It works by storing the URIs as dialog variables and registering callbacks in dialog 
559
+				module for in dialog requests.
560
+			</para>
561
+
502 562
 			<example>
503 563
 				<title><function>uac_replace_to</function> usage</title>
504 564
 				<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 62
 extern unsigned short restore_to_avp_type;
60 63
 extern int_str restore_to_avp_name;
61 64
 
65
+extern struct dlg_binds dlg_api;
66
+static str from_dlgvar[] = {str_init("_uac_fu"), str_init("_uac_funew")};
67
+static str to_dlgvar[] = {str_init("_uac_to"), str_init("_uac_tonew") };
62 68
 
63 69
 static char enc_table64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
64 70
 		"abcdefghijklmnopqrstuvwxyz0123456789+/";
... ...
@@ -67,6 +73,9 @@ static int dec_table64[256];
67 73
 
68 74
 static void restore_uris_reply(struct cell* t, int type, struct tmcb_params *p);
69 75
 
76
+static void replace_callback(struct dlg_cell *dlg, int type,
77
+		struct dlg_cb_params *_params);
78
+
70 79
 #define text3B64_len(_l)   ( ( ((_l)+2)/3 ) << 2 )
71 80
 
72 81
 /* The reply, were the From-Line was replaced. */
... ...
@@ -235,9 +244,18 @@ int replace_uri( struct sip_msg *msg, str *display, str *uri,
235 244
 	char *p;
236 245
 	str param;
237 246
 	str buf;
238
-	int uac_flag;
247
+	unsigned int uac_flag;
239 248
 	int i;
240 249
 	int_str avp_value;
250
+	struct dlg_cell* dlg = 0;
251
+	str * dlgvar_names;
252
+
253
+	uac_flag = (hdr==msg->from)?FL_USE_UAC_FROM:FL_USE_UAC_TO;
254
+	if(msg->msg_flags & uac_flag)
255
+	{
256
+		LM_ERR("Called uac_replace multiple times on the message\n");
257
+		return -1;
258
+	}
241 259
 
242 260
 	/* consistency check! in AUTO mode, do NOT allow URI changing
243 261
 	 * in sequential request */
... ...
@@ -347,84 +365,133 @@ int replace_uri( struct sip_msg *msg, str *display, str *uri,
347 365
 	if (restore_mode==UAC_NO_RESTORE)
348 366
 		return 0;
349 367
 
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);
368
+	/* trying to get dialog */
369
+	if (dlg_api.get_dlg) {
370
+		dlg = dlg_api.get_dlg(msg);
371
+	}
372
+
373
+	if (dlg) {
374
+		dlgvar_names = (uac_flag==FL_USE_UAC_FROM)?from_dlgvar:to_dlgvar;
375
+		if(dlg_api.get_dlg_var(dlg, &dlgvar_names[0])) {
376
+
377
+			LM_INFO("Already called uac_replace for this dialog\n");
378
+			/* delete the from_new dlg var */
379
+
380
+			if (dlg_api.set_dlg_var(dlg, &dlgvar_names[1], 0) < 0) {
381
+				LM_ERR("cannot store new uri value\n");
382
+				dlg_api.release_dlg(dlg);
383
+				goto error;
384
+			}
385
+			LM_INFO("Deleted <%.*s> var in dialog\n",
386
+					dlgvar_names[1].len, dlgvar_names[1].s);
387
+		}
388
+		else {
389
+			/* the first time uac_replace is called for this dialog */
390
+
391
+			if (dlg_api.set_dlg_var(dlg, &dlgvar_names[0], &body->uri) < 0) {
392
+				LM_ERR("cannot store value\n");
393
+				dlg_api.release_dlg(dlg);
394
+				goto error;
395
+			}
396
+			LM_DBG("Stored <%.*s> var in dialog with value %.*s\n",
397
+					dlgvar_names[0].len, dlgvar_names[0].s, body->uri.len, body->uri.s);
398
+
399
+			if (dlg_api.register_dlgcb(dlg, DLGCB_REQ_WITHIN|DLGCB_CONFIRMED|DLGCB_TERMINATED,
400
+					(void*)(unsigned long)replace_callback, (void*)(unsigned long)uac_flag, 0) != 0) {
401
+				LM_ERR("cannot register callback\n");
402
+				dlg_api.release_dlg(dlg);
403
+				goto error;
404
+			}
405
+		}
406
+		if (dlg_api.set_dlg_var(dlg, &dlgvar_names[1], uri) < 0) {
407
+			LM_ERR("cannot store new uri value\n");
408
+			dlg_api.release_dlg(dlg);
355 409
 			goto error;
356 410
 		}
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;
411
+		LM_DBG("Stored <%.*s> var in dialog with value %.*s\n",
412
+				dlgvar_names[1].len, dlgvar_names[1].s, uri->len, uri->s);
413
+		dlg_api.release_dlg(dlg);
361 414
 	} else {
362
-		if (uri->len>MAX_URI_SIZE) {
363
-			LM_ERR("new %.*s uri too long\n",hdr->name.len,hdr->name.s);
415
+		if (!uac_rrb.append_fromtag) {
416
+			LM_ERR("'append_fromtag' RR param is not enabled!"
417
+			" - required by AUTO restore mode\n");
364 418
 			goto error;
365 419
 		}
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 420
 
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];
421
+		/* build RR parameter */
422
+		buf.s = buf_s;
423
+		if ( body->uri.len>uri->len ) {
424
+			if (body->uri.len>MAX_URI_SIZE) {
425
+				 LM_ERR("old %.*s uri too long\n",hdr->name.len,hdr->name.s);
426
+				goto error;
427
+			}
428
+			memcpy( buf.s, body->uri.s, body->uri.len);
429
+			for( i=0 ; i<uri->len ; i++ )
430
+				buf.s[i] ^=uri->s[i];
431
+			buf.len = body->uri.len;
432
+		} else {
433
+			if (uri->len>MAX_URI_SIZE) {
434
+				LM_ERR("new %.*s uri too long\n",hdr->name.len,hdr->name.s);
435
+				goto error;
436
+			}
437
+			memcpy( buf.s, uri->s, uri->len);
438
+			for( i=0 ; i<body->uri.len ; i++ )
439
+				buf.s[i] ^=body->uri.s[i];
440
+			buf.len = uri->len;
441
+		}
376 442
 
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);
443
+		/* encrypt parameter ;) */
444
+		if (uac_passwd.len)
445
+			for( i=0 ; i<buf.len ; i++)
446
+				buf.s[i] ^= uac_passwd.s[i%uac_passwd.len];
384 447
 
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;
448
+		/* encode the param */
449
+		if (encode_uri( &buf , &replace)<0 )
450
+		{
451
+			LM_ERR("failed to encode uris\n");
452
+			goto error;
453
+		}
454
+		LM_DBG("encode is=<%.*s> len=%d\n",replace.len,replace.s,replace.len);
400 455
 
401
-	if (uac_rrb.add_rr_param( msg, &param)!=0)
402
-	{
403
-		LM_ERR("add_RR_param failed\n");
404
-		goto error1;
456
+		/* add RR parameter */
457
+		param.len = 1+rr_param->len+1+replace.len;
458
+		param.s = (char*)pkg_malloc(param.len);
459
+		if (param.s==0)
460
+		{
461
+			LM_ERR("no more pkg mem\n");
462
+			goto error;
463
+		}
464
+		p = param.s;
465
+		*(p++) = ';';
466
+		memcpy( p, rr_param->s, rr_param->len);
467
+		p += rr_param->len;
468
+		*(p++) = '=';
469
+		memcpy( p, replace.s, replace.len);
470
+		p += replace.len;
471
+
472
+		if (uac_rrb.add_rr_param( msg, &param)!=0)
473
+		{
474
+			LM_ERR("add_RR_param failed\n");
475
+			goto error1;
476
+		}
477
+		pkg_free(param.s);
405 478
 	}
406 479
 
480
+	if ((msg->msg_flags&(FL_USE_UAC_FROM|FL_USE_UAC_TO))==0) {
481
+		/* add TM callback to restore the FROM/TO hdr in reply */
482
+		if (uac_tmb.register_tmcb( msg, 0, TMCB_RESPONSE_IN,
483
+			restore_uris_reply,0,0)!=1) {
484
+			LM_ERR("failed to install TM callback\n");
485
+			goto error;
486
+		}
487
+	}
488
+	msg->msg_flags |= uac_flag;
407 489
 
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;
490
+	if ( (Trans=uac_tmb.t_gett())!=NULL && Trans!=T_UNDEFINED &&
491
+		Trans->uas.request) {
492
+		Trans->uas.request->msg_flags |= uac_flag;
425 493
 	}
426 494
 
427
-	pkg_free(param.s);
428 495
 	return 0;
429 496
 error1:
430 497
 	pkg_free(param.s);
... ...
@@ -705,3 +772,98 @@ void restore_uris_reply(struct cell* t, int type, struct tmcb_params *p)
705 772
 	}
706 773
 }
707 774
 
775
+/************************** DIALOG CB function ******************************/
776
+
777
+static void replace_callback(struct dlg_cell *dlg, int type,
778
+		struct dlg_cb_params *_params)
779
+{
780
+	struct lump* l;
781
+	struct sip_msg *msg;
782
+	str old_uri;
783
+	str* new_uri;
784
+	char *p;
785
+	unsigned int uac_flag;
786
+	int dlgvar_index = 0;
787
+	str* dlgvar_names;
788
+
789
+	if (!dlg || !_params || _params->direction == DLG_DIR_NONE || !_params->req)
790
+		return;
791
+
792
+	uac_flag = (unsigned int)(unsigned long)*(_params->param);
793
+
794
+	msg = _params->req;
795
+	if(msg->msg_flags & uac_flag)
796
+		return;
797
+
798
+	dlgvar_names = (uac_flag==FL_USE_UAC_FROM)?from_dlgvar:to_dlgvar;
799
+
800
+	/* check the request direction */
801
+	if ( ((uac_flag == FL_USE_UAC_TO) && _params->direction == DLG_DIR_DOWNSTREAM) ||
802
+		((uac_flag != FL_USE_UAC_TO) && _params->direction == DLG_DIR_UPSTREAM) ) {
803
+		/* replace the TO URI */
804
+		if ( msg->to==0 && (parse_headers(msg,HDR_TO_F,0)!=0 || msg->to==0) ) {
805
+			LM_ERR("failed to parse TO hdr\n");
806
+			return;
807
+		}
808
+		old_uri = ((struct to_body*)msg->to->parsed)->uri;
809
+	} else {
810
+		/* replace the FROM URI */
811
+		if ( parse_from_header(msg)<0 ) {
812
+			LM_ERR("failed to find/parse FROM hdr\n");
813
+			return;
814
+		}
815
+		old_uri = ((struct to_body*)msg->from->parsed)->uri;
816
+	}
817
+
818
+	if (_params->direction == DLG_DIR_DOWNSTREAM) {
819
+		dlgvar_index = 1;
820
+		LM_DBG("DOWNSTREAM direction detected - replacing uri"
821
+				" with the new uri\n");
822
+	} else {
823
+		LM_DBG("UPSTREAM direction detected - replacing uri"
824
+				" with the original uri\n");
825
+	}
826
+
827
+	if ((new_uri = dlg_api.get_dlg_var(dlg, &dlgvar_names[dlgvar_index])) == 0) {
828
+		LM_DBG("<%.*s> param not found\n", dlgvar_names[dlgvar_index].len,
829
+				dlgvar_names[dlgvar_index].s);
830
+		return;
831
+	}
832
+
833
+	LM_DBG("Replace [%.*s] eith [%.*s]\n", old_uri.len, old_uri.s,
834
+			new_uri->len, new_uri->s);
835
+
836
+	/* duplicate the decoded value */
837
+	p = pkg_malloc( new_uri->len);
838
+	if (!p) {
839
+		LM_ERR("no more pkg mem\n");
840
+		return;
841
+	}
842
+	memcpy( p, new_uri->s, new_uri->len);
843
+
844
+	/* build del/add lumps */
845
+	l = del_lump( msg, old_uri.s-msg->buf, old_uri.len, 0);
846
+	if (l==0) {
847
+		LM_ERR("del lump failed\n");
848
+		goto free;
849
+	}
850
+
851
+	if (insert_new_lump_after( l, p, new_uri->len, 0)==0) {
852
+		LM_ERR("insert new lump failed\n");
853
+		goto free;
854
+	}
855
+
856
+	/* register tm callback to change replies but only if not registered earlier */
857
+	if (!(msg->msg_flags & (FL_USE_UAC_FROM|FL_USE_UAC_TO)) &&
858
+			uac_tmb.register_tmcb( msg, 0, TMCB_RESPONSE_IN,
859
+			restore_uris_reply, 0, 0) != 1 ) {
860
+		LM_ERR("failed to install TM callback\n");
861
+		return;
862
+	}
863
+	msg->msg_flags |= uac_flag;
864
+
865
+	return;
866
+
867
+free:
868
+	pkg_free(p);
869
+}
... ...
@@ -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 87
 pv_spec_t auth_username_spec;
87 88
 pv_spec_t auth_realm_spec;
88 89
 pv_spec_t auth_password_spec;
90
+struct dlg_binds dlg_api;
89 91
 
90 92
 static int w_replace_from(struct sip_msg* msg, char* p1, char* p2);
91 93
 static int w_restore_from(struct sip_msg* msg);
... ...
@@ -286,12 +288,17 @@ static int mod_init(void)
286 288
 
287 289
 		if (restore_mode==UAC_AUTO_RESTORE) {
288 290
 			/* 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;
291
+
292
+			memset(&dlg_api, 0, sizeof(struct dlg_binds));
293
+			if (load_dlg_api(&dlg_api)!=0) {
294
+				if (!uac_rrb.append_fromtag) {
295
+					LM_ERR("'append_fromtag' RR param is not enabled!"
296
+						" - required by AUTO restore mode\n");
297
+					goto error;
298
+				}
299
+				LM_DBG("failed to find dialog API - is dialog module loaded?\n");
294 300
 			}
301
+
295 302
 			/* get all requests doing loose route */
296 303
 			if (uac_rrb.register_rrcb( rr_checker, 0)!=0) {
297 304
 				LM_ERR("failed to install RR callback\n");