parse_hname2.c

Go to the documentation of this file.
00001 /*
00002  * $Id: parse_hname2.c 4892 2008-09-11 17:44:28Z henningw $ 
00003  *
00004  * Copyright (C) 2001-2003 FhG Fokus
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  * History:
00023  * --------
00024  * 2006-02-17 Session-Expires, Min-SE (dhsueh@somanetworks.com)
00025  */
00026 
00027 /*!
00028  * \file
00029  * \brief Fast 32-bit Header Field Name Parser
00030  * \ingroup parser
00031  */
00032 
00033 #include <string.h>
00034 
00035 #include "parse_hname2.h"
00036 #include "keys.h"
00037 
00038 #define LOWER_BYTE(b) ((b) | 0x20)
00039 #define LOWER_DWORD(d) ((d) | 0x20202020)
00040 
00041 /*!
00042  * Skip all white-chars and return position of the first
00043  * non-white char
00044  */
00045 static inline char* skip_ws(char* p, unsigned int size)
00046 {
00047    char* end;
00048    
00049    end = p + size;
00050    for(; p < end; p++) {
00051       if ((*p != ' ') && (*p != '\t')) return p;
00052    }
00053    return p;
00054 }
00055    
00056 /*
00057  * Parser macros
00058  */
00059 #include "case_via.h"      /* Via */
00060 #include "case_from.h"     /* From */
00061 #include "case_to.h"       /* To */
00062 #include "case_cseq.h"     /* CSeq */
00063 #include "case_call.h"     /* Call-ID */
00064 #include "case_cont.h"     /* Contact, Content-Type, Content-Length,
00065                               Content-Purpose, Content-Action,
00066                               Content-Disposition */
00067 #include "case_rout.h"     /* Route */
00068 #include "case_max.h"      /* Max-Forwards */
00069 #include "case_reco.h"     /* Record-Route */
00070 #include "case_path.h"     /* Path */
00071 #include "case_auth.h"     /* Authorization */
00072 #include "case_expi.h"     /* Expires */
00073 #include "case_prox.h"     /* Proxy-Authorization, Proxy-Require */
00074 #include "case_allo.h"     /* Allow */
00075 #include "case_unsu.h"     /* Unsupported */
00076 #include "case_even.h"     /* Event */
00077 #include "case_acce.h"     /* Accept, Accept-Language */
00078 #include "case_orga.h"     /* Organization */
00079 #include "case_prio.h"     /* Priority */
00080 #include "case_subj.h"     /* Subject */
00081 #include "case_user.h"     /* User-Agent */
00082 #include "case_supp.h"     /* Supported */
00083 #include "case_dive.h"     /* Diversion */
00084 #include "case_remo.h"     /* Remote-Party-ID */
00085 #include "case_refe.h"     /* Refer-To */
00086 #include "case_sess.h"     /* Session-Expires */
00087 #include "case_min_.h"     /* Min-SE */
00088 #include "case_p_pr.h"     /* P-Preferred-Identity */
00089 #include "case_p_as.h"     /* P-Asserted-Identity */
00090 #include "case_priv.h"     /* Privacy */
00091 #include "case_retr.h"     /* Retry-After */
00092 
00093 
00094 #define READ(val) \
00095 (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16) + (*(val + 3) << 24))
00096 
00097 
00098 #define FIRST_QUATERNIONS       \
00099    case _via1_: via1_CASE; \
00100    case _from_: from_CASE; \
00101    case _to12_: to12_CASE; \
00102    case _cseq_: cseq_CASE; \
00103    case _call_: call_CASE; \
00104    case _cont_: cont_CASE; \
00105    case _rout_: rout_CASE; \
00106    case _max__: max_CASE;  \
00107    case _reco_: reco_CASE; \
00108    case _via2_: via2_CASE; \
00109    case _auth_: auth_CASE; \
00110    case _supp_: supp_CASE; \
00111    case _expi_: expi_CASE; \
00112    case _prox_: prox_CASE; \
00113    case _allo_: allo_CASE; \
00114    case _path_: path_CASE; \
00115    case _unsu_: unsu_CASE; \
00116    case _even_: even_CASE; \
00117    case _acce_: acce_CASE; \
00118    case _orga_: orga_CASE; \
00119    case _prio_: prio_CASE; \
00120    case _subj_: subj_CASE; \
00121    case _user_: user_CASE; \
00122    case _dive_: dive_CASE; \
00123    case _remo_: remo_CASE; \
00124    case _refe_: refe_CASE; \
00125    case _sess_: sess_CASE; \
00126    case _min__: min__CASE; \
00127    case _p_pr_: p_pr_CASE; \
00128    case _p_as_: p_as_CASE; \
00129    case _priv_: priv_CASE; \
00130    case _retr_: retr_CASE; \
00131 
00132 
00133 #define PARSE_COMPACT(id)          \
00134         switch(*(p + 1)) {         \
00135         case ' ':                  \
00136            hdr->type = id;    \
00137            p += 2;            \
00138            goto dc_end;       \
00139                               \
00140         case ':':                  \
00141            hdr->type = id;    \
00142            hdr->name.len = 1; \
00143            return (p + 2);    \
00144         }
00145 
00146 
00147 char* parse_hname2(char* begin, char* end, struct hdr_field* hdr)
00148 {
00149    register char* p;
00150    register unsigned int val;
00151 
00152    if ((end - begin) < 4) {
00153       hdr->type = HDR_ERROR_T;
00154       return begin;
00155    }
00156 
00157    p = begin;
00158 
00159    val = LOWER_DWORD(READ(p));
00160    hdr->name.s = begin;
00161 
00162    switch(val) {
00163    FIRST_QUATERNIONS;
00164 
00165    default:
00166       switch(LOWER_BYTE(*p)) {
00167       case 't':
00168          switch(LOWER_BYTE(*(p + 1))) {
00169          case 'o':
00170          case ' ':
00171             hdr->type = HDR_TO_T; 
00172             p += 2;
00173             goto dc_end;
00174             
00175          case ':':
00176             hdr->type = HDR_TO_T; 
00177             hdr->name.len = 1;
00178             return (p + 2);
00179          }
00180          break;
00181 
00182       case 'v': PARSE_COMPACT(HDR_VIA_T);           break;
00183       case 'f': PARSE_COMPACT(HDR_FROM_T);          break;
00184       case 'i': PARSE_COMPACT(HDR_CALLID_T);        break;
00185       case 'm': PARSE_COMPACT(HDR_CONTACT_T);       break;
00186       case 'l': PARSE_COMPACT(HDR_CONTENTLENGTH_T); break;
00187       case 'k': PARSE_COMPACT(HDR_SUPPORTED_T);     break;
00188       case 'c': PARSE_COMPACT(HDR_CONTENTTYPE_T);   break;
00189       case 'o': PARSE_COMPACT(HDR_EVENT_T);         break;
00190       case 'x': PARSE_COMPACT(HDR_SESSION_EXPIRES_T); break;
00191       }
00192       goto other;
00193         }
00194 
00195    /* Double colon hasn't been found yet */
00196  dc_end:
00197    p = skip_ws(p, end - p);
00198    if (*p != ':') {
00199            goto other;
00200    } else {
00201       hdr->name.len = p - hdr->name.s;
00202       return (p + 1);
00203    }
00204 
00205    /* Unknown header type */
00206  other:
00207    p = memchr(p, ':', end - p);
00208    if (!p) {        /* No double colon found, error.. */
00209       hdr->type = HDR_ERROR_T;
00210       hdr->name.s = 0;
00211       hdr->name.len = 0;
00212       return 0;
00213    } else {
00214       hdr->type = HDR_OTHER_T;
00215       hdr->name.len = p - hdr->name.s;
00216       return (p + 1);
00217    }
00218 }

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