From: Matthew Jordan Date: Thu, 30 Oct 2014 01:46:55 +0000 (+0000) Subject: channels/chan_sip: Support mutltiple Supported and Required headers X-Git-Tag: 12.7.0-rc1~20 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2b398410d916354badcacbd01199d49bdeb6966d;p=thirdparty%2Fasterisk.git 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 git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/12@426596 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 6d449b8ce1..3dfa734e94 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -25332,7 +25332,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]; @@ -25344,31 +25346,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; diff --git a/channels/sip/reqresp_parser.c b/channels/sip/reqresp_parser.c index aa09f86463..8818b5562c 100644 --- a/channels/sip/reqresp_parser.c +++ b/channels/sip/reqresp_parser.c @@ -1595,10 +1595,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;