From 7056ed05759237312c35a6a42706959f94a63b76 Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Tue, 13 May 2008 09:38:50 +0000 Subject: Ticket #533: Support for parsing Retry-After SIP header git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1954 74dad513-b988-da41-8d7b-12977e46ad98 --- pjsip/include/pjsip/sip_msg.h | 10 ++++- pjsip/src/pjsip/sip_msg.c | 87 ++++++++++++++++++++++++++++++++++++++++++- pjsip/src/pjsip/sip_parser.c | 21 ++++++++++- 3 files changed, 115 insertions(+), 3 deletions(-) (limited to 'pjsip') diff --git a/pjsip/include/pjsip/sip_msg.h b/pjsip/include/pjsip/sip_msg.h index 8a202c4b..97bf1a73 100644 --- a/pjsip/include/pjsip/sip_msg.h +++ b/pjsip/include/pjsip/sip_msg.h @@ -1649,7 +1649,15 @@ PJ_DECL(pjsip_require_hdr*) pjsip_require_hdr_init( pj_pool_t *pool, /** * Retry-After header. */ -typedef pjsip_generic_int_hdr pjsip_retry_after_hdr; +typedef struct pjsip_retry_after_hdr +{ + /** Standard header field. */ + PJSIP_DECL_HDR_MEMBER(struct pjsip_retry_after_hdr); + pj_int32_t ivalue; /**< Retry-After value */ + pjsip_param param; /**< Optional parameters */ + pj_str_t comment; /**< Optional comments. */ +} pjsip_retry_after_hdr; + /** * Create new Retry-After header instance. diff --git a/pjsip/src/pjsip/sip_msg.c b/pjsip/src/pjsip/sip_msg.c index f635a3da..20cece07 100644 --- a/pjsip/src/pjsip/sip_msg.c +++ b/pjsip/src/pjsip/sip_msg.c @@ -1644,6 +1644,22 @@ PJ_DEF(pjsip_require_hdr*) pjsip_require_hdr_create(pj_pool_t *pool) /* * Retry-After header. */ +static int pjsip_retry_after_hdr_print(pjsip_retry_after_hdr *r, + char *buf, pj_size_t size ); +static pjsip_retry_after_hdr* pjsip_retry_after_hdr_clone(pj_pool_t *pool, + const pjsip_retry_after_hdr *r); +static pjsip_retry_after_hdr* +pjsip_retry_after_hdr_shallow_clone(pj_pool_t *pool, + const pjsip_retry_after_hdr *r ); + +static pjsip_hdr_vptr retry_after_hdr_vptr = +{ + (pjsip_hdr_clone_fptr) &pjsip_retry_after_hdr_clone, + (pjsip_hdr_clone_fptr) &pjsip_retry_after_hdr_shallow_clone, + (pjsip_hdr_print_fptr) &pjsip_retry_after_hdr_print, +}; + + PJ_DEF(pjsip_retry_after_hdr*) pjsip_retry_after_hdr_init( pj_pool_t *pool, void *mem, int value ) @@ -1652,8 +1668,9 @@ PJ_DEF(pjsip_retry_after_hdr*) pjsip_retry_after_hdr_init( pj_pool_t *pool, PJ_UNUSED_ARG(pool); - init_hdr(hdr, PJSIP_H_RETRY_AFTER, &generic_int_hdr_vptr); + init_hdr(hdr, PJSIP_H_RETRY_AFTER, &retry_after_hdr_vptr); hdr->ivalue = value; + pj_list_init(&hdr->param); return hdr; } @@ -1665,6 +1682,74 @@ PJ_DEF(pjsip_retry_after_hdr*) pjsip_retry_after_hdr_create(pj_pool_t *pool, } +static int pjsip_retry_after_hdr_print(pjsip_retry_after_hdr *hdr, + char *buf, pj_size_t size) +{ + char *p = buf; + char *endbuf = buf + size; + const pj_str_t *hname = &hdr->name; + const pjsip_parser_const_t *pc = pjsip_parser_const(); + int printed; + + if ((pj_ssize_t)size < hdr->name.slen + 2+11) + return -1; + + pj_memcpy(p, hdr->name.ptr, hdr->name.slen); + p += hname->slen; + *p++ = ':'; + *p++ = ' '; + + p += pj_utoa(hdr->ivalue, p); + + if (hdr->comment.slen) { + pj_bool_t enclosed; + + if (endbuf-p < hdr->comment.slen + 3) + return -1; + + enclosed = (*hdr->comment.ptr == '('); + if (!enclosed) + *p++ = '('; + pj_memcpy(p, hdr->comment.ptr, hdr->comment.slen); + p += hdr->comment.slen; + if (!enclosed) + *p++ = ')'; + + if (!pj_list_empty(&hdr->param)) + *p++ = ' '; + } + + printed = pjsip_param_print_on(&hdr->param, p, endbuf-p, + &pc->pjsip_TOKEN_SPEC, + &pc->pjsip_TOKEN_SPEC, + ';'); + if (printed < 0) + return printed; + + p += printed; + + return p - buf; +} + +static pjsip_retry_after_hdr* pjsip_retry_after_hdr_clone(pj_pool_t *pool, + const pjsip_retry_after_hdr *rhs) +{ + pjsip_retry_after_hdr *hdr = pjsip_retry_after_hdr_create(pool, rhs->ivalue); + pj_strdup(pool, &hdr->comment, &rhs->comment); + pjsip_param_clone(pool, &hdr->param, &rhs->param); + return hdr; +} + +static pjsip_retry_after_hdr* +pjsip_retry_after_hdr_shallow_clone(pj_pool_t *pool, + const pjsip_retry_after_hdr *rhs) +{ + pjsip_retry_after_hdr *hdr = PJ_POOL_ALLOC_T(pool, pjsip_retry_after_hdr); + pj_memcpy(hdr, rhs, sizeof(*hdr)); + pjsip_param_shallow_clone(pool, &hdr->param, &rhs->param); + return hdr; +} + /////////////////////////////////////////////////////////////////////////////// /* * Supported header. diff --git a/pjsip/src/pjsip/sip_parser.c b/pjsip/src/pjsip/sip_parser.c index 88edf707..839e3bed 100644 --- a/pjsip/src/pjsip/sip_parser.c +++ b/pjsip/src/pjsip/sip_parser.c @@ -1825,8 +1825,27 @@ static pjsip_hdr* parse_hdr_require( pjsip_parse_ctx *ctx ) static pjsip_hdr* parse_hdr_retry_after(pjsip_parse_ctx *ctx) { pjsip_retry_after_hdr *hdr; + pj_scanner *scanner = ctx->scanner; + pj_str_t tmp; + hdr = pjsip_retry_after_hdr_create(ctx->pool, 0); - parse_generic_int_hdr(hdr, ctx->scanner); + + pj_scan_get(scanner, &pconst.pjsip_DIGIT_SPEC, &tmp); + hdr->ivalue = pj_strtoul(&tmp); + + while (!pj_scan_is_eof(scanner) && *scanner->curptr!='\r' && + *scanner->curptr=='\n') + { + if (*scanner->curptr=='(') { + pj_scan_get_quote(scanner, '(', ')', &hdr->comment); + } else if (*scanner->curptr==';') { + pjsip_param *prm = PJ_POOL_ALLOC_T(ctx->pool, pjsip_param); + int_parse_param(scanner, ctx->pool, &prm->name, &prm->value, 0); + pj_list_push_back(&hdr->param, prm); + } + } + + parse_hdr_end(scanner); return (pjsip_hdr*)hdr; } -- cgit v1.2.3