Browse code

Merge branch 'master' of https://github.com/kamailio/kamailio

Patric Marschall authored on 16/06/2015 13:38:01
Showing 7 changed files
... ...
@@ -42,9 +42,6 @@
42 42
 #include "dlg_req_within.h"
43 43
 #include "dlg_db_handler.h"
44 44
 
45
-#define MAX_LDG_LOCKS  2048
46
-#define MIN_LDG_LOCKS  2
47
-
48 45
 extern int dlg_ka_interval;
49 46
 
50 47
 /*! global dialog table */
... ...
@@ -223,7 +220,7 @@ int dlg_clean_run(ticks_t ti)
223 223
 	tm = (unsigned int)time(NULL);
224 224
 	for(i=0; i<d_table->size; i++)
225 225
 	{
226
-		lock_set_get(d_table->locks, d_table->entries[i].lock_idx);
226
+		dlg_lock(d_table, &d_table->entries[i]);
227 227
 		dlg = d_table->entries[i].first;
228 228
 		while (dlg) {
229 229
 			tdlg = dlg;
... ...
@@ -243,7 +240,7 @@ int dlg_clean_run(ticks_t ti)
243 243
 				tdlg->dflags |= DLG_FLAG_CHANGED;
244 244
 			}
245 245
 		}
246
-		lock_set_release(d_table->locks, d_table->entries[i].lock_idx);
246
+		dlg_unlock(d_table, &d_table->entries[i]);
247 247
 	}
248 248
 	return 0;
249 249
 }
... ...
@@ -288,30 +285,13 @@ int init_dlg_table(unsigned int size)
288 288
 	d_table->size = size;
289 289
 	d_table->entries = (struct dlg_entry*)(d_table+1);
290 290
 
291
-	n = (size<MAX_LDG_LOCKS)?size:MAX_LDG_LOCKS;
292
-	for(  ; n>=MIN_LDG_LOCKS ; n-- ) {
293
-		d_table->locks = lock_set_alloc(n);
294
-		if (d_table->locks==0)
295
-			continue;
296
-		if (lock_set_init(d_table->locks)==0) {
297
-			lock_set_dealloc(d_table->locks);
298
-			d_table->locks = 0;
299
-			continue;
300
-		}
301
-		d_table->locks_no = n;
302
-		break;
303
-	}
304
-
305
-	if (d_table->locks==0) {
306
-		LM_ERR("unable to allocted at least %d locks for the hash table\n",
307
-			MIN_LDG_LOCKS);
308
-		goto error1;
309
-	}
310
-
311 291
 	for( i=0 ; i<size; i++ ) {
312 292
 		memset( &(d_table->entries[i]), 0, sizeof(struct dlg_entry) );
293
+		if(lock_init(&d_table->entries[i].lock)<0) {
294
+			LM_ERR("failed to init lock for slot: %d\n", i);
295
+			goto error1;
296
+		}
313 297
 		d_table->entries[i].next_id = rand() % (3*size);
314
-		d_table->entries[i].lock_idx = i % d_table->locks_no;
315 298
 	}
316 299
 
317 300
 	return 0;
... ...
@@ -411,11 +391,6 @@ void destroy_dlg_table(void)
411 411
 	if (d_table==0)
412 412
 		return;
413 413
 
414
-	if (d_table->locks) {
415
-		lock_set_destroy(d_table->locks);
416
-		lock_set_dealloc(d_table->locks);
417
-	}
418
-
419 414
 	for( i=0 ; i<d_table->size; i++ ) {
420 415
 		dlg = d_table->entries[i].first;
421 416
 		while (dlg) {
... ...
@@ -423,7 +398,7 @@ void destroy_dlg_table(void)
423 423
 			dlg = dlg->next;
424 424
 			destroy_dlg(l_dlg);
425 425
 		}
426
-
426
+		lock_destroy(&d_table->entries[i].lock);
427 427
 	}
428 428
 
429 429
 	shm_free(d_table);
... ...
@@ -33,6 +33,7 @@
33 33
 #include "../../locking.h"
34 34
 #include "../../lib/kmi/mi.h"
35 35
 #include "../../timer.h"
36
+#include "../../atomic_ops.h"
36 37
 #include "dlg_timer.h"
37 38
 #include "dlg_cb.h"
38 39
 
... ...
@@ -134,7 +135,9 @@ typedef struct dlg_entry
134 134
 	struct dlg_cell    *first;	/*!< dialog list */
135 135
 	struct dlg_cell    *last;	/*!< optimisation, end of the dialog list */
136 136
 	unsigned int       next_id;	/*!< next id */
137
-	unsigned int       lock_idx;	/*!< lock index */
137
+	gen_lock_t lock;     /* mutex to access items in the slot */
138
+	atomic_t locker_pid; /* pid of the process that holds the lock */
139
+	int rec_lock_level;  /* recursive lock count */
138 140
 } dlg_entry_t;
139 141
 
140 142
 
... ...
@@ -143,8 +146,6 @@ typedef struct dlg_table
143 143
 {
144 144
 	unsigned int       size;	/*!< size of the dialog table */
145 145
 	struct dlg_entry   *entries;	/*!< dialog hash table */
146
-	unsigned int       locks_no;	/*!< number of locks */
147
-	gen_lock_set_t     *locks;	/*!< lock table */
148 146
 } dlg_table_t;
149 147
 
150 148
 
... ...
@@ -160,12 +161,22 @@ extern dlg_table_t *d_table;
160 160
 
161 161
 
162 162
 /*!
163
- * \brief Set a dialog lock
163
+ * \brief Set a dialog lock (re-entrant)
164 164
  * \param _table dialog table
165 165
  * \param _entry locked entry
166 166
  */
167 167
 #define dlg_lock(_table, _entry) \
168
-		lock_set_get( (_table)->locks, (_entry)->lock_idx);
168
+		do { \
169
+			int mypid; \
170
+			mypid = my_pid(); \
171
+			if (likely(atomic_get( &(_entry)->locker_pid) != mypid)) { \
172
+				lock_get( &(_entry)->lock); \
173
+				atomic_set( &(_entry)->locker_pid, mypid); \
174
+			} else { \
175
+				/* locked within the same process that executed us */ \
176
+				(_entry)->rec_lock_level++; \
177
+			} \
178
+		} while(0)
169 179
 
170 180
 
171 181
 /*!
... ...
@@ -174,7 +185,15 @@ extern dlg_table_t *d_table;
174 174
  * \param _entry locked entry
175 175
  */
176 176
 #define dlg_unlock(_table, _entry) \
177
-		lock_set_release( (_table)->locks, (_entry)->lock_idx);
177
+		do { \
178
+			if (likely((_entry)->rec_lock_level == 0)) { \
179
+				atomic_set( &(_entry)->locker_pid, 0); \
180
+				lock_release( &(_entry)->lock); \
181
+			} else  { \
182
+				/* recursive locked => decrease lock count */ \
183
+				(_entry)->rec_lock_level--; \
184
+			} \
185
+		} while(0)
178 186
 
179 187
 /*!
180 188
  * \brief Unlink a dialog from the list without locking
... ...
@@ -10,7 +10,7 @@ Juha Heinanen
10 10
 
11 11
    <jh@tutpro.com>
12 12
 
13
-   Copyright (c) 2005-2014 Juha Heinanen
13
+   Copyright © 2005-2014 Juha Heinanen
14 14
      __________________________________________________________________
15 15
 
16 16
    Table of Contents
... ...
@@ -62,12 +62,13 @@ Juha Heinanen
62 62
               3.35. lcr_rule_hash_size (integer)
63 63
               3.36. lcr_gw_count (integer)
64 64
               3.37. dont_strip_or_tag_flag (integer)
65
-              3.38. fetch_rows (integer)
66
-              3.39. ping_interval (integer)
67
-              3.40. ping_inactivate_threshold (integer)
68
-              3.41. ping_valid_reply_codes (string)
69
-              3.42. ping_from (string)
70
-              3.43. ping_socket (string)
65
+              3.38. priority_ordering (integer)
66
+              3.39. fetch_rows (integer)
67
+              3.40. ping_interval (integer)
68
+              3.41. ping_inactivate_threshold (integer)
69
+              3.42. ping_valid_reply_codes (string)
70
+              3.43. ping_from (string)
71
+              3.44. ping_socket (string)
71 72
 
72 73
         4. Functions
73 74
 
... ...
@@ -128,25 +129,26 @@ Juha Heinanen
128 128
    1.35. Setting lcr_rule_hash_size module parameter
129 129
    1.36. Setting lcr_gw_count module parameter
130 130
    1.37. Setting dont_strip_or_tag_flag module parameter
131
-   1.38. Set fetch_rows parameter
132
-   1.39. Set ping_interval parameter
133
-   1.40. Set ping_inactive_threshold parameter
134
-   1.41. Set ping_valid_reply_codes parameter
135
-   1.42. Set ping_from parameter
136
-   1.43. Set ping_socket parameter
137
-   1.44. load_gws usage
138
-   1.45. next_gw usage from a route block
139
-   1.46. next_gw usage from a failure route block
140
-   1.47. inactivate_gw usage
141
-   1.48. defunct_gw usage
142
-   1.49. from_gw usage
131
+   1.38. Setting priority_ordering module parameter
132
+   1.39. Set fetch_rows parameter
133
+   1.40. Set ping_interval parameter
134
+   1.41. Set ping_inactivate_threshold parameter
135
+   1.42. Set ping_valid_reply_codes parameter
136
+   1.43. Set ping_from parameter
137
+   1.44. Set ping_socket parameter
138
+   1.45. load_gws usage
139
+   1.46. next_gw usage from a route block
140
+   1.47. next_gw usage from a failure route block
141
+   1.48. inactivate_gw usage
142
+   1.49. defunct_gw usage
143 143
    1.50. from_gw usage
144
-   1.51. to_gw usage
144
+   1.51. from_gw usage
145 145
    1.52. to_gw usage
146
-   1.53. lcr.reload RPC example
147
-   1.54. lcr.dump_gws RPC example
148
-   1.55. lcr.dump_rules RPC example
149
-   1.56. lcr.defunct_gw RPC example
146
+   1.53. to_gw usage
147
+   1.54. lcr.reload RPC example
148
+   1.55. lcr.dump_gws RPC example
149
+   1.56. lcr.dump_rules RPC example
150
+   1.57. lcr.defunct_gw RPC example
150 151
 
151 152
 Chapter 1. Admin Guide
152 153
 
... ...
@@ -197,12 +199,13 @@ Chapter 1. Admin Guide
197 197
         3.35. lcr_rule_hash_size (integer)
198 198
         3.36. lcr_gw_count (integer)
199 199
         3.37. dont_strip_or_tag_flag (integer)
200
-        3.38. fetch_rows (integer)
201
-        3.39. ping_interval (integer)
202
-        3.40. ping_inactivate_threshold (integer)
203
-        3.41. ping_valid_reply_codes (string)
204
-        3.42. ping_from (string)
205
-        3.43. ping_socket (string)
200
+        3.38. priority_ordering (integer)
201
+        3.39. fetch_rows (integer)
202
+        3.40. ping_interval (integer)
203
+        3.41. ping_inactivate_threshold (integer)
204
+        3.42. ping_valid_reply_codes (string)
205
+        3.43. ping_from (string)
206
+        3.44. ping_socket (string)
206 207
 
207 208
    4. Functions
208 209
 
... ...
@@ -248,9 +251,14 @@ Chapter 1. Admin Guide
248 248
    currently designated as defunct) are ordered for forwarding purposes as
249 249
    follows:
250 250
 
251
-     * (1) according to longest Request-URI user part match
252
-     * (2) according to tuple's priority
253
-     * (3) according to tuple's randomized weight
251
+    1. according to longest Request-URI user part match
252
+    2. according to tuple's priority
253
+    3. according to tuple's randomized weight
254
+
255
+   or, if priority_ordering parameter is set to value 1, as follows:
256
+
257
+    1. according to tuple's priority
258
+    2. according to tuple's randomized weight
254 259
 
255 260
    A tuple can be marked as a "stopper" tuple. If a "stopper" tuple
256 261
    matches, then matching stops at it and all other tuples with shorter
... ...
@@ -349,18 +357,19 @@ Chapter 1. Admin Guide
349 349
    3.35. lcr_rule_hash_size (integer)
350 350
    3.36. lcr_gw_count (integer)
351 351
    3.37. dont_strip_or_tag_flag (integer)
352
-   3.38. fetch_rows (integer)
353
-   3.39. ping_interval (integer)
354
-   3.40. ping_inactivate_threshold (integer)
355
-   3.41. ping_valid_reply_codes (string)
356
-   3.42. ping_from (string)
357
-   3.43. ping_socket (string)
352
+   3.38. priority_ordering (integer)
353
+   3.39. fetch_rows (integer)
354
+   3.40. ping_interval (integer)
355
+   3.41. ping_inactivate_threshold (integer)
356
+   3.42. ping_valid_reply_codes (string)
357
+   3.43. ping_from (string)
358
+   3.44. ping_socket (string)
358 359
 
359 360
 3.1. db_url (string)
360 361
 
361 362
    URL of the database table to be used.
362 363
 
363
-   Default value is "mysql://kamailioro:kamailioro@localhost/kamailio".
364
+   Default value is “mysql://kamailioro:kamailioro@localhost/kamailio”.
364 365
 
365 366
    Example 1.1. Setting db_url module parameter
366 367
 ...
... ...
@@ -371,7 +380,7 @@ modparam("lcr","db_url","dbdriver://username:password@dbhost/dbname")
371 371
 
372 372
    Name of the table holding gateways definitions.
373 373
 
374
-   Default value is "lcr_gw".
374
+   Default value is “lcr_gw”.
375 375
 
376 376
    Example 1.2. Setting gw_table module parameter
377 377
 ...
... ...
@@ -383,7 +392,7 @@ modparam("lcr", "lcr_gw_table","gw")
383 383
    Name of the auto-increment, primary key column. Common to all lcr
384 384
    module tables.
385 385
 
386
-   Default value is "id".
386
+   Default value is “id”.
387 387
 
388 388
    Example 1.3. Setting id_column module parameter
389 389
 ...
... ...
@@ -397,7 +406,7 @@ modparam("lcr", "id_column", "row_id")
397 397
    the column is integer from 1 to lcr_count. In lcr_gw table, value of
398 398
    the column is from 0 to lcr_count.
399 399
 
400
-   Default value is "lcr_id".
400
+   Default value is “lcr_id”.
401 401
 
402 402
    Example 1.4. Setting lcr_id_column module parameter
403 403
 ...
... ...
@@ -408,7 +417,7 @@ modparam("lcr", "lcr_id_column", "lcr_identifier")
408 408
 
409 409
    Name of the column holding gateway's name for documentation purpose.
410 410
 
411
-   Default value is "gw_name".
411
+   Default value is “gw_name”.
412 412
 
413 413
    Example 1.5. Setting gw_name_column module parameter
414 414
 ...
... ...
@@ -419,7 +428,7 @@ modparam("lcr", "gw_name_column", "name")
419 419
 
420 420
    Name of the column holding the IPv4 or IPv6 address of the gateway.
421 421
 
422
-   Default value is "ip_addr".
422
+   Default value is “ip_addr”.
423 423
 
424 424
    Example 1.6. Setting ip_addr_column module parameter
425 425
 ...
... ...
@@ -431,7 +440,7 @@ modparam("lcr", "ip_addr_column", "ip")
431 431
    Name of the column holding gateway's hostname that is used in
432 432
    Request-URI hostpart, when request is sent to the gateway.
433 433
 
434
-   Default value is "hostname".
434
+   Default value is “hostname”.
435 435
 
436 436
    Example 1.7. Setting hostname_column module parameter
437 437
 ...
... ...
@@ -442,7 +451,7 @@ modparam("lcr", "hostname_column", "host")
442 442
 
443 443
    Name of the column holding the port number of the gateway.
444 444
 
445
-   Default value is "port".
445
+   Default value is “port”.
446 446
 
447 447
    Example 1.8. Setting port_column module parameter
448 448
 ...
... ...
@@ -454,7 +463,7 @@ modparam("lcr", "port_column", "port")
454 454
    Name of the column holding gateway's parameters that is used in
455 455
    Request-URI, when request is sent to the gateway.
456 456
 
457
-   Default value is "params".
457
+   Default value is “params”.
458 458
 
459 459
    Example 1.9. Setting params_column module parameter
460 460
 ...
... ...
@@ -465,7 +474,7 @@ modparam("lcr", "params_column", "parameters")
465 465
 
466 466
    Name of the column holding the uri scheme of the gateway.
467 467
 
468
-   Default value is "uri_scheme".
468
+   Default value is “uri_scheme”.
469 469
 
470 470
    Example 1.10. Setting uri_scheme_column module parameter
471 471
 ...
... ...
@@ -477,7 +486,7 @@ modparam("lcr", "uri_scheme_column", "uri_scheme")
477 477
    Name of the column holding the transport protocol to be used for the
478 478
    gateway.
479 479
 
480
-   Default value is "transport".
480
+   Default value is “transport”.
481 481
 
482 482
    Example 1.11. Setting transport_column module parameter
483 483
 ...
... ...
@@ -489,7 +498,7 @@ modparam("lcr", "transport_column", "trans")
489 489
    Name of the column holding the number of characters to be stripped from
490 490
    the front of Request-URI user part before inserting tag.
491 491
 
492
-   Default value is "strip".
492
+   Default value is “strip”.
493 493
 
494 494
    Example 1.12. Setting strip_column module parameter
495 495
 ...
... ...
@@ -501,7 +510,7 @@ modparam("lcr", "strip_column", "strip_count")
501 501
    Name of the column holding gateway specific tag string that is added to
502 502
    Request URI userpart after stripping.
503 503
 
504
-   Default value is "tag".
504
+   Default value is “tag”.
505 505
 
506 506
    Example 1.13. Setting tag_column module parameter
507 507
 ...
... ...
@@ -512,7 +521,7 @@ modparam("lcr", "tag_column", "gw_tag")
512 512
 
513 513
    Name of the column holding gateway specific flag values.
514 514
 
515
-   Default value is "flags".
515
+   Default value is “flags”.
516 516
 
517 517
    Example 1.14. Setting flags_column module parameter
518 518
 ...
... ...
@@ -526,7 +535,7 @@ modparam("lcr", "flags_column", "gw_flags")
526 526
    max UNIX timestamp value) or greater, gw is considered currently unused
527 527
    and is not loaded into memory at all.
528 528
 
529
-   Default value is "defunct".
529
+   Default value is “defunct”.
530 530
 
531 531
    Example 1.15. Setting defunct_column module parameter
532 532
 ...
... ...
@@ -537,7 +546,7 @@ modparam("lcr", "defunct_column", "defunct_until")
537 537
 
538 538
    Name of the table holding the LCR rules.
539 539
 
540
-   Default value is "lcr_rule".
540
+   Default value is “lcr_rule”.
541 541
 
542 542
    Example 1.16. Setting lcr_rule_table module parameter
543 543
 ...
... ...
@@ -549,7 +558,7 @@ modparam("lcr", "lcr_rule_table", "rules")
549 549
    Name of the column holding prefix of Request-URI user part and prefix
550 550
    of gateway.
551 551
 
552
-   Default value is "prefix".
552
+   Default value is “prefix”.
553 553
 
554 554
    Example 1.17. Setting prefix_column module parameter
555 555
 ...
... ...
@@ -560,7 +569,7 @@ modparam("lcr", "prefix_column", "number_prefix")
560 560
 
561 561
    Name of the column holding the From (caller's) URI.
562 562
 
563
-   Default value is "from_uri".
563
+   Default value is “from_uri”.
564 564
 
565 565
    Example 1.18. Setting from_uri_column module parameter
566 566
 ...
... ...
@@ -572,7 +581,7 @@ modparam("lcr", "from_uri_column", "caller_uri")
572 572
    Name of the column holding the regular expression to match against the
573 573
    complete request URI (including the "sip:" prefix).
574 574
 
575
-   Default value is "request_uri".
575
+   Default value is “request_uri”.
576 576
 
577 577
    Example 1.19. Setting request_uri_column module parameter
578 578
 ...
... ...
@@ -583,7 +592,7 @@ modparam("lcr", "request_uri_column", "callee_uri")
583 583
 
584 584
    Name of the column holding rule's stopper attribute.
585 585
 
586
-   Default value is "stopper".
586
+   Default value is “stopper”.
587 587
 
588 588
    Example 1.20. Setting stopper_column module parameter
589 589
 ...
... ...
@@ -595,7 +604,7 @@ modparam("lcr", "stopper_column", "stop")
595 595
    Name of the column telling is the rule is currently enabled or
596 596
    disabled.
597 597
 
598
-   Default value is "enabled".
598
+   Default value is “enabled”.
599 599
 
600 600
    Example 1.21. Setting enabled_column module parameter
601 601
 ...
... ...
@@ -607,7 +616,7 @@ modparam("lcr", "enabled_column", "in_use")
607 607
    Name of the table holding information about the LCR rule targets
608 608
    (gateways).
609 609
 
610
-   Default value is "lcr_rule_target".
610
+   Default value is “lcr_rule_target”.
611 611
 
612 612
    Example 1.22. Setting lcr_rule_target_table module parameter
613 613
 ...
... ...
@@ -619,7 +628,7 @@ modparam("lcr", "lcr_rule_target_table", "rules")
619 619
    Name of lcr_rule_target_table column containing an id of lcr_rule
620 620
    table.
621 621
 
622
-   Default value is "rule_id".
622
+   Default value is “rule_id”.
623 623
 
624 624
    Example 1.23. Setting rule_id_column module parameter
625 625
 ...
... ...
@@ -630,7 +639,7 @@ modparam("lcr", "rule_id_column", "rule")
630 630
 
631 631
    Name of lcr_rule_target_table column containing an id of lcr_gw table.
632 632
 
633
-   Default value is "gw_id".
633
+   Default value is “gw_id”.
634 634
 
635 635
    Example 1.24. Setting gw_id_column module parameter
636 636
 ...
... ...
@@ -641,7 +650,7 @@ modparam("lcr", "gw_id_column", "gw")
641 641
 
642 642
    Name of the column holding the priority of the rule target.
643 643
 
644
-   Default value is "priority".
644
+   Default value is “priority”.
645 645
 
646 646
    Example 1.25. Setting priority_column module parameter
647 647
 ...
... ...
@@ -652,7 +661,7 @@ modparam("lcr", "priority_column", "priority")
652 652
 
653 653
    Name of the column holding weight of rule target.
654 654
 
655
-   Default value is "weight".
655
+   Default value is “weight”.
656 656
 
657 657
    Example 1.26. Setting weight_column module parameter
658 658
 ...
... ...
@@ -796,7 +805,18 @@ modparam("lcr", "lcr_gw_count", 1024)
796 796
 modparam("lcr", "dont_strip_or_tag_flag", 10)
797 797
 ...
798 798
 
799
-3.38. fetch_rows (integer)
799
+3.38. priority_ordering (integer)
800
+
801
+   Defines how matching gateways are ordered (see Overview section).
802
+
803
+   Default value is 0.
804
+
805
+   Example 1.38.  Setting priority_ordering module parameter
806
+...
807
+modparam("lcr", "priority_ordering", 1)
808
+...
809
+
810
+3.39. fetch_rows (integer)
800 811
 
801 812
    The number of the rows to be fetched at once from database when loading
802 813
    data from lcr_rule table. This value can be used to tune the load time
... ...
@@ -804,14 +824,14 @@ modparam("lcr", "dont_strip_or_tag_flag", 10)
804 804
    3750. In order for this parameter to have effect, the database driver
805 805
    must support fetch_result() capability.
806 806
 
807
-   Default value is "1024".
807
+   Default value is “1024”.
808 808
 
809
-   Example 1.38. Set fetch_rows parameter
809
+   Example 1.39. Set fetch_rows parameter
810 810
 ...
811 811
 modparam("lcr", "fetch_rows", 3000)
812 812
 ...
813 813
 
814
-3.39. ping_interval (integer)
814
+3.40. ping_interval (integer)
815 815
 
816 816
    Interval in seconds for sending OPTIONS ping requests to gateways that,
817 817
    due to failures, have been marked as inactive by inactivate_gw()
... ...
@@ -821,62 +841,61 @@ modparam("lcr", "fetch_rows", 3000)
821 821
 
822 822
    If value of this parameter is greater than zero, tm module must have
823 823
    been loaded and parameters lcr_id_avp and defunct_gw_avp must have been
824
-   defined. Value "0" disables sending of OPTIONS ping requests to failed
824
+   defined. Value “0” disables sending of OPTIONS ping requests to failed
825 825
    gateways.
826 826
 
827
-   Default value is "0".
827
+   Default value is “0”.
828 828
 
829
-   Example 1.39.  Set ping_interval parameter
829
+   Example 1.40.  Set ping_interval parameter
830 830
 ...
831 831
 modparam("lcr", "ping_interval", 15)
832 832
 ...
833 833
 
834
-3.40. ping_inactivate_threshold (integer)
834
+3.41. ping_inactivate_threshold (integer)
835 835
 
836 836
    Tells after how many failures (= inactivate_gw() function calls) a
837 837
    gateway is marked as inactive.
838 838
 
839
-   Default value is "1", i.e., gateway is marked inactive after first
840
-   failure.
839
+   Default value is “1”, i.e., gateway is inactivated after first failure.
841 840
 
842
-   Example 1.40.  Set ping_inactive_threshold parameter
841
+   Example 1.41.  Set ping_inactivate_threshold parameter
843 842
 ...
844
-modparam("lcr", "ping_inactive_threshold", 3)
843
+modparam("lcr", "ping_inactivate_threshold", 3)
845 844
 ...
846 845
 
847
-3.41. ping_valid_reply_codes (string)
846
+3.42. ping_valid_reply_codes (string)
848 847
 
849 848
    A comma separated list of SIP reply codes, which are accepted as valid
850 849
    replies to OPTIONS ping requests. Reply codes 2xx are by default
851 850
    accepted as valid replies and they don't need to be listed here.
852 851
 
853
-   Default value is "", i.e., only 2xx replies are considered as valid
852
+   Default value is “”, i.e., only 2xx replies are considered as valid
854 853
    replies.
855 854
 
856
-   Example 1.41.  Set ping_valid_reply_codes parameter
855
+   Example 1.42.  Set ping_valid_reply_codes parameter
857 856
 ...
858 857
 modparam("lcr", "ping_valid_reply_codes", "403,405,501")
859 858
 ...
860 859
 
861
-3.42. ping_from (string)
860
+3.43. ping_from (string)
862 861
 
863 862
    From URI used in OPTIONS ping requests.
864 863
 
865
-   Default value is "sip:pinger@localhost".
864
+   Default value is “sip:pinger@localhost”.
866 865
 
867
-   Example 1.42.  Set ping_from parameter
866
+   Example 1.43.  Set ping_from parameter
868 867
 ...
869 868
 modparam("lcr", "ping_from", "sip:proxy.operator.com")
870 869
 ...
871 870
 
872
-3.43. ping_socket (string)
871
+3.44. ping_socket (string)
873 872
 
874 873
    Socket to be used for sending OPTIONS ping request. If not set or set
875
-   to "", default socket is used.
874
+   to “”, default socket is used.
876 875
 
877
-   Default value is "".
876
+   Default value is “”.
878 877
 
879
-   Example 1.43.  Set ping_socket parameter
878
+   Example 1.44.  Set ping_socket parameter
880 879
 ...
881 880
 modparam("lcr", "ping_socket", "192.98.102.10:5060")
882 881
 ...
... ...
@@ -912,7 +931,7 @@ modparam("lcr", "ping_socket", "192.98.102.10:5060")
912 912
 
913 913
    This function can be used from REQUEST_ROUTE.
914 914
 
915
-   Example 1.44. load_gws usage
915
+   Example 1.45. load_gws usage
916 916
 ...
917 917
 if (!load_gws(1, $rU, $var(caller_uri))) {
918 918
         sl_send_reply("500", "Server Internal Error - Cannot load gateways");
... ...
@@ -942,7 +961,7 @@ if (!load_gws(1, $rU, $var(caller_uri))) {
942 942
 
943 943
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
944 944
 
945
-   Example 1.45. next_gw usage from a route block
945
+   Example 1.46. next_gw usage from a route block
946 946
 ...
947 947
 if (!next_gw()) {
948 948
         sl_send_reply("503", "Service not available - No gateways");
... ...
@@ -950,7 +969,7 @@ if (!next_gw()) {
950 950
 };
951 951
 ...
952 952
 
953
-   Example 1.46. next_gw usage from a failure route block
953
+   Example 1.47. next_gw usage from a failure route block
954 954
 ...
955 955
 if (!next_gw()) {
956 956
         t_reply("503", "Service not available - No more gateways");
... ...
@@ -970,7 +989,7 @@ if (!next_gw()) {
970 970
 
971 971
    This function can be used from REQUEST_ROUTE and FAILURE_ROUTE.
972 972
 
973
-   Example 1.47. inactivate_gw usage
973
+   Example 1.48. inactivate_gw usage
974 974
 ...
975 975
 failure_route [GW_FAILURE] {
976 976
 ...
... ...
@@ -991,7 +1010,7 @@ failure_route [GW_FAILURE] {
991 991
 
992 992
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
993 993
 
994
-   Example 1.48. defunct_gw usage
994
+   Example 1.49. defunct_gw usage
995 995
 ...
996 996
 defunct_gw(60);
997 997
 ...
... ...
@@ -1023,7 +1042,7 @@ defunct_gw(60);
1023 1023
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE,
1024 1024
    ONREPLY_ROUTE.
1025 1025
 
1026
-   Example 1.49. from_gw usage
1026
+   Example 1.50. from_gw usage
1027 1027
 ...
1028 1028
 if (from_gw(1, $avp(s:real_source_addr), 2) {
1029 1029
         ...
... ...
@@ -1053,7 +1072,7 @@ if (from_gw(1, $avp(s:real_source_addr), 2) {
1053 1053
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE,
1054 1054
    ONREPLY_ROUTE.
1055 1055
 
1056
-   Example 1.50. from_gw usage
1056
+   Example 1.51. from_gw usage
1057 1057
 ...
1058 1058
 $var(lcr_id) = from_any_gw("192.168.1.1", 3);
1059 1059
 ...
... ...
@@ -1074,7 +1093,7 @@ $var(lcr_id) = from_any_gw("192.168.1.1", 3);
1074 1074
 
1075 1075
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
1076 1076
 
1077
-   Example 1.51. to_gw usage
1077
+   Example 1.52. to_gw usage
1078 1078
 ...
1079 1079
 if (to_gw("1")) {
1080 1080
         ...
... ...
@@ -1100,7 +1119,7 @@ if (to_gw("1")) {
1100 1100
 
1101 1101
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
1102 1102
 
1103
-   Example 1.52. to_gw usage
1103
+   Example 1.53. to_gw usage
1104 1104
 ...
1105 1105
 if (to_any_gw("192.55.66.2", 1)) {
1106 1106
         ...
... ...
@@ -1123,7 +1142,7 @@ if (to_any_gw("192.55.66.2", 1)) {
1123 1123
 
1124 1124
    Parameters: none
1125 1125
 
1126
-   Example 1.53. lcr.reload RPC example
1126
+   Example 1.54. lcr.reload RPC example
1127 1127
                 $ kamcmd lcr.reload
1128 1128
 
1129 1129
 5.2. lcr.dump_gws
... ...
@@ -1132,7 +1151,7 @@ if (to_any_gw("192.55.66.2", 1)) {
1132 1132
 
1133 1133
    Parameters: none
1134 1134
 
1135
-   Example 1.54. lcr.dump_gws RPC example
1135
+   Example 1.55. lcr.dump_gws RPC example
1136 1136
                 $ kamcmd lcr.dump_gws
1137 1137
 
1138 1138
 5.3. lcr.dump_rules
... ...
@@ -1142,7 +1161,7 @@ if (to_any_gw("192.55.66.2", 1)) {
1142 1142
 
1143 1143
    Parameters: none
1144 1144
 
1145
-   Example 1.55. lcr.dump_rules RPC example
1145
+   Example 1.56. lcr.dump_rules RPC example
1146 1146
                 $ kamcmd lcr.dump_rules
1147 1147
 
1148 1148
 5.4. lcr.defunct_gw
... ...
@@ -1155,7 +1174,7 @@ if (to_any_gw("192.55.66.2", 1)) {
1155 1155
 
1156 1156
    Parameters: lcr_id gw_id period
1157 1157
 
1158
-   Example 1.56. lcr.defunct_gw RPC example
1158
+   Example 1.57. lcr.defunct_gw RPC example
1159 1159
                 $ kamcmd lcr.defunct_gw 1 4 120
1160 1160
 
1161 1161
 6. Known Limitations
... ...
@@ -44,20 +44,35 @@
44 44
 	are ordered for forwarding purposes as follows:
45 45
 	</para>
46 46
 	<para>
47
-	<itemizedlist>
47
+	<orderedlist>
48 48
             <listitem>
49
-                <para>(1) according to longest Request-URI user part match
49
+                <para>according to longest Request-URI user part match
50 50
                 </para>
51 51
             </listitem>
52 52
             <listitem>
53
-                <para>(2) according to tuple's priority
53
+                <para>according to tuple's priority
54 54
                 </para>
55 55
             </listitem>
56 56
             <listitem>
57
-                <para>(3) according to tuple's randomized weight
57
+                <para>according to tuple's randomized weight
58 58
                 </para>
59 59
             </listitem>
60
-        </itemizedlist>
60
+        </orderedlist>
61
+	</para>
62
+	<para>
63
+    or, if priority_ordering parameter is set to value 1, as follows:
64
+	</para>
65
+	<para>
66
+	<orderedlist>
67
+            <listitem>
68
+                <para>according to tuple's priority
69
+                </para>
70
+            </listitem>
71
+            <listitem>
72
+                <para>according to tuple's randomized weight
73
+                </para>
74
+            </listitem>
75
+        </orderedlist>
61 76
 	</para>
62 77
 	<para>
63 78
 	A tuple can be marked as a "stopper" tuple.  If a "stopper"
... ...
@@ -971,6 +986,29 @@ modparam("lcr", "dont_strip_or_tag_flag", 10)
971 971
 	</section>
972 972
 
973 973
 	<section>
974
+		<title><varname>priority_ordering</varname> (integer)</title>
975
+		<para>
976
+		Defines how matching gateways are ordered (see Overview section).
977
+		</para>
978
+		<para>
979
+		<emphasis>
980
+			Default value is 0.
981
+		</emphasis>
982
+		</para>
983
+		<example>
984
+		<title>
985
+		Setting <varname>priority_ordering</varname> module
986
+		parameter
987
+		</title>
988
+		<programlisting format="linespecific">
989
+...
990
+modparam("lcr", "priority_ordering", 1)
991
+...
992
+</programlisting>
993
+                </example>
994
+	</section>
995
+
996
+	<section>
974 997
 		<title><varname>fetch_rows</varname> (integer)</title>
975 998
 		<para>
976 999
 		The number of the rows to be fetched at once from database
... ...
@@ -218,6 +218,9 @@ str ping_valid_reply_codes_param = {"", 0};
218 218
 str ping_socket_param = {"", 0};
219 219
 str ping_from_param = {"sip:pinger@localhost", 20};
220 220
 
221
+/* use priority as main ordering criteria */
222
+static unsigned int priority_ordering_param = 0;
223
+
221 224
 /*
222 225
  * Other module types and variables
223 226
  */
... ...
@@ -345,6 +348,7 @@ static param_export_t params[] = {
345 345
     {"lcr_rule_hash_size",       INT_PARAM, &lcr_rule_hash_size_param},
346 346
     {"lcr_gw_count",             INT_PARAM, &lcr_gw_count_param},
347 347
     {"dont_strip_or_prefix_flag",INT_PARAM, &dont_strip_or_prefix_flag_param},
348
+    {"priority_ordering",        INT_PARAM, &priority_ordering_param},
348 349
     {"fetch_rows",               INT_PARAM, &fetch_rows_param},
349 350
     {"ping_interval",            INT_PARAM, &ping_interval_param},
350 351
     {"ping_inactivate_threshold",  INT_PARAM, &ping_inactivate_threshold_param},
... ...
@@ -465,6 +469,12 @@ static int mod_init(void)
465 465
 	return -1;
466 466
     }
467 467
 
468
+    if ((priority_ordering_param != 0) && (priority_ordering_param != 1)) {
469
+        LM_ERR("invalid priority_ordering value <%d>\n",
470
+	       priority_ordering_param);
471
+	return -1;
472
+    }
473
+
468 474
     /* Process AVP params */
469 475
 
470 476
     if (gw_uri_avp_param && *gw_uri_avp_param) {
... ...
@@ -780,6 +790,17 @@ static int comp_matched(const void *m1, const void *m2)
780 780
     struct matched_gw_info *mi1 = (struct matched_gw_info *) m1;
781 781
     struct matched_gw_info *mi2 = (struct matched_gw_info *) m2;
782 782
 
783
+    if (priority_ordering_param) {
784
+        /* Sort by priority */
785
+	if (mi1->priority < mi2->priority) return 1;
786
+	if (mi1->priority == mi2->priority) {
787
+	    /* Sort by randomized weigth */
788
+	    if (mi1->weight > mi2->weight) return 1;
789
+	    if (mi1->weight == mi2->weight) return 0;
790
+	}
791
+	return -1;
792
+    }
793
+
783 794
     /* Sort by prefix_len */
784 795
     if (mi1->prefix_len > mi2->prefix_len) return 1;
785 796
     if (mi1->prefix_len == mi2->prefix_len) {
... ...
@@ -789,9 +810,7 @@ static int comp_matched(const void *m1, const void *m2)
789 789
 	    /* Sort by randomized weigth */
790 790
 	    if (mi1->weight > mi2->weight) return 1;
791 791
 	    if (mi1->weight == mi2->weight) return 0;
792
-	    return -1;
793 792
 	}
794
-	return -1;
795 793
     }
796 794
     return -1;
797 795
 }
... ...
@@ -837,21 +837,30 @@ start_recording();
837 837
 	<section>
838 838
 		<title><acronym>MI</acronym> Commands</title>
839 839
 		<section id="rtpengine.m.nh_enable_rtpp">
840
-			<title><function moreinfo="none">nh_enable_rtpp</function></title>
840
+			<title><function moreinfo="none">nh_enable_rtpp proxy_url/all 0/1</function></title>
841 841
 			<para>
842
-			Enables a &rtp; proxy if parameter value is greater than 0.
843
-			Disables it if a zero value is given.
842
+			Enables a &rtp; proxy if the second parameter value is greater than 0. Disables it if a zero value is given.
843
+			The first parameter is either a specific &rtp; proxy url (exactly as defined in
844
+			the config file) or the keyword <emphasis>all</emphasis>.
845
+			The second parameter value must be a number in decimal.
844 846
 			</para>
845 847
 			<para>
846
-			The first parameter is the &rtp; proxy url (exactly as defined in
847
-			the config file).
848
+            When try to enable the &rtp; proxy, an application ping command is sent to it.
849
+            If it fails, the proxy is not enabled.
850
+            Displays <emphasis>success</emphasis> or <emphasis>fail</emphasis> when try to enable/disable.
848 851
 			</para>
849 852
 			<para>
850
-			The second parameter value must be a number in decimal.
853
+			NOTE: If a &rtp; proxy is defined multiple times (in the same or diferent sets), all of its instances will be enabled/disabled.
854
+			</para>
855
+			<para>
856
+			NOTE: If a &rtp; proxy is in the disabled permanent state and one tries to enable it, even if the ping fails,
857
+            it is moved to a disabled temporary state and a recheck_ticks are given to it.
858
+            While the recheck_ticks are grater than 0, the proxy is considered disabled temporary, and it is not taken into consideration for sending data.
859
+            When the recheck_ticks are 0, the proxy is retested <emphasis>when trying to send data</emphasis>(not automatically retested), and data can be send to it on success.
851 860
 			</para>
852 861
 			<para>
853
-			NOTE: if a &rtp; proxy is defined multiple times (in the same or
854
-			diferente sete), all of its instances will be enables/disabled.
862
+			NOTE: When specify the IPv6 &rtp; proxy url one must prefix it with <emphasis>::</emphasis>
863
+            to escape the :: from the IPv6 address. See the example below.
855 864
 			</para>
856 865
 			<example>
857 866
 			<title>
... ...
@@ -859,28 +868,68 @@ start_recording();
859 859
 			<programlisting format="linespecific">
860 860
 ...
861 861
 $ &ctltool; fifo nh_enable_rtpp udp:192.168.2.133:8081 0
862
+$ &ctltool; fifo nh_enable_rtpp ::udp6:fe80::9a90:96ff:fea8:fd99:9999 1
863
+$ &ctltool; fifo nh_enable_rtpp all 1
862 864
 ...
863 865
 			</programlisting>
864 866
 			</example>
865 867
 		</section>
866 868
 
867
-			<section id="rtpengine.m.nh_show_rtpp">
868
-			<title><function moreinfo="none">nh_show_rtpp</function></title>
869
+	    <section id="rtpengine.m.nh_show_rtpp">
870
+			<title><function moreinfo="none">nh_show_rtpp proxy_url/all</function></title>
869 871
 			<para>
870 872
 			Displays all the &rtp; proxies and their information: set and
871
-			status (disabled or not, weight and recheck_ticks). If a RTP proxy has been disabled by a mi command
872
-			a "(permanent)" quote will appear when printing the disabled status. This is to differentiate from
873
-			a temporary disable due to the proxy being not found responsive by kamailio.
873
+			status (disabled or not, weight and recheck_ticks). If a &rtp; proxy has been disabled by
874
+            nh_enable_rtpp mi command a "(permanent)" quote will appear when printing the disabled status.
875
+            This is to differentiate from a temporary disable due to the proxy being not found responsive
876
+            by kamailio. In addition, when disabled permanent, recheck_ticks have no meaning and "N\A"
877
+            is printed instead of the value.
878
+			</para>
879
+			<para>
880
+            It takes either a specific &rtp; proxy url (exactly as defined in
881
+			the config file) or the keyword <emphasis>all</emphasis> as a parameter.
874 882
 			</para>
875 883
 			<para>
876
-			No parameter.
884
+			NOTE: When specify the IPv6 &rtp; proxy url one must prefix it with <emphasis>::</emphasis>
885
+            to escape the :: from the IPv6 address. See the example below.
877 886
 			</para>
878 887
 			<example>
879 888
 			<title>
880 889
 				<function moreinfo="none">nh_show_rtpp</function> usage</title>
881 890
 			<programlisting format="linespecific">
882 891
 ...
883
-$ &ctltool; fifo nh_show_rtpp
892
+$ &ctltool; fifo nh_show_rtpp udp:192.168.2.133:8081
893
+$ &ctltool; fifo nh_show_rtpp ::udp6:fe80::9a90:96ff:fea8:fd99:9999
894
+$ &ctltool; fifo nh_show_rtpp all
895
+...
896
+			</programlisting>
897
+			</example>
898
+		</section>
899
+
900
+	    <section id="rtpengine.m.nh_ping_rtpp">
901
+			<title><function moreinfo="none">nh_ping_rtpp proxy_url/all</function></title>
902
+			<para>
903
+            Sends an application ping command to the &rtp; proxy. If the proxy does not respond,
904
+            it will be disabled, but not permanent. If the proxy responds, no action is taken.
905
+            Displays the ping result, i.e.
906
+            <emphasis>success</emphasis> or <emphasis>fail</emphasis> when try to ping.
907
+			</para>
908
+			<para>
909
+            It takes either a specific &rtp; proxy url (exactly as defined in
910
+			the config file) or the keyword <emphasis>all</emphasis> as a parameter.
911
+			</para>
912
+			<para>
913
+			NOTE: When specify the IPv6 &rtp; proxy url one must prefix it with <emphasis>::</emphasis>
914
+            to escape the :: from the IPv6 address. See the example below.
915
+			</para>
916
+			<example>
917
+			<title>
918
+				<function moreinfo="none">nh_ping_rtpp</function> usage</title>
919
+			<programlisting format="linespecific">
920
+...
921
+$ &ctltool; fifo nh_ping_rtpp udp:192.168.2.133:8081
922
+$ &ctltool; fifo nh_ping_rtpp ::udp6:fe80::9a90:96ff:fea8:fd99:9999
923
+$ &ctltool; fifo nh_ping_rtpp all
884 924
 ...
885 925
 			</programlisting>
886 926
 			</example>
... ...
@@ -102,11 +102,12 @@ MODULE_VERSION
102 102
 #define MI_SET_NATPING_STATE		"nh_enable_ping"
103 103
 #define MI_DEFAULT_NATPING_STATE	1
104 104
 
105
-#define MI_ENABLE_RTP_PROXY			"nh_enable_rtpp"
106 105
 #define MI_MIN_RECHECK_TICKS		0
107 106
 #define MI_MAX_RECHECK_TICKS		(unsigned int)-1
108 107
 
108
+#define MI_ENABLE_RTP_PROXY			"nh_enable_rtpp"
109 109
 #define MI_SHOW_RTP_PROXIES			"nh_show_rtpp"
110
+#define MI_PING_RTP_PROXY           "nh_ping_rtpp"
110 111
 
111 112
 #define MI_RTP_PROXY_NOT_FOUND		"RTP proxy not found"
112 113
 #define MI_RTP_PROXY_NOT_FOUND_LEN	(sizeof(MI_RTP_PROXY_NOT_FOUND)-1)
... ...
@@ -118,6 +119,8 @@ MODULE_VERSION
118 118
 #define MI_SET_LEN					(sizeof(MI_SET)-1)
119 119
 #define MI_INDEX					"index"
120 120
 #define MI_INDEX_LEN				(sizeof(MI_INDEX)-1)
121
+#define MI_ENABLED					"enabled"
122
+#define MI_ENABLED_LEN				(sizeof(MI_ENABLED)-1)
121 123
 #define MI_DISABLED					"disabled"
122 124
 #define MI_DISABLED_LEN				(sizeof(MI_DISABLED)-1)
123 125
 #define MI_WEIGHT					"weight"
... ...
@@ -125,6 +128,24 @@ MODULE_VERSION
125 125
 #define MI_RECHECK_TICKS			"recheck_ticks"
126 126
 #define MI_RECHECK_T_LEN			(sizeof(MI_RECHECK_TICKS)-1)
127 127
 
128
+#define MI_ERROR                    "Error when adding rtpp node details"
129
+#define MI_ERROR_LEN                (sizeof(MI_ERROR)-1)
130
+#define MI_ALL                      "all"
131
+#define MI_ALL_LEN           		(sizeof(MI_ALL)-1)
132
+#define MI_ENABLE                   "enable"
133
+#define MI_ENABLE_LEN         		(sizeof(MI_ENABLE)-1)
134
+#define MI_DISABLE                  "disable"
135
+#define MI_DISABLE_LEN         		(sizeof(MI_DISABLE)-1)
136
+#define MI_PING                     "ping"
137
+#define MI_PING_LEN         		(sizeof(MI_PING)-1)
138
+#define MI_SUCCESS                  "success"
139
+#define MI_SUCCESS_LEN         		(sizeof(MI_SUCCESS)-1)
140
+#define MI_FAIL                     "fail"
141
+#define MI_FAIL_LEN         		(sizeof(MI_FAIL)-1)
142
+
143
+#define MI_FOUND_ALL                   2
144
+#define MI_FOUND_ONE                   1
145
+#define MI_FOUND_NONE                  0
128 146
 
129 147
 
130 148
 #define	CPORT		"22222"
... ...
@@ -135,6 +156,7 @@ enum rtpe_operation {
135 135
 	OP_DELETE,
136 136
 	OP_START_RECORDING,
137 137
 	OP_QUERY,
138
+	OP_PING,
138 139
 };
139 140
 
140 141
 struct ng_flags_parse {
... ...
@@ -148,6 +170,7 @@ static const char *command_strings[] = {
148 148
 	[OP_DELETE]		= "delete",
149 149
 	[OP_START_RECORDING]	= "start recording",
150 150
 	[OP_QUERY]		= "query",
151
+	[OP_PING]		= "ping",
151 152
 };
152 153
 
153 154
 static char *gencookie();
... ...
@@ -179,14 +202,22 @@ static int get_ip_type(char *str_addr);
179 179
 static int get_ip_scope(char *str_addr); // useful for link-local ipv6
180 180
 static int bind_force_send_ip(int sock_idx);
181 181
 
182
+static int add_rtpp_node_info(struct mi_node *node,
183
+                              struct rtpp_node *crt_rtpp,
184
+                              struct rtpp_set *rtpp_list);
185
+
186
+static int rtpp_test_ping(struct rtpp_node *node);
187
+
182 188
 /* Pseudo-Variables */
183 189
 static int pv_get_rtpstat_f(struct sip_msg *, pv_param_t *, pv_value_t *);
184 190
 
185 191
 /*mi commands*/
186 192
 static struct mi_root* mi_enable_rtp_proxy(struct mi_root* cmd_tree,
187 193
 		void* param );
188
-static struct mi_root* mi_show_rtpproxies(struct mi_root* cmd_tree,
194
+static struct mi_root* mi_show_rtp_proxy(struct mi_root* cmd_tree,
189 195
 		void* param);
196
+static struct mi_root* mi_ping_rtp_proxy(struct mi_root* cmd_tree,
197
+        void* param);
190 198
 
191 199
 
192 200
 static int rtpengine_disable_tout = 60;
... ...
@@ -224,6 +255,8 @@ static int_str setid_avp;
224 224
 static str            write_sdp_pvar_str = {NULL, 0};
225 225
 static pv_spec_t*     write_sdp_pvar = NULL;
226 226
 
227
+#define RTPENGINE_SESS_LIMIT_MSG "Parallel session limit reached"
228
+#define RTPENGINE_SESS_LIMIT_MSG_LEN (sizeof(RTPENGINE_SESS_LIMIT_MSG)-1)
227 229
 
228 230
 char* force_send_ip_str="";
229 231
 int force_send_ip_af = AF_UNSPEC;
... ...
@@ -303,8 +336,9 @@ static param_export_t params[] = {
303 303
 };
304 304
 
305 305
 static mi_export_t mi_cmds[] = {
306
-	{MI_ENABLE_RTP_PROXY,     mi_enable_rtp_proxy,  0,                0, 0},
307
-	{MI_SHOW_RTP_PROXIES,     mi_show_rtpproxies,   MI_NO_INPUT_FLAG, 0, 0},
306
+	{MI_ENABLE_RTP_PROXY,     mi_enable_rtp_proxy,  0,  0,  0},
307
+	{MI_SHOW_RTP_PROXIES,     mi_show_rtp_proxy,    0,  0,  0},
308
+	{MI_PING_RTP_PROXY,       mi_ping_rtp_proxy,    0,  0,  0},
308 309
 	{ 0, 0, 0, 0, 0}
309 310
 };
310 311
 
... ...
@@ -423,7 +457,7 @@ static int bind_force_send_ip(int sock_idx)
423 423
 			memset(&tmp, 0, sizeof(tmp));
424 424
 			getsockname(rtpp_socks[sock_idx], (struct sockaddr *) &tmp, &sock_len);
425 425
 			inet_ntop(AF_INET, &tmp.sin_addr, str_addr, INET_ADDRSTRLEN);
426
-			LM_INFO("Binding on %s:%d\n", str_addr, ntohs(tmp.sin_port));
426
+			LM_DBG("Binding on %s:%d\n", str_addr, ntohs(tmp.sin_port));
427 427
 
428 428
 			break;
429 429
 
... ...
@@ -447,7 +481,7 @@ static int bind_force_send_ip(int sock_idx)
447 447
 			memset(&tmp6, 0, sizeof(tmp6));
448 448
 			getsockname(rtpp_socks[sock_idx], (struct sockaddr *) &tmp6, &sock_len);
449 449
 			inet_ntop(AF_INET6, &tmp6.sin6_addr, str_addr6, INET6_ADDRSTRLEN);
450
-			LM_INFO("Binding on ipv6 %s:%d\n", str_addr6, ntohs(tmp6.sin6_port));
450
+			LM_DBG("Binding on ipv6 %s:%d\n", str_addr6, ntohs(tmp6.sin6_port));
451 451
 
452 452
 			break;
453 453
 
... ...
@@ -779,67 +813,204 @@ static int fixup_set_id(void ** param, int param_no)
779 779
 	return 0;
780 780
 }
781 781
 
782
-static struct mi_root* mi_enable_rtp_proxy(struct mi_root* cmd_tree,
783
-												void* param )
784
-{	struct mi_node* node;
785
-	str rtpp_url;
782
+static int rtpp_test_ping(struct rtpp_node *node)
783
+{
784
+    bencode_buffer_t bencbuf;
785
+    bencode_item_t *dict;
786
+    char *cp;
787
+    int ret;
788
+
789
+    if (bencode_buffer_init(&bencbuf)) {
790
+        return -1;
791
+    }
792
+    dict = bencode_dictionary(&bencbuf);
793
+    bencode_dictionary_add_string(dict, "command", command_strings[OP_PING]);
794
+
795
+    if (bencbuf.error) {
796
+        goto error;
797
+    }
798
+
799
+    cp = send_rtpp_command(node, dict, &ret);
800
+    if (!cp) {
801
+        goto error;
802
+    }
803
+
804
+    dict = bencode_decode_expect(&bencbuf, cp, ret, BENCODE_DICTIONARY);
805
+    if (!dict || bencode_dictionary_get_strcmp(dict, "result", "pong")) {
806
+        goto error;
807
+    }
808
+
809
+    bencode_buffer_free(&bencbuf);
810
+    return 0;
811
+
812
+error:
813
+    bencode_buffer_free(&bencbuf);
814
+    return -1;
815
+}
816
+
817
+static struct mi_root* mi_enable_rtp_proxy(struct mi_root *cmd_tree,
818
+												void *param )
819
+{
820
+	struct mi_node *node, *crt_node;
821
+	struct rtpp_set *rtpp_list;
822
+	struct rtpp_node *crt_rtpp, *found_rtpp;
823
+	struct mi_root *root;
824
+	struct mi_attr *attr;
786 825
 	unsigned int enable;
787
-	struct rtpp_set * rtpp_list;
788
-	struct rtpp_node * crt_rtpp;
789
-	int found;
826
+	int found, found_rtpp_disabled;
827
+	str rtpp_url;
828
+	str snode, sattr, svalue;
790 829
 
791
-	found = 0;
830
+	found = MI_FOUND_NONE;
831
+	found_rtpp_disabled = 0;
832
+	found_rtpp = NULL;
833
+	enable = 0;
792 834
 
793
-	if(rtpp_set_list ==NULL)
794
-		goto end;
835
+	if (rtpp_set_list == NULL) {
836
+	    return init_mi_tree(404, MI_RTP_PROXY_NOT_FOUND, MI_RTP_PROXY_NOT_FOUND_LEN);
837
+	}
795 838
 
796 839
 	node = cmd_tree->node.kids;
797
-	if(node == NULL)
798
-		return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
840
+	if (node == NULL) {
841
+		return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
842
+	}
799 843
 
800
-	if(node->value.s == NULL || node->value.len ==0)
801
-		return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
844
+	if (node->value.s == NULL || node->value.len ==0) {
845
+		return init_mi_tree(400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
846
+	}
802 847
 
848
+	/* get proxy */
803 849
 	rtpp_url = node->value;
804 850
 
805 851
 	node = node->next;
806
-	if(node == NULL)
807
-		return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
852
+	if (node == NULL) {
853
+		return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
854
+	}
808 855
 
809
-	enable = 0;
810
-	if( strno2int( &node->value, &enable) <0)
856
+	if (node->value.s == NULL || node->value.len ==0) {
857
+		return init_mi_tree(400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
858
+	}
859
+
860
+	/* get value (enable/disable) */
861
+	if(strno2int(&node->value, &enable) < 0) {
811 862
 		goto error;
863
+	}
864
+
865
+	node = node->next;
866
+	if (node != NULL) {
867
+		return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
868
+	}
869
+
870
+    /* found a matching all - show all rtpp */
871
+    if (strncmp(MI_ALL, rtpp_url.s, MI_ALL_LEN) == 0) {
872
+        found = MI_FOUND_ALL;
873
+    }
812 874
 
813 875
 	for(rtpp_list = rtpp_set_list->rset_first; rtpp_list != NULL;
814
-					rtpp_list = rtpp_list->rset_next){
876
+					rtpp_list = rtpp_list->rset_next) {
815 877
 
816 878
 		for(crt_rtpp = rtpp_list->rn_first; crt_rtpp != NULL;
817
-						crt_rtpp = crt_rtpp->rn_next){
818
-			/*found a matching rtpp*/
879
+						crt_rtpp = crt_rtpp->rn_next) {
880
+
881
+	        /* found a matching rtpp - show it */
882
+	        if (found == MI_FOUND_ALL ||
883
+                    (crt_rtpp->rn_url.len == rtpp_url.len &&
884
+	                strncmp(crt_rtpp->rn_url.s, rtpp_url.s, rtpp_url.len) == 0)) {
885
+	            /* do ping when try to enable the rtpp */
886
+	            if (enable) {
887
+
888
+	                /* if ping success, enable the rtpp and reset ticks */
889
+	                if (rtpp_test_ping(crt_rtpp) == 0) {
890
+					    crt_rtpp->rn_disabled = 0;
891
+	                    crt_rtpp->rn_recheck_ticks = MI_MIN_RECHECK_TICKS;
892
+
893
+	                /* if ping fail, disable the rtpps but _not_ permanently*/
894
+	                } else {
895
+	                    crt_rtpp->rn_recheck_ticks = get_ticks() + rtpengine_disable_tout;
896
+					    crt_rtpp->rn_disabled = 1;
897
+	                    found_rtpp_disabled = 1;
898
+	                }
899
+
900
+	            /* do not ping when disable the rtpp; disable it permanenty */
901
+	            } else {
902
+					crt_rtpp->rn_disabled = 1;
903
+	                crt_rtpp->rn_recheck_ticks = MI_MAX_RECHECK_TICKS;
904
+	            }
905
+
906
+                if (found == MI_FOUND_NONE) {
907
+                        found = MI_FOUND_ONE;
908
+                        found_rtpp = crt_rtpp;
909
+                }
910
+	        }
911
+		}
912
+	}
819 913
 
820
-			if(crt_rtpp->rn_url.len == rtpp_url.len){
914
+	root = init_mi_tree(200, MI_OK_S, MI_OK_LEN);
915
+	if (!root) {
916
+		LM_ERR("the MI tree cannot be initialized!\n");
917
+		return 0;
918
+	}
919
+	node = &root->node;
821 920
 
822
-				if(strncmp(crt_rtpp->rn_url.s, rtpp_url.s, rtpp_url.len) == 0){
823
-					/*set the enabled/disabled status*/
824
-					found = 1;
825
-					crt_rtpp->rn_recheck_ticks =
826
-						enable? MI_MIN_RECHECK_TICKS : MI_MAX_RECHECK_TICKS;
827
-					crt_rtpp->rn_disabled = enable?0:1;
828
-				}
829
-			}
830
-		}
921
+	switch (found) {
922
+	    case MI_FOUND_ALL:
923
+	        snode.s = MI_ALL;
924
+	        snode.len = MI_ALL_LEN;
925
+            break;
926
+	    case MI_FOUND_ONE:
927
+	        snode.s = found_rtpp->rn_url.s;
928
+	        snode.len = found_rtpp->rn_url.len;
929
+	        break;
930
+	    default:
931
+	        if (root) {
932
+	            free_mi_tree(root);
933
+	        }
934
+	        return init_mi_tree(404, MI_RTP_PROXY_NOT_FOUND, MI_RTP_PROXY_NOT_FOUND_LEN);
935
+	}
936
+
937
+    svalue.s = MI_SUCCESS;
938
+    svalue.len = MI_SUCCESS_LEN;
939
+
940
+    if (enable) {
941
+        sattr.s = MI_ENABLE;
942
+        sattr.len = MI_ENABLE_LEN;
943
+
944
+        if (found_rtpp_disabled) {
945
+            svalue.s = MI_FAIL;
946
+            svalue.len = MI_FAIL_LEN;
947
+        }
948
+    } else {
949
+        sattr.s = MI_DISABLE;
950
+        sattr.len = MI_DISABLE_LEN;
951
+    }
952
+
953
+	if (!(crt_node = add_mi_node_child(node, 0,
954
+	                                   snode.s, snode.len,
955
+	                                   0, 0)) ) {
956
+	    LM_ERR("cannot add the child node to the tree\n");
957
+	    goto error;
831 958
 	}
832 959
 
833
-end:
834
-	if(found)
835
-		return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
836
-	return init_mi_tree(404,MI_RTP_PROXY_NOT_FOUND,MI_RTP_PROXY_NOT_FOUND_LEN);
960
+	if ((attr = add_mi_attr(crt_node, MI_DUP_VALUE,
961
+	                        sattr.s, sattr.len,
962
+	                        svalue.s, svalue.len)) == 0) {
963
+	    LM_ERR("cannot add attributes to the node\n");
964
+	    goto error;
965
+	}
966
+
967
+
968
+	return root;
969
+
837 970
 error:
838
-	return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
971
+	if (root) {
972
+	    free_mi_tree(root);
973
+	}
974
+	return init_mi_tree(404, MI_ERROR, MI_ERROR_LEN);
839 975
 }
840 976
 
841 977
 
842 978
 
979
+
843 980
 #define add_rtpp_node_int_info(_parent, _name, _name_len, _value, _child,\
844 981
 								_len, _string, _error)\
845 982
 	do {\
... ...
@@ -853,86 +1024,294 @@ error:
853 853
 			goto _error;\
854 854
 	}while(0);
855 855
 
856
-static struct mi_root* mi_show_rtpproxies(struct mi_root* cmd_tree,
857
-												void* param)
856
+
857
+static int add_rtpp_node_info (struct mi_node *node,
858
+	                           struct rtpp_node *crt_rtpp,
859
+	                           struct rtpp_set *rtpp_list)
858 860
 {
859
-	struct mi_node* node, *crt_node, *child;
860
-	struct mi_root* root;
861
-	struct mi_attr * attr;
862
-	struct rtpp_set * rtpp_list;
863
-	struct rtpp_node * crt_rtpp;
864
-	char * string, *id;
865 861
 	int id_len, len;
862
+    int rtpp_ticks;
863
+	struct mi_node *crt_node, *child;
864
+	struct mi_attr *attr;
865
+	char *string, *id;
866 866
 
867 867
 	string = id = 0;
868 868
 
869
+	id = int2str(rtpp_list->id_set, &id_len);
870
+	if(!id) {
871
+	    LM_ERR("cannot convert set id\n");
872
+	    goto error;
873
+	}
874
+
875
+	if(!(crt_node = add_mi_node_child(node, 0, crt_rtpp->rn_url.s,
876
+	        crt_rtpp->rn_url.len, 0,0)) ) {
877
+	    LM_ERR("cannot add the child node to the tree\n");
878
+	    goto error;
879
+	}
880
+
881
+	LM_DBG("adding node name %s \n",crt_rtpp->rn_url.s );
882
+
883
+	if((attr = add_mi_attr(crt_node, MI_DUP_VALUE, MI_SET, MI_SET_LEN,
884
+	                        id, id_len))== 0) {
885
+	    LM_ERR("cannot add attributes to the node\n");
886
+	    goto error;
887
+	}
888
+
889
+	add_rtpp_node_int_info(crt_node, MI_INDEX, MI_INDEX_LEN,
890
+	    crt_rtpp->idx, child, len, string, error);
891
+
892
+	if ((1 == crt_rtpp->rn_disabled ) && (crt_rtpp->rn_recheck_ticks == MI_MAX_RECHECK_TICKS)) {
893
+	    if( !(child = add_mi_node_child(crt_node, MI_DUP_VALUE, MI_DISABLED, MI_DISABLED_LEN,
894
+	                    MI_DISABLED_PERMANENT, MI_DISABLED_PERMANENT_LEN))) {
895
+	        LM_ERR("cannot add disabled (permanent) message\n");
896
+	        goto error;
897
+	    }
898
+	}
899
+	else {
900
+	    add_rtpp_node_int_info(crt_node, MI_DISABLED, MI_DISABLED_LEN,
901
+	        crt_rtpp->rn_disabled, child, len, string, error);
902
+	}
903
+
904
+	add_rtpp_node_int_info(crt_node, MI_WEIGHT, MI_WEIGHT_LEN,
905
+	    crt_rtpp->rn_weight, child, len, string, error);
906
+
907
+	if (crt_rtpp->rn_recheck_ticks == MI_MAX_RECHECK_TICKS) {
908
+	    if( !(child = add_mi_node_child(crt_node, MI_DUP_VALUE,
909
+	                  MI_RECHECK_TICKS, MI_RECHECK_T_LEN,
910
+	                  "N/A", sizeof("N/A") - 1))) {
911
+	        LM_ERR("cannot add MAX recheck_ticks value\n");
912
+	        goto error;
913
+	    }
914
+	} else {