diff options
author | Benny Prijono <bennylp@teluu.com> | 2005-11-23 20:56:30 +0000 |
---|---|---|
committer | Benny Prijono <bennylp@teluu.com> | 2005-11-23 20:56:30 +0000 |
commit | 9894af102a5d2e61e7629b99b7746210a8fd3475 (patch) | |
tree | 261a8df5003bab4bd60a3218ce06f845386dc7b9 | |
parent | 3366b25100e19ce91de500de827aed0606390f70 (diff) |
Added tel: uri and user-defined uri parser
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@82 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r-- | pjsip/build/pjsip_core.dsp | 10 | ||||
-rw-r--r-- | pjsip/include/pjsip/print_util.h | 2 | ||||
-rw-r--r-- | pjsip/include/pjsip/sip_config.h | 6 | ||||
-rw-r--r-- | pjsip/include/pjsip/sip_parser.h | 7 | ||||
-rw-r--r-- | pjsip/include/pjsip/sip_tel_uri.h | 71 | ||||
-rw-r--r-- | pjsip/include/pjsip/sip_uri.h | 5 | ||||
-rw-r--r-- | pjsip/include/pjsip_core.h | 1 | ||||
-rw-r--r-- | pjsip/src/pjsip/sip_auth_msg.c | 9 | ||||
-rw-r--r-- | pjsip/src/pjsip/sip_endpoint.c | 8 | ||||
-rw-r--r-- | pjsip/src/pjsip/sip_msg.c | 17 | ||||
-rw-r--r-- | pjsip/src/pjsip/sip_parser.c | 134 | ||||
-rw-r--r-- | pjsip/src/pjsip/sip_tel_uri.c | 416 | ||||
-rw-r--r-- | pjsip/src/pjsip/sip_uri.c | 12 | ||||
-rw-r--r-- | pjsip/src/test-pjsip/test.c | 2 | ||||
-rw-r--r-- | pjsip/src/test-pjsip/uri.c | 212 |
15 files changed, 850 insertions, 62 deletions
diff --git a/pjsip/build/pjsip_core.dsp b/pjsip/build/pjsip_core.dsp index 92a6353f..8893fa00 100644 --- a/pjsip/build/pjsip_core.dsp +++ b/pjsip/build/pjsip_core.dsp @@ -41,7 +41,7 @@ RSC=rc.exe # PROP Intermediate_Dir ".\output\pjsip-core-i386-win32-vc6-release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD CPP /nologo /MD /W4 /Zi /O2 /Oy /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /c
+# ADD CPP /nologo /MD /W4 /Zi /O2 /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
@@ -119,6 +119,10 @@ SOURCE=..\src\pjsip\sip_resolve.c # End Source File
# Begin Source File
+SOURCE=..\src\pjsip\sip_tel_uri.c
+# End Source File
+# Begin Source File
+
SOURCE=..\src\pjsip\sip_transaction.c
# End Source File
# Begin Source File
@@ -199,6 +203,10 @@ SOURCE=..\include\pjsip\sip_resolve.h # End Source File
# Begin Source File
+SOURCE=..\include\pjsip\sip_tel_uri.h
+# End Source File
+# Begin Source File
+
SOURCE=..\include\pjsip\sip_transaction.h
# End Source File
# Begin Source File
diff --git a/pjsip/include/pjsip/print_util.h b/pjsip/include/pjsip/print_util.h index c72d1ab2..0951612a 100644 --- a/pjsip/include/pjsip/print_util.h +++ b/pjsip/include/pjsip/print_util.h @@ -55,7 +55,7 @@ if (str2.slen) { \ if (len1+str2.slen >= (endbuf-buf)) return -1; \ pj_memcpy(buf,str1,len1); \ - printed=pj_strncpy2_escape(buf,&str2,(endbuf-buf-len1),&unres);\ + printed=pj_strncpy2_escape(buf+len1,&str2,(endbuf-buf-len1),&unres);\ if (printed < 0) return -1; \ buf += (printed+len1); \ } \ diff --git a/pjsip/include/pjsip/sip_config.h b/pjsip/include/pjsip/sip_config.h index 98441918..972a080f 100644 --- a/pjsip/include/pjsip/sip_config.h +++ b/pjsip/include/pjsip/sip_config.h @@ -75,6 +75,12 @@ /* Module related constants. */ #define PJSIP_MAX_MODULE 8 +/* Maximum header types. */ +#define PJSIP_MAX_HEADER_TYPES 64 + +/* Maximum URI types. */ +#define PJSIP_MAX_URI_TYPES 4 + /***************************************************************************** * Default timeout settings, in miliseconds. */ diff --git a/pjsip/include/pjsip/sip_parser.h b/pjsip/include/pjsip/sip_parser.h index d6e46e5f..b2e49694 100644 --- a/pjsip/include/pjsip/sip_parser.h +++ b/pjsip/include/pjsip/sip_parser.h @@ -59,7 +59,7 @@ enum /** * Parser syntax error exception value. */ -#define PJSIP_SYN_ERR_EXCEPTION 1 +extern int PJSIP_SYN_ERR_EXCEPTION; /** * This structure is used to get error reporting from parser. @@ -109,7 +109,8 @@ typedef pjsip_hdr* (pjsip_parse_hdr_func)(pjsip_parse_ctx *context); * Most of the specification of header parser handler (pjsip_parse_hdr_func) * also applies here (except the separator part). */ -typedef void* (pjsip_parse_uri_func)(pj_scanner *scanner, pj_pool_t *pool); +typedef void* (pjsip_parse_uri_func)(pj_scanner *scanner, pj_pool_t *pool, + pj_bool_t parse_params); /** * Register header parser handler. The parser handler MUST follow the @@ -148,7 +149,7 @@ PJ_DECL(pj_status_t) pjsip_unregister_hdr_parser( const char *hname, * * @return zero on success. */ -PJ_DECL(pj_status_t) pjsip_register_uri_parser( const char *scheme, +PJ_DECL(pj_status_t) pjsip_register_uri_parser( char *scheme, pjsip_parse_uri_func *func); /** diff --git a/pjsip/include/pjsip/sip_tel_uri.h b/pjsip/include/pjsip/sip_tel_uri.h new file mode 100644 index 00000000..5ade09c6 --- /dev/null +++ b/pjsip/include/pjsip/sip_tel_uri.h @@ -0,0 +1,71 @@ +/* $Id$ */ +/* + * Copyright (C) 2003-2006 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 + */ +#ifndef __PJSIP_TEL_URI_H__ +#define __PJSIP_TEL_URI_H__ + +/** + * @file sip_tel_uri.h + * @brief Tel: URI + */ + +#include <pjsip/sip_uri.h> + + +PJ_BEGIN_DECL + +/** + * tel: URI. + */ +typedef struct pjsip_tel_uri +{ + pjsip_uri_vptr *vptr; /**< Pointer to virtual function table. */ + pj_str_t number; /**< Global or local phone number */ + pj_str_t context; /**< Phone context (for local number). */ + pj_str_t ext_param; /**< Extension param. */ + pj_str_t isub_param; /**< ISDN sub-address param. */ + pjsip_param other_param;/**< Other parameter. */ +} pjsip_tel_uri; + + +/** + * Create a new tel: URI. + * + * @param pool The pool. + * + * @return New instance of tel: URI. + */ +PJ_DECL(pjsip_tel_uri*) pjsip_tel_uri_create(pj_pool_t *pool); + +/** + * This function compares two numbers for equality, according to rules as + * specified in RFC 3966. + * + * @param nb1 The first number. + * @param nb2 The second number. + * + * @return Zero if equal, -1 if nb1 is less than nb2, or +1 if + * nb1 is greater than nb2. + */ +PJ_DECL(int) pjsip_tel_nb_cmp(const pj_str_t *nb1, const pj_str_t *nb2); + + +PJ_END_DECL + + +#endif /* __PJSIP_TEL_URI_H__ */ diff --git a/pjsip/include/pjsip/sip_uri.h b/pjsip/include/pjsip/sip_uri.h index 0e13b300..63f0dfe1 100644 --- a/pjsip/include/pjsip/sip_uri.h +++ b/pjsip/include/pjsip/sip_uri.h @@ -27,6 +27,7 @@ #include <pjsip/sip_types.h> #include <pjsip/sip_config.h> #include <pj/list.h> +#include <pjlib-util/scanner.h> PJ_BEGIN_DECL @@ -102,12 +103,16 @@ PJ_DECL(void) pjsip_param_shallow_clone(pj_pool_t *pool, * @param param_list The parameter list. * @param buf Buffer. * @param size Size of buffer. + * @param pname_unres Specification of allowed characters in pname. + * @param pvalue_unres Specification of allowed characters in pvalue. * @param sep Separator character (either ';' or ','). * * @return The number of bytes printed, or -1 on errr. */ PJ_DECL(pj_ssize_t) pjsip_param_print_on(const pjsip_param *param_list, char *buf, pj_size_t size, + const pj_cis_t *pname_unres, + const pj_cis_t *pvalue_unres, int sep); /** diff --git a/pjsip/include/pjsip_core.h b/pjsip/include/pjsip_core.h index 6ae1c2cf..8ae286a5 100644 --- a/pjsip/include/pjsip_core.h +++ b/pjsip/include/pjsip_core.h @@ -28,6 +28,7 @@ #include <pjsip/sip_msg.h> #include <pjsip/sip_parser.h> #include <pjsip/sip_resolve.h> +#include <pjsip/sip_tel_uri.h> #include <pjsip/sip_transaction.h> #include <pjsip/sip_transport.h> #include <pjsip/sip_uri.h> diff --git a/pjsip/src/pjsip/sip_auth_msg.c b/pjsip/src/pjsip/sip_auth_msg.c index 366bff0b..84c41cc9 100644 --- a/pjsip/src/pjsip/sip_auth_msg.c +++ b/pjsip/src/pjsip/sip_auth_msg.c @@ -18,6 +18,7 @@ */ #include <pjsip/sip_auth_msg.h> #include <pjsip/sip_auth_parser.h> +#include <pjsip/sip_parser.h> #include <pj/pool.h> #include <pj/list.h> #include <pj/string.h> @@ -79,7 +80,9 @@ static int print_digest_credential(pjsip_digest_credential *cred, char *buf, pj_ copy_advance_pair(buf, ", qop=", 6, cred->qop); copy_advance_pair(buf, ", nc=", 5, cred->nc); - printed = pjsip_param_print_on(&cred->other_param, buf, endbuf-buf, ','); + printed = pjsip_param_print_on(&cred->other_param, buf, endbuf-buf, + &pjsip_PARAM_CHAR_SPEC, + &pjsip_PARAM_CHAR_SPEC, ','); if (printed < 0) return -1; buf += printed; @@ -231,7 +234,9 @@ static int print_digest_challenge( pjsip_digest_challenge *chal, copy_advance_pair(buf, ",algorithm=", 11, chal->algorithm); copy_advance_pair_quote_cond(buf, ",qop=", 5, chal->qop, '"', '"'); - printed = pjsip_param_print_on(&chal->other_param, buf, endbuf-buf, ','); + printed = pjsip_param_print_on(&chal->other_param, buf, endbuf-buf, + &pjsip_PARAM_CHAR_SPEC, + &pjsip_PARAM_CHAR_SPEC, ','); if (printed < 0) return -1; buf += printed; diff --git a/pjsip/src/pjsip/sip_endpoint.c b/pjsip/src/pjsip/sip_endpoint.c index 011b3358..dae3d5b1 100644 --- a/pjsip/src/pjsip/sip_endpoint.c +++ b/pjsip/src/pjsip/sip_endpoint.c @@ -104,8 +104,13 @@ struct pjsip_endpoint static void endpt_transport_callback(pjsip_endpoint*, pj_status_t, pjsip_rx_data*); +/* Defined in sip_parser.c */ void init_sip_parser(void); +/* Defined in sip_tel_uri.c */ +pj_status_t pjsip_tel_uri_subsys_init(void); + + /* * This is the global handler for memory allocation failure, for pools that * are created by the endpoint (by default, all pools ARE allocated by @@ -377,6 +382,9 @@ PJ_DEF(pj_status_t) pjsip_endpt_create(pj_pool_factory *pf, /* Init parser. */ init_sip_parser(); + /* Init tel: uri */ + pjsip_tel_uri_subsys_init(); + /* Get name. */ if (name != NULL) { pj_str_t temp; diff --git a/pjsip/src/pjsip/sip_msg.c b/pjsip/src/pjsip/sip_msg.c index 6f963abb..2dc83dda 100644 --- a/pjsip/src/pjsip/sip_msg.c +++ b/pjsip/src/pjsip/sip_msg.c @@ -17,6 +17,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <pjsip/sip_msg.h> +#include <pjsip/sip_parser.h> #include <pjsip/print_util.h> #include <pj/string.h> #include <pj/pool.h> @@ -927,7 +928,9 @@ static int pjsip_contact_hdr_print( pjsip_contact_hdr *hdr, char *buf, buf += printed + 9; } - printed = pjsip_param_print_on(&hdr->other_param, buf, endbuf-buf,';'); + printed = pjsip_param_print_on(&hdr->other_param, buf, endbuf-buf, + &pjsip_PARAM_CHAR_SPEC, + &pjsip_PARAM_CHAR_SPEC, ';'); if (printed < 0) return printed; buf += printed; @@ -1120,7 +1123,9 @@ static int pjsip_fromto_hdr_print( pjsip_fromto_hdr *hdr, copy_advance_pair(buf, ";tag=", 5, hdr->tag); - printed = pjsip_param_print_on(&hdr->other_param, buf, endbuf-buf, ';'); + printed = pjsip_param_print_on(&hdr->other_param, buf, endbuf-buf, + &pjsip_PARAM_CHAR_SPEC, + &pjsip_PARAM_CHAR_SPEC, ';'); if (printed < 0) return -1; buf += printed; @@ -1243,7 +1248,9 @@ static int pjsip_routing_hdr_print( pjsip_routing_hdr *hdr, return -1; buf += printed; - printed = pjsip_param_print_on(&hdr->other_param, buf, endbuf-buf, ';'); + printed = pjsip_param_print_on(&hdr->other_param, buf, endbuf-buf, + &pjsip_PARAM_CHAR_SPEC, + &pjsip_PARAM_CHAR_SPEC, ';'); if (printed < 0) return -1; buf += printed; @@ -1406,7 +1413,9 @@ static int pjsip_via_hdr_print( pjsip_via_hdr *hdr, copy_advance_pair(buf, ";received=", 10, hdr->recvd_param); copy_advance_pair(buf, ";branch=", 8, hdr->branch_param); - printed = pjsip_param_print_on(&hdr->other_param, buf, endbuf-buf, ';'); + printed = pjsip_param_print_on(&hdr->other_param, buf, endbuf-buf, + &pjsip_PARAM_CHAR_SPEC, + &pjsip_PARAM_CHAR_SPEC, ';'); if (printed < 0) return -1; buf += printed; diff --git a/pjsip/src/pjsip/sip_parser.c b/pjsip/src/pjsip/sip_parser.c index 1b430de0..7b163578 100644 --- a/pjsip/src/pjsip/sip_parser.c +++ b/pjsip/src/pjsip/sip_parser.c @@ -49,14 +49,15 @@ #define HDR_CHAR HNV_UNRESERVED UNRESERVED ESCAPED #define PJSIP_VERSION "SIP/2.0" -#define PJSIP_SYN_ERR_EXCEPTION 1 #define UNREACHED(expr) -//#define IS_NEWLINE(c) ((c)=='\r' || (c)=='\n') -#define IS_NEWLINE(c) ((c)=='\r') +#define IS_NEWLINE(c) ((c)=='\r' || (c)=='\n') #define IS_SPACE(c) ((c)==' ' || (c)=='\t') +/* + * Header parser records. + */ typedef struct handler_rec { char hname[PJSIP_MAX_HNAME_LEN+1]; @@ -65,13 +66,27 @@ typedef struct handler_rec pjsip_parse_hdr_func *handler; } handler_rec; -static handler_rec handler[127]; +static handler_rec handler[PJSIP_MAX_HEADER_TYPES]; static unsigned handler_count; static int parser_is_initialized; /* + * URI parser records. + */ +typedef struct uri_parser_rec +{ + pj_str_t scheme; + pjsip_parse_uri_func *parse; +} uri_parser_rec; + +static uri_parser_rec uri_handler[PJSIP_MAX_URI_TYPES]; +static unsigned uri_handler_count; + +/* * Global vars (also extern). */ +int PJSIP_SYN_ERR_EXCEPTION; + const pj_str_t pjsip_USER_STR = { "user", 4}; const pj_str_t pjsip_METHOD_STR = { "method", 6}; const pj_str_t pjsip_TRANSPORT_STR = { "transport", 9}; @@ -246,6 +261,17 @@ static pj_status_t init_parser() initialized = 1; + /* + * Syntax error exception number. + */ + status = pj_exception_id_alloc("PJSIP: syntax error", + &PJSIP_SYN_ERR_EXCEPTION); + PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); + + /* + * Init character input spec (cis) + */ + pj_cis_buf_init(&cis_buf); status = pj_cis_init(&cis_buf, &pjsip_DIGIT_SPEC); @@ -309,6 +335,20 @@ static pj_status_t init_parser() pj_cis_add_str( &pjsip_DISPLAY_SPEC, ":\r\n<"); pj_cis_invert(&pjsip_DISPLAY_SPEC); + /* + * Register URI parsers. + */ + + status = pjsip_register_uri_parser("sip", &int_parse_sip_url); + PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); + + status = pjsip_register_uri_parser("sips", &int_parse_sip_url); + PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); + + /* + * Register header parsers. + */ + status = pjsip_register_hdr_parser( "Accept", NULL, &parse_hdr_accept); PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); @@ -373,7 +413,10 @@ static pj_status_t init_parser() status = pjsip_register_hdr_parser( "Via", NULL, &parse_hdr_via); PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); - /* Register auth parser. */ + /* + * Register auth parser. + */ + status = pjsip_auth_init_parser(); return status; @@ -382,13 +425,10 @@ static pj_status_t init_parser() void init_sip_parser(void) { if (!parser_is_initialized) { - /* Prevent race cond. */ - pj_enter_critical_section(); if (!parser_is_initialized) { init_parser(); parser_is_initialized = 1; } - pj_leave_critical_section(); } } @@ -398,9 +438,9 @@ void init_sip_parser(void) * - >0 if handler is 'greater' than header name. */ PJ_INLINE(int) compare_handler( const handler_rec *r1, - const char *name, - pj_size_t name_len, - pj_uint32_t hash ) + const char *name, + pj_size_t name_len, + pj_uint32_t hash ) { PJ_UNUSED_ARG(name_len); @@ -538,6 +578,31 @@ static pjsip_parse_hdr_func * find_handler(const pj_str_t *hname) return comp==0 ? first->handler : NULL; } +/* Find URI handler. */ +static pjsip_parse_uri_func* find_uri_handler(const pj_str_t *scheme) +{ + unsigned i; + for (i=0; i<uri_handler_count; ++i) { + if (pj_stricmp_alnum(&uri_handler[i].scheme, scheme)==0) + return uri_handler[i].parse; + } + return NULL; +} + +/* Register URI parser. */ +PJ_DEF(pj_status_t) pjsip_register_uri_parser( char *scheme, + pjsip_parse_uri_func *func) +{ + if (uri_handler_count >= PJ_ARRAY_SIZE(uri_handler)) + return PJ_ETOOMANY; + + uri_handler[uri_handler_count].scheme = pj_str((char*)scheme); + uri_handler[uri_handler_count].parse = func; + ++uri_handler_count; + + return PJ_SUCCESS; +} + /* Public function to parse SIP message. */ PJ_DEF(pjsip_msg*) pjsip_parse_msg( pj_pool_t *pool, char *buf, pj_size_t size, @@ -547,8 +612,6 @@ PJ_DEF(pjsip_msg*) pjsip_parse_msg( pj_pool_t *pool, pj_scanner scanner; pjsip_parse_ctx context; - init_sip_parser(); - pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER, &on_syntax_error); @@ -569,8 +632,6 @@ PJ_DEF(pjsip_msg *) pjsip_parse_rdata( char *buf, pj_size_t size, pj_scanner scanner; pjsip_parse_ctx context; - init_sip_parser(); - pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER, &on_syntax_error); @@ -625,8 +686,6 @@ PJ_DEF(pj_bool_t) pjsip_find_msg( const char *buf, pj_size_t size, pj_scanner scanner; PJ_USE_EXCEPTION; - init_sip_parser(); - pj_scan_init(&scanner, (char*)line, hdr_end-line, PJ_SCAN_AUTOSKIP_WS_HEADER, &on_syntax_error); @@ -694,8 +753,6 @@ PJ_DEF(pjsip_uri*) pjsip_parse_uri( pj_pool_t *pool, pjsip_uri *uri = NULL; PJ_USE_EXCEPTION; - init_sip_parser(); - pj_scan_init(&scanner, buf, size, 0, &on_syntax_error); @@ -871,6 +928,10 @@ parse_headers: } while (IS_SPACE(*scanner->curptr)); } + /* Restore flag. Flag may be set in int_parse_sip_url() */ + scanner->skip_ws = PJ_SCAN_AUTOSKIP_WS_HEADER; + + /* Continue parse next header, if any. */ if (!pj_scan_is_eof(scanner) && !IS_NEWLINE(*scanner->curptr)) { goto parse_headers; } @@ -1018,19 +1079,17 @@ static pjsip_uri *int_parse_uri_or_name_addr( pj_scanner *scanner, pj_pool_t *po next_ch = pj_scan_peek( scanner, &pjsip_DISPLAY_SPEC, &scheme); - if (next_ch==':' && - (parser_stricmp(scheme, pjsip_SIP_STR)==0 || - parser_stricmp(scheme, pjsip_SIPS_STR)==0)) - { - uri = (pjsip_uri*) - int_parse_sip_url( scanner, pool, - (opt & PJSIP_PARSE_URI_IN_FROM_TO_HDR)== 0); + if (next_ch==':') { + pjsip_parse_uri_func *func = find_uri_handler(&scheme); - } else if (next_ch==':') { + if (func == NULL) { + /* Unsupported URI scheme */ + PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); + } + + uri = (*func)( scanner, pool, + (opt & PJSIP_PARSE_URI_IN_FROM_TO_HDR)== 0); - /* Not supported. */ - PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); - UNREACHED({return NULL; /* Not reached. */}); } else { uri = (pjsip_uri*)int_parse_name_addr( scanner, pool ); @@ -1062,6 +1121,7 @@ static pjsip_uri *int_parse_uri(pj_scanner *scanner, pj_pool_t *pool, } else { pj_str_t scheme; int colon; + pjsip_parse_uri_func *func; /* Get scheme. */ colon = pj_scan_peek(scanner, &pjsip_TOKEN_SPEC, &scheme); @@ -1069,16 +1129,12 @@ static pjsip_uri *int_parse_uri(pj_scanner *scanner, pj_pool_t *pool, PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); } - if ((parser_stricmp(scheme, pjsip_SIP_STR)==0 || - parser_stricmp(scheme, pjsip_SIPS_STR)==0)) - { - return (pjsip_uri*)int_parse_sip_url( scanner, pool, parse_params); - - } else if (parser_stricmp(scheme, pjsip_TEL_STR)==0) { - PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); - UNREACHED({ return NULL; /* Not reached. */ }) + func = find_uri_handler(&scheme); + if (func) { + return (pjsip_uri*)(*func)(scanner, pool, parse_params); } else { + /* Unsupported URI scheme */ PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); UNREACHED({ return NULL; /* Not reached. */ }) } @@ -1773,8 +1829,6 @@ PJ_DEF(void*) pjsip_parse_hdr( pj_pool_t *pool, const pj_str_t *hname, pjsip_parse_ctx context; PJ_USE_EXCEPTION; - init_sip_parser(); - pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER, &on_syntax_error); diff --git a/pjsip/src/pjsip/sip_tel_uri.c b/pjsip/src/pjsip/sip_tel_uri.c new file mode 100644 index 00000000..4563f6dc --- /dev/null +++ b/pjsip/src/pjsip/sip_tel_uri.c @@ -0,0 +1,416 @@ +/* $Id$ */ +/* + * Copyright (C) 2003-2006 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 <pjsip/sip_tel_uri.h> +#include <pjsip/sip_msg.h> +#include <pjsip/sip_parser.h> +#include <pjsip/print_util.h> +#include <pj/pool.h> +#include <pj/assert.h> +#include <pj/string.h> +#include <pj/ctype.h> +#include <pj/except.h> +#include <pjlib-util/string.h> +#include <pjlib-util/scanner.h> + +#define ALPHA +#define DIGITS "0123456789" +#define HEX "aAbBcCdDeEfF" +#define HEX_DIGITS DIGITS HEX +#define VISUAL_SEP "-.()" +#define PHONE_DIGITS DIGITS VISUAL_SEP +#define GLOBAL_DIGITS "+" PHONE_DIGITS +#define LOCAL_DIGITS HEX_DIGITS "*#" VISUAL_SEP +#define NUMBER_SPEC LOCAL_DIGITS GLOBAL_DIGITS +#define PHONE_CONTEXT ALPHA GLOBAL_DIGITS +//#define RESERVED ";/?:@&=+$," +#define RESERVED "/:@&$,+" +#define MARK "-_.!~*'()" +#define UNRESERVED ALPHA DIGITS MARK +#define ESCAPED "%" +#define URIC RESERVED UNRESERVED ESCAPED "[]+" +#define PARAM_UNRESERVED "[]/:&+$" +#define PARAM_CHAR PARAM_UNRESERVED UNRESERVED ESCAPED + +static pj_cis_buf_t cis_buf; +static pj_cis_t pjsip_TEL_NUMBER_SPEC; +static pj_cis_t pjsip_TEL_EXT_VALUE_SPEC; +static pj_cis_t pjsip_TEL_PHONE_CONTEXT_SPEC; +static pj_cis_t pjsip_TEL_URIC_SPEC; +static pj_cis_t pjsip_TEL_VISUAL_SEP_SPEC; +static pj_cis_t pjsip_TEL_PNAME_SPEC; +static pj_cis_t pjsip_TEL_PVALUE_SPEC; +static pj_cis_t pjsip_TEL_PARSING_PVALUE_SPEC; + +static pj_str_t pjsip_ISUB_STR = { "isub", 4 }; +static pj_str_t pjsip_EXT_STR = { "ext", 3 }; +static pj_str_t pjsip_PH_CTX_STR = { "phone-context", 13 }; + + +static const pj_str_t *tel_uri_get_scheme( const pjsip_tel_uri* ); +static void *tel_uri_get_uri( pjsip_tel_uri* ); +static int tel_uri_print( pjsip_uri_context_e context, + const pjsip_tel_uri *url, + char *buf, pj_size_t size); +static int tel_uri_cmp( pjsip_uri_context_e context, + const pjsip_tel_uri *url1, const pjsip_tel_uri *url2); +static pjsip_tel_uri* tel_uri_clone(pj_pool_t *pool, const pjsip_tel_uri *rhs); +static pjsip_tel_uri *tel_uri_parse( pj_scanner *scanner, pj_pool_t *pool, + pj_bool_t parse_params); + +#ifdef __GNUC__ +# define HAPPY_FLAG (void*) +#else +# define HAPPY_FLAG +#endif + +static pjsip_uri_vptr tel_uri_vptr = +{ + HAPPY_FLAG &tel_uri_get_scheme, + HAPPY_FLAG &tel_uri_get_uri, + HAPPY_FLAG &tel_uri_print, + HAPPY_FLAG &tel_uri_cmp, + HAPPY_FLAG &tel_uri_clone +}; + + +PJ_DEF(pjsip_tel_uri*) pjsip_tel_uri_create(pj_pool_t *pool) +{ + pjsip_tel_uri *uri = pj_pool_zalloc(pool, sizeof(pjsip_tel_uri)); + uri->vptr = &tel_uri_vptr; + pj_list_init(&uri->other_param); + return uri; +} + + +static const pj_str_t *tel_uri_get_scheme( const pjsip_tel_uri *uri ) +{ + PJ_UNUSED_ARG(uri); + return &pjsip_TEL_STR; +} + +static void *tel_uri_get_uri( pjsip_tel_uri *uri ) +{ + return uri; +} + + +pj_status_t pjsip_tel_uri_subsys_init(void) +{ + pj_status_t status; + + pj_cis_buf_init(&cis_buf); + + status = pj_cis_init(&cis_buf, &pjsip_TEL_EXT_VALUE_SPEC); + PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); + pj_cis_add_str(&pjsip_TEL_EXT_VALUE_SPEC, PHONE_DIGITS); + + status = pj_cis_init(&cis_buf, &pjsip_TEL_NUMBER_SPEC); + PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); + pj_cis_add_str(&pjsip_TEL_NUMBER_SPEC, NUMBER_SPEC); + + status = pj_cis_init(&cis_buf, &pjsip_TEL_VISUAL_SEP_SPEC); + PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); + pj_cis_add_str(&pjsip_TEL_VISUAL_SEP_SPEC, VISUAL_SEP); + + status = pj_cis_init(&cis_buf, &pjsip_TEL_PHONE_CONTEXT_SPEC); + PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); + pj_cis_add_alpha(&pjsip_TEL_PHONE_CONTEXT_SPEC); + pj_cis_add_num(&pjsip_TEL_PHONE_CONTEXT_SPEC); + pj_cis_add_str(&pjsip_TEL_PHONE_CONTEXT_SPEC, PHONE_CONTEXT); + + status = pj_cis_init(&cis_buf, &pjsip_TEL_URIC_SPEC); + PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); + pj_cis_add_alpha(&pjsip_TEL_URIC_SPEC); + pj_cis_add_num(&pjsip_TEL_URIC_SPEC); + pj_cis_add_str(&pjsip_TEL_URIC_SPEC, URIC); + + status = pj_cis_init(&cis_buf, &pjsip_TEL_PNAME_SPEC); + PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); + pj_cis_add_alpha(&pjsip_TEL_PNAME_SPEC); + pj_cis_add_num(&pjsip_TEL_PNAME_SPEC); + pj_cis_add_str(&pjsip_TEL_PNAME_SPEC, "-"); + + status = pj_cis_init(&cis_buf, &pjsip_TEL_PVALUE_SPEC); + PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); + pj_cis_add_alpha(&pjsip_TEL_PVALUE_SPEC); + pj_cis_add_num(&pjsip_TEL_PVALUE_SPEC); + pj_cis_add_str(&pjsip_TEL_PVALUE_SPEC, PARAM_CHAR); + + status = pj_cis_dup(&pjsip_TEL_PARSING_PVALUE_SPEC, &pjsip_TEL_URIC_SPEC); + PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); + pj_cis_add_cis(&pjsip_TEL_PARSING_PVALUE_SPEC, &pjsip_TEL_PVALUE_SPEC); + pj_cis_add_str(&pjsip_TEL_PARSING_PVALUE_SPEC, "="); + + status = pjsip_register_uri_parser("tel", &tel_uri_parse); + PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); + + return PJ_SUCCESS; +} + +/* Print tel: URI */ +static int tel_uri_print( pjsip_uri_context_e context, + const pjsip_tel_uri *uri, + char *buf, pj_size_t size) +{ + int printed; + char *startbuf = buf; + char *endbuf = buf+size; + + PJ_UNUSED_ARG(context); + + /* Print scheme. */ + copy_advance(buf, pjsip_TEL_STR); + *buf++ = ':'; + + /* Print number. */ + copy_advance_escape(buf, uri->number, pjsip_TEL_NUMBER_SPEC); + + /* ISDN sub-address or extension must appear first. */ + + /* Extension param. */ + copy_advance_pair_escape(buf, ";ext=", 5, uri->ext_param, + pjsip_TEL_EXT_VALUE_SPEC); + + /* ISDN sub-address. */ + copy_advance_pair_escape(buf, ";isub=", 6, uri->isub_param, + pjsip_TEL_URIC_SPEC); + + /* Followed by phone context, if present. */ + copy_advance_pair_escape(buf, ";phone-context=", 15, uri->context, + pjsip_TEL_PHONE_CONTEXT_SPEC); + + + /* Print other parameters. */ + printed = pjsip_param_print_on(&uri->other_param, buf, (endbuf-buf), + &pjsip_TEL_PNAME_SPEC, + &pjsip_TEL_PVALUE_SPEC, ';'); + if (printed < 0) + return -1; + buf += printed; + + return (buf-startbuf); +} + +/* Compare two numbers, according to RFC 3966: + * - both must be either local or global numbers. + * - The 'global-number-digits' and the 'local-number-digits' must be + * equal, after removing all visual separators. + */ +PJ_DEF(int) pjsip_tel_nb_cmp(const pj_str_t *number1, const pj_str_t *number2) +{ + const char *s1 = number1->ptr, + *e1 = number1->ptr + number1->slen, + *s2 = number2->ptr, + *e2 = number2->ptr + number2->slen; + + /* Compare each number, ignoreing visual separators. */ + while (s1!=e1 && s2!=e2) { + int diff; + + if (pj_cis_match(&pjsip_TEL_VISUAL_SEP_SPEC, *s1)) { + ++s1; + continue; + } + if (pj_cis_match(&pjsip_TEL_VISUAL_SEP_SPEC, *s2)) { + ++s2; + continue; + } + + diff = pj_tolower(*s1) - pj_tolower(*s2); + if (!diff) { + ++s1, ++s2; + continue; + } else + return diff; + } + + /* Exhaust remaining visual separators. */ + while (s1!=e1 && pj_cis_match(&pjsip_TEL_VISUAL_SEP_SPEC, *s1)) + ++s1; + while (s2!=e2 && pj_cis_match(&pjsip_TEL_VISUAL_SEP_SPEC, *s2)) + ++s2; + + if (s1==e1 && s2==e2) + return 0; + else if (s1==e1) + return -1; + else + return 1; +} + +/* Compare two tel: URI */ +static int tel_uri_cmp( pjsip_uri_context_e context, + const pjsip_tel_uri *url1, const pjsip_tel_uri *url2) +{ + int result; + + PJ_UNUSED_ARG(context); + + /* Scheme must match. */ + if (url1->vptr != url2->vptr) + return -1; + + /* Compare number. */ + result = pjsip_tel_nb_cmp(&url1->number, &url2->number); + if (result != 0) + return result; + + /* Compare phone-context as hostname or as as global nb. */ + if (url1->context.slen) { + if (*url1->context.ptr != '+') + result = pj_stricmp(&url1->context, &url2->context); + else + result = pjsip_tel_nb_cmp(&url1->context, &url2->context); + + if (result != 0) + return result; + + } else if (url2->context.slen) + return -1; + + /* Compare extension. */ + if (url1->ext_param.slen) { + result = pjsip_tel_nb_cmp(&url1->ext_param, &url2->ext_param); + if (result != 0) + return result; + } + + /* Compare isub bytes by bytes. */ + if (url1->isub_param.slen) { + result = pj_stricmp(&url1->isub_param, &url2->isub_param); + if (result != 0) + return result; + } + + /* Other parameters are compared regardless of the order. + * If one URI has parameter not found in the other URI, the URIs are + * not equal. + */ + if (url1->other_param.next != &url1->other_param) { + const pjsip_param *p1, *p2; + int cnt1 = 0, cnt2 = 0; + + p1 = url1->other_param.next; + while (p1 != &url1->other_param) { + p2 = pjsip_param_cfind(&url2->other_param, &p1->name); + if (!p2 ) + return 1; + + result = pj_stricmp(&p1->value, &p2->value); + if (result != 0) + return result; + + p1 = p1->next; + ++cnt1; + } + + p2 = url2->other_param.next; + while (p2 != &url2->other_param) + ++cnt2, p2 = p2->next; + + if (cnt1 < cnt2) + return -1; + else if (cnt1 > cnt2) + return 1; + + } else if (url2->other_param.next != &url2->other_param) + return -1; + + /* Equal. */ + return 0; +} + +/* Clone tel: URI */ +static pjsip_tel_uri* tel_uri_clone(pj_pool_t *pool, const pjsip_tel_uri *rhs) +{ + pjsip_tel_uri *uri = pjsip_tel_uri_create(pool); + + pj_strdup(pool, &uri->number, &rhs->number); + pj_strdup(pool, &uri->context, &rhs->context); + pj_strdup(pool, &uri->ext_param, &rhs->ext_param); + pj_strdup(pool, &uri->isub_param, &rhs->isub_param); + pjsip_param_clone(pool, &uri->other_param, &rhs->other_param); + + return uri; +} + +/* Parse tel: URI */ +static pjsip_tel_uri *tel_uri_parse( pj_scanner *scanner, pj_pool_t *pool, + pj_bool_t parse_params) +{ + pjsip_tel_uri *uri; + pj_str_t token; + int skip_ws = scanner->skip_ws; + + scanner->skip_ws = 0; + + /* Parse scheme. */ + pj_scan_get(scanner, &pjsip_TOKEN_SPEC, &token); + if (pj_scan_get_char(scanner) != ':') + PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); + if (pj_stricmp_alnum(&token, &pjsip_TEL_STR) != 0) + PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); + + /* Create URI */ + uri = pjsip_tel_uri_create(pool); + + /* Get the phone number. */ + pj_scan_get(scanner, &pjsip_TEL_NUMBER_SPEC, &uri->number); + uri->number = pj_str_unescape(pool, &uri->number); + + /* Get all parameters. */ + if (parse_params && *scanner->curptr==';') { + pj_str_t pname, pvalue; + + do { + /* Eat the ';' separator. */ + pj_scan_get_char(scanner); + + /* Get pname. */ + pj_scan_get(scanner, &pjsip_PARAM_CHAR_SPEC, &pname); + + if (*scanner->curptr == '=') { + pj_scan_get_char(scanner); + pj_scan_get(scanner, &pjsip_TEL_PARSING_PVALUE_SPEC, &pvalue); + } else { + pvalue.slen = 0; + pvalue.ptr = NULL; + } + + /* Save the parameters. */ + if (pj_stricmp_alnum(&pname, &pjsip_ISUB_STR)==0) { + uri->isub_param = pvalue; + } else if (pj_stricmp_alnum(&pname, &pjsip_EXT_STR)==0) { + uri->ext_param = pvalue; + } else if (pj_stricmp_alnum(&pname, &pjsip_PH_CTX_STR)==0) { + uri->context = pvalue; + } else { + pjsip_param *param = pj_pool_alloc(pool, sizeof(pjsip_param)); + param->name = pname; + param->value = pvalue; + pj_list_insert_before(&uri->other_param, param); + } + + } while (*scanner->curptr==';'); + } + + scanner->skip_ws = skip_ws; + return uri; +} + diff --git a/pjsip/src/pjsip/sip_uri.c b/pjsip/src/pjsip/sip_uri.c index 6c4efb53..09fd8ef8 100644 --- a/pjsip/src/pjsip/sip_uri.c +++ b/pjsip/src/pjsip/sip_uri.c @@ -87,6 +87,8 @@ PJ_DEF(void) pjsip_param_shallow_clone( pj_pool_t *pool, PJ_DEF(pj_ssize_t) pjsip_param_print_on( const pjsip_param *param_list, char *buf, pj_size_t size, + const pj_cis_t *pname_spec, + const pj_cis_t *pvalue_spec, int sep) { const pjsip_param *p; @@ -103,10 +105,10 @@ PJ_DEF(pj_ssize_t) pjsip_param_print_on( const pjsip_param *param_list, do { *buf++ = (char)sep; - copy_advance_escape(buf, p->name, pjsip_PARAM_CHAR_SPEC); + copy_advance_escape(buf, p->name, (*pname_spec)); if (p->value.slen) { *buf++ = '='; - copy_advance_escape(buf, p->value, pjsip_PARAM_CHAR_SPEC); + copy_advance_escape(buf, p->value, (*pvalue_spec)); } p = p->next; } while (p != param_list); @@ -308,7 +310,9 @@ static int pjsip_url_print( pjsip_uri_context_e context, } /* Other param. */ - printed = pjsip_param_print_on(&url->other_param, buf, endbuf-buf, ';'); + printed = pjsip_param_print_on(&url->other_param, buf, endbuf-buf, + &pjsip_PARAM_CHAR_SPEC, + &pjsip_PARAM_CHAR_SPEC, ';'); if (printed < 0) return -1; buf += printed; @@ -448,8 +452,6 @@ static pj_status_t pjsip_url_compare( pjsip_uri_context_e context, * the rule of each header. We'll just compare them string to * string.. */ - PJ_TODO(MORE_COMPLIANT_HEADER_PARAM_COMPARISON_IN_URL); - if (pj_stricmp(&p1->value, &p2->value) != 0) return PJSIP_ECMPHEADERPARAM; } else { diff --git a/pjsip/src/test-pjsip/test.c b/pjsip/src/test-pjsip/test.c index b940ffa1..92e0c33a 100644 --- a/pjsip/src/test-pjsip/test.c +++ b/pjsip/src/test-pjsip/test.c @@ -82,7 +82,7 @@ int test_main(void) PJ_LOG(3,("","")); DO_TEST(uri_test()); - //DO_TEST(msg_test()); + DO_TEST(msg_test()); on_return: diff --git a/pjsip/src/test-pjsip/uri.c b/pjsip/src/test-pjsip/uri.c index 7afcbbef..29a16dd5 100644 --- a/pjsip/src/test-pjsip/uri.c +++ b/pjsip/src/test-pjsip/uri.c @@ -57,6 +57,17 @@ 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_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_dummy( pj_pool_t *pool ); #define ERR_NOT_EQUAL -1001 @@ -66,7 +77,8 @@ struct uri_test { pj_status_t status; char str[PJSIP_MAX_URL_SIZE]; - pjsip_uri *(*creator)(pj_pool_t *pool); + pjsip_uri *(*creator)(pj_pool_t *pool); + const char *printed; pj_size_t len; } uri_test_array[] = { @@ -226,7 +238,78 @@ struct uri_test 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%21+%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" + }, + }; static pjsip_uri *create_uri0(pj_pool_t *pool) @@ -474,6 +557,110 @@ static pjsip_uri *create_uri17(pj_pool_t *pool) 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%21+="); + 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(pool, sizeof(*p)); + p->name = p->value = pj_str("p1"); + pj_list_insert_before(&uri->other_param, p); + + return (pjsip_uri*)uri; +} + + static pjsip_uri *create_dummy(pj_pool_t *pool) { PJ_UNUSED_ARG(pool); @@ -572,9 +759,24 @@ static pj_status_t do_uri_test(pj_pool_t *pool, struct uri_test *entry) pj_add_timestamp(&cmp_time, &t2); /* Compare text. */ - if (pj_strcmp(&s1, &s2) != 0) { - /* Not equal. */ - status = -60; + if (entry->printed) { + if (pj_strcmp2(&s1, entry->printed) != 0) { + /* Not equal. */ + PJ_LOG(3,("", " 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,("", " uri print mismatch:\n" + " uri1='%s'\n" + " uri2='%s'", + s1.ptr, s2.ptr)); + status = -70; + } } on_return: |