Browse code

- migrated to new debug functions - some global variables renamed to avoid mistaken overlaping - new random selection algorithm (6) - support for loading destination list from database - ability to reload the destination list from database upon a mi command - documentation updated

git-svn-id: https://openser.svn.sourceforge.net/svnroot/openser/trunk@2532 689a6050-402a-0410-94f2-e92a70836424

Daniel-Constantin Mierla authored on 27/07/2007 11:38:55
Showing 5 changed files
... ...
@@ -1,4 +1,3 @@
1
-
2 1
 DISPATCHER Module
3 2
 
4 3
 Daniel-Constantin Mierla
... ...
@@ -14,7 +13,7 @@ Carsten Bock
14 13
    Copyright � 2004 FhG FOKUS
15 14
 
16 15
    Copyright � 2005 Voice-System.RO
17
-     _________________________________________________________
16
+     __________________________________________________________
18 17
 
19 18
    Table of Contents
20 19
    1. User's Guide
... ...
@@ -28,16 +27,20 @@ Carsten Bock
28 27
         1.3. Exported Parameters
29 28
 
30 29
               1.3.1. list_file (string)
31
-              1.3.2. force_dst (int)
32
-              1.3.3. flags (int)
33
-              1.3.4. use_default (int)
34
-              1.3.5. dst_avp (str)
35
-              1.3.6. grp_avp (str)
36
-              1.3.7. cnt_avp (str)
37
-              1.3.8. ds_ping_method (string)
38
-              1.3.9. ds_ping_from (string)
39
-              1.3.10. ds_ping_interval (int)
40
-              1.3.11. ds_probing_threshhold (int)
30
+              1.3.2. db_url (string)
31
+              1.3.3. table_name (string)
32
+              1.3.4. setid_col (string)
33
+              1.3.5. destination_col (string)
34
+              1.3.6. force_dst (int)
35
+              1.3.7. flags (int)
36
+              1.3.8. use_default (int)
37
+              1.3.9. dst_avp (str)
38
+              1.3.10. grp_avp (str)
39
+              1.3.11. cnt_avp (str)
40
+              1.3.12. ds_ping_method (string)
41
+              1.3.13. ds_ping_from (string)
42
+              1.3.14. ds_ping_interval (int)
43
+              1.3.15. ds_probing_threshhold (int)
41 44
 
42 45
         1.4. Exported Functions
43 46
 
... ...
@@ -54,6 +57,7 @@ Carsten Bock
54 57
 
55 58
               1.5.1. ds_set_state
56 59
               1.5.2. ds_list
60
+              1.5.3. ds_reload
57 61
 
58 62
         1.6. Installation & Running
59 63
 
... ...
@@ -65,33 +69,37 @@ Carsten Bock
65 69
 
66 70
    List of Examples
67 71
    1-1. Set the "list_file" parameter
68
-   1-2. Set the "force_dst" parameter
69
-   1-3. Set the "flags" parameter
70
-   1-4. Set the "use_default" parameter
71
-   1-5. Set the "dst_avp" parameter
72
-   1-6. Set the "grp_avp" parameter
73
-   1-7. Set the "cnt_avp" parameter
74
-   1-8. Set the "ds_ping_method" parameter
75
-   1-9. Set the "ds_ping_from" parameter
76
-   1-10. Set the "ds_ping_interval" parameter
77
-   1-11. Set the "ds_probing_threshhold" parameter
78
-   1-12. ds_select_dst usage
79
-   1-13. dispatcher list file
80
-   1-14. OpenSER config script - sample dispatcher usage
81
-     _________________________________________________________
72
+   1-2. Set "db_url" parameter
73
+   1-3. Set "table_name" parameter
74
+   1-4. Set "setid_col" parameter
75
+   1-5. Set "destination_col" parameter
76
+   1-6. Set the "force_dst" parameter
77
+   1-7. Set the "flags" parameter
78
+   1-8. Set the "use_default" parameter
79
+   1-9. Set the "dst_avp" parameter
80
+   1-10. Set the "grp_avp" parameter
81
+   1-11. Set the "cnt_avp" parameter
82
+   1-12. Set the "ds_ping_method" parameter
83
+   1-13. Set the "ds_ping_from" parameter
84
+   1-14. Set the "ds_ping_interval" parameter
85
+   1-15. Set the "ds_probing_threshhold" parameter
86
+   1-16. ds_select_dst usage
87
+   1-17. dispatcher list file
88
+   1-18. OpenSER config script - sample dispatcher usage
89
+     __________________________________________________________
82 90
 
83 91
 Chapter 1. User's Guide
84 92
 
85 93
 1.1. Overview
86 94
 
87
-   This modules implements a dispatcher for destination
88
-   addresses. It computes hashes over parts of the request and
89
-   selects an address from a destination set. The selected
90
-   address is used then as outbound proxy.
95
+   This modules implements a dispatcher for destination addresses.
96
+   It computes hashes over parts of the request and selects an
97
+   address from a destination set. The selected address is used
98
+   then as outbound proxy.
91 99
 
92 100
    The module can be used as a stateless load balancer, having no
93 101
    guarantee of fair distribution.
94
-     _________________________________________________________
102
+     __________________________________________________________
95 103
 
96 104
 1.2. Dependencies
97 105
 
... ...
@@ -100,7 +108,7 @@ Chapter 1. User's Guide
100 108
    The following modules must be loaded before this module:
101 109
 
102 110
      * TM - only if active recovery of failed hosts is required.
103
-     _________________________________________________________
111
+     __________________________________________________________
104 112
 
105 113
 1.2.2. External libraries or applications
106 114
 
... ...
@@ -108,7 +116,7 @@ Chapter 1. User's Guide
108 116
    before running OpenSER with this module:
109 117
 
110 118
      * none.
111
-     _________________________________________________________
119
+     __________________________________________________________
112 120
 
113 121
 1.3. Exported Parameters
114 122
 
... ...
@@ -117,71 +125,122 @@ Chapter 1. User's Guide
117 125
    Path to the file with destination sets.
118 126
 
119 127
    Default value is "/etc/openser/dispatcher.list" or
120
-   "/usr/local/etc/openser/dispatcher.list". 
128
+   "/usr/local/etc/openser/dispatcher.list".
121 129
 
122 130
    Example 1-1. Set the "list_file" parameter
123 131
 ...
124 132
 modparam("dispatcher", "list_file", "/var/run/openser/dispatcher.list")
125 133
 ...
126
-     _________________________________________________________
134
+     __________________________________________________________
127 135
 
128
-1.3.2. force_dst (int)
136
+1.3.2. db_url (string)
129 137
 
130
-   If set to 1, force overwriting of destination address when
131
-   that is already set.
138
+   If you want to load the sets of gateways from the database you
139
+   must set this parameter.
132 140
 
133
-   Default value is "0". 
141
+   Default value is "NULL" (disable DB support).
134 142
 
135
-   Example 1-2. Set the "force_dst" parameter
143
+   Example 1-2. Set "db_url" parameter
144
+...
145
+modparam("dispatcher", "db_url", "mysql://user:passwb@localhost/database
146
+")
147
+...
148
+     __________________________________________________________
149
+
150
+1.3.3. table_name (string)
151
+
152
+   If you want to load the sets of gateways from the database you
153
+   must set this parameter as the database name.
154
+
155
+   Default value is "dispatcher".
156
+
157
+   Example 1-3. Set "table_name" parameter
158
+...
159
+modparam("dispatcher", "table_name", "my_dispatcher")
160
+...
161
+     __________________________________________________________
162
+
163
+1.3.4. setid_col (string)
164
+
165
+   The column's name in the database storing the gateway's group
166
+   id.
167
+
168
+   Default value is "setid".
169
+
170
+   Example 1-4. Set "setid_col" parameter
171
+...
172
+modparam("dispatcher", "setid_col", "groupid")
173
+...
174
+     __________________________________________________________
175
+
176
+1.3.5. destination_col (string)
177
+
178
+   The column's name in the database storing the gateway's sip
179
+   uri.
180
+
181
+   Default value is "destination".
182
+
183
+   Example 1-5. Set "destination_col" parameter
184
+...
185
+modparam("dispatcher", "destination_col", "uri")
186
+...
187
+     __________________________________________________________
188
+
189
+1.3.6. force_dst (int)
190
+
191
+   If set to 1, force overwriting of destination address when that
192
+   is already set.
193
+
194
+   Default value is "0".
195
+
196
+   Example 1-6. Set the "force_dst" parameter
136 197
 ...
137 198
 modparam("dispatcher", "force_dst", 1)
138 199
 ...
139
-     _________________________________________________________
200
+     __________________________________________________________
140 201
 
141
-1.3.3. flags (int)
202
+1.3.7. flags (int)
142 203
 
143
-   Various flags that affect dispatcher's behaviour. The flags
144
-   are defined as a bitmask on an integer value. If flag 1 is set
145
-   only the username part of the uri will be used when computing
146
-   an uri based hash. If no flags are set the username, hostname
147
-   and port will be used The port is used only if different from
148
-   5060 (normal sip uri) or 5061 (in the sips case).
204
+   Various flags that affect dispatcher's behaviour. The flags are
205
+   defined as a bitmask on an integer value. If flag 1 is set only
206
+   the username part of the uri will be used when computing an uri
207
+   based hash. If no flags are set the username, hostname and port
208
+   will be used The port is used only if different from 5060
209
+   (normal sip uri) or 5061 (in the sips case).
149 210
 
150 211
    If flag 2 is set, then the failover support is enabled. The
151 212
    functions exported by the module will store the rest of
152 213
    addresses from the destination set in AVP, and use these AVPs
153 214
    to contact next address when the current-tried fails.
154 215
 
155
-   Default value is "0". 
216
+   Default value is "0".
156 217
 
157
-   Example 1-3. Set the "flags" parameter
218
+   Example 1-7. Set the "flags" parameter
158 219
  ...
159 220
  modparam("dispatcher", "flags", 3)
160 221
  ...
222
+     __________________________________________________________
161 223
 
162
-     _________________________________________________________
163
-
164
-1.3.4. use_default (int)
224
+1.3.8. use_default (int)
165 225
 
166 226
    If the parameter is set to 1, the last address in destination
167
-   set is used as last option to send the message. For example,
168
-   it is good when wanting to send the call to an anouncement
169
-   server saying: "the gateways are full, try later".
227
+   set is used as last option to send the message. For example, it
228
+   is good when wanting to send the call to an anouncement server
229
+   saying: "the gateways are full, try later".
170 230
 
171
-   Default value is "0". 
231
+   Default value is "0".
172 232
 
173
-   Example 1-4. Set the "use_default" parameter
233
+   Example 1-8. Set the "use_default" parameter
174 234
  ...
175 235
  modparam("dispatcher", "use_default", 1)
176 236
  ...
237
+     __________________________________________________________
177 238
 
178
-     _________________________________________________________
239
+1.3.9. dst_avp (str)
179 240
 
180
-1.3.5. dst_avp (str)
181
-
182
-   The name of the avp which will hold the list with addresses,
183
-   in the order they have been selected by the chosen algorithm.
184
-   If use_default is 1, the value of last dst_avp_id is the last
241
+   The name of the avp which will hold the list with addresses, in
242
+   the order they have been selected by the chosen algorithm. If
243
+   use_default is 1, the value of last dst_avp_id is the last
185 244
    address in destination set. The first dst_avp_id is the
186 245
    selected destinations. All the other addresses from the
187 246
    destination set will be added in the avp list to be able to
... ...
@@ -189,118 +248,111 @@ modparam("dispatcher", "force_dst", 1)
189 248
 
190 249
    Note
191 250
 
192
-   You must set this parameter if you want do do load balancing
193
-   fail over.
251
+        You must set this parameter if you want do do load balancing
252
+        fail over.
194 253
 
195
-   Default value is "null" - don't add AVPs. 
254
+   Default value is "null" - don't add AVPs.
196 255
 
197
-   Example 1-5. Set the "dst_avp" parameter
256
+   Example 1-9. Set the "dst_avp" parameter
198 257
  ...
199 258
  modparam("dispatcher", "dst_avp", "$avp(i:271)")
200 259
  ...
260
+     __________________________________________________________
201 261
 
202
-     _________________________________________________________
203
-
204
-1.3.6. grp_avp (str)
262
+1.3.10. grp_avp (str)
205 263
 
206 264
    The name of the avp storing the group id of the destination
207 265
    set. Good to have it for later usage or checks.
208 266
 
209 267
    Note
210 268
 
211
-   You must set this parameter if you want do do load balancing
212
-   fail over.
269
+        You must set this parameter if you want do do load balancing
270
+        fail over.
213 271
 
214
-   Default value is "null" - don't add AVP. 
272
+   Default value is "null" - don't add AVP.
215 273
 
216
-   Example 1-6. Set the "grp_avp" parameter
274
+   Example 1-10. Set the "grp_avp" parameter
217 275
  ...
218 276
  modparam("dispatcher", "grp_avp", "$avp(i:272)")
219 277
  ...
278
+     __________________________________________________________
220 279
 
221
-     _________________________________________________________
222
-
223
-1.3.7. cnt_avp (str)
280
+1.3.11. cnt_avp (str)
224 281
 
225
-   The name of the avp storing the number of destination
226
-   addresses kept in dst_avp avps.
282
+   The name of the avp storing the number of destination addresses
283
+   kept in dst_avp avps.
227 284
 
228 285
    Note
229 286
 
230
-   You must set this parameter if you want do do load balancing
231
-   fail over.
287
+        You must set this parameter if you want do do load balancing
288
+        fail over.
232 289
 
233
-   Default value is "null" - don't add AVP. 
290
+   Default value is "null" - don't add AVP.
234 291
 
235
-   Example 1-7. Set the "cnt_avp" parameter
292
+   Example 1-11. Set the "cnt_avp" parameter
236 293
  ...
237 294
  modparam("dispatcher", "cnt_avp", "$avp(i:273)")
238 295
  ...
296
+     __________________________________________________________
239 297
 
240
-     _________________________________________________________
241
-
242
-1.3.8. ds_ping_method (string)
298
+1.3.12. ds_ping_method (string)
243 299
 
244 300
    With this Method you can define, with which method you want to
245 301
    probe the failed gateways. This method is only available, if
246 302
    compiled with the probing of failed gateways enabled.
247 303
 
248
-   Default value is "OPTIONS". 
304
+   Default value is "OPTIONS".
249 305
 
250
-   Example 1-8. Set the "ds_ping_method" parameter
306
+   Example 1-12. Set the "ds_ping_method" parameter
251 307
  ...
252 308
  modparam("dispatcher", "ds_ping_method", "INFO")
253 309
  ...
310
+     __________________________________________________________
254 311
 
255
-     _________________________________________________________
256
-
257
-1.3.9. ds_ping_from (string)
312
+1.3.13. ds_ping_from (string)
258 313
 
259 314
    With this Method you can define the "From:"-Line for the
260 315
    request, sent to the failed gateways. This method is only
261 316
    available, if compiled with the probing of failed gateways
262 317
    enabled.
263 318
 
264
-   Default value is "sip:dispatcher@localhost". 
319
+   Default value is "sip:dispatcher@localhost".
265 320
 
266
-   Example 1-9. Set the "ds_ping_from" parameter
321
+   Example 1-13. Set the "ds_ping_from" parameter
267 322
  ...
268 323
  modparam("dispatcher", "ds_ping_from", "sip:proxy@sip.somehost.com")
269 324
  ...
325
+     __________________________________________________________
270 326
 
271
-     _________________________________________________________
272
-
273
-1.3.10. ds_ping_interval (int)
327
+1.3.14. ds_ping_interval (int)
274 328
 
275 329
    With this Method you can define the interval for sending a
276 330
    request to a failed gateway. This parameter is only used, when
277 331
    the TM-Module is loaded. If set to "0", the pinging of failed
278 332
    requests is disabled.
279 333
 
280
-   Default value is "10". 
334
+   Default value is "10".
281 335
 
282
-   Example 1-10. Set the "ds_ping_interval" parameter
336
+   Example 1-14. Set the "ds_ping_interval" parameter
283 337
  ...
284 338
  modparam("dispatcher", "ds_ping_interval", 30)
285 339
  ...
340
+     __________________________________________________________
286 341
 
287
-     _________________________________________________________
288
-
289
-1.3.11. ds_probing_threshhold (int)
342
+1.3.15. ds_probing_threshhold (int)
290 343
 
291
-   If you want to set a gateway into probing mode, you will need
292
-   a specific number of requests until it will change from
293
-   "active" to probing. The number of attempts can be set with
294
-   this parameter.
344
+   If you want to set a gateway into probing mode, you will need a
345
+   specific number of requests until it will change from "active"
346
+   to probing. The number of attempts can be set with this
347
+   parameter.
295 348
 
296
-   Default value is "3". 
349
+   Default value is "3".
297 350
 
298
-   Example 1-11. Set the "ds_probing_threshhold" parameter
351
+   Example 1-15. Set the "ds_probing_threshhold" parameter
299 352
  ...
300 353
  modparam("dispatcher", "ds_probing_threshhold", 10)
301 354
  ...
302
-
303
-     _________________________________________________________
355
+     __________________________________________________________
304 356
 
305 357
 1.4. Exported Functions
306 358
 
... ...
@@ -312,16 +364,16 @@ modparam("dispatcher", "force_dst", 1)
312 364
 
313 365
      * set - the id of the set from where to pick up destination
314 366
        address. It is the first column in destination list file.
315
-     * alg - the algorithm used to select the destination
316
-       address.
367
+     * alg - the algorithm used to select the destination address.
317 368
           + "0" - hash over callid
318 369
           + "1" - hash over from uri.
319 370
           + "2" - hash over to uri.
320 371
           + "3" - hash over request-uri.
321 372
           + "4" - round-robin (next destination).
322 373
           + "5" - hash over authorization-username
323
-            (Proxy-Authorization or "normal" authorization). If
324
-            no username is found, round robin is used.
374
+            (Proxy-Authorization or "normal" authorization). If no
375
+            username is found, round robin is used.
376
+          + "6" - random (using rand()).
325 377
           + "X" - if the algorithm is not implemented, the first
326 378
             entry in set is chosen.
327 379
 
... ...
@@ -332,17 +384,17 @@ modparam("dispatcher", "force_dst", 1)
332 384
 
333 385
    This function can be used from REQUEST_ROUTE.
334 386
 
335
-   Example 1-12. ds_select_dst usage
387
+   Example 1-16. ds_select_dst usage
336 388
 ...
337 389
 ds_select_dst("1", "0");
338 390
 ...
339
-     _________________________________________________________
391
+     __________________________________________________________
340 392
 
341 393
 1.4.2. ds_select_domain(set, alg)
342 394
 
343 395
    The method selects a destination from addresses set and
344
-   rewrites the host and port from R-URI. The parameters have
345
-   same meaning as for ds_select_dst().
396
+   rewrites the host and port from R-URI. The parameters have same
397
+   meaning as for ds_select_dst().
346 398
 
347 399
    If the bit 2 in 'flags' is set, the rest of the addresses from
348 400
    the destination set is stored in AVP list. You can use
... ...
@@ -350,7 +402,7 @@ ds_select_dst("1", "0");
350 402
    forking to all possible destinations.
351 403
 
352 404
    This function can be used from REQUEST_ROUTE.
353
-     _________________________________________________________
405
+     __________________________________________________________
354 406
 
355 407
 1.4.3. ds_next_dst()
356 408
 
... ...
@@ -358,7 +410,7 @@ ds_select_dst("1", "0");
358 410
    'dst_avp_id' and sets the dst_uri (outbound proxy address).
359 411
 
360 412
    This function can be used from FAILURE_ROUTE.
361
-     _________________________________________________________
413
+     __________________________________________________________
362 414
 
363 415
 1.4.4. ds_next_domain()
364 416
 
... ...
@@ -366,18 +418,18 @@ ds_select_dst("1", "0");
366 418
    'dst_avp_id' and sets the domain part of the request uri.
367 419
 
368 420
    This function can be used from FAILURE_ROUTE.
369
-     _________________________________________________________
421
+     __________________________________________________________
370 422
 
371 423
 1.4.5. ds_mark_dst()
372 424
 
373
-   Mark the last used address from destination set as inactive,
374
-   in order to be ingnored in the future. In this way it can be
425
+   Mark the last used address from destination set as inactive, in
426
+   order to be ingnored in the future. In this way it can be
375 427
    implemented an automatic detection of failed gateways. When an
376 428
    address is marked as inactive, it will be ignored by
377 429
    'ds_select_dst' and 'ds_select_domain'.
378 430
 
379 431
    This function can be used from FAILURE_ROUTE.
380
-     _________________________________________________________
432
+     __________________________________________________________
381 433
 
382 434
 1.4.6. ds_mark_dst("s")
383 435
 
... ...
@@ -400,26 +452,26 @@ ds_select_dst("1", "0");
400 452
        probing.
401 453
 
402 454
    This function can be used from FAILURE_ROUTE.
403
-     _________________________________________________________
455
+     __________________________________________________________
404 456
 
405 457
 1.4.7. ds_is_from_list()
406 458
 
407
-   This function returns true, if the current request comes from
408
-   a host from the dispatcher-list; otherwise false.
459
+   This function returns true, if the current request comes from a
460
+   host from the dispatcher-list; otherwise false.
409 461
 
410 462
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE,
411 463
    BRANCH_ROUTE and ONREPLY_ROUTE.
412
-     _________________________________________________________
464
+     __________________________________________________________
413 465
 
414 466
 1.4.8. ds_is_from_list("group")
415 467
 
416
-   This function returns true, if the current request comes from
417
-   a host in the given group of the dispatcher-list; otherwise
468
+   This function returns true, if the current request comes from a
469
+   host in the given group of the dispatcher-list; otherwise
418 470
    false.
419 471
 
420 472
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE,
421 473
    BRANCH_ROUTE and ONREPLY_ROUTE.
422
-     _________________________________________________________
474
+     __________________________________________________________
423 475
 
424 476
 1.5. Exported MI Functions
425 477
 
... ...
@@ -445,7 +497,7 @@ ds_select_dst("1", "0");
445 497
                 _group_
446 498
                 _address_
447 499
                 _empty_line_
448
-     _________________________________________________________
500
+     __________________________________________________________
449 501
 
450 502
 1.5.2. ds_list
451 503
 
... ...
@@ -458,7 +510,20 @@ ds_select_dst("1", "0");
458 510
    MI FIFO Command Format:
459 511
                 :ds_list:_reply_fifo_file_
460 512
                 _empty_line_
461
-     _________________________________________________________
513
+     __________________________________________________________
514
+
515
+1.5.3. ds_reload
516
+
517
+   It reloads the groups and included destinations. Available only
518
+   when DB support configured.
519
+
520
+   Name: ds_reload
521
+
522
+   Parameters: none
523
+
524
+   MI DATAGRAM Command Format:
525
+                ":ds_reload:\n."
526
+     __________________________________________________________
462 527
 
463 528
 1.6. Installation & Running
464 529
 
... ...
@@ -469,7 +534,7 @@ ds_select_dst("1", "0");
469 534
    integer value. Destination address must be a valid SIP URI.
470 535
    Empty lines or lines starting with "#" are ignored.
471 536
 
472
-   Example 1-13. dispatcher list file
537
+   Example 1-17. dispatcher list file
473 538
 ...
474 539
 # $Id$
475 540
 # dispatcher destination sets
... ...
@@ -484,13 +549,13 @@ ds_select_dst("1", "0");
484 549
 1 sip:127.0.0.1:7072
485 550
 1 sip:127.0.0.1:7074
486 551
 ...
487
-     _________________________________________________________
552
+     __________________________________________________________
488 553
 
489 554
 1.6.2. OpenSER config file
490 555
 
491 556
    Next picture displays a sample usage of dispatcher.
492 557
 
493
-   Example 1-14. OpenSER config script - sample dispatcher usage
558
+   Example 1-18. OpenSER config script - sample dispatcher usage
494 559
 ...
495 560
 # $Id$
496 561
 # sample config file for dispatcher module
... ...
@@ -536,17 +601,17 @@ route{
536 601
 }
537 602
 
538 603
 ...
539
-     _________________________________________________________
604
+     __________________________________________________________
540 605
 
541 606
 Chapter 2. Developer's Guide
542 607
 
543 608
    The module does not provide any API to use in other OpenSER
544 609
    modules.
545
-     _________________________________________________________
610
+     __________________________________________________________
546 611
 
547 612
 Chapter 3. Frequently Asked Questions
548 613
 
549
-   3.1. Does dispatcher provide a fair distribution? 
614
+   3.1. Does dispatcher provide a fair distribution?
550 615
    3.2. Is dispatcher dialog stateful?
551 616
    3.3. Where can I find more about OpenSER?
552 617
    3.4. Where can I post a question about this module?
... ...
@@ -571,8 +636,8 @@ Chapter 3. Frequently Asked Questions
571 636
 
572 637
    3.4. Where can I post a question about this module?
573 638
 
574
-   First at all check if your question was already answered on
575
-   one of our mailing lists:
639
+   First at all check if your question was already answered on one
640
+   of our mailing lists:
576 641
 
577 642
      * User Mailing List -
578 643
        http://openser.org/cgi-bin/mailman/listinfo/users
... ...
@@ -35,6 +35,8 @@
35 35
  * re-enabling of destinations (carsten)
36 36
  * 2007-05-08  Ported the changes to SVN-Trunk, renamed ds_is_domain to
37 37
  * ds_is_from_list and modified the function to work with IPv6 adresses.
38
+ * 2007-07-18  removed index stuff 
39
+ * 			   added DB support to load/reload data(ancuta)
38 40
  */
39 41
 
40 42
 #include <stdio.h>
... ...
@@ -55,16 +57,12 @@
55 57
 #include "../../parser/digest/digest.h"
56 58
 #include "../../resolve.h"
57 59
 #include "../tm/tm_load.h"
60
+#include "../../db/db.h"
61
+#include "../../db/db_res.h"
58 62
 
59 63
 #include "dispatch.h"
60 64
 
61
-typedef struct _ds_setidx
62
-{
63
-	int id;
64
-	int index;
65
-	struct _ds_setidx *next;
66
-} ds_setidx_t, *ds_setidx_p;
67
-
65
+#define DS_TABLE_VERSION	1
68 66
 
69 67
 typedef struct _ds_dest
70 68
 {
... ...
@@ -73,7 +71,6 @@ typedef struct _ds_dest
73 71
 	struct ip_addr ip_address; /* IP-Address of the entry */
74 72
     unsigned short int port; /* Port of the request URI */
75 73
     int failure_count;
76
-    	
77 74
 	struct _ds_dest *next;
78 75
 } ds_dest_t, *ds_dest_p;
79 76
 
... ...
@@ -81,7 +78,6 @@ typedef struct _ds_set
81 78
 {
82 79
 	int id;				/* id of dst set */
83 80
 	int nr;				/* number of items in dst set */
84
-	int index;			/* index pf dst set */
85 81
 	int last;			/* last used item in dst set */
86 82
 	ds_dest_p dlist;
87 83
 	struct _ds_set *next;
... ...
@@ -89,39 +85,201 @@ typedef struct _ds_set
89 85
 
90 86
 extern int ds_force_dst;
91 87
 
92
-ds_setidx_p _ds_index = NULL;
93
-ds_set_p _ds_list = NULL;
94
-int _ds_list_nr = 0;
88
+static db_func_t ds_dbf;
89
+static db_con_t* ds_db_handle = 0;
90
+ds_set_p *ds_lists=NULL;
91
+int *ds_list_nr, *crt_idx, *next_idx;
95 92
 
96
-/**
97
- *
98
- */
93
+#define _ds_list 	(ds_lists[*crt_idx])
94
+#define _ds_list_nr (*ds_list_nr)
95
+
96
+void destroy_list(int);
97
+
98
+int init_data()
99
+{
100
+	int * p;
101
+
102
+	ds_lists = (ds_set_p*)shm_malloc(2*sizeof(ds_set_p));
103
+	if(!ds_lists)
104
+	{
105
+		LM_ERR("Out of memory\n");
106
+		return -1;
107
+	}
108
+	ds_lists[0] = ds_lists[1] = 0;
109
+
110
+	
111
+	p = (int*)shm_malloc(3*sizeof(int));
112
+	if(!p)
113
+	{
114
+		LM_ERR("Out of memory\n");
115
+		return -1;
116
+	}
117
+
118
+	crt_idx = p;
119
+	next_idx = p+1;
120
+	ds_list_nr = p+2;
121
+	*crt_idx= *next_idx = 0;
122
+
123
+	return 0;
124
+}
125
+
126
+int add_dest2list(int id, str uri, int list_idx, int * setn)
127
+{
128
+	ds_dest_p dp = NULL;
129
+	ds_set_p  sp = NULL;
130
+	
131
+	/* For DNS-Lookups */
132
+	static char hn[256];
133
+	struct hostent* he;
134
+	struct sip_uri puri;
135
+
136
+	/* check uri */
137
+	if(parse_uri(uri.s, uri.len, &puri)!=0 || puri.host.len>254)
138
+	{
139
+		LM_ERR("bad uri [%.*s]\n", uri.len, uri.s);
140
+		goto err;
141
+	}
142
+	
143
+	/* get dest set */
144
+	sp = ds_lists[list_idx];
145
+	while(sp)
146
+	{
147
+		if(sp->id == id)
148
+			break;
149
+		sp = sp->next;
150
+	}
151
+
152
+	if(sp==NULL)
153
+	{
154
+		sp = (ds_set_p)shm_malloc(sizeof(ds_set_t));
155
+		if(sp==NULL)
156
+		{
157
+			LM_ERR("no more memory.\n");
158
+			goto err;
159
+		}
160
+		
161
+		memset(sp, 0, sizeof(ds_set_t));
162
+		sp->next = ds_lists[list_idx];
163
+		ds_lists[list_idx] = sp;
164
+		*setn = *setn+1;
165
+	}
166
+	sp->id = id;
167
+	sp->nr++;
168
+
169
+	/* store uri */
170
+	dp = (ds_dest_p)shm_malloc(sizeof(ds_dest_t));
171
+	if(dp==NULL)
172
+	{
173
+		LM_ERR("no more memory!\n");
174
+		goto err;
175
+	}
176
+	memset(dp, 0, sizeof(ds_dest_t));
177
+
178
+	dp->uri.s = (char*)shm_malloc((uri.len+1)*sizeof(char));
179
+	if(dp->uri.s==NULL)
180
+	{
181
+		LM_ERR("no more memory!\n");
182
+		goto err;
183
+	}
184
+	strncpy(dp->uri.s, uri.s, uri.len);
185
+	dp->uri.s[uri.len]='\0';
186
+	dp->uri.len = uri.len;
187
+
188
+	/* The Hostname needs to be \0 terminated for resolvehost, so we
189
+	 * make a copy here. */
190
+	strncpy(hn, puri.host.s, puri.host.len);
191
+	hn[puri.host.len]='\0';
192
+		
193
+	/* Do a DNS-Lookup for the Host-Name: */
194
+	he=resolvehost(hn, 1);
195
+	if (he==0)
196
+	{
197
+		LM_ERR("could not resolve %.*s\n", puri.host.len, puri.host.s);
198
+		pkg_free(hn);
199
+		goto err;
200
+	}
201
+	/* Free the hostname */
202
+	hostent2ip_addr(&dp->ip_address, he, 0);
203
+		
204
+	/* Copy the Port out of the URI: */
205
+	dp->port = puri.port_no;		
206
+
207
+	dp->next = sp->dlist;
208
+	sp->dlist = dp;
209
+
210
+	LM_DBG("dest [%d/%d] <%.*s>\n", sp->id, sp->nr, dp->uri.len, dp->uri.s);
211
+	
212
+	return 0;
213
+err:
214
+	/* free allocated memory */
215
+	if(dp!=NULL)
216
+	{
217
+		if(dp->uri.s!=NULL)
218
+			shm_free(dp->uri.s);
219
+		shm_free(dp);
220
+	}
221
+	return -1;
222
+}
223
+
224
+/* compact destinations from sets for fast access */
225
+int reindex_dests(int list_idx, int setn)
226
+{
227
+	int j;
228
+	ds_set_p  sp = NULL;
229
+	ds_dest_p dp = NULL, dp0= NULL;
230
+
231
+	for(sp = ds_lists[list_idx]; sp!= NULL;	sp->dlist = dp0, sp = sp->next)
232
+	{
233
+		dp0 = (ds_dest_p)shm_malloc(sp->nr*sizeof(ds_dest_t));
234
+		if(dp0==NULL)
235
+		{
236
+			LM_ERR("no more memory!\n");
237
+			goto err1;
238
+		}
239
+		memset(dp0, 0, sp->nr*sizeof(ds_dest_t));
240
+
241
+		/*copy from the old pointer to destination, and then free it*/
242
+		for(j=sp->nr-1; j>=0 && sp->dlist!= NULL; j--)
243
+		{
244
+			memcpy(&dp0[j], sp->dlist, sizeof(ds_dest_t));
245
+			if(j==sp->nr-1)
246
+				dp0[j].next = NULL;
247
+			else
248
+				dp0[j].next = &dp0[j+1];
249
+	
250
+			dp = sp->dlist;
251
+			sp->dlist = dp->next;
252
+			
253
+			shm_free(dp);
254
+			dp=NULL;
255
+		}
256
+	}
257
+
258
+	LM_DBG("found [%d] dest sets\n", setn);
259
+	return 0;
260
+
261
+err1:
262
+	return -1;
263
+}
264
+
265
+/*load groups of destinations from file */
99 266
 int ds_load_list(char *lfile)
100 267
 {
101 268
 	char line[256], *p;
102 269
 	FILE *f = NULL;
103
-	int id, i, j, setn;
270
+	int id, setn;
104 271
 	str uri;
105
-	struct sip_uri puri;
106
-	ds_dest_p dp = NULL, dp0 = NULL;
107
-	ds_set_p  sp = NULL, sp0 = NULL;
108
-	ds_setidx_p si = NULL, si0 = NULL;
109 272
 
110
-	/* For DNS-Lookups */
111
-	char *hn;
112
-	struct hostent* he;
113
-	
114 273
 	if(lfile==NULL || strlen(lfile)<=0)
115 274
 	{
116
-		LOG(L_ERR, "DISPATCHER:ds_load_list: bad list file\n");
275
+		LM_ERR("bad list file\n");
117 276
 		return -1;
118 277
 	}
119 278
 
120 279
 	f = fopen(lfile, "r");
121 280
 	if(f==NULL)
122 281
 	{
123
-		LOG(L_ERR, "DISPATCHER:ds_load_list: can't open list file [%s]\n",
124
-				lfile);
282
+		LM_ERR("can't open list file [%s]\n", lfile);
125 283
 		return -1;
126 284
 		
127 285
 	}
... ...
@@ -149,7 +307,7 @@ int ds_load_list(char *lfile)
149 307
 			p++;
150 308
 		if(*p=='\0' || *p=='#')
151 309
 		{
152
-			LOG(L_ERR, "DISPATCHER:ds_load_list: bad line [%s]\n", line);
310
+			LM_ERR("bad line [%s]\n", line);
153 311
 			goto error;
154 312
 		}
155 313
 
... ...
@@ -159,253 +317,193 @@ int ds_load_list(char *lfile)
159 317
 			p++;
160 318
 		uri.len = p-uri.s;
161 319
 
162
-		/* check uri */
163
-		if(parse_uri(uri.s, uri.len, &puri)!=0)
164
-		{
165
-			LOG(L_ERR, "DISPATCHER:ds_load_list: bad uri [%.*s]\n",
166
-					uri.len, uri.s);
167
-			goto error;
168
-		}
169
-		
170
-		/* check index */
171
-		si = _ds_index;
172
-		while(si)
173
-		{
174
-			if(si->id == id)
175
-				break;
176
-			si = si->next;
177
-		}
178
-
179
-		if(si==NULL)
180
-		{
181
-			si = (ds_setidx_p)shm_malloc(sizeof(ds_setidx_t));
182
-			if(si==NULL)
183
-			{
184
-				LOG(L_ERR, "DISPATCHER:ds_load_list: no more memory\n");
185
-				goto error;
186
-			}
187
-			memset(si, 0, sizeof(ds_setidx_t));
188
-			si->id = id;
189
-			si->next = _ds_index;
190
-			if(_ds_index!=NULL)
191
-				si->index = _ds_index->index + 1;
192
-			
193
-			_ds_index = si;
194
-		}
195
-		
196
-		/* get dest set */
197
-		sp = _ds_list;
198
-		while(sp)
199
-		{
200
-			if(sp->id == id)
201
-				break;
202
-			sp = sp->next;
203
-		}
204
-
205
-		if(sp==NULL)
206
-		{
207
-			sp = (ds_set_p)shm_malloc(sizeof(ds_set_t));
208
-			if(sp==NULL)
209
-			{
210
-				LOG(L_ERR, "DISPATCHER:ds_load_list: no more memory.\n");
211
-				goto error;
212
-			}
213
-			memset(sp, 0, sizeof(ds_set_t));
214
-			sp->next = _ds_list;
215
-			_ds_list = sp;
216
-			setn++;
217
-		}
218
-		sp->id = id;
219
-		sp->nr++;
220
-		sp->index = si->index;
221
-
222
-		/* store uri */
223
-		dp = (ds_dest_p)shm_malloc(sizeof(ds_dest_t));
224
-		if(dp==NULL)
225
-		{
226
-			LOG(L_ERR, "DISPATCHER:ds_load_list: no more memory!\n");
320
+		if(add_dest2list(id, uri, *next_idx, &setn) != 0)
227 321
 			goto error;
228
-		}
229
-		memset(dp, 0, sizeof(ds_dest_t));
230
-
231
-		dp->uri.s = (char*)shm_malloc(uri.len+1);
232
-		if(dp->uri.s==NULL)
233
-		{
234
-			LOG(L_ERR, "DISPATCHER:ds_load_list: no more memory!!\n");
235
-			shm_free(dp);
236
-			goto error;
237
-		}
238
-		strncpy(dp->uri.s, uri.s, uri.len);
239
-		dp->uri.s[uri.len]='\0';
240
-		dp->uri.len = uri.len;
241
-
242
-		/* The Hostname needs to be \0 terminated for resolvehost, so we
243
-		 * make a copy here. */
244
-		hn = (char*)pkg_malloc(puri.host.len + 1);
245
-		if(hn==NULL)
246
-		{
247
-			LOG(L_ERR, "DISPATCHER:ds_load_list: no more memory!!\n");
248
-			pkg_free(hn);
249
-			goto error;
250
-		}
251
-		strncpy(hn, puri.host.s, puri.host.len);
252
-		hn[puri.host.len]='\0';
253
-		
254
-		/* Do a DNS-Lookup for the Host-Name: */
255
-		he=resolvehost(hn, 1);
256
-		if (he==0){
257
-			LOG(L_ERR, "DISPATCHER:ds_load_list: could not resolve %.*s\n",
258
-					puri.host.len, puri.host.s);
259
-			pkg_free(hn);
260
-			goto error;
261
-		}
262
-		/* Free the hostname */
263
-		pkg_free(hn);
264
-		hostent2ip_addr(&dp->ip_address, he, 0);
265
-		
266
-		/* Copy the Port out of the URI: */
267
-		dp->port = puri.port_no;		
268
-
269
-		dp->next = sp->dlist;
270
-		sp->dlist = dp;
271
-		DBG("DISPATCHER:ds_load_list: dest [%d/%d/%d] <%.*s>\n", sp->index,
272
-				sp->id, sp->nr, dp->uri.len, dp->uri.s);
322
+					
273 323
 		
274 324
 next_line:
275 325
 		p = fgets(line, 256, f);
276 326
 	}
277 327
 		
328
+	if(reindex_dests(*next_idx, setn)!=0){
329
+		LM_ERR("error on reindex\n");
330
+		goto error;
331
+	}
332
+
278 333
 	fclose(f);
279 334
 	f = NULL;
280
-	
281
-	DBG("DISPATCHER:ds_load_list: found [%d] dest sets\n", setn);
282
-	
283
-	/* re-index destination sets for fast access */
284
-	sp0 = (ds_set_p)shm_malloc(setn*sizeof(ds_set_t));
285
-	if(sp0==NULL)
335
+	_ds_list_nr = setn;
336
+	return 0;
337
+
338
+error:
339
+	if(f!=NULL)
340
+		fclose(f);
341
+	destroy_list(*next_idx);
342
+	return -1;
343
+}
344
+
345
+/*connect to the DB*/
346
+int init_db_conn()
347
+{
348
+	str table;
349
+	int ver;
350
+
351
+	if(ds_table_name == 0)
286 352
 	{
287
-		LOG(L_ERR, "DISPATCHER:ds_load_list: no more memory!!\n");
288
-		goto error;
353
+		LM_ERR("invalid database name\n");
354
+		return -1;
289 355
 	}
290
-	memset(sp0, 0, setn*sizeof(ds_set_t));
291
-	sp = _ds_list;
292
-	for(i=setn-1; i>=0; i--)
356
+
357
+	/* Find a database module */
358
+	if (bind_dbmod(ds_db_url, &ds_dbf) < 0)
293 359
 	{
294
-		memcpy(&sp0[i], sp, sizeof(ds_set_t));
295
-		if(i==setn-1)
296
-			sp0[i].next = NULL;
297
-		else
298
-			sp0[i].next = &sp0[i+1];
299
-		dp0 = (ds_dest_p)shm_malloc(sp0[i].nr*sizeof(ds_dest_t));
300
-		if(dp0==NULL)
301
-		{
302
-			LOG(L_ERR, "DISPATCHER:ds_load_list: no more memory!\n");
303
-			ds_destroy_list();
304
-			goto error;
305
-		}
306
-		memset(dp0, 0, sp0[i].nr*sizeof(ds_dest_t));
307
-		dp = sp0[i].dlist;
308
-		for(j=sp0[i].nr-1; j>=0; j--)
309
-		{
310
-			memcpy(&dp0[j], dp, sizeof(ds_dest_t));
311
-			if(j==sp0[j].nr-1)
312
-				dp0[j].next = NULL;
313
-			else
314
-				dp0[j].next = &dp0[j+1];
315
-			dp = dp->next;
316
-		}
317
-		sp0[i].dlist = dp0;
318
-		sp = sp->next;
360
+		LM_ERR("Unable to bind to a database driver\n");
361
+		return -1;
319 362
 	}
363
+
364
+	if ((ds_db_handle = ds_dbf.init(ds_db_url)) == 0)
365
+	{
366
+		LM_ERR("unable to connect to the database\n");
367
+		return -1;
368
+	}
369
+
370
+	table.s = ds_table_name;
371
+	table.len = strlen(table.s);
372
+
373
+	ver = table_version(&ds_dbf, ds_db_handle, &table );
374
+	if (ver < 0) 
375
+	{
376
+		LM_ERR("failed to query table version\n");
377
+		return -1;
378
+	} else if (ver != DS_TABLE_VERSION) {
379
+		LM_ERR("invalid table version (found %d , required %d)\n"
380
+			"(use openser_mysql.sh reinstall)\n",
381
+			ver, DS_TABLE_VERSION );
382
+		return -1;
383
+	}
384
+
385
+	return 0;
386
+}
387
+
388
+/*load groups of destinations from DB*/
389
+int ds_load_db()
390
+{
391
+	int i, id, nr_rows, setn;
392
+	str uri;
393
+	db_res_t * res;
394
+	db_val_t * values;
395
+	db_row_t * rows;
396
+	db_key_t query_cols[2] = {ds_set_id_col, ds_dest_uri_col};
320 397
 	
321
-	sp = _ds_list;
322
-	_ds_list = sp0;
323
-	while(sp)
398
+	if( (*crt_idx) != (*next_idx))
324 399
 	{
325
-		dp = sp->dlist;
326
-		while(dp)
327
-		{
328
-			dp0 = dp;
329
-			dp = dp->next;
330
-			shm_free(dp0);
331
-		}
332
-		sp0 = sp;
333
-		sp = sp->next;
334
-		shm_free(sp0);
400
+		LM_WARN("load command already generated, aborting reload...\n");
401
+		return 0;
335 402
 	}
336 403
 
337
-	_ds_list_nr = setn;
404
+	if(ds_db_url != NULL && ds_db_handle == NULL && init_db_conn()!= 0)
405
+			return -1;
338 406
 	
339
-	return 0;
407
+	if (ds_dbf.use_table(ds_db_handle, ds_table_name) < 0)
408
+	{
409
+		LM_ERR("error in use_table\n");
410
+		return -1;
411
+	}
340 412
 
341
-error:
342
-	if(f!=NULL)
343
-		fclose(f);
413
+	/*select the whole table and all the columns*/
414
+	if(ds_dbf.query(ds_db_handle,0,0,0,query_cols, 0, 2, 0, &res) < 0)
415
+	{
416
+		LM_ERR("error while querying database\n");
417
+		return -1;
418
+	}
344 419
 
345
-	si = _ds_index;
346
-	while(si)
420
+	nr_rows = RES_ROW_N(res);
421
+	rows 	= RES_ROWS(res);
422
+	if(nr_rows == 0)
347 423
 	{
348
-		si0 = si;
349
-		si = si->next;
350
-		shm_free(si0);
424
+		LM_WARN("no dispatching data in the db - module cannot run\n");
425
+		ds_dbf.free_result(ds_db_handle, res);
426
+		return 1;
351 427
 	}
352
-	_ds_index = NULL;
353 428
 
354
-	sp = _ds_list;
355
-	while(sp)
429
+	setn = 0;
430
+	*next_idx = (*crt_idx + 1)%2;
431
+	destroy_list(*next_idx);
432
+	
433
+	for(i=0; i<nr_rows; i++)
356 434
 	{
357
-		dp = sp->dlist;
358
-		while(dp)
359
-		{
360
-			if(dp->uri.s!=NULL)
361
-				shm_free(dp->uri.s);
362
-			dp->uri.s=NULL;
363
-			dp0 = dp;
364
-			dp = dp->next;
365
-			shm_free(dp0);
366
-		}
367
-		sp0 = sp;
368
-		sp = sp->next;
369
-		shm_free(sp0);
435
+		values = ROW_VALUES(rows+i);
436
+
437
+		id = VAL_INT(values);
438
+		uri.s = VAL_STR(values+1).s;
439
+		uri.len = strlen(uri.s);
440
+
441
+		if(add_dest2list(id, uri, *next_idx, &setn) != 0)
442
+			goto err2;
443
+
370 444
 	}
445
+
446
+	if(reindex_dests(*next_idx, setn)!=0)
447
+	{
448
+		LM_ERR("error on reindex\n");
449
+		goto err2;
450
+	}
451
+
452
+	/*update data*/
453
+	_ds_list_nr = setn;
454
+	*crt_idx = *next_idx;
455
+	ds_dbf.free_result(ds_db_handle, res);
456
+
457
+	return 0;
458
+
459
+err2:
460
+	destroy_list(*next_idx);
461
+	ds_dbf.free_result(ds_db_handle, res);
462
+	*next_idx = *crt_idx; 
463
+
371 464
 	return -1;
372 465
 }
373 466
 
467
+/*called from dispatcher.c: free all*/
468
+int ds_destroy_list()
469
+{
470
+	destroy_list(0);
471
+	destroy_list(1);
472
+
473
+	shm_free(ds_lists);
474
+	shm_free(crt_idx);
475
+
476
+	if(ds_db_handle){
477
+		ds_dbf.close(ds_db_handle);
478
+		ds_db_handle = 0;
479
+	}
480
+	return 0;
481
+}
374 482
 /**
375 483
  *
376 484
  */
377
-int ds_destroy_list()
485
+void destroy_list(int list_id)
378 486
 {
379
-	int i;
380 487
 	ds_set_p  sp = NULL;
381
-	ds_setidx_p si = NULL, si0 = NULL;
382
-	
383
-	sp = _ds_list;
488
+	ds_dest_p dest = NULL;
489
+
490
+	sp = ds_lists[list_id];
491
+
384 492
 	while(sp)
385 493
 	{
386
-		for(i=0; i<sp->nr; i++)
494
+		for(dest = sp->dlist; dest!= NULL; dest=dest->next)
387 495
 		{
388
-			if(sp->dlist[i].uri.s!=NULL)
389
-			{
390
-				shm_free(sp->dlist[i].uri.s);
391
-				sp->dlist[i].uri.s = NULL;
392
-			}
496
+			if(dest->uri.s!=NULL)
497
+   			{
498
+   				shm_free(dest->uri.s);
499
+   				dest->uri.s = NULL;
500
+	   		}
393 501
 		}
394 502
 		shm_free(sp->dlist);
395 503
 		sp = sp->next;
396 504
 	}
397
-	if (_ds_list) shm_free(_ds_list);
398 505
 	
399
-	si = _ds_index;
400
-	while(si)
401
-	{
402
-		si0 = si;
403
-		si = si->next;
404
-		shm_free(si0);
405
-	}
406
-	_ds_index = NULL;
407
-
408
-	return 0;
506
+	ds_lists[list_id]  = NULL;
409 507
 }
410 508
 
411 509
 /**
... ...
@@ -484,18 +582,20 @@ static inline int get_uri_hash_keys(str* key1, str* key2,
484 582
 {
485 583
 	struct sip_uri tmp_p_uri; /* used only if parsed_uri==0 */
486 584
 	
487
-	if (parsed_uri==0){
488
-		if (parse_uri(uri->s, uri->len, &tmp_p_uri)<0){
489
-			LOG(L_ERR, "DISPATCHER: get_uri_hash_keys: invalid uri %.*s\n",
490
-					uri->len, uri->len?uri->s:"");
585
+	if (parsed_uri==0)
586
+	{
587
+		if (parse_uri(uri->s, uri->len, &tmp_p_uri)<0)
588
+		{
589
+			LM_ERR("invalid uri %.*s\n", uri->len, uri->len?uri->s:"");
491 590
 			goto error;
492 591
 		}
493 592
 		parsed_uri=&tmp_p_uri;
494 593
 	}
495 594
 	/* uri sanity checks */
496
-	if (parsed_uri->host.s==0){
497
-			LOG(L_ERR, "DISPATCHER: get_uri_hash_keys: invalid uri, no host"
498
-					   "present: %.*s\n", uri->len, uri->len?uri->s:"");
595
+	if (parsed_uri->host.s==0)
596
+	{
597
+			LM_ERR("invalid uri, no host present: %.*s\n",
598
+					uri->len, uri->len?uri->s:"");
499 599
 			goto error;
500 600
 	}
501 601
 	
... ...
@@ -505,20 +605,21 @@ static inline int get_uri_hash_keys(str* key1, str* key2,
505 605
 	*key1=parsed_uri->user;
506 606
 	key2->s=0;
507 607
 	key2->len=0;
508
-	if (!(flags & DS_HASH_USER_ONLY)){
509
-		/* key2=host */
608
+	if (!(flags & DS_HASH_USER_ONLY))
609
+	{	/* key2=host */
510 610
 		*key2=parsed_uri->host;
511 611
 		/* add port if needed */
512
-		if (parsed_uri->port.s!=0){ /* uri has a port */
612
+		if (parsed_uri->port.s!=0)
613
+		{ /* uri has a port */
513 614
 			/* skip port if == 5060 or sips and == 5061 */
514 615
 			if (parsed_uri->port_no !=
515 616
 					((parsed_uri->type==SIPS_URI_T)?SIPS_PORT:SIP_PORT))
516 617
 				key2->len+=parsed_uri->port.len+1 /* ':' */;
517 618
 		}
518 619
 	}
519
-	if (key1->s==0){
520
-		LOG(L_WARN, "DISPATCHER: get_uri_hashs_keys: empty username in:"
521
-					" %.*s\n", uri->len, uri->len?uri->s:"");
620
+	if (key1->s==0)
621
+	{
622
+		LM_WARN("empty username in: %.*s\n", uri->len, uri->len?uri->s:"");
522 623
 	}
523 624
 	return 0;
524 625
 error:
... ...
@@ -538,19 +639,19 @@ int ds_hash_fromuri(struct sip_msg *msg, unsigned int *hash)
538 639
 	
539 640
 	if(msg==NULL || hash == NULL)
540 641
 	{
541
-		LOG(L_ERR, "DISPATCHER:ds_hash_fromuri: bad parameters\n");
642
+		LM_ERR("bad parameters\n");
542 643
 		return -1;
543 644
 	}
544 645
 	
545 646
 	if(parse_from_header(msg)<0)
546 647
 	{
547
-		LOG(L_ERR, "DISPATCHER:ds_hash_fromuri:ERROR cannot parse From hdr\n");
648
+		LM_ERR("cannot parse From hdr\n");
548 649
 		return -1;
549 650
 	}
550 651
 	
551 652
 	if(msg->from==NULL || get_from(msg)==NULL)
552 653
 	{
553
-		LOG(L_ERR, "DISPATCHER:ds_hash_fromuri:ERROR cannot get From uri\n");
654
+		LM_ERR("cannot get From uri\n");
554 655
 		return -1;
555 656
 	}
556 657
 	
... ...
@@ -576,13 +677,13 @@ int ds_hash_touri(struct sip_msg *msg, unsigned int *hash)
576 677
 	
577 678
 	if(msg==NULL || hash == NULL)
578 679
 	{
579
-		LOG(L_ERR, "DISPATCHER:ds_hash_touri: bad parameters\n");
680
+		LM_ERR("bad parameters\n");
580 681
 		return -1;
581 682
 	}
582 683
 	if ((msg->to==0) && ((parse_headers(msg, HDR_TO_F, 0)==-1) ||
583 684
 				(msg->to==0)))
584 685
 	{
585
-		LOG(L_ERR, "DISPATCHER:ds_hash_touri:ERROR cannot parse To hdr\n");
686
+		LM_ERR("cannot parse To hdr\n");
586 687
 		return -1;
587 688
 	}
588 689
 	
... ...
@@ -607,14 +708,14 @@ int ds_hash_callid(struct sip_msg *msg, unsigned int *hash)
607 708
 	str cid;
608 709
 	if(msg==NULL || hash == NULL)
609 710
 	{
610
-		LOG(L_ERR, "DISPATCHER:ds_hash_callid: bad parameters\n");
711
+		LM_ERR("bad parameters\n");
611 712
 		return -1;
612 713
 	}
613 714
 	
614 715
 	if(msg->callid==NULL && ((parse_headers(msg, HDR_CALLID_F, 0)==-1) ||
615 716
 				(msg->callid==NULL)) )
616 717
 	{
617
-		LOG(L_ERR, "DISPATCHER:ds_hash_callid:ERROR cannot parse Call-Id\n");
718
+		LM_ERR("cannot parse Call-Id\n");
618 719
 		return -1;