| /* $Id$ */ |
| /* |
| * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) |
| * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| */ |
| #include "test.h" |
| #include <pjsip.h> |
| #include <pjlib.h> |
| |
| #define THIS_FILE "uri_test.c" |
| |
| |
| #define ALPHANUM "abcdefghijklmnopqrstuvwxyz" \ |
| "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ |
| "0123456789" |
| #define MARK "-_.!~*'()" |
| #define USER_CHAR ALPHANUM MARK "&=+$,;?/" |
| #define PASS_CHAR ALPHANUM MARK "&=+$," |
| #define PARAM_CHAR ALPHANUM MARK "[]/:&+$" |
| |
| #define POOL_SIZE 8000 |
| #if defined(PJ_DEBUG) && PJ_DEBUG!=0 |
| # define LOOP_COUNT 10000 |
| #else |
| # define LOOP_COUNT 40000 |
| #endif |
| #define AVERAGE_URL_LEN 80 |
| #define THREAD_COUNT 4 |
| |
| static struct |
| { |
| pj_highprec_t parse_len, print_len, cmp_len; |
| pj_timestamp parse_time, print_time, cmp_time; |
| } var; |
| |
| |
| /* URI creator functions. */ |
| static pjsip_uri *create_uri0( pj_pool_t *pool ); |
| static pjsip_uri *create_uri1( pj_pool_t *pool ); |
| static pjsip_uri *create_uri2( pj_pool_t *pool ); |
| static pjsip_uri *create_uri3( pj_pool_t *pool ); |
| static pjsip_uri *create_uri4( pj_pool_t *pool ); |
| static pjsip_uri *create_uri5( pj_pool_t *pool ); |
| static pjsip_uri *create_uri6( pj_pool_t *pool ); |
| static pjsip_uri *create_uri7( pj_pool_t *pool ); |
| static pjsip_uri *create_uri8( pj_pool_t *pool ); |
| static pjsip_uri *create_uri9( pj_pool_t *pool ); |
| static pjsip_uri *create_uri10( pj_pool_t *pool ); |
| static pjsip_uri *create_uri11( pj_pool_t *pool ); |
| static pjsip_uri *create_uri12( pj_pool_t *pool ); |
| static pjsip_uri *create_uri13( pj_pool_t *pool ); |
| static pjsip_uri *create_uri14( pj_pool_t *pool ); |
| static pjsip_uri *create_uri15( pj_pool_t *pool ); |
| static pjsip_uri *create_uri16( pj_pool_t *pool ); |
| static pjsip_uri *create_uri17( pj_pool_t *pool ); |
| static pjsip_uri *create_uri18( pj_pool_t *pool ); |
| static pjsip_uri *create_uri25( pj_pool_t *pool ); |
| static pjsip_uri *create_uri26( pj_pool_t *pool ); |
| static pjsip_uri *create_uri27( pj_pool_t *pool ); |
| static pjsip_uri *create_uri28( pj_pool_t *pool ); |
| static pjsip_uri *create_uri29( pj_pool_t *pool ); |
| static pjsip_uri *create_uri30( pj_pool_t *pool ); |
| static pjsip_uri *create_uri31( pj_pool_t *pool ); |
| static pjsip_uri *create_uri32( pj_pool_t *pool ); |
| static pjsip_uri *create_uri33( pj_pool_t *pool ); |
| static pjsip_uri *create_uri34( pj_pool_t *pool ); |
| static pjsip_uri *create_uri35( pj_pool_t *pool ); |
| static pjsip_uri *create_uri36( pj_pool_t *pool ); |
| static pjsip_uri *create_uri37( pj_pool_t *pool ); |
| static pjsip_uri *create_uri38( pj_pool_t *pool ); |
| static pjsip_uri *create_uri39( pj_pool_t *pool ); |
| static pjsip_uri *create_uri40( pj_pool_t *pool ); |
| static pjsip_uri *create_dummy( pj_pool_t *pool ); |
| |
| #define ERR_NOT_EQUAL -1001 |
| #define ERR_SYNTAX_ERR -1002 |
| |
| struct uri_test |
| { |
| pj_status_t status; |
| char str[PJSIP_MAX_URL_SIZE]; |
| pjsip_uri *(*creator)(pj_pool_t *pool); |
| const char *printed; |
| pj_size_t len; |
| } uri_test_array[] = |
| { |
| { |
| PJ_SUCCESS, |
| "sip:localhost", |
| &create_uri0 |
| }, |
| { |
| PJ_SUCCESS, |
| "sip:user@localhost", |
| &create_uri1 |
| }, |
| { |
| PJ_SUCCESS, |
| "sip:user:password@localhost:5060", |
| &create_uri2, }, |
| { |
| /* Port is specified should not match unspecified port. */ |
| ERR_NOT_EQUAL, |
| "sip:localhost:5060", |
| &create_uri3 |
| }, |
| { |
| /* All recognized parameters. */ |
| PJ_SUCCESS, |
| "sip:localhost;transport=tcp;user=ip;ttl=255;lr;maddr=127.0.0.1;method=ACK", |
| &create_uri4 |
| }, |
| { |
| /* Params mixed with other params and header params. */ |
| PJ_SUCCESS, |
| "sip:localhost;pickup=hurry;user=phone;message=I%20am%20sorry" |
| "?Subject=Hello%20There&Server=SIP%20Server", |
| &create_uri5 |
| }, |
| { |
| /* SIPS. */ |
| PJ_SUCCESS, |
| "sips:localhost", |
| &create_uri6, |
| }, |
| { |
| /* Name address */ |
| PJ_SUCCESS, |
| "<sip:localhost>", |
| &create_uri7 |
| }, |
| { |
| /* Name address with display name and SIPS scheme with some redundant |
| * whitespaced. |
| */ |
| PJ_SUCCESS, |
| " Power Administrator <sips:localhost>", |
| &create_uri8 |
| }, |
| { |
| /* Name address. */ |
| PJ_SUCCESS, |
| " \"User\" <sip:user@localhost:5071>", |
| &create_uri9 |
| }, |
| { |
| /* Escaped sequence in display name (display=Strange User\"\\\"). */ |
| PJ_SUCCESS, |
| " \"Strange User\\\"\\\\\\\"\" <sip:localhost>", |
| &create_uri10, |
| }, |
| { |
| /* Errorneous escaping in display name. */ |
| ERR_SYNTAX_ERR, |
| " \"Rogue User\\\" <sip:localhost>", |
| &create_uri11, |
| }, |
| { |
| /* Dangling quote in display name, but that should be OK. */ |
| PJ_SUCCESS, |
| "Strange User\" <sip:localhost>", |
| &create_uri12, |
| }, |
| { |
| /* Special characters in parameter value must be quoted. */ |
| PJ_SUCCESS, |
| "sip:localhost;pvalue=\"hello world\"", |
| &create_uri13, |
| }, |
| { |
| /* Excercise strange character sets allowed in display, user, password, |
| * host, and port. |
| */ |
| PJ_SUCCESS, |
| "This is -. !% *_+`'~ me <sip:a19A&=+$,;?/%2c:%40a&Zz=+$,@" |
| "my_proxy09.MY-domain.com:9801>", |
| &create_uri14, |
| }, |
| { |
| /* Another excercise to the allowed character sets to the hostname. */ |
| PJ_SUCCESS, |
| "sip:" ALPHANUM "-_.com", |
| &create_uri15, |
| }, |
| { |
| /* Another excercise to the allowed character sets to the username |
| * and password. |
| */ |
| PJ_SUCCESS, |
| "sip:" USER_CHAR ":" PASS_CHAR "@host", |
| &create_uri16, |
| }, |
| { |
| /* Excercise to the pname and pvalue, and mixup of other-param |
| * between 'recognized' params. |
| */ |
| PJ_SUCCESS, |
| "sip:host;user=ip;" PARAM_CHAR "%21=" PARAM_CHAR "%21" |
| ";lr;other=1;transport=sctp;other2", |
| &create_uri17, |
| }, |
| { |
| /* 18: This should trigger syntax error. */ |
| ERR_SYNTAX_ERR, |
| "sip:", |
| &create_dummy, |
| }, |
| { |
| /* 19: Syntax error: whitespace after scheme. */ |
| ERR_SYNTAX_ERR, |
| "sip :host", |
| &create_dummy, |
| }, |
| { |
| /* 20: Syntax error: whitespace before hostname. */ |
| ERR_SYNTAX_ERR, |
| "sip: host", |
| &create_dummy, |
| }, |
| { |
| /* 21: Syntax error: invalid port. */ |
| ERR_SYNTAX_ERR, |
| "sip:user:password", |
| &create_dummy, |
| }, |
| { |
| /* 22: Syntax error: no host. */ |
| ERR_SYNTAX_ERR, |
| "sip:user@", |
| &create_dummy, |
| }, |
| { |
| /* 23: Syntax error: no user/host. */ |
| ERR_SYNTAX_ERR, |
| "sip:@", |
| &create_dummy, |
| }, |
| { |
| /* 24: Syntax error: empty string. */ |
| ERR_SYNTAX_ERR, |
| "", |
| &create_dummy, |
| }, |
| { |
| /* 25: Simple tel: URI with global context */ |
| PJ_SUCCESS, |
| "tel:+1-201-555-0123", |
| &create_uri25, |
| "tel:+1-201-555-0123" |
| }, |
| { |
| /* 26: Simple tel: URI with local context */ |
| PJ_SUCCESS, |
| "tel:7042;phone-context=example.com", |
| &create_uri26, |
| "tel:7042;phone-context=example.com" |
| }, |
| { |
| /* 27: Simple tel: URI with local context */ |
| PJ_SUCCESS, |
| "tel:863-1234;phone-context=+1-914-555", |
| &create_uri27, |
| "tel:863-1234;phone-context=+1-914-555" |
| }, |
| { |
| /* 28: Comparison between local and global number */ |
| ERR_NOT_EQUAL, |
| "tel:+1", |
| &create_uri28, |
| "tel:+1" |
| }, |
| { |
| /* 29: tel: with some visual chars and spaces */ |
| PJ_SUCCESS, |
| "tel:(44).1234-*#+Deaf", |
| &create_uri29, |
| "tel:(44).1234-*#+Deaf" |
| }, |
| { |
| /* 30: isub parameters */ |
| PJ_SUCCESS, |
| "tel:+1;isub=/:@&$,-_.!~*'()[]/:&$aA1%21+=", |
| &create_uri30, |
| "tel:+1;isub=/:@&$,-_.!~*'()[]/:&$aA1!+%3d" |
| }, |
| { |
| /* 31: extension number parsing and encoding */ |
| PJ_SUCCESS, |
| "tel:+1;ext=+123", |
| &create_uri31, |
| "tel:+1;ext=%2b123" |
| }, |
| { |
| /* 32: context parameter parsing and encoding */ |
| PJ_SUCCESS, |
| "tel:911;phone-context=+1-911", |
| &create_uri32, |
| "tel:911;phone-context=+1-911" |
| }, |
| { |
| /* 33: case-insensitive comparison */ |
| PJ_SUCCESS, |
| "tel:911;phone-context=emergency.example.com", |
| &create_uri33, |
| "tel:911;phone-context=emergency.example.com" |
| }, |
| { |
| /* 34: parameter only appears in one URL */ |
| ERR_NOT_EQUAL, |
| "tel:911;p1=p1;p2=p2", |
| &create_uri34, |
| "tel:911;p1=p1;p2=p2" |
| }, |
| { |
| /* 35: IPv6 in host and maddr parameter */ |
| PJ_SUCCESS, |
| "sip:user@[::1];maddr=[::01]", |
| &create_uri35, |
| "sip:user@[::1];maddr=[::01]" |
| }, |
| { |
| /* 36: IPv6 in host and maddr, without username */ |
| PJ_SUCCESS, |
| "sip:[::1];maddr=[::01]", |
| &create_uri36, |
| "sip:[::1];maddr=[::01]" |
| }, |
| { |
| /* 37: Non-ASCII UTF-8 in display name, with quote */ |
| PJ_SUCCESS, |
| "\"\xC0\x81\" <sip:localhost>", |
| &create_uri37, |
| "\"\xC0\x81\" <sip:localhost>" |
| }, |
| { |
| /* 38: Non-ASCII UTF-8 in display name, without quote */ |
| PJ_SUCCESS, |
| "\xC0\x81 <sip:localhost>", |
| &create_uri38, |
| "\"\xC0\x81\" <sip:localhost>" |
| }, |
| { |
| /* Even number of backslash before end quote in display name. */ |
| PJ_SUCCESS, |
| "\"User\\\\\" <sip:localhost>", |
| &create_uri39, |
| }, |
| { |
| /* Quoted display name. */ |
| PJ_SUCCESS, |
| "\"\\\"User\\\"\" <sip:localhost>", |
| &create_uri40, |
| } |
| |
| }; |
| |
| static pjsip_uri *create_uri0(pj_pool_t *pool) |
| { |
| /* "sip:localhost" */ |
| pjsip_sip_uri *url = pjsip_sip_uri_create(pool, 0); |
| |
| pj_strdup2(pool, &url->host, "localhost"); |
| return (pjsip_uri*)url; |
| } |
| |
| static pjsip_uri *create_uri1(pj_pool_t *pool) |
| { |
| /* "sip:user@localhost" */ |
| pjsip_sip_uri *url = pjsip_sip_uri_create(pool, 0); |
| |
| pj_strdup2( pool, &url->user, "user"); |
| pj_strdup2( pool, &url->host, "localhost"); |
| |
| return (pjsip_uri*) url; |
| } |
| |
| static pjsip_uri *create_uri2(pj_pool_t *pool) |
| { |
| /* "sip:user:password@localhost:5060" */ |
| pjsip_sip_uri *url = pjsip_sip_uri_create(pool, 0); |
| |
| pj_strdup2( pool, &url->user, "user"); |
| pj_strdup2( pool, &url->passwd, "password"); |
| pj_strdup2( pool, &url->host, "localhost"); |
| url->port = 5060; |
| |
| return (pjsip_uri*) url; |
| } |
| |
| static pjsip_uri *create_uri3(pj_pool_t *pool) |
| { |
| /* Like: "sip:localhost:5060", but without the port. */ |
| pjsip_sip_uri *url = pjsip_sip_uri_create(pool, 0); |
| |
| pj_strdup2(pool, &url->host, "localhost"); |
| return (pjsip_uri*)url; |
| } |
| |
| static pjsip_uri *create_uri4(pj_pool_t *pool) |
| { |
| /* "sip:localhost;transport=tcp;user=ip;ttl=255;lr;maddr=127.0.0.1;method=ACK" */ |
| pjsip_sip_uri *url = pjsip_sip_uri_create(pool, 0); |
| |
| pj_strdup2(pool, &url->host, "localhost"); |
| pj_strdup2(pool, &url->transport_param, "tcp"); |
| pj_strdup2(pool, &url->user_param, "ip"); |
| url->ttl_param = 255; |
| url->lr_param = 1; |
| pj_strdup2(pool, &url->maddr_param, "127.0.0.1"); |
| pj_strdup2(pool, &url->method_param, "ACK"); |
| |
| return (pjsip_uri*)url; |
| } |
| |
| #define param_add(list,pname,pvalue) \ |
| do { \ |
| pjsip_param *param; \ |
| param=PJ_POOL_ALLOC_T(pool, pjsip_param); \ |
| param->name = pj_str(pname); \ |
| param->value = pj_str(pvalue); \ |
| pj_list_insert_before(&list, param); \ |
| } while (0) |
| |
| static pjsip_uri *create_uri5(pj_pool_t *pool) |
| { |
| /* "sip:localhost;pickup=hurry;user=phone;message=I%20am%20sorry" |
| "?Subject=Hello%20There&Server=SIP%20Server" |
| */ |
| pjsip_sip_uri *url = pjsip_sip_uri_create(pool, 0); |
| |
| pj_strdup2(pool, &url->host, "localhost"); |
| pj_strdup2(pool, &url->user_param, "phone"); |
| |
| //pj_strdup2(pool, &url->other_param, ";pickup=hurry;message=I%20am%20sorry"); |
| param_add(url->other_param, "pickup", "hurry"); |
| param_add(url->other_param, "message", "I am sorry"); |
| |
| //pj_strdup2(pool, &url->header_param, "?Subject=Hello%20There&Server=SIP%20Server"); |
| param_add(url->header_param, "Subject", "Hello There"); |
| param_add(url->header_param, "Server", "SIP Server"); |
| return (pjsip_uri*)url; |
| |
| } |
| |
| static pjsip_uri *create_uri6(pj_pool_t *pool) |
| { |
| /* "sips:localhost" */ |
| pjsip_sip_uri *url = pjsip_sip_uri_create(pool, 1); |
| |
| pj_strdup2(pool, &url->host, "localhost"); |
| return (pjsip_uri*)url; |
| } |
| |
| static pjsip_uri *create_uri7(pj_pool_t *pool) |
| { |
| /* "<sip:localhost>" */ |
| pjsip_name_addr *name_addr = pjsip_name_addr_create(pool); |
| pjsip_sip_uri *url; |
| |
| url = pjsip_sip_uri_create(pool, 0); |
| name_addr->uri = (pjsip_uri*) url; |
| |
| pj_strdup2(pool, &url->host, "localhost"); |
| return (pjsip_uri*)name_addr; |
| } |
| |
| static pjsip_uri *create_uri8(pj_pool_t *pool) |
| { |
| /* " Power Administrator <sips:localhost>" */ |
| pjsip_name_addr *name_addr = pjsip_name_addr_create(pool); |
| pjsip_sip_uri *url; |
| |
| url = pjsip_sip_uri_create(pool, 1); |
| name_addr->uri = (pjsip_uri*) url; |
| |
| pj_strdup2(pool, &name_addr->display, "Power Administrator"); |
| pj_strdup2(pool, &url->host, "localhost"); |
| return (pjsip_uri*)name_addr; |
| } |
| |
| static pjsip_uri *create_uri9(pj_pool_t *pool) |
| { |
| /* " \"User\" <sip:user@localhost:5071>" */ |
| pjsip_name_addr *name_addr = pjsip_name_addr_create(pool); |
| pjsip_sip_uri *url; |
| |
| url = pjsip_sip_uri_create(pool, 0); |
| name_addr->uri = (pjsip_uri*) url; |
| |
| pj_strdup2(pool, &name_addr->display, "User"); |
| pj_strdup2(pool, &url->user, "user"); |
| pj_strdup2(pool, &url->host, "localhost"); |
| url->port = 5071; |
| return (pjsip_uri*)name_addr; |
| } |
| |
| static pjsip_uri *create_uri10(pj_pool_t *pool) |
| { |
| /* " \"Strange User\\\"\\\\\\\"\" <sip:localhost>" */ |
| pjsip_name_addr *name_addr = pjsip_name_addr_create(pool); |
| pjsip_sip_uri *url; |
| |
| url = pjsip_sip_uri_create(pool, 0); |
| name_addr->uri = (pjsip_uri*) url; |
| |
| pj_strdup2(pool, &name_addr->display, "Strange User\\\"\\\\\\\""); |
| pj_strdup2(pool, &url->host, "localhost"); |
| return (pjsip_uri*)name_addr; |
| } |
| |
| static pjsip_uri *create_uri11(pj_pool_t *pool) |
| { |
| /* " \"Rogue User\\\" <sip:localhost>" */ |
| pjsip_name_addr *name_addr = pjsip_name_addr_create(pool); |
| pjsip_sip_uri *url; |
| |
| url = pjsip_sip_uri_create(pool, 0); |
| name_addr->uri = (pjsip_uri*) url; |
| |
| pj_strdup2(pool, &name_addr->display, "Rogue User\\"); |
| pj_strdup2(pool, &url->host, "localhost"); |
| return (pjsip_uri*)name_addr; |
| } |
| |
| static pjsip_uri *create_uri12(pj_pool_t *pool) |
| { |
| /* "Strange User\" <sip:localhost>" */ |
| pjsip_name_addr *name_addr = pjsip_name_addr_create(pool); |
| pjsip_sip_uri *url; |
| |
| url = pjsip_sip_uri_create(pool, 0); |
| name_addr->uri = (pjsip_uri*) url; |
| |
| pj_strdup2(pool, &name_addr->display, "Strange User\""); |
| pj_strdup2(pool, &url->host, "localhost"); |
| return (pjsip_uri*)name_addr; |
| } |
| |
| static pjsip_uri *create_uri13(pj_pool_t *pool) |
| { |
| /* "sip:localhost;pvalue=\"hello world\"" */ |
| pjsip_sip_uri *url; |
| url = pjsip_sip_uri_create(pool, 0); |
| pj_strdup2(pool, &url->host, "localhost"); |
| //pj_strdup2(pool, &url->other_param, ";pvalue=\"hello world\""); |
| param_add(url->other_param, "pvalue", "\"hello world\""); |
| return (pjsip_uri*)url; |
| } |
| |
| static pjsip_uri *create_uri14(pj_pool_t *pool) |
| { |
| /* "This is -. !% *_+`'~ me <sip:a19A&=+$,;?/%2c:%40a&Zz=+$,@my_proxy09.my-domain.com:9801>" */ |
| pjsip_name_addr *name_addr = pjsip_name_addr_create(pool); |
| pjsip_sip_uri *url; |
| |
| url = pjsip_sip_uri_create(pool, 0); |
| name_addr->uri = (pjsip_uri*) url; |
| |
| pj_strdup2(pool, &name_addr->display, "This is -. !% *_+`'~ me"); |
| pj_strdup2(pool, &url->user, "a19A&=+$,;?/,"); |
| pj_strdup2(pool, &url->passwd, "@a&Zz=+$,"); |
| pj_strdup2(pool, &url->host, "my_proxy09.MY-domain.com"); |
| url->port = 9801; |
| return (pjsip_uri*)name_addr; |
| } |
| |
| static pjsip_uri *create_uri15(pj_pool_t *pool) |
| { |
| /* "sip:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.com" */ |
| pjsip_sip_uri *url; |
| url = pjsip_sip_uri_create(pool, 0); |
| pj_strdup2(pool, &url->host, ALPHANUM "-_.com"); |
| return (pjsip_uri*)url; |
| } |
| |
| static pjsip_uri *create_uri16(pj_pool_t *pool) |
| { |
| /* "sip:" USER_CHAR ":" PASS_CHAR "@host" */ |
| pjsip_sip_uri *url; |
| url = pjsip_sip_uri_create(pool, 0); |
| pj_strdup2(pool, &url->user, USER_CHAR); |
| pj_strdup2(pool, &url->passwd, PASS_CHAR); |
| pj_strdup2(pool, &url->host, "host"); |
| return (pjsip_uri*)url; |
| } |
| |
| static pjsip_uri *create_uri17(pj_pool_t *pool) |
| { |
| /* "sip:host;user=ip;" PARAM_CHAR "%21=" PARAM_CHAR "%21;lr;other=1;transport=sctp;other2" */ |
| pjsip_sip_uri *url; |
| url = pjsip_sip_uri_create(pool, 0); |
| pj_strdup2(pool, &url->host, "host"); |
| pj_strdup2(pool, &url->user_param, "ip"); |
| pj_strdup2(pool, &url->transport_param, "sctp"); |
| param_add(url->other_param, PARAM_CHAR "!", PARAM_CHAR "!"); |
| param_add(url->other_param, "other", "1"); |
| param_add(url->other_param, "other2", ""); |
| url->lr_param = 1; |
| return (pjsip_uri*)url; |
| } |
| |
| |
| static pjsip_uri *create_uri25(pj_pool_t *pool) |
| { |
| /* "tel:+1-201-555-0123" */ |
| pjsip_tel_uri *uri = pjsip_tel_uri_create(pool); |
| |
| uri->number = pj_str("+1-201-555-0123"); |
| return (pjsip_uri*)uri; |
| } |
| |
| static pjsip_uri *create_uri26(pj_pool_t *pool) |
| { |
| /* tel:7042;phone-context=example.com */ |
| pjsip_tel_uri *uri = pjsip_tel_uri_create(pool); |
| |
| uri->number = pj_str("7042"); |
| uri->context = pj_str("example.com"); |
| return (pjsip_uri*)uri; |
| } |
| |
| static pjsip_uri *create_uri27(pj_pool_t *pool) |
| { |
| /* "tel:863-1234;phone-context=+1-914-555" */ |
| pjsip_tel_uri *uri = pjsip_tel_uri_create(pool); |
| |
| uri->number = pj_str("863-1234"); |
| uri->context = pj_str("+1-914-555"); |
| return (pjsip_uri*)uri; |
| } |
| |
| /* "tel:1" */ |
| static pjsip_uri *create_uri28(pj_pool_t *pool) |
| { |
| pjsip_tel_uri *uri = pjsip_tel_uri_create(pool); |
| |
| uri->number = pj_str("1"); |
| return (pjsip_uri*)uri; |
| } |
| |
| /* "tel:(44).1234-*#+Deaf" */ |
| static pjsip_uri *create_uri29(pj_pool_t *pool) |
| { |
| pjsip_tel_uri *uri = pjsip_tel_uri_create(pool); |
| |
| uri->number = pj_str("(44).1234-*#+Deaf"); |
| return (pjsip_uri*)uri; |
| } |
| |
| /* "tel:+1;isub=/:@&$,-_.!~*'()[]/:&$aA1%21+=" */ |
| static pjsip_uri *create_uri30(pj_pool_t *pool) |
| { |
| pjsip_tel_uri *uri = pjsip_tel_uri_create(pool); |
| |
| uri->number = pj_str("+1"); |
| uri->isub_param = pj_str("/:@&$,-_.!~*'()[]/:&$aA1!+="); |
| return (pjsip_uri*)uri; |
| } |
| |
| /* "tel:+1;ext=+123" */ |
| static pjsip_uri *create_uri31(pj_pool_t *pool) |
| { |
| pjsip_tel_uri *uri = pjsip_tel_uri_create(pool); |
| |
| uri->number = pj_str("+1"); |
| uri->ext_param = pj_str("+123"); |
| return (pjsip_uri*)uri; |
| } |
| |
| /* "tel:911;phone-context=+1-911" */ |
| static pjsip_uri *create_uri32(pj_pool_t *pool) |
| { |
| pjsip_tel_uri *uri = pjsip_tel_uri_create(pool); |
| |
| uri->number = pj_str("911"); |
| uri->context = pj_str("+1-911"); |
| return (pjsip_uri*)uri; |
| } |
| |
| /* "tel:911;phone-context=emergency.example.com" */ |
| static pjsip_uri *create_uri33(pj_pool_t *pool) |
| { |
| pjsip_tel_uri *uri = pjsip_tel_uri_create(pool); |
| |
| uri->number = pj_str("911"); |
| uri->context = pj_str("EMERGENCY.EXAMPLE.COM"); |
| return (pjsip_uri*)uri; |
| } |
| |
| /* "tel:911;p1=p1;p2=p2" */ |
| static pjsip_uri *create_uri34(pj_pool_t *pool) |
| { |
| pjsip_tel_uri *uri = pjsip_tel_uri_create(pool); |
| pjsip_param *p; |
| |
| uri->number = pj_str("911"); |
| |
| p = PJ_POOL_ALLOC_T(pool, pjsip_param); |
| p->name = p->value = pj_str("p1"); |
| pj_list_insert_before(&uri->other_param, p); |
| |
| return (pjsip_uri*)uri; |
| } |
| |
| /* "sip:user@[::1];maddr=[::01]" */ |
| static pjsip_uri *create_uri35( pj_pool_t *pool ) |
| { |
| pjsip_sip_uri *url; |
| url = pjsip_sip_uri_create(pool, 0); |
| url->user = pj_str("user"); |
| url->host = pj_str("::1"); |
| url->maddr_param = pj_str("::01"); |
| return (pjsip_uri*)url; |
| } |
| |
| /* "sip:[::1];maddr=[::01]" */ |
| static pjsip_uri *create_uri36( pj_pool_t *pool ) |
| { |
| pjsip_sip_uri *url; |
| url = pjsip_sip_uri_create(pool, 0); |
| url->host = pj_str("::1"); |
| url->maddr_param = pj_str("::01"); |
| return (pjsip_uri*)url; |
| |
| } |
| |
| /* "\"\xC0\x81\" <sip:localhost>" */ |
| static pjsip_uri *create_uri37( pj_pool_t *pool ) |
| { |
| pjsip_name_addr *name; |
| pjsip_sip_uri *url; |
| |
| name = pjsip_name_addr_create(pool); |
| name->display = pj_str("\xC0\x81"); |
| |
| url = pjsip_sip_uri_create(pool, 0); |
| url->host = pj_str("localhost"); |
| |
| name->uri = (pjsip_uri*)url; |
| |
| return (pjsip_uri*)name; |
| |
| } |
| |
| /* "\xC0\x81 <sip:localhost>" */ |
| static pjsip_uri *create_uri38( pj_pool_t *pool ) |
| { |
| pjsip_name_addr *name; |
| pjsip_sip_uri *url; |
| |
| name = pjsip_name_addr_create(pool); |
| name->display = pj_str("\xC0\x81"); |
| |
| url = pjsip_sip_uri_create(pool, 0); |
| url->host = pj_str("localhost"); |
| |
| name->uri = (pjsip_uri*)url; |
| |
| return (pjsip_uri*)name; |
| |
| } |
| |
| /* "\"User\\\\\" <sip:localhost>" */ |
| static pjsip_uri *create_uri39(pj_pool_t *pool) |
| { |
| pjsip_name_addr *name_addr = pjsip_name_addr_create(pool); |
| pjsip_sip_uri *url; |
| |
| url = pjsip_sip_uri_create(pool, 0); |
| name_addr->uri = (pjsip_uri*) url; |
| |
| pj_strdup2(pool, &name_addr->display, "User\\\\"); |
| pj_strdup2(pool, &url->host, "localhost"); |
| return (pjsip_uri*)name_addr; |
| } |
| |
| /* "\"\\\"User\\\"\" <sip:localhost>" */ |
| static pjsip_uri *create_uri40(pj_pool_t *pool) |
| { |
| pjsip_name_addr *name_addr = pjsip_name_addr_create(pool); |
| pjsip_sip_uri *url; |
| |
| url = pjsip_sip_uri_create(pool, 0); |
| name_addr->uri = (pjsip_uri*) url; |
| |
| pj_strdup2(pool, &name_addr->display, "\\\"User\\\""); |
| pj_strdup2(pool, &url->host, "localhost"); |
| return (pjsip_uri*)name_addr; |
| } |
| |
| static pjsip_uri *create_dummy(pj_pool_t *pool) |
| { |
| PJ_UNUSED_ARG(pool); |
| return NULL; |
| } |
| |
| /*****************************************************************************/ |
| |
| /* |
| * Test one test entry. |
| */ |
| static pj_status_t do_uri_test(pj_pool_t *pool, struct uri_test *entry) |
| { |
| pj_status_t status; |
| int len; |
| char *input; |
| pjsip_uri *parsed_uri, *ref_uri; |
| pj_str_t s1 = {NULL, 0}, s2 = {NULL, 0}; |
| pj_timestamp t1, t2; |
| |
| if (entry->len == 0) |
| entry->len = pj_ansi_strlen(entry->str); |
| |
| #if defined(PJSIP_UNESCAPE_IN_PLACE) && PJSIP_UNESCAPE_IN_PLACE!=0 |
| input = pj_pool_alloc(pool, entry->len + 1); |
| pj_memcpy(input, entry->str, entry->len); |
| input[entry->len] = '\0'; |
| #else |
| input = entry->str; |
| #endif |
| |
| /* Parse URI text. */ |
| pj_get_timestamp(&t1); |
| var.parse_len = var.parse_len + entry->len; |
| parsed_uri = pjsip_parse_uri(pool, input, entry->len, 0); |
| if (!parsed_uri) { |
| /* Parsing failed. If the entry says that this is expected, then |
| * return OK. |
| */ |
| status = entry->status==ERR_SYNTAX_ERR ? PJ_SUCCESS : -10; |
| if (status != 0) { |
| PJ_LOG(3,(THIS_FILE, " uri parse error!\n" |
| " uri='%s'\n", |
| input)); |
| } |
| goto on_return; |
| } |
| pj_get_timestamp(&t2); |
| pj_sub_timestamp(&t2, &t1); |
| pj_add_timestamp(&var.parse_time, &t2); |
| |
| /* Create the reference URI. */ |
| ref_uri = entry->creator(pool); |
| |
| /* Print both URI. */ |
| s1.ptr = (char*) pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE); |
| s2.ptr = (char*) pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE); |
| |
| pj_get_timestamp(&t1); |
| len = pjsip_uri_print( PJSIP_URI_IN_OTHER, parsed_uri, s1.ptr, PJSIP_MAX_URL_SIZE); |
| if (len < 1) { |
| status = -20; |
| goto on_return; |
| } |
| s1.ptr[len] = '\0'; |
| s1.slen = len; |
| |
| var.print_len = var.print_len + len; |
| pj_get_timestamp(&t2); |
| pj_sub_timestamp(&t2, &t1); |
| pj_add_timestamp(&var.print_time, &t2); |
| |
| len = pjsip_uri_print( PJSIP_URI_IN_OTHER, ref_uri, s2.ptr, PJSIP_MAX_URL_SIZE); |
| if (len < 1) { |
| status = -30; |
| goto on_return; |
| } |
| s2.ptr[len] = '\0'; |
| s2.slen = len; |
| |
| /* Full comparison of parsed URI with reference URI. */ |
| pj_get_timestamp(&t1); |
| status = pjsip_uri_cmp(PJSIP_URI_IN_OTHER, parsed_uri, ref_uri); |
| if (status != 0) { |
| /* Not equal. See if this is the expected status. */ |
| status = entry->status==ERR_NOT_EQUAL ? PJ_SUCCESS : -40; |
| if (status != 0) { |
| PJ_LOG(3,(THIS_FILE, " uri comparison mismatch, status=%d:\n" |
| " uri1='%s'\n" |
| " uri2='%s'", |
| status, s1.ptr, s2.ptr)); |
| } |
| goto on_return; |
| |
| } else { |
| /* Equal. See if this is the expected status. */ |
| status = entry->status==PJ_SUCCESS ? PJ_SUCCESS : -50; |
| if (status != PJ_SUCCESS) { |
| goto on_return; |
| } |
| } |
| |
| var.cmp_len = var.cmp_len + len; |
| pj_get_timestamp(&t2); |
| pj_sub_timestamp(&t2, &t1); |
| pj_add_timestamp(&var.cmp_time, &t2); |
| |
| /* Compare text. */ |
| if (entry->printed) { |
| if (pj_strcmp2(&s1, entry->printed) != 0) { |
| /* Not equal. */ |
| PJ_LOG(3,(THIS_FILE, " uri print mismatch:\n" |
| " printed='%s'\n" |
| " expectd='%s'", |
| s1.ptr, entry->printed)); |
| status = -60; |
| } |
| } else { |
| if (pj_strcmp(&s1, &s2) != 0) { |
| /* Not equal. */ |
| PJ_LOG(3,(THIS_FILE, " uri print mismatch:\n" |
| " uri1='%s'\n" |
| " uri2='%s'", |
| s1.ptr, s2.ptr)); |
| status = -70; |
| } |
| } |
| |
| on_return: |
| return status; |
| } |
| |
| |
| static int simple_uri_test(void) |
| { |
| unsigned i; |
| pj_pool_t *pool; |
| pj_status_t status; |
| |
| PJ_LOG(3,(THIS_FILE, " simple test")); |
| for (i=0; i<PJ_ARRAY_SIZE(uri_test_array); ++i) { |
| pool = pjsip_endpt_create_pool(endpt, "", POOL_SIZE, POOL_SIZE); |
| status = do_uri_test(pool, &uri_test_array[i]); |
| pjsip_endpt_release_pool(endpt, pool); |
| if (status != PJ_SUCCESS) { |
| PJ_LOG(3,(THIS_FILE, " error %d when testing entry %d", |
| status, i)); |
| return status; |
| } |
| } |
| |
| return 0; |
| } |
| |
| #if INCLUDE_BENCHMARKS |
| static int uri_benchmark(unsigned *p_parse, unsigned *p_print, unsigned *p_cmp) |
| { |
| unsigned i, loop; |
| pj_status_t status = PJ_SUCCESS; |
| pj_timestamp zero; |
| pj_time_val elapsed; |
| pj_highprec_t avg_parse, avg_print, avg_cmp, kbytes; |
| |
| pj_bzero(&var, sizeof(var)); |
| |
| zero.u32.hi = zero.u32.lo = 0; |
| |
| var.parse_len = var.print_len = var.cmp_len = 0; |
| var.parse_time.u32.hi = var.parse_time.u32.lo = 0; |
| var.print_time.u32.hi = var.print_time.u32.lo = 0; |
| var.cmp_time.u32.hi = var.cmp_time.u32.lo = 0; |
| for (loop=0; loop<LOOP_COUNT; ++loop) { |
| for (i=0; i<PJ_ARRAY_SIZE(uri_test_array); ++i) { |
| pj_pool_t *pool; |
| pool = pjsip_endpt_create_pool(endpt, "", POOL_SIZE, POOL_SIZE); |
| status = do_uri_test(pool, &uri_test_array[i]); |
| pjsip_endpt_release_pool(endpt, pool); |
| if (status != PJ_SUCCESS) { |
| PJ_LOG(3,(THIS_FILE, " error %d when testing entry %d", |
| status, i)); |
| pjsip_endpt_release_pool(endpt, pool); |
| goto on_return; |
| } |
| } |
| } |
| |
| kbytes = var.parse_len; |
| pj_highprec_mod(kbytes, 1000000); |
| pj_highprec_div(kbytes, 100000); |
| elapsed = pj_elapsed_time(&zero, &var.parse_time); |
| avg_parse = pj_elapsed_usec(&zero, &var.parse_time); |
| pj_highprec_mul(avg_parse, AVERAGE_URL_LEN); |
| pj_highprec_div(avg_parse, var.parse_len); |
| if (avg_parse == 0) |
| avg_parse = 1; |
| avg_parse = 1000000 / avg_parse; |
| |
| PJ_LOG(3,(THIS_FILE, |
| " %u.%u MB of urls parsed in %d.%03ds (avg=%d urls/sec)", |
| (unsigned)(var.parse_len/1000000), (unsigned)kbytes, |
| elapsed.sec, elapsed.msec, |
| (unsigned)avg_parse)); |
| |
| *p_parse = (unsigned)avg_parse; |
| |
| kbytes = var.print_len; |
| pj_highprec_mod(kbytes, 1000000); |
| pj_highprec_div(kbytes, 100000); |
| elapsed = pj_elapsed_time(&zero, &var.print_time); |
| avg_print = pj_elapsed_usec(&zero, &var.print_time); |
| pj_highprec_mul(avg_print, AVERAGE_URL_LEN); |
| pj_highprec_div(avg_print, var.parse_len); |
| if (avg_print == 0) |
| avg_print = 1; |
| avg_print = 1000000 / avg_print; |
| |
| PJ_LOG(3,(THIS_FILE, |
| " %u.%u MB of urls printed in %d.%03ds (avg=%d urls/sec)", |
| (unsigned)(var.print_len/1000000), (unsigned)kbytes, |
| elapsed.sec, elapsed.msec, |
| (unsigned)avg_print)); |
| |
| *p_print = (unsigned)avg_print; |
| |
| kbytes = var.cmp_len; |
| pj_highprec_mod(kbytes, 1000000); |
| pj_highprec_div(kbytes, 100000); |
| elapsed = pj_elapsed_time(&zero, &var.cmp_time); |
| avg_cmp = pj_elapsed_usec(&zero, &var.cmp_time); |
| pj_highprec_mul(avg_cmp, AVERAGE_URL_LEN); |
| pj_highprec_div(avg_cmp, var.cmp_len); |
| if (avg_cmp == 0) |
| avg_cmp = 1; |
| avg_cmp = 1000000 / avg_cmp; |
| |
| PJ_LOG(3,(THIS_FILE, |
| " %u.%u MB of urls compared in %d.%03ds (avg=%d urls/sec)", |
| (unsigned)(var.cmp_len/1000000), (unsigned)kbytes, |
| elapsed.sec, elapsed.msec, |
| (unsigned)avg_cmp)); |
| |
| *p_cmp = (unsigned)avg_cmp; |
| |
| on_return: |
| return status; |
| } |
| #endif /* INCLUDE_BENCHMARKS */ |
| |
| /*****************************************************************************/ |
| |
| int uri_test(void) |
| { |
| enum { COUNT = 1, DETECT=0, PARSE=1, PRINT=2 }; |
| struct { |
| unsigned parse; |
| unsigned print; |
| unsigned cmp; |
| } run[COUNT]; |
| unsigned i, max; |
| pj_ssize_t avg_len; |
| char desc[200]; |
| pj_status_t status; |
| |
| status = simple_uri_test(); |
| if (status != PJ_SUCCESS) |
| return status; |
| |
| #if INCLUDE_BENCHMARKS |
| for (i=0; i<COUNT; ++i) { |
| PJ_LOG(3,(THIS_FILE, " benchmarking (%d of %d)...", i+1, COUNT)); |
| status = uri_benchmark(&run[i].parse, &run[i].print, &run[i].cmp); |
| if (status != PJ_SUCCESS) |
| return status; |
| } |
| |
| /* Calculate average URI length */ |
| for (i=0, avg_len=0; i<PJ_ARRAY_SIZE(uri_test_array); ++i) { |
| avg_len += uri_test_array[i].len; |
| } |
| avg_len /= PJ_ARRAY_SIZE(uri_test_array); |
| |
| |
| /* |
| * Print maximum parse/sec |
| */ |
| for (i=0, max=0; i<COUNT; ++i) |
| if (run[i].parse > max) max = run[i].parse; |
| |
| PJ_LOG(3,("", " Maximum URI parse/sec=%u", max)); |
| |
| pj_ansi_sprintf(desc, "Number of SIP/TEL URIs that can be <B>parsed</B> with " |
| "<tt>pjsip_parse_uri()</tt> per second " |
| "(tested with %d URI set, with average length of " |
| "%d chars)", |
| (int)PJ_ARRAY_SIZE(uri_test_array), (int)avg_len); |
| |
| report_ival("uri-parse-per-sec", max, "URI/sec", desc); |
| |
| /* URI parsing bandwidth */ |
| report_ival("uri-parse-bandwidth-mb", (int)avg_len*max/1000000, "MB/sec", |
| "URI parsing bandwidth in megabytes (number of megabytes " |
| "worth of URI that can be parsed per second)"); |
| |
| |
| /* Print maximum print/sec */ |
| for (i=0, max=0; i<COUNT; ++i) |
| if (run[i].print > max) max = run[i].print; |
| |
| PJ_LOG(3,("", " Maximum URI print/sec=%u", max)); |
| |
| pj_ansi_sprintf(desc, "Number of SIP/TEL URIs that can be <B>printed</B> with " |
| "<tt>pjsip_uri_print()</tt> per second " |
| "(tested with %d URI set, with average length of " |
| "%d chars)", |
| (int)PJ_ARRAY_SIZE(uri_test_array), (int)avg_len); |
| |
| report_ival("uri-print-per-sec", max, "URI/sec", desc); |
| |
| /* Print maximum detect/sec */ |
| for (i=0, max=0; i<COUNT; ++i) |
| if (run[i].cmp > max) max = run[i].cmp; |
| |
| PJ_LOG(3,("", " Maximum URI comparison/sec=%u", max)); |
| |
| pj_ansi_sprintf(desc, "Number of SIP/TEL URIs that can be <B>compared</B> with " |
| "<tt>pjsip_uri_cmp()</tt> per second " |
| "(tested with %d URI set, with average length of " |
| "%d chars)", |
| (int)PJ_ARRAY_SIZE(uri_test_array), (int)avg_len); |
| |
| report_ival("uri-cmp-per-sec", max, "URI/sec", desc); |
| |
| #endif /* INCLUDE_BENCHMARKS */ |
| |
| return PJ_SUCCESS; |
| } |
| |