blob: 4435d1a485a42b73bf7648f761ab86f24a775214 [file] [log] [blame]
Benny Prijono5dcb38d2005-11-21 01:55:47 +00001/* $Id$ */
2/*
3 * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#include "test.h"
20#include <pjsip_core.h>
21#include <pjlib.h>
22
23
24#define ALPHANUM "abcdefghijklmnopqrstuvwxyz" \
25 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
26 "0123456789"
27#define MARK "-_.!~*'()"
28#define USER_CHAR ALPHANUM MARK "&=+$,;?/"
29#define PASS_CHAR ALPHANUM MARK "&=+$,"
30#define PARAM_CHAR ALPHANUM MARK "[]/:&+$"
31
32#define POOL_SIZE 4000
33#define LOOP_COUNT 1000
34#define AVERAGE_URL_LEN 80
35#define THREAD_COUNT 4
36
37static pj_uint32_t parse_len;
38static pj_timestamp parse_time, print_time;
39
40
41/* URI creator functions. */
42static pjsip_uri *create_uri0( pj_pool_t *pool );
43static pjsip_uri *create_uri1( pj_pool_t *pool );
44static pjsip_uri *create_uri2( pj_pool_t *pool );
45static pjsip_uri *create_uri3( pj_pool_t *pool );
46static pjsip_uri *create_uri4( pj_pool_t *pool );
47static pjsip_uri *create_uri5( pj_pool_t *pool );
48static pjsip_uri *create_uri6( pj_pool_t *pool );
49static pjsip_uri *create_uri7( pj_pool_t *pool );
50static pjsip_uri *create_uri8( pj_pool_t *pool );
51static pjsip_uri *create_uri9( pj_pool_t *pool );
52static pjsip_uri *create_uri10( pj_pool_t *pool );
53static pjsip_uri *create_uri11( pj_pool_t *pool );
54static pjsip_uri *create_uri12( pj_pool_t *pool );
55static pjsip_uri *create_uri13( pj_pool_t *pool );
56static pjsip_uri *create_uri14( pj_pool_t *pool );
57static pjsip_uri *create_uri15( pj_pool_t *pool );
58static pjsip_uri *create_uri16( pj_pool_t *pool );
59static pjsip_uri *create_uri17( pj_pool_t *pool );
60static pjsip_uri *create_dummy( pj_pool_t *pool );
61
62#define ERR_NOT_EQUAL -1001
63#define ERR_SYNTAX_ERR -1002
64
65struct uri_test
66{
67 pj_status_t status;
68 char str[PJSIP_MAX_URL_SIZE];
69 pjsip_uri *(*creator)(pj_pool_t *pool);
70 pj_size_t len;
71} uri_test_array[] =
72{
73 {
74 PJ_SUCCESS,
75 "sip:localhost",
76 &create_uri0
77 },
78 {
79 PJ_SUCCESS,
80 "sip:user@localhost",
81 &create_uri1
82 },
83 {
84 PJ_SUCCESS,
85 "sip:user:password@localhost:5060",
86 &create_uri2,
87 },
88 {
89 /* Port is specified should not match unspecified port. */
90 ERR_NOT_EQUAL,
91 "sip:localhost:5060",
92 &create_uri3
93 },
94 {
95 /* All recognized parameters. */
96 PJ_SUCCESS,
97 "sip:localhost;transport=tcp;user=ip;ttl=255;lr;maddr=127.0.0.1;method=ACK",
98 &create_uri4
99 },
100 {
101 /* Params mixed with other params and header params. */
102 PJ_SUCCESS,
103 "sip:localhost;pickup=hurry;user=phone;message=I%20am%20sorry"
104 "?Subject=Hello%20There&Server=SIP%20Server",
105 &create_uri5
106 },
107 {
108 /* SIPS. */
109 PJ_SUCCESS,
110 "sips:localhost",
111 &create_uri6,
112 },
113 {
114 /* Name address */
115 PJ_SUCCESS,
116 "<sip:localhost>",
117 &create_uri7
118 },
119 {
120 /* Name address with display name and SIPS scheme with some redundant
121 * whitespaced.
122 */
123 PJ_SUCCESS,
124 " Power Administrator <sips:localhost>",
125 &create_uri8
126 },
127 {
128 /* Name address. */
129 PJ_SUCCESS,
130 " \"User\" <sip:user@localhost:5071>",
131 &create_uri9
132 },
133 {
134 /* Escaped sequence in display name (display=Strange User\"\\\"). */
135 PJ_SUCCESS,
136 " \"Strange User\\\"\\\\\\\"\" <sip:localhost>",
137 &create_uri10,
138 },
139 {
140 /* Errorneous escaping in display name. */
141 ERR_SYNTAX_ERR,
142 " \"Rogue User\\\" <sip:localhost>",
143 &create_uri11,
144 },
145 {
146 /* Dangling quote in display name, but that should be OK. */
147 PJ_SUCCESS,
148 "Strange User\" <sip:localhost>",
149 &create_uri12,
150 },
151 {
152 /* Special characters in parameter value must be quoted. */
153 PJ_SUCCESS,
154 "sip:localhost;pvalue=\"hello world\"",
155 &create_uri13,
156 },
157 {
158 /* Excercise strange character sets allowed in display, user, password,
159 * host, and port.
160 */
161 PJ_SUCCESS,
162 "This is -. !% *_+`'~ me <sip:a19A&=+$,;?/%2c:%40a&Zz=+$,@"
163 "my_proxy09.MY-domain.com:9801>",
164 &create_uri14,
165 },
166 {
167 /* Another excercise to the allowed character sets to the hostname. */
168 PJ_SUCCESS,
169 "sip:" ALPHANUM "-_.com",
170 &create_uri15,
171 },
172 {
173 /* Another excercise to the allowed character sets to the username
174 * and password.
175 */
176 PJ_SUCCESS,
177 "sip:" USER_CHAR ":" PASS_CHAR "@host",
178 &create_uri16,
179 },
180 {
181 /* Excercise to the pname and pvalue, and mixup of other-param
182 * between 'recognized' params.
183 */
184 PJ_SUCCESS,
185 "sip:host;user=ip;" PARAM_CHAR "%21=" PARAM_CHAR "%21"
186 ";lr;other=1;transport=sctp;other2",
187 &create_uri17,
188 },
189 {
190 /* 18: This should trigger syntax error. */
191 ERR_SYNTAX_ERR,
192 "sip:",
193 &create_dummy,
194 },
195 {
196 /* 19: Syntax error: whitespace after scheme. */
197 ERR_SYNTAX_ERR,
198 "sip :host",
199 &create_dummy,
200 },
201 {
202 /* 20: Syntax error: whitespace before hostname. */
203 ERR_SYNTAX_ERR,
204 "sip: host",
205 &create_dummy,
206 },
207 {
208 /* 21: Syntax error: invalid port. */
209 ERR_SYNTAX_ERR,
210 "sip:user:password",
211 &create_dummy,
212 },
213 {
214 /* 22: Syntax error: no host. */
215 ERR_SYNTAX_ERR,
216 "sip:user@",
217 &create_dummy,
218 },
219 {
220 /* 23: Syntax error: no user/host. */
221 ERR_SYNTAX_ERR,
222 "sip:@",
223 &create_dummy,
224 },
225 {
226 /* 24: Syntax error: empty string. */
227 ERR_SYNTAX_ERR,
228 "",
229 &create_dummy,
230 }
231};
232
233static pjsip_uri *create_uri0(pj_pool_t *pool)
234{
235 /* "sip:localhost" */
236 pjsip_url *url = pjsip_url_create(pool, 0);
237
238 pj_strdup2(pool, &url->host, "localhost");
239 return (pjsip_uri*)url;
240}
241
242static pjsip_uri *create_uri1(pj_pool_t *pool)
243{
244 /* "sip:user@localhost" */
245 pjsip_url *url = pjsip_url_create(pool, 0);
246
247 pj_strdup2( pool, &url->user, "user");
248 pj_strdup2( pool, &url->host, "localhost");
249
250 return (pjsip_uri*) url;
251}
252
253static pjsip_uri *create_uri2(pj_pool_t *pool)
254{
255 /* "sip:user:password@localhost:5060" */
256 pjsip_url *url = pjsip_url_create(pool, 0);
257
258 pj_strdup2( pool, &url->user, "user");
259 pj_strdup2( pool, &url->passwd, "password");
260 pj_strdup2( pool, &url->host, "localhost");
261 url->port = 5060;
262
263 return (pjsip_uri*) url;
264}
265
266static pjsip_uri *create_uri3(pj_pool_t *pool)
267{
268 /* Like: "sip:localhost:5060", but without the port. */
269 pjsip_url *url = pjsip_url_create(pool, 0);
270
271 pj_strdup2(pool, &url->host, "localhost");
272 return (pjsip_uri*)url;
273}
274
275static pjsip_uri *create_uri4(pj_pool_t *pool)
276{
277 /* "sip:localhost;transport=tcp;user=ip;ttl=255;lr;maddr=127.0.0.1;method=ACK" */
278 pjsip_url *url = pjsip_url_create(pool, 0);
279
280 pj_strdup2(pool, &url->host, "localhost");
281 pj_strdup2(pool, &url->transport_param, "tcp");
282 pj_strdup2(pool, &url->user_param, "ip");
283 url->ttl_param = 255;
284 url->lr_param = 1;
285 pj_strdup2(pool, &url->maddr_param, "127.0.0.1");
286 pj_strdup2(pool, &url->method_param, "ACK");
287
288 return (pjsip_uri*)url;
289}
290
291#define param_add(list,pname,pvalue) \
292 do { \
293 pjsip_param *param; \
294 param=pj_pool_alloc(pool, sizeof(pjsip_param)); \
295 param->name = pj_str(pname); \
296 param->value = pj_str(pvalue); \
297 pj_list_insert_before(&list, param); \
298 } while (0)
299
300static pjsip_uri *create_uri5(pj_pool_t *pool)
301{
302 /* "sip:localhost;pickup=hurry;user=phone;message=I%20am%20sorry"
303 "?Subject=Hello%20There&Server=SIP%20Server"
304 */
305 pjsip_url *url = pjsip_url_create(pool, 0);
306
307 pj_strdup2(pool, &url->host, "localhost");
308 pj_strdup2(pool, &url->user_param, "phone");
309
310 //pj_strdup2(pool, &url->other_param, ";pickup=hurry;message=I%20am%20sorry");
311 param_add(url->other_param, "pickup", "hurry");
312 param_add(url->other_param, "message", "I am sorry");
313
314 //pj_strdup2(pool, &url->header_param, "?Subject=Hello%20There&Server=SIP%20Server");
315 param_add(url->header_param, "Subject", "Hello There");
316 param_add(url->header_param, "Server", "SIP Server");
317 return (pjsip_uri*)url;
318
319}
320
321static pjsip_uri *create_uri6(pj_pool_t *pool)
322{
323 /* "sips:localhost" */
324 pjsip_url *url = pjsip_url_create(pool, 1);
325
326 pj_strdup2(pool, &url->host, "localhost");
327 return (pjsip_uri*)url;
328}
329
330static pjsip_uri *create_uri7(pj_pool_t *pool)
331{
332 /* "<sip:localhost>" */
333 pjsip_name_addr *name_addr = pjsip_name_addr_create(pool);
334 pjsip_url *url;
335
336 url = pjsip_url_create(pool, 0);
337 name_addr->uri = (pjsip_uri*) url;
338
339 pj_strdup2(pool, &url->host, "localhost");
340 return (pjsip_uri*)name_addr;
341}
342
343static pjsip_uri *create_uri8(pj_pool_t *pool)
344{
345 /* " Power Administrator <sips:localhost>" */
346 pjsip_name_addr *name_addr = pjsip_name_addr_create(pool);
347 pjsip_url *url;
348
349 url = pjsip_url_create(pool, 1);
350 name_addr->uri = (pjsip_uri*) url;
351
352 pj_strdup2(pool, &name_addr->display, "Power Administrator");
353 pj_strdup2(pool, &url->host, "localhost");
354 return (pjsip_uri*)name_addr;
355}
356
357static pjsip_uri *create_uri9(pj_pool_t *pool)
358{
359 /* " \"User\" <sip:user@localhost:5071>" */
360 pjsip_name_addr *name_addr = pjsip_name_addr_create(pool);
361 pjsip_url *url;
362
363 url = pjsip_url_create(pool, 0);
364 name_addr->uri = (pjsip_uri*) url;
365
366 pj_strdup2(pool, &name_addr->display, "User");
367 pj_strdup2(pool, &url->user, "user");
368 pj_strdup2(pool, &url->host, "localhost");
369 url->port = 5071;
370 return (pjsip_uri*)name_addr;
371}
372
373static pjsip_uri *create_uri10(pj_pool_t *pool)
374{
375 /* " \"Strange User\\\"\\\\\\\"\" <sip:localhost>" */
376 pjsip_name_addr *name_addr = pjsip_name_addr_create(pool);
377 pjsip_url *url;
378
379 url = pjsip_url_create(pool, 0);
380 name_addr->uri = (pjsip_uri*) url;
381
382 pj_strdup2(pool, &name_addr->display, "Strange User\\\"\\\\\\\"");
383 pj_strdup2(pool, &url->host, "localhost");
384 return (pjsip_uri*)name_addr;
385}
386
387static pjsip_uri *create_uri11(pj_pool_t *pool)
388{
389 /* " \"Rogue User\\\" <sip:localhost>" */
390 pjsip_name_addr *name_addr = pjsip_name_addr_create(pool);
391 pjsip_url *url;
392
393 url = pjsip_url_create(pool, 0);
394 name_addr->uri = (pjsip_uri*) url;
395
396 pj_strdup2(pool, &name_addr->display, "Rogue User\\");
397 pj_strdup2(pool, &url->host, "localhost");
398 return (pjsip_uri*)name_addr;
399}
400
401static pjsip_uri *create_uri12(pj_pool_t *pool)
402{
403 /* "Strange User\" <sip:localhost>" */
404 pjsip_name_addr *name_addr = pjsip_name_addr_create(pool);
405 pjsip_url *url;
406
407 url = pjsip_url_create(pool, 0);
408 name_addr->uri = (pjsip_uri*) url;
409
410 pj_strdup2(pool, &name_addr->display, "Strange User\"");
411 pj_strdup2(pool, &url->host, "localhost");
412 return (pjsip_uri*)name_addr;
413}
414
415static pjsip_uri *create_uri13(pj_pool_t *pool)
416{
417 /* "sip:localhost;pvalue=\"hello world\"" */
418 pjsip_url *url;
419 url = pjsip_url_create(pool, 0);
420 pj_strdup2(pool, &url->host, "localhost");
421 //pj_strdup2(pool, &url->other_param, ";pvalue=\"hello world\"");
422 param_add(url->other_param, "pvalue", "hello world");
423 return (pjsip_uri*)url;
424}
425
426static pjsip_uri *create_uri14(pj_pool_t *pool)
427{
428 /* "This is -. !% *_+`'~ me <sip:a19A&=+$,;?/%2c:%40a&Zz=+$,@my_proxy09.my-domain.com:9801>" */
429 pjsip_name_addr *name_addr = pjsip_name_addr_create(pool);
430 pjsip_url *url;
431
432 url = pjsip_url_create(pool, 0);
433 name_addr->uri = (pjsip_uri*) url;
434
435 pj_strdup2(pool, &name_addr->display, "This is -. !% *_+`'~ me");
436 pj_strdup2(pool, &url->user, "a19A&=+$,;?/,");
437 pj_strdup2(pool, &url->passwd, "@a&Zz=+$,");
438 pj_strdup2(pool, &url->host, "my_proxy09.MY-domain.com");
439 url->port = 9801;
440 return (pjsip_uri*)name_addr;
441}
442
443static pjsip_uri *create_uri15(pj_pool_t *pool)
444{
445 /* "sip:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.com" */
446 pjsip_url *url;
447 url = pjsip_url_create(pool, 0);
448 pj_strdup2(pool, &url->host, ALPHANUM "-_.com");
449 return (pjsip_uri*)url;
450}
451
452static pjsip_uri *create_uri16(pj_pool_t *pool)
453{
454 /* "sip:" USER_CHAR ":" PASS_CHAR "@host" */
455 pjsip_url *url;
456 url = pjsip_url_create(pool, 0);
457 pj_strdup2(pool, &url->user, USER_CHAR);
458 pj_strdup2(pool, &url->passwd, PASS_CHAR);
459 pj_strdup2(pool, &url->host, "host");
460 return (pjsip_uri*)url;
461}
462
463static pjsip_uri *create_uri17(pj_pool_t *pool)
464{
465 /* "sip:host;user=ip;" PARAM_CHAR "%21=" PARAM_CHAR "%21;lr;other=1;transport=sctp;other2" */
466 pjsip_url *url;
467 url = pjsip_url_create(pool, 0);
468 pj_strdup2(pool, &url->host, "host");
469 pj_strdup2(pool, &url->user_param, "ip");
470 pj_strdup2(pool, &url->transport_param, "sctp");
471 param_add(url->other_param, PARAM_CHAR "!", PARAM_CHAR "!");
472 param_add(url->other_param, "other", "1");
473 param_add(url->other_param, "other2", "");
474 url->lr_param = 1;
475 return (pjsip_uri*)url;
476}
477
478static pjsip_uri *create_dummy(pj_pool_t *pool)
479{
480 PJ_UNUSED_ARG(pool);
481 return NULL;
482}
483
484/*****************************************************************************/
485
486/*
487 * Test one test entry.
488 */
489static pj_status_t do_uri_test(pj_pool_t *pool, struct uri_test *entry)
490{
491 pj_status_t status;
492 int len;
493 pjsip_uri *parsed_uri, *ref_uri;
494 pj_str_t s1 = {NULL, 0}, s2 = {NULL, 0};
495 pj_timestamp t1, t2;
496
497 entry->len = pj_native_strlen(entry->str);
498
499 /* Parse URI text. */
500 pj_get_timestamp(&t1);
501 parse_len += entry->len;
502 parsed_uri = pjsip_parse_uri(pool, entry->str, entry->len, 0);
503 if (!parsed_uri) {
504 /* Parsing failed. If the entry says that this is expected, then
505 * return OK.
506 */
507 status = entry->status==ERR_SYNTAX_ERR ? PJ_SUCCESS : -10;
508 if (status != 0) {
509 PJ_LOG(3,("", " uri parse error!\n"
510 " uri='%s'\n",
511 entry->str));
512 }
513 goto on_return;
514 }
515 pj_get_timestamp(&t2);
516 pj_sub_timestamp(&t2, &t1);
517 pj_add_timestamp(&parse_time, &t2);
518
519 /* Create the reference URI. */
520 ref_uri = entry->creator(pool);
521
522 /* Print both URI. */
523 s1.ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
524 s2.ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
525
526 pj_get_timestamp(&t1);
527 len = pjsip_uri_print( PJSIP_URI_IN_OTHER, parsed_uri, s1.ptr, PJSIP_MAX_URL_SIZE);
528 if (len < 1) {
529 status = -20;
530 goto on_return;
531 }
532 s1.ptr[len] = '\0';
533 s1.slen = len;
534
535 pj_get_timestamp(&t2);
536 pj_sub_timestamp(&t2, &t1);
537 pj_add_timestamp(&print_time, &t2);
538
539 len = pjsip_uri_print( PJSIP_URI_IN_OTHER, ref_uri, s2.ptr, PJSIP_MAX_URL_SIZE);
540 if (len < 1) {
541 status = -30;
542 goto on_return;
543 }
544 s2.ptr[len] = '\0';
545 s2.slen = len;
546
547 /* Full comparison of parsed URI with reference URI. */
548 status = pjsip_uri_cmp(PJSIP_URI_IN_OTHER, parsed_uri, ref_uri);
549 if (status != 0) {
550 /* Not equal. See if this is the expected status. */
551 status = entry->status==ERR_NOT_EQUAL ? PJ_SUCCESS : -40;
552 if (status != 0) {
553 PJ_LOG(3,("", " uri comparison mismatch, status=%d:\n"
554 " uri1='%s'\n"
555 " uri2='%s'",
556 status, s1.ptr, s2.ptr));
557 }
558 goto on_return;
559
560 } else {
561 /* Equal. See if this is the expected status. */
562 status = entry->status==PJ_SUCCESS ? PJ_SUCCESS : -50;
563 if (status != PJ_SUCCESS) {
564 goto on_return;
565 }
566 }
567
568 /* Compare text. */
569 if (pj_strcmp(&s1, &s2) != 0) {
570 /* Not equal. */
571 status = -60;
572 }
573
574on_return:
575 return status;
576}
577
578pj_status_t uri_test()
579{
580 unsigned i, loop;
581 pj_pool_t *pool;
582 pj_status_t status;
583 pj_timestamp zero;
584 pj_highprec_t avg_parse, avg_print;
585
586 zero.u32.hi = zero.u32.lo = 0;
587
588 PJ_LOG(3,("", " simple test"));
589 pool = pjsip_endpt_create_pool(endpt, "", POOL_SIZE, POOL_SIZE);
590 for (i=0; i<PJ_ARRAY_SIZE(uri_test_array); ++i) {
591 status = do_uri_test(pool, &uri_test_array[i]);
592 if (status != PJ_SUCCESS) {
593 PJ_LOG(3,("uri_test", " error %d when testing entry %d",
594 status, i));
595 goto on_return;
596 }
597 }
598 pjsip_endpt_destroy_pool(endpt, pool);
599
600 PJ_LOG(3,("", " benchmarking..."));
601 parse_len = 0;
602 parse_time.u32.hi = parse_time.u32.lo = 0;
603 print_time.u32.hi = print_time.u32.lo = 0;
604 pool = pjsip_endpt_create_pool(endpt, "", POOL_SIZE, POOL_SIZE);
605 for (loop=0; loop<LOOP_COUNT; ++loop) {
606 for (i=0; i<PJ_ARRAY_SIZE(uri_test_array); ++i) {
607 status = do_uri_test(pool, &uri_test_array[i]);
608 if (status != PJ_SUCCESS) {
609 PJ_LOG(3,("uri_test", " error %d when testing entry %d",
610 status, i));
611 goto on_return;
612 }
613 }
614 }
615
616 avg_parse = pj_elapsed_usec(&zero, &parse_time);
617 pj_highprec_mul(avg_parse, AVERAGE_URL_LEN);
618 pj_highprec_div(avg_parse, parse_len);
619 avg_parse = 1000000 / avg_parse;
620
621 avg_print = pj_elapsed_usec(&zero, &print_time);
622 pj_highprec_mul(avg_print, AVERAGE_URL_LEN);
623 pj_highprec_div(avg_print, parse_len);
624 avg_print = 1000000 / avg_print;
625
626 PJ_LOG(3,("", " done. Average parse=%d url/sec, print=%d url/sec",
627 (unsigned)avg_parse, (unsigned)avg_print));
628
629 PJ_LOG(3,("", " multithreaded test"));
630
631
632on_return:
633 pjsip_endpt_destroy_pool(endpt, pool);
634 return status;
635}
636