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 }
1.5.6