Browse code

- added a new flag parameter which can be used (for now) to select only the username or the username, host and port when hashing after an uri - improved uri hashing (password is ignored, port is used only if sip and port != 5060 or sips and port!=5061) - fixed empty username in uri crash (all thanks to Andrei)

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

Daniel-Constantin Mierla authored on 08/08/2005 15:44:29
Showing 5 changed files
... ...
@@ -25,6 +25,7 @@ Daniel-Constantin Mierla
25 25
 
26 26
               1.3.1. list_file (string)
27 27
               1.3.2. force_dst (int)
28
+              1.3.3. flags (int)
28 29
 
29 30
         1.4. Exported Functions
30 31
 
... ...
@@ -42,9 +43,10 @@ Daniel-Constantin Mierla
42 43
    List of Examples
43 44
    1-1. Set the "list_file" parameter
44 45
    1-2. Set the "force_dst" parameter
45
-   1-3. ds_select_dst usage
46
-   1-4. dispatcher list file
47
-   1-5. OpenSER config script - sample dispatcher usage
46
+   1-3. Set the "flags" parameter
47
+   1-4. ds_select_dst usage
48
+   1-5. dispatcher list file
49
+   1-6. OpenSER config script - sample dispatcher usage
48 50
      _________________________________________________________
49 51
 
50 52
 Chapter 1. User's Guide
... ...
@@ -105,6 +107,24 @@ modparam("dispatcher", "force_dst", 1)
105 107
 ...
106 108
      _________________________________________________________
107 109
 
110
+1.3.3. flags (int)
111
+
112
+   Various flags that affect the hashing behaviour. For now only
113
+   the flag 1 is defined. If flag 1 is set only the username part
114
+   of the uri will be used when computing an uri based hash. If
115
+   no flags are set the username, hostname and port will be used
116
+   The port is used only if different from 5060 (normal sip uri)
117
+   or 5061 (in the sips case).
118
+
119
+   Default value is "0". 
120
+
121
+   Example 1-3. Set the "flags" parameter
122
+ ...
123
+ modparam("dispatcher", "flags", 1)
124
+ ...
125
+
126
+     _________________________________________________________
127
+
108 128
 1.4. Exported Functions
109 129
 
110 130
 1.4.1. ds_select_dst(set, alg)
... ...
@@ -120,11 +140,11 @@ modparam("dispatcher", "force_dst", 1)
120 140
           + "0" - hash over callid
121 141
           + "1" - hash over from uri.
122 142
           + "2" - hash over to uri.
123
-          + "3" - hash over ruri.
143
+          + "3" - hash over request-uri.
124 144
           + "X" - if the algorithm is not implemented, the first
125 145
             entry in set is chosen.
126 146
 
127
-   Example 1-3. ds_select_dst usage
147
+   Example 1-4. ds_select_dst usage
128 148
 ...
129 149
 ds_select_dst("1", "0");
130 150
 ...
... ...
@@ -146,7 +166,7 @@ ds_select_dst("1", "0");
146 166
    integer value. Destination address must be a valid SIP URI.
147 167
    Empty lines or lines starting with "#" are ignored.
148 168
 
149
-   Example 1-4. dispatcher list file
169
+   Example 1-5. dispatcher list file
150 170
 ...
151 171
 # $Id$
152 172
 # dispatcher destination sets
... ...
@@ -167,7 +187,7 @@ ds_select_dst("1", "0");
167 187
 
168 188
    Next picture displays a sample usage of dispatcher.
169 189
 
170
-   Example 1-5. OpenSER config script - sample dispatcher usage
190
+   Example 1-6. OpenSER config script - sample dispatcher usage
171 191
 ...
172 192
 # $Id$
173 193
 # sample config file for dispatcher module
... ...
@@ -250,9 +270,9 @@ Chapter 3. Frequently Asked Questions
250 270
    one of our mailing lists:
251 271
 
252 272
      * User Mailing List -
253
-       http://openser.org/mailman/listinfo/users
273
+       http://openser.org/cgi-bin/mailman/listinfo/users
254 274
      * Developer Mailing List -
255
-       http://openser.org/mailman/listinfo/devel
275
+       http://openser.org/cgi-bin/mailman/listinfo/devel
256 276
 
257 277
    E-mails regarding any stable version should be sent to
258 278
    <users@openser.org> and e-mail regarding development versions
... ...
@@ -365,10 +365,14 @@ unsigned int ds_get_hash(str *x, str *y)
365 365
 	h=0;
366 366
 	if(x)
367 367
 	{
368
-		for (p=x->s; p<=(x->s+x->len-4); p+=4)
368
+		p=x->s;
369
+		if (x->len>=4)
369 370
 		{
370
-			v=(*p<<24)+(p[1]<<16)+(p[2]<<8)+p[3];
371
-			h+=v^(v>>3);
371
+			for (; p<=(x->s+x->len-4); p+=4)
372
+			{
373
+				v=(*p<<24)+(p[1]<<16)+(p[2]<<8)+p[3];
374
+				h+=v^(v>>3);
375
+			}
372 376
 		}
373 377
 		v=0;
374 378
 		for (;p<(x->s+x->len); p++)
... ...
@@ -380,10 +384,14 @@ unsigned int ds_get_hash(str *x, str *y)
380 384
 	}
381 385
 	if(y)
382 386
 	{
383
-		for (p=y->s; p<=(y->s+y->len-4); p+=4)
387
+		p=y->s;
388
+		if (y->len>=4) 
384 389
 		{
385
-			v=(*p<<24)+(p[1]<<16)+(p[2]<<8)+p[3];
386
-			h+=v^(v>>3);
390
+			for (; p<=(y->s+y->len-4); p+=4)
391
+			{
392
+				v=(*p<<24)+(p[1]<<16)+(p[2]<<8)+p[3];
393
+				h+=v^(v>>3);
394
+			}
387 395
 		}
388 396
 	
389 397
 		v=0;
... ...
@@ -399,12 +407,78 @@ unsigned int ds_get_hash(str *x, str *y)
399 407
 	return (h)?h:1;
400 408
 }
401 409
 
410
+
411
+/*
412
+ * gets the part of the uri we will use as a key for hashing
413
+ * params:  key1       - will be filled with first part of the key
414
+ *                       (uri user or "" if no user)
415
+ *          key2       - will be filled with the second part of the key
416
+ *                       (uri host:port)
417
+ *          uri        - str with the whole uri
418
+ *          parsed_uri - struct sip_uri pointer with the parsed uri
419
+ *                       (it must point inside uri). It can be null
420
+ *                       (in this case the uri will be parsed internally).
421
+ *          flags  -    if & DS_HASH_USER_ONLY, only the user part of the uri
422
+ *                      will be used
423
+ * returns: -1 on error, 0 on success
424
+ */
425
+static inline int get_uri_hash_keys(str* key1, str* key2,
426
+							str* uri, struct sip_uri* parsed_uri, int flags)
427
+{
428
+	struct sip_uri tmp_p_uri; /* used only if parsed_uri==0 */
429
+	
430
+	if (parsed_uri==0){
431
+		if (parse_uri(uri->s, uri->len, &tmp_p_uri)<0){
432
+			LOG(L_ERR, "DISPATCHER: get_uri_hash_keys: invalid uri %.*s\n",
433
+					uri->len, uri->len?uri->s:"");
434
+			goto error;
435
+		}
436
+		parsed_uri=&tmp_p_uri;
437
+	}
438
+	/* uri sanity checks */
439
+	if (parsed_uri->host.s==0){
440
+			LOG(L_ERR, "DISPATCHER: get_uri_hash_keys: invalid uri, no host"
441
+					   "present: %.*s\n", uri->len, uri->len?uri->s:"");
442
+			goto error;
443
+	}
444
+	
445
+	/* we want: user@host:port if port !=5060
446
+	 *          user@host if port==5060
447
+	 *          user if the user flag is set*/
448
+	*key1=parsed_uri->user;
449
+	key2->s=0;
450
+	key2->len=0;
451
+	if (!(flags & DS_HASH_USER_ONLY)){
452
+		/* key2=host */
453
+		*key2=parsed_uri->host;
454
+		/* add port if needed */
455
+		if (parsed_uri->port.s!=0){ /* uri has a port */
456
+			/* skip port if == 5060 or sips and == 5061 */
457
+			if (parsed_uri->port_no !=
458
+					((parsed_uri->type==SIPS_URI_T)?SIPS_PORT:SIP_PORT))
459
+				key2->len+=parsed_uri->port.len+1 /* ':' */;
460
+		}
461
+	}
462
+	if (key1->s==0){
463
+		LOG(L_WARN, "DISPATCHER: get_uri_hashs_keys: empty username in:"
464
+					" %.*s\n", uri->len, uri->len?uri->s:"");
465
+	}
466
+	return 0;
467
+error:
468
+	return -1;
469
+}
470
+
471
+
472
+
402 473
 /**
403 474
  *
404 475
  */
405 476
 int ds_hash_fromuri(struct sip_msg *msg, unsigned int *hash)
406 477
 {
407 478
 	str from;
479
+	str key1;
480
+	str key2;
481
+	
408 482
 	if(msg==NULL || hash == NULL)
409 483
 	{
410 484
 		LOG(L_ERR, "DISPATCHER:ds_hash_fromuri: bad parameters\n");
... ...
@@ -423,11 +497,11 @@ int ds_hash_fromuri(struct sip_msg *msg, unsigned int *hash)
423 497
 		return -1;
424 498
 	}
425 499
 	
426
-	from.s   = get_from(msg)->uri.s;
427
-	from.len = get_from(msg)->uri.len; 
500
+	from   = get_from(msg)->uri;
428 501
 	trim(&from);
429
-	
430
-	*hash = ds_get_hash(&from, NULL);
502
+	if (get_uri_hash_keys(&key1, &key2, &from, 0, ds_flags)<0)
503
+		return -1;
504
+	*hash = ds_get_hash(&key1, &key2);
431 505
 	
432 506
 	return 0;
433 507
 }
... ...
@@ -440,6 +514,9 @@ int ds_hash_fromuri(struct sip_msg *msg, unsigned int *hash)
440 514
 int ds_hash_touri(struct sip_msg *msg, unsigned int *hash)
441 515
 {
442 516
 	str to;
517
+	str key1;
518
+	str key2;
519
+	
443 520
 	if(msg==NULL || hash == NULL)
444 521
 	{
445 522
 		LOG(L_ERR, "DISPATCHER:ds_hash_touri: bad parameters\n");
... ...
@@ -453,15 +530,18 @@ int ds_hash_touri(struct sip_msg *msg, unsigned int *hash)
453 530
 	}
454 531
 	
455 532
 	
456
-	to.s   = get_to(msg)->uri.s;
457
-	to.len = get_to(msg)->uri.len; 
533
+	to   = get_to(msg)->uri;
458 534
 	trim(&to);
459 535
 	
460
-	*hash = ds_get_hash(&to, NULL);
536
+	if (get_uri_hash_keys(&key1, &key2, &to, 0, ds_flags)<0)
537
+		return -1;
538
+	*hash = ds_get_hash(&key1, &key2);
461 539
 	
462 540
 	return 0;
463 541
 }
464 542
 
543
+
544
+
465 545
 /**
466 546
  *
467 547
  */
... ...
@@ -494,8 +574,9 @@ int ds_hash_callid(struct sip_msg *msg, unsigned int *hash)
494 574
 
495 575
 int ds_hash_ruri(struct sip_msg *msg, unsigned int *hash)
496 576
 {
497
-	str hostport;
498 577
 	str* uri;
578
+	str key1;
579
+	str key2;
499 580
 	
500 581
 	
501 582
 	if(msg==NULL || hash == NULL)
... ...
@@ -509,24 +590,15 @@ int ds_hash_ruri(struct sip_msg *msg, unsigned int *hash)
509 590
 	}
510 591
 	
511 592
 	uri=GET_RURI(msg);
512
-	hostport=*uri; /* we want only sip:user@host:port */
513
-	if (msg->parsed_uri.port.s){
514
-		hostport.len=(int)(msg->parsed_uri.port.s-uri->s)+
515
-						msg->parsed_uri.port.len;
516
-	}else if(msg->parsed_uri.host.s){
517
-		hostport.len=(int)(msg->parsed_uri.host.s-uri->s)+
518
-						msg->parsed_uri.host.len;
519
-	}else{ /* missing host! => error */
520
-		LOG(L_ERR, "DISPATCHER: ds_hash_uri: ERROR: bad uri <%.*s>\n",
521
-					uri->len, uri->s);
593
+	if (get_uri_hash_keys(&key1, &key2, uri, &msg->parsed_uri, ds_flags)<0)
522 594
 		return -1;
523
-	}
524 595
 	
525
-	*hash = ds_get_hash(&hostport, NULL);
596
+	*hash = ds_get_hash(&key1, &key2);
526 597
 	return 0;
527 598
 }
528 599
 
529 600
 
601
+
530 602
 /**
531 603
  *
532 604
  */
... ...
@@ -31,6 +31,10 @@
31 31
 
32 32
 #include "../../parser/msg_parser.h"
33 33
 
34
+
35
+#define DS_HASH_USER_ONLY 1  /* use only the uri user part for hashing */
36
+extern int ds_flags; 
37
+
34 38
 int ds_load_list(char *lfile);
35 39
 int ds_destroy_list();
36 40
 int ds_select_dst(struct sip_msg *msg, char *set, char *alg, int mode);
... ...
@@ -46,6 +46,7 @@ MODULE_VERSION
46 46
 /** parameters */
47 47
 char *dslistfile = CFG_DIR"dispatcher.list";
48 48
 int  force_dst = 0;
49
+int  ds_flags   = 0; 
49 50
 
50 51
 /** module functions */
51 52
 static int mod_init(void);
... ...
@@ -68,6 +69,7 @@ static cmd_export_t cmds[]={
68 69
 static param_export_t params[]={
69 70
 	{"list_file",      STR_PARAM, &dslistfile},
70 71
 	{"force_dst",      INT_PARAM, &force_dst},
72
+	{"flags",          INT_PARAM, &ds_flags},
71 73
 	{0,0,0}
72 74
 };
73 75
 
... ...
@@ -96,6 +96,30 @@ modparam("dispatcher", "force_dst", 1)
96 96
 </programlisting>
97 97
 		</example>
98 98
 	</section>
99
+ 	<section>
100
+ 	    <title><varname>flags</varname> (int)</title>
101
+ 	    <para>
102
+ 		Various flags that affect the hashing behaviour.
103
+ 		For now only the flag 1 is defined. If flag 1 is set only the username
104
+ 		part of the uri will be used when computing an uri based hash.
105
+ 		If no flags are set the username, hostname and port will be used
106
+ 		The port is used only if different from 5060 (normal sip uri) or 5061
107
+ 		(in the sips case).
108
+ 	    </para>
109
+ 	    <para>
110
+ 		<emphasis>
111
+ 		    Default value is <quote>0</quote>.
112
+ 		</emphasis>
113
+ 	    </para>
114
+ 	    <example>
115
+ 		<title>Set the <quote>flags</quote> parameter</title>
116
+ <programlisting format="linespecific">
117
+ ...
118
+ modparam("dispatcher", "flags", 1)
119
+ ...
120
+ </programlisting>
121
+ 	    </example>
122
+ 	</section>
99 123
 	</section>
100 124
 	<section>
101 125
 	<title>Exported Functions</title>
... ...
@@ -137,7 +161,7 @@ modparam("dispatcher", "force_dst", 1)
137 161
 			</listitem>
138 162
 			<listitem>
139 163
 				<para>
140
-				<quote>3</quote> - hash over ruri.
164
+				<quote>3</quote> - hash over request-uri.
141 165
 				</para>
142 166
 			</listitem>
143 167
 			<listitem>