From c99d9cd5ab9be3bce89f84a54abbe87348529a2e Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Tue, 5 Aug 2008 19:28:17 +0000 Subject: Implement ticket #551: Generic URI scheme handler (thanks Juri Glaß for the patch) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@2193 74dad513-b988-da41-8d7b-12977e46ad98 --- pjsip/include/pjsip/sip_parser.h | 1 + pjsip/include/pjsip/sip_uri.h | 29 +++++++++++++ pjsip/src/pjsip/sip_parser.c | 41 +++++++++++++++++- pjsip/src/pjsip/sip_uri.c | 93 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 163 insertions(+), 1 deletion(-) (limited to 'pjsip') diff --git a/pjsip/include/pjsip/sip_parser.h b/pjsip/include/pjsip/sip_parser.h index afd4c440..e9bba36d 100644 --- a/pjsip/include/pjsip/sip_parser.h +++ b/pjsip/include/pjsip/sip_parser.h @@ -358,6 +358,7 @@ typedef struct pjsip_parser_const_t pj_cis_t pjsip_NOT_COMMA_OR_NEWLINE;/**< Array elements. */ pj_cis_t pjsip_DISPLAY_SPEC; /**< Used when searching for display name. */ + pj_cis_t pjsip_OTHER_URI_CONTENT; /**< Generic URI content. */ } pjsip_parser_const_t; diff --git a/pjsip/include/pjsip/sip_uri.h b/pjsip/include/pjsip/sip_uri.h index 5f5ea7e1..a6a0f52e 100644 --- a/pjsip/include/pjsip/sip_uri.h +++ b/pjsip/include/pjsip/sip_uri.h @@ -414,7 +414,36 @@ PJ_DECL(void) pjsip_name_addr_assign(pj_pool_t *pool, pjsip_name_addr *addr, const pjsip_name_addr *rhs); +/** + * @} + */ +/** + * @defgroup PJSIP_OTHER_URI Other URI schemes + * @ingroup PJSIP_URI + * @brief Container for non SIP/tel URI scheme (e.g. "http:", "mailto:") + * @{ + */ + +/** + * Generic URI container for non SIP/tel URI scheme. + */ +typedef struct pjsip_other_uri +{ + pjsip_uri_vptr *vptr; /**< Pointer to virtual function table. */ + pj_str_t scheme; /**< The URI scheme (e.g. "mailto") */ + pj_str_t content; /**< The whole URI content */ +} pjsip_other_uri; + + +/** + * Create a generic URI object. + * + * @param pool The pool to allocate memory from. + * + * @return The URI instance. + */ +PJ_DECL(pjsip_other_uri*) pjsip_other_uri_create(pj_pool_t *pool); /** diff --git a/pjsip/src/pjsip/sip_parser.c b/pjsip/src/pjsip/sip_parser.c index e4d2c0d2..644ad843 100644 --- a/pjsip/src/pjsip/sip_parser.c +++ b/pjsip/src/pjsip/sip_parser.c @@ -48,6 +48,11 @@ #define HNV_UNRESERVED "[]/?:+$" #define HDR_CHAR HNV_UNRESERVED UNRESERVED ESCAPED +/* A generic URI can consist of (For a complete BNF see RFC 2396): + #?;:@&=+-_.!~*'()%$,/ + */ +#define GENERIC_URI_CHARS "#?;:@&=+-_.!~*'()%$,/" "%" + #define PJSIP_VERSION "SIP/2.0" #define UNREACHED(expr) @@ -152,6 +157,9 @@ static void* int_parse_sip_url( pj_scanner *scanner, static pjsip_name_addr * int_parse_name_addr( pj_scanner *scanner, pj_pool_t *pool ); +static void* int_parse_other_uri(pj_scanner *scanner, + pj_pool_t *pool, + pj_bool_t parse_params); static void parse_hdr_end( pj_scanner *scanner ); static pjsip_hdr* parse_hdr_accept( pjsip_parse_ctx *ctx ); @@ -376,6 +384,10 @@ static pj_status_t init_parser() pj_cis_add_str( &pconst.pjsip_DISPLAY_SPEC, ":\r\n<"); pj_cis_invert(&pconst.pjsip_DISPLAY_SPEC); + status = pj_cis_dup(&pconst.pjsip_OTHER_URI_CONTENT, &pconst.pjsip_ALNUM_SPEC); + PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); + pj_cis_add_str( &pconst.pjsip_OTHER_URI_CONTENT, GENERIC_URI_CHARS); + /* * Register URI parsers. */ @@ -690,7 +702,7 @@ static pjsip_parse_uri_func* find_uri_handler(const pj_str_t *scheme) if (parser_stricmp(uri_handler[i].scheme, (*scheme))==0) return uri_handler[i].parse; } - return NULL; + return &int_parse_other_uri; } /* Register URI parser. */ @@ -1463,6 +1475,33 @@ static pjsip_name_addr *int_parse_name_addr( pj_scanner *scanner, } +/* Parse other URI */ +static void* int_parse_other_uri(pj_scanner *scanner, + pj_pool_t *pool, + pj_bool_t parse_params) +{ + pjsip_other_uri *uri = 0; + const pjsip_parser_const_t *pc = pjsip_parser_const(); + int skip_ws = scanner->skip_ws; + + PJ_UNUSED_ARG(parse_params); + + scanner->skip_ws = 0; + + uri = pjsip_other_uri_create(pool); + + pj_scan_get(scanner, &pc->pjsip_TOKEN_SPEC, &uri->scheme); + if (pj_scan_get_char(scanner) != ':') { + PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); + } + + pj_scan_get(scanner, &pc->pjsip_OTHER_URI_CONTENT, &uri->content); + scanner->skip_ws = skip_ws; + + return uri; +} + + /* Parse SIP request line. */ static void int_parse_req_line( pj_scanner *scanner, pj_pool_t *pool, pjsip_request_line *req_line) diff --git a/pjsip/src/pjsip/sip_uri.c b/pjsip/src/pjsip/sip_uri.c index b066dc66..c5bb2c5d 100644 --- a/pjsip/src/pjsip/sip_uri.c +++ b/pjsip/src/pjsip/sip_uri.c @@ -617,3 +617,96 @@ static int pjsip_name_addr_compare( pjsip_uri_context_e context, return 0; } +/////////////////////////////////////////////////////////////////////////////// + +static const pj_str_t *other_uri_get_scheme( const pjsip_other_uri*); +static void *other_uri_get_uri( pjsip_other_uri*); +static pj_ssize_t other_uri_print( pjsip_uri_context_e context, + const pjsip_other_uri *url, + char *buf, pj_size_t size); +static int other_uri_cmp( pjsip_uri_context_e context, + const pjsip_other_uri *url1, + const pjsip_other_uri *url2); +static pjsip_other_uri* other_uri_clone( pj_pool_t *pool, + const pjsip_other_uri *rhs); + +static pjsip_uri_vptr other_uri_vptr = +{ + (P_GET_SCHEME) &other_uri_get_scheme, + (P_GET_URI) &other_uri_get_uri, + (P_PRINT_URI) &other_uri_print, + (P_CMP_URI) &other_uri_cmp, + (P_CLONE) &other_uri_clone +}; + + +PJ_DEF(pjsip_other_uri*) pjsip_other_uri_create(pj_pool_t *pool) +{ + pjsip_other_uri *uri = PJ_POOL_ZALLOC_T(pool, pjsip_other_uri); + uri->vptr = &other_uri_vptr; + return uri; +} + +static const pj_str_t *other_uri_get_scheme( const pjsip_other_uri *uri ) +{ + return &uri->scheme; +} + +static void *other_uri_get_uri( pjsip_other_uri *uri ) +{ + return uri; +} + +static pj_ssize_t other_uri_print(pjsip_uri_context_e context, + const pjsip_other_uri *uri, + char *buf, pj_size_t size) +{ + char *startbuf = buf; + char *endbuf = buf + size; + + PJ_UNUSED_ARG(context); + + if (uri->scheme.slen + uri->content.slen + 1 > (int)size) + return -1; + + /* Print scheme. */ + copy_advance(buf, uri->scheme); + *buf++ = ':'; + + /* Print content. */ + copy_advance(buf, uri->content); + + return (buf - startbuf); +} + +static int other_uri_cmp(pjsip_uri_context_e context, + const pjsip_other_uri *uri1, + const pjsip_other_uri *uri2) +{ + PJ_UNUSED_ARG(context); + + /* Scheme must match. */ + if (pj_stricmp(&uri1->scheme, &uri2->scheme) != 0) { + return PJSIP_ECMPSCHEME; + } + + /* Content must match. */ + if(pj_stricmp(&uri1->content, &uri2->content) != 0) { + return -1; + } + + /* Equal. */ + return 0; +} + +/* Clone *: URI */ +static pjsip_other_uri* other_uri_clone(pj_pool_t *pool, + const pjsip_other_uri *rhs) +{ + pjsip_other_uri *uri = pjsip_other_uri_create(pool); + pj_strdup(pool, &uri->scheme, &rhs->scheme); + pj_strdup(pool, &uri->content, &rhs->content); + + return uri; +} + -- cgit v1.2.3