summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2008-08-05 19:28:17 +0000
committerBenny Prijono <bennylp@teluu.com>2008-08-05 19:28:17 +0000
commitc99d9cd5ab9be3bce89f84a54abbe87348529a2e (patch)
tree88dbefe829e108bc75b672b584d022959cb76081
parent0b4ecc3c596af2032c986107d7c9b8f671e277fa (diff)
Implement ticket #551: Generic URI scheme handler (thanks Juri Glaß for the patch)
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@2193 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjsip/include/pjsip/sip_parser.h1
-rw-r--r--pjsip/include/pjsip/sip_uri.h29
-rw-r--r--pjsip/src/pjsip/sip_parser.c41
-rw-r--r--pjsip/src/pjsip/sip_uri.c93
4 files changed, 163 insertions, 1 deletions
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;
+}
+