summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2009-11-04 13:17:31 +0000
committerBenny Prijono <bennylp@teluu.com>2009-11-04 13:17:31 +0000
commit5bba86aff1c5236d9f106e3e13fbfa4954556898 (patch)
tree006da74263fa71bcc0959b39c0a93b8147c6eef9
parentffb29852a54771b54218e24595b123f1f5b96e22 (diff)
Fixed ticket #940: Multiple header rows with the same name may not be completely processed by PJSIP modules
- the parser now collect and aggregate all Supported/Require header fields into single header git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@2985 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjsip/include/pjsip/sip_transport.h9
-rw-r--r--pjsip/src/pjsip/sip_parser.c50
-rw-r--r--tests/pjsua/scripts-sipp/uac-inv-multiple-require.xml91
3 files changed, 138 insertions, 12 deletions
diff --git a/pjsip/include/pjsip/sip_transport.h b/pjsip/include/pjsip/sip_transport.h
index 0e461638..b971762f 100644
--- a/pjsip/include/pjsip/sip_transport.h
+++ b/pjsip/include/pjsip/sip_transport.h
@@ -385,9 +385,16 @@ struct pjsip_rx_data
/** Content-length header. */
pjsip_clen_hdr *clen;
- /** The first Require header. */
+ /** "Require" header containing aggregates of all Require
+ * headers found in the message, or NULL.
+ */
pjsip_require_hdr *require;
+ /** "Supported" header containing aggregates of all Supported
+ * headers found in the message, or NULL.
+ */
+ pjsip_supported_hdr *supported;
+
/** The list of error generated by the parser when parsing
this message.
*/
diff --git a/pjsip/src/pjsip/sip_parser.c b/pjsip/src/pjsip/sip_parser.c
index a5a8e033..5f004ca1 100644
--- a/pjsip/src/pjsip/sip_parser.c
+++ b/pjsip/src/pjsip/sip_parser.c
@@ -1007,11 +1007,17 @@ parse_headers:
if (handler) {
hdr = (*handler)(ctx);
+ /* Note:
+ * hdr MAY BE NULL, if parsing does not yield a new header
+ * instance, e.g. the values have been added to existing
+ * header. See http://trac.pjsip.org/repos/ticket/940
+ */
+
/* Check if we've just parsed a Content-Type header.
* We will check for a message body if we've got Content-Type
* header.
*/
- if (hdr->type == PJSIP_H_CONTENT_TYPE) {
+ if (hdr && hdr->type == PJSIP_H_CONTENT_TYPE) {
ctype_hdr = (pjsip_ctype_hdr*)hdr;
}
@@ -1027,7 +1033,8 @@ parse_headers:
* different Contact headers.
* So here we must insert list instead of just insert one header.
*/
- pj_list_insert_nodes_before(&msg->hdr, hdr);
+ if (hdr)
+ pj_list_insert_nodes_before(&msg->hdr, hdr);
/* Parse until EOF or an empty line is found. */
} while (!pj_scan_is_eof(scanner) && !IS_NEWLINE(*scanner->curptr));
@@ -1639,7 +1646,14 @@ static void parse_generic_array_hdr( pjsip_generic_array_hdr *hdr,
goto end;
}
- pj_scan_get( scanner, &pconst.pjsip_NOT_COMMA_OR_NEWLINE, &hdr->values[0]);
+ if (hdr->count >= PJ_ARRAY_SIZE(hdr->values)) {
+ /* Too many elements */
+ on_syntax_error(scanner);
+ return;
+ }
+
+ pj_scan_get( scanner, &pconst.pjsip_NOT_COMMA_OR_NEWLINE,
+ &hdr->values[hdr->count]);
hdr->count++;
while (*scanner->curptr == ',') {
@@ -1917,13 +1931,19 @@ static pjsip_hdr* parse_hdr_from( pjsip_parse_ctx *ctx )
/* Parse Require: header. */
static pjsip_hdr* parse_hdr_require( pjsip_parse_ctx *ctx )
{
- pjsip_require_hdr *hdr = pjsip_require_hdr_create(ctx->pool);
- parse_generic_array_hdr(hdr, ctx->scanner);
+ pjsip_require_hdr *hdr;
+ pj_bool_t new_hdr = (ctx->rdata->msg_info.require == NULL);
+
+ if (ctx->rdata && ctx->rdata->msg_info.require) {
+ hdr = ctx->rdata->msg_info.require;
+ } else {
+ hdr = pjsip_require_hdr_create(ctx->pool);
+ ctx->rdata->msg_info.require = hdr;
+ }
- if (ctx->rdata && ctx->rdata->msg_info.require == NULL)
- ctx->rdata->msg_info.require = hdr;
+ parse_generic_array_hdr(hdr, ctx->scanner);
- return (pjsip_hdr*)hdr;
+ return new_hdr ? (pjsip_hdr*)hdr : NULL;
}
/* Parse Retry-After: header. */
@@ -1960,12 +1980,20 @@ static pjsip_hdr* parse_hdr_retry_after(pjsip_parse_ctx *ctx)
/* Parse Supported: header. */
static pjsip_hdr* parse_hdr_supported(pjsip_parse_ctx *ctx)
{
- pjsip_supported_hdr *hdr = pjsip_supported_hdr_create(ctx->pool);
+ pjsip_supported_hdr *hdr;
+ pj_bool_t new_hdr = (ctx->rdata->msg_info.supported == NULL);
+
+ if (ctx->rdata && ctx->rdata->msg_info.supported) {
+ hdr = ctx->rdata->msg_info.supported;
+ } else {
+ hdr = pjsip_supported_hdr_create(ctx->pool);
+ ctx->rdata->msg_info.supported = hdr;
+ }
+
parse_generic_array_hdr(hdr, ctx->scanner);
- return (pjsip_hdr*)hdr;
+ return new_hdr ? (pjsip_hdr*)hdr : NULL;
}
-
/* Parse To: header. */
static pjsip_hdr* parse_hdr_to( pjsip_parse_ctx *ctx )
{
diff --git a/tests/pjsua/scripts-sipp/uac-inv-multiple-require.xml b/tests/pjsua/scripts-sipp/uac-inv-multiple-require.xml
new file mode 100644
index 00000000..b0790f6e
--- /dev/null
+++ b/tests/pjsua/scripts-sipp/uac-inv-multiple-require.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE scenario SYSTEM "sipp.dtd">
+
+
+<scenario name="Multiple Require header fields">
+ <!-- UAC with bad ACK causes assertion with pjsip 1.4 -->
+ <send retrans="500">
+ <![CDATA[
+
+ INVITE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
+ Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
+ From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[call_number]
+ To: sut <sip:[service]@[remote_ip]:[remote_port]>
+ Call-ID: [call_id]
+ CSeq: 1 INVITE
+ Contact: sip:sipp@[local_ip]:[local_port]
+ Max-Forwards: 70
+ Require: timer
+ Require: toto
+ Subject: Performance Test
+ Content-Type: application/sdp
+ Content-Length: [len]
+
+ v=0
+ o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
+ s=-
+ c=IN IP[media_ip_type] [media_ip]
+ t=0 0
+ m=audio [media_port] RTP/AVP 0
+ a=rtpmap:0 PCMU/8000
+
+ ]]>
+ </send>
+
+ <recv response="100"
+ optional="true">
+ </recv>
+
+ <recv response="180" optional="true">
+ </recv>
+
+ <recv response="200" rtd="true">
+ </recv>
+
+ <send>
+ <![CDATA[
+
+ ACK sip:[service]@[remote_ip]:[remote_port] SIP/2.0
+ Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
+ From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[call_number]
+ To: sut <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]
+ Call-ID: [call_id]
+ CSeq: 1 ACK
+ Contact: sip:sipp@[local_ip]:[local_port]
+ Max-Forwards: 70
+ Subject: Performance Test
+ Content-Length: 0
+
+ ]]>
+ </send>
+
+ <pause/>
+
+ <send retrans="500">
+ <![CDATA[
+
+ BYE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
+ Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=z9hG4bK-1
+ From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[call_number]
+ To: sut <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]
+ Call-ID: [call_id]
+ CSeq: 2 BYE
+ Contact: sip:sipp@[local_ip]:[local_port]
+ Max-Forwards: 70
+ Subject: Performance Test
+ Content-Length: 0
+
+ ]]>
+ </send>
+
+ <recv response="200" crlf="true">
+ </recv>
+
+ <!-- definition of the response time repartition table (unit is ms) -->
+ <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/>
+
+ <!-- definition of the call length repartition table (unit is ms) -->
+ <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/>
+
+</scenario>
+