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: https://svn.pjsip.org/repos/pjproject/trunk@2985 74dad513-b988-da41-8d7b-12977e46ad98
This commit is contained in:
Benny Prijono 2009-11-04 13:17:31 +00:00
parent 8db270b0fe
commit 611083d09e
3 changed files with 139 additions and 13 deletions

View File

@ -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.
*/

View File

@ -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);
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;
}
parse_generic_array_hdr(hdr, ctx->scanner);
if (ctx->rdata && ctx->rdata->msg_info.require == NULL)
ctx->rdata->msg_info.require = hdr;
return (pjsip_hdr*)hdr;
return new_hdr ? (pjsip_hdr*)hdr : NULL;
}
/* Parse Retry-After: header. */
@ -1960,11 +1980,19 @@ 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);
parse_generic_array_hdr(hdr, ctx->scanner);
return (pjsip_hdr*)hdr;
}
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 new_hdr ? (pjsip_hdr*)hdr : NULL;
}
/* Parse To: header. */
static pjsip_hdr* parse_hdr_to( pjsip_parse_ctx *ctx )

View File

@ -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>