channels/chan_sip: Support mutltiple Supported and Required headers
authorMatthew Jordan <mjordan@digium.com>
Thu, 30 Oct 2014 01:48:00 +0000 (01:48 +0000)
committerMatthew Jordan <mjordan@digium.com>
Thu, 30 Oct 2014 01:48:00 +0000 (01:48 +0000)
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
........

Merged revisions 426597 from http://svn.asterisk.org/svn/asterisk/branches/13

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@426598 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_sip.c
channels/sip/reqresp_parser.c

index 8d44b34..43cb2e9 100644 (file)
@@ -25081,7 +25081,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];
@@ -25093,31 +25095,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;
index f914595..aa568a0 100644 (file)
@@ -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;