parse_hname2.c

Go to the documentation of this file.
00001 /*
00002  * $Id$
00003  *
00004  * Fast 32-bit Header Field Name Parser
00005  *
00006  * Copyright (C) 2001-2003 FhG Fokus
00007  *
00008  * This file is part of ser, a free SIP server.
00009  *
00010  * ser is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version
00014  *
00015  * For a license to use the ser software under conditions
00016  * other than those described here, or to purchase support for this
00017  * software, please contact iptel.org by e-mail at the following addresses:
00018  *    info@iptel.org
00019  *
00020  * ser is distributed in the hope that it will be useful,
00021  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  * GNU General Public License for more details.
00024  *
00025  * You should have received a copy of the GNU General Public License
00026  * along with this program; if not, write to the Free Software
00027  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00028  *
00029  * History:
00030  * --------
00031  * 2003-02-28 scratchpad compatibility abandoned (jiri)
00032  * 2003-01-27 next baby-step to removing ZT - PRESERVE_ZT (jiri)
00033  * 2003-05-01 added support for Accept HF (janakj)
00034  * 2007-01-26 Date, Identity, Identity_info HF support added (gergo)
00035  * 2007-07-27 added support for Retry-After (andrei)
00036  */
00037 
00043 #include "../comp_defs.h"
00044 #include "parse_hname2.h"
00045 #include "keys.h"
00046 #include "../ut.h"  /* q_memchr */
00047 
00048 #define LOWER_BYTE(b) ((b) | 0x20)
00049 #define LOWER_DWORD(d) ((d) | 0x20202020)
00050 
00053 static inline char* skip_ws(char* p, unsigned int size)
00054 {
00055         char* end;
00056 
00057         end = p + size;
00058         for(; p < end; p++) {
00059                 if ((*p != ' ') && (*p != '\t')) return p;
00060         }
00061         return p;
00062 }
00063 
00067 
00068 #include "case_via.h"      /* Via */
00069 #include "case_from.h"     /* From */
00070 #include "case_to.h"       /* To */
00071 #include "case_cseq.h"     /* CSeq */
00072 #include "case_call.h"     /* Call-ID */
00073 #include "case_cont.h"     /* Contact, Content-Type, Content-Length, Content-Purpose,
00074                             * Content-Action, Content-Disposition */
00075 #include "case_rout.h"     /* Route */
00076 #include "case_max.h"      /* Max-Forwards */
00077 #include "case_reco.h"     /* Record-Route */
00078 #include "case_auth.h"     /* Authorization */
00079 #include "case_expi.h"     /* Expires */
00080 #include "case_prox.h"     /* Proxy-Authorization, Proxy-Require */
00081 #include "case_allo.h"     /* Allow */
00082 #include "case_unsu.h"     /* Unsupported */
00083 #include "case_even.h"     /* Event */
00084 #include "case_sip.h"      /* Sip-If-Match */
00085 #include "case_acce.h"     /* Accept, Accept-Language */
00086 #include "case_orga.h"     /* Organization */
00087 #include "case_prio.h"     /* Priority */
00088 #include "case_subj.h"     /* Subject */
00089 #include "case_user.h"     /* User-Agent */
00090 #include "case_serv.h"     /* Server */
00091 #include "case_supp.h"     /* Supported */
00092 #include "case_dive.h"     /* Diversion */
00093 #include "case_remo.h"     /* Remote-Party-ID */
00094 #include "case_refe.h"     /* Refer-To */
00095 #include "case_sess.h"     /* Session-Expires */
00096 #include "case_reje.h"     /* Reject-Contact */
00097 #include "case_min.h"      /* Min-SE */
00098 #include "case_subs.h"     /* Subscription-State */
00099 #include "case_requ.h"     /* Require */
00100 #include "case_www.h"      /* WWW-Authenticate */
00101 #include "case_date.h"     /* Date */
00102 #include "case_iden.h"     /* Identity, Identity-info */
00103 #include "case_retr.h"     /* Retry-After */
00104 #include "case_path.h"     /* Path */
00105 #include "case_priv.h"
00106 #include "case_reas.h"     /* Reason */
00107 #include "case_p_as.h"     /* P-Asserted-Identity */
00108 #include "case_p_pr.h"     /* P-Preferred-Identity */
00109 
00112 #define READ(val) \
00113 (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16) + (*(val + 3) << 24))
00114 
00115 #define READ3(val) \
00116 (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16))
00117 
00118 #define FIRST_QUATERNIONS       \
00119         case _via1_: via1_CASE; \
00120         case _from_: from_CASE; \
00121         case _to12_: to12_CASE; \
00122         case _cseq_: cseq_CASE; \
00123         case _call_: call_CASE; \
00124         case _cont_: cont_CASE; \
00125         case _rout_: rout_CASE; \
00126         case _max__: max_CASE;  \
00127         case _reco_: reco_CASE; \
00128         case _via2_: via2_CASE; \
00129         case _auth_: auth_CASE; \
00130         case _supp_: supp_CASE; \
00131         case _expi_: expi_CASE; \
00132         case _prox_: prox_CASE; \
00133         case _allo_: allo_CASE; \
00134         case _unsu_: unsu_CASE; \
00135         case _even_: even_CASE; \
00136         case _sip_ : sip_CASE;  \
00137         case _acce_: acce_CASE; \
00138         case _orga_: orga_CASE; \
00139         case _prio_: prio_CASE; \
00140         case _subj_: subj_CASE; \
00141         case _subs_: subs_CASE; \
00142         case _user_: user_CASE; \
00143         case _serv_: serv_CASE; \
00144         case _dive_: dive_CASE; \
00145         case _remo_: remo_CASE; \
00146         case _refe_: refe_CASE; \
00147         case _sess_: sess_CASE; \
00148         case _reje_: reje_CASE; \
00149         case _min__: min_CASE;  \
00150         case _requ_: requ_CASE;  \
00151         case _www__: www_CASE; \
00152         case _date_: date_CASE; \
00153         case _iden_: iden_CASE; \
00154         case _retr_: retr_CASE; \
00155         case _path_: path_CASE; \
00156         case _priv_: priv_CASE; \
00157         case _reas_: reas_CASE; \
00158         case _p_as_: p_as_CASE; \
00159         case _p_pr_: p_pr_CASE;
00160 
00161 
00162 #define PARSE_COMPACT(id)          \
00163         switch(*(p + 1)) {         \
00164         case ' ':                  \
00165                 hdr->type = id;    \
00166                 p += 2;            \
00167                 goto dc_end;       \
00168                                    \
00169         case ':':                  \
00170                 hdr->type = id;    \
00171                 hdr->name.len = 1; \
00172                 return (p + 2);    \
00173         }
00174 
00175 #if 0
00176 int hdr_update_type(struct hdr_field* hdr)
00177 {
00178         if(hdr==0 || hdr->name.s==0)
00179                 return -1;
00180         switch(hdr->name.len) {
00181                 case 19:
00182                         if(strncasecmp(hdr->name.s, "P-Asserted-Identity", 19)==0)
00183                                 hdr->type = HDR_PAI_T;
00184                 break;
00185                 case 20:
00186                         if(strncasecmp(hdr->name.s, "P-Preferred-Identity", 20)==0)
00187                                 hdr->type = HDR_PPI_T;
00188                 break;
00189         }
00190 
00191         return 0;
00192 }
00193 #endif
00194 
00195 char* parse_hname2(char* begin, char* end, struct hdr_field* hdr)
00196 {
00197         register char* p;
00198         register unsigned int val;
00199 
00200         if ((end - begin) < 4) {
00201                 hdr->type = HDR_ERROR_T;
00202                 return begin;
00203         }
00204 
00205         p = begin;
00206 
00207         val = LOWER_DWORD(READ(p));
00208         hdr->name.s = begin;
00209 
00210         switch(val) {
00211         FIRST_QUATERNIONS;
00212 
00213         default:
00214                 switch(LOWER_BYTE(*p)) {
00215                 case 't':
00216                         switch(LOWER_BYTE(*(p + 1))) {
00217                         case 'o':
00218                         case ' ':
00219                                 hdr->type = HDR_TO_T;
00220                                 p += 2;
00221                                 goto dc_end;
00222 
00223                         case ':':
00224                                 hdr->type = HDR_TO_T;
00225                                 hdr->name.len = 1;
00226                                 return (p + 2);
00227                         }
00228                         break;
00229 
00230                 case 'v': PARSE_COMPACT(HDR_VIA_T);           break;
00231                 case 'f': PARSE_COMPACT(HDR_FROM_T);          break;
00232                 case 'i': PARSE_COMPACT(HDR_CALLID_T);        break;
00233                 case 'm': PARSE_COMPACT(HDR_CONTACT_T);       break;
00234                 case 'l': PARSE_COMPACT(HDR_CONTENTLENGTH_T); break;
00235                 case 'k': PARSE_COMPACT(HDR_SUPPORTED_T);     break;
00236                 case 'c': PARSE_COMPACT(HDR_CONTENTTYPE_T);   break;
00237                 case 'o': PARSE_COMPACT(HDR_EVENT_T);         break;
00238                 case 'x': PARSE_COMPACT(HDR_SESSIONEXPIRES_T);break;
00239                 case 'a': PARSE_COMPACT(HDR_ACCEPTCONTACT_T); break;
00240                 case 'u': PARSE_COMPACT(HDR_ALLOWEVENTS_T);   break;
00241                 case 'e': PARSE_COMPACT(HDR_CONTENTENCODING_T); break;
00242                 case 'b': PARSE_COMPACT(HDR_REFERREDBY_T);    break;
00243                 case 'j': PARSE_COMPACT(HDR_REJECTCONTACT_T); break;
00244                 case 'd': PARSE_COMPACT(HDR_REQUESTDISPOSITION_T); break;
00245                 case 's': PARSE_COMPACT(HDR_SUBJECT_T);       break;
00246                 case 'r': PARSE_COMPACT(HDR_REFER_TO_T);      break;
00247                 case 'y': PARSE_COMPACT(HDR_IDENTITY_T);      break;
00248                 case 'n': PARSE_COMPACT(HDR_IDENTITY_INFO_T); break;
00249                 }
00250                 goto other;
00251         }
00252 
00253              /* Double colon hasn't been found yet */
00254  dc_end:
00255         p = skip_ws(p, end - p);
00256         if (*p != ':') {
00257                 goto other;
00258         } else {
00259                 hdr->name.len = p - hdr->name.s;
00260                 return (p + 1);
00261         }
00262 
00263              /* Unknown header type */
00264  other:
00265         p = q_memchr(p, ':', end - p);
00266         if (!p) {        /* No double colon found, error.. */
00267                 hdr->type = HDR_ERROR_T;
00268                 hdr->name.s = 0;
00269                 hdr->name.len = 0;
00270                 return 0;
00271         } else {
00272                 hdr->type = HDR_OTHER_T;
00273                 hdr->name.len = p - hdr->name.s;
00274                 /*hdr_update_type(hdr);*/
00275                 return (p + 1);
00276         }
00277 }
00278