channels/chan_sip: Support mutltiple Supported and Required headers

A SIP request may contain multiple Supported: and Required: headers. Currently,
chan_sip only parses the first Supported/Required header it finds. This patch
adds support for multiple Supported/Required headers for INVITE requests.

Review: https://reviewboard.asterisk.org/r/2478

ASTERISK-21721 #close
Reported by: Olle Johansson
patches:
  rb2478.patch uploaded by oej (License 5267)
........

Merged revisions 426594 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........

Merged revisions 426595 from http://svn.asterisk.org/svn/asterisk/branches/11
........

Merged revisions 426596 from http://svn.asterisk.org/svn/asterisk/branches/12


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/13@426597 65c4cc65-6c06-0410-ace0-fbb531ad65f3
changes/97/197/1
Matthew Jordan 11 years ago
parent b1acfd36fd
commit ab07cf71f8

@ -25071,7 +25071,9 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, str
int reinvite = 0;
struct ast_party_redirecting redirecting;
struct ast_set_party_redirecting update_redirecting;
int supported_start = 0;
int require_start = 0;
char unsupported[256] = { 0, };
struct {
char exten[AST_MAX_EXTENSION];
char context[AST_MAX_CONTEXT];
@ -25083,31 +25085,37 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, str
/* Find out what they support */
if (!p->sipoptions) {
const char *supported = sip_get_header(req, "Supported");
if (!ast_strlen_zero(supported)) {
p->sipoptions = parse_sip_options(supported, NULL, 0);
}
const char *supported = NULL;
do {
supported = __get_header(req, "Supported", &supported_start);
if (!ast_strlen_zero(supported)) {
p->sipoptions |= parse_sip_options(supported, NULL, 0);
}
} while (!ast_strlen_zero(supported));
}
/* Find out what they require */
required = sip_get_header(req, "Require");
if (!ast_strlen_zero(required)) {
char unsupported[256] = { 0, };
required_profile = parse_sip_options(required, unsupported, ARRAY_LEN(unsupported));
/* If there are any options required that we do not support,
* then send a 420 with only those unsupported options listed */
if (!ast_strlen_zero(unsupported)) {
transmit_response_with_unsupported(p, "420 Bad extension (unsupported)", req, unsupported);
ast_log(LOG_WARNING, "Received SIP INVITE with unsupported required extension: required:%s unsupported:%s\n", required, unsupported);
p->invitestate = INV_COMPLETED;
if (!p->lastinvite)
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
res = INV_REQ_ERROR;
goto request_invite_cleanup;
do {
required = __get_header(req, "Require", &require_start);
if (!ast_strlen_zero(required)) {
required_profile |= parse_sip_options(required, unsupported, ARRAY_LEN(unsupported));
}
} while (!ast_strlen_zero(required));
/* If there are any options required that we do not support,
* then send a 420 with only those unsupported options listed */
if (!ast_strlen_zero(unsupported)) {
transmit_response_with_unsupported(p, "420 Bad extension (unsupported)", req, unsupported);
ast_log(LOG_WARNING, "Received SIP INVITE with unsupported required extension: required:%s unsupported:%s\n", required, unsupported);
p->invitestate = INV_COMPLETED;
if (!p->lastinvite) {
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
}
res = -1;
goto request_invite_cleanup;
}
/* The option tags may be present in Supported: or Require: headers.
Include the Require: option tags for further processing as well */
p->sipoptions |= required_profile;

@ -1692,10 +1692,6 @@ unsigned int parse_sip_options(const char *options, char *unsupported, size_t un
size_t outlen = unsupported_len;
char *cur_out = out;
if (out && (outlen > 0)) {
memset(out, 0, outlen);
}
if (ast_strlen_zero(options) )
return 0;

Loading…
Cancel
Save