parse_supported.c

Go to the documentation of this file.
00001 /*
00002  * $Id: parse_supported.c 4720 2008-08-23 10:56:15Z henningw $
00003  *
00004  * Copyright (C) 2006 Andreas Granig <agranig@linguin.org>
00005  *
00006  * This file is part of Kamailio, a free SIP server.
00007  *
00008  * Kamailio is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * Kamailio is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  */
00022 
00023 /*!
00024  * \file
00025  * \brief Supported parser
00026  * \ingroup parser
00027  */
00028 
00029 #include "../mem/mem.h"
00030 #include "keys.h"
00031 #include "parse_supported.h"
00032 
00033 #define IS_DELIM(c) (*(c) == ' ' || *(c) == '\t' || *(c) == '\r' || *(c) == '\n' || *(c) == ',')
00034 
00035 /* from parser/parse_hname2.c: */
00036 #define LOWER_BYTE(b) ((b) | 0x20)
00037 #define LOWER_DWORD(d) ((d) | 0x20202020)
00038 #define READ(val) \
00039    (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16) + (*(val + 3) << 24))
00040 
00041 
00042 /*!
00043  * Parse Supported HF body.
00044  */
00045 static inline int parse_supported_body(str *body, unsigned int *sup)
00046 {
00047    register char* p;
00048    register unsigned int val;
00049    int len, pos = 0;
00050 
00051    *sup = 0;
00052 
00053    p = body->s;
00054    len = body->len;
00055 
00056    while (pos < len) {
00057       /* skip spaces and commas */
00058       for (; pos < len && IS_DELIM(p); ++pos, ++p);
00059 
00060       val = LOWER_DWORD(READ(p));
00061       switch (val) {
00062 
00063          /* "path" */
00064          case _path_:
00065             if(pos + 4 <= len && IS_DELIM(p+4)) {
00066                *sup |= F_SUPPORTED_PATH;
00067                pos += 5; p += 5;
00068             }
00069             break;
00070 
00071          /* "100rel" */
00072          case _100r_:
00073             if ( pos+6 <= len
00074                 && LOWER_BYTE(*(p+4))=='e' && LOWER_BYTE(*(p+5))=='l'
00075                 && IS_DELIM(p+6)) {
00076                *sup |= F_SUPPORTED_100REL;
00077                pos += SUPPORTED_100REL_LEN + 1;
00078                p   += SUPPORTED_100REL_LEN + 1;
00079             }
00080             break;
00081 
00082          /* "timer" */
00083          case _time_:
00084             if ( pos+5 <= len && LOWER_BYTE(*(p+4))=='r'
00085                 && IS_DELIM(p+5) ) {
00086                *sup |= F_SUPPORTED_TIMER;
00087                pos += SUPPORTED_TIMER_LEN + 1;
00088                p   += SUPPORTED_TIMER_LEN + 1;
00089             }
00090             break;
00091 
00092          /* unknown */
00093          default:
00094             /* skip element */
00095             for (; pos < len && !IS_DELIM(p); ++pos, ++p);
00096             break;
00097       }
00098    }
00099    
00100    return 0;
00101 }
00102 
00103 /*!
00104  * Parse all Supported headers
00105  */
00106 int parse_supported( struct sip_msg *msg)
00107 {
00108    unsigned int supported;
00109    struct hdr_field  *hdr;
00110    struct supported_body *sb;
00111 
00112    /* maybe the header is already parsed! */
00113    if (msg->supported && msg->supported->parsed)
00114       return 0;
00115 
00116    /* parse to the end in order to get all SUPPORTED headers */
00117    if (parse_headers(msg,HDR_EOH_F,0)==-1 || !msg->supported)
00118       return -1;
00119 
00120    /* bad luck! :-( - we have to parse them */
00121    supported = 0;
00122    for( hdr=msg->supported ; hdr ; hdr=hdr->sibling) {
00123       if (hdr->parsed) {
00124          supported |= ((struct supported_body*)hdr->parsed)->supported;
00125          continue;
00126       }
00127 
00128       sb = (struct supported_body*)pkg_malloc(sizeof(struct supported_body));
00129       if (sb == 0) {
00130          LM_ERR("out of pkg_memory\n");
00131          return -1;
00132       }
00133 
00134       parse_supported_body(&(hdr->body), &(sb->supported));
00135       sb->supported_all = 0;
00136       hdr->parsed = (void*)sb;
00137       supported |= sb->supported;
00138    }
00139 
00140    ((struct supported_body*)msg->supported->parsed)->supported_all = 
00141       supported;
00142    return 0;
00143 }

Generated on Thu May 24 00:00:28 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6