parser/parse_hname2.c
67386619
 /*
  * $Id$
32822438
  *
  * Fast 32-bit Header Field Name Parser
7dd0b342
  *
c32feee5
  * Copyright (C) 2001-2003 FhG Fokus
7dd0b342
  *
  * This file is part of ser, a free SIP server.
  *
  * ser is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
  * For a license to use the ser software under conditions
  * other than those described here, or to purchase support for this
  * software, please contact iptel.org by e-mail at the following addresses:
  *    info@iptel.org
  *
  * ser is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
67386619
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
7dd0b342
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
1540fad1
  *
  * History:
  * --------
18dbc018
  * 2003-02-28 scratchpad compatibility abandoned (jiri)
1540fad1
  * 2003-01-27 next baby-step to removing ZT - PRESERVE_ZT (jiri)
71be0c4a
  * 2003-05-01 added support for Accept HF (janakj)
e7317b87
  * 2007-01-26 Date, Identity, Identity_info HF support added (gergo)
b861de9c
  * 2007-07-27 added support for Retry-After (andrei)
3881f12c
  */
 
 
1540fad1
 #include "../comp_defs.h"
e3c29827
 #include "parse_hname2.h"
 #include "keys.h"
2bb60634
 #include "../ut.h"  /* q_memchr */
3881f12c
 
32822438
 #define LOWER_BYTE(b) ((b) | 0x20)
 #define LOWER_DWORD(d) ((d) | 0x20202020)
3881f12c
 
 /*
c32feee5
  * Skip all white-chars and return position of the first
3881f12c
  * non-white char
  */
 static inline char* skip_ws(char* p, unsigned int size)
 {
 	char* end;
67386619
 
3881f12c
 	end = p + size;
 	for(; p < end; p++) {
 		if ((*p != ' ') && (*p != '\t')) return p;
 	}
 	return p;
 }
67386619
 
e3c29827
 /*
  * Parser macros
  */
 #include "case_via.h"      /* Via */
 #include "case_from.h"     /* From */
 #include "case_to.h"       /* To */
 #include "case_cseq.h"     /* CSeq */
 #include "case_call.h"     /* Call-ID */
67386619
 #include "case_cont.h"     /* Contact, Content-Type, Content-Length, Content-Purpose,
2f43c732
 			    * Content-Action, Content-Disposition */
e3c29827
 #include "case_rout.h"     /* Route */
 #include "case_max.h"      /* Max-Forwards */
 #include "case_reco.h"     /* Record-Route */
 #include "case_auth.h"     /* Authorization */
 #include "case_expi.h"     /* Expires */
 #include "case_prox.h"     /* Proxy-Authorization, Proxy-Require */
 #include "case_allo.h"     /* Allow */
 #include "case_unsu.h"     /* Unsupported */
a054d7d5
 #include "case_even.h"     /* Event */
9200d410
 #include "case_sip.h"      /* Sip-If-Match */
2f43c732
 #include "case_acce.h"     /* Accept, Accept-Language */
 #include "case_orga.h"     /* Organization */
 #include "case_prio.h"     /* Priority */
 #include "case_subj.h"     /* Subject */
 #include "case_user.h"     /* User-Agent */
fbac8f84
 #include "case_serv.h"     /* Server */
2f43c732
 #include "case_supp.h"     /* Supported */
dccbcda9
 #include "case_dive.h"     /* Diversion */
 #include "case_remo.h"     /* Remote-Party-ID */
8b482f1a
 #include "case_refe.h"     /* Refer-To */
67386619
 #include "case_sess.h"     /* Session-Expires */
 #include "case_reje.h"     /* Reject-Contact */
8a4f3a74
 #include "case_min.h"      /* Min-SE */
48862405
 #include "case_subs.h"     /* Subscription-State */
e696bf82
 #include "case_requ.h"     /* Require */
3ed13e77
 #include "case_www.h"      /* WWW-Authenticate */
e7317b87
 #include "case_date.h"     /* Date */
 #include "case_iden.h"     /* Identity, Identity-info */
b861de9c
 #include "case_retr.h"     /* Retry-After */
097613bf
 
3881f12c
 
 #define READ(val) \
 (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16) + (*(val + 3) << 24))
 
3ed13e77
 #define READ3(val) \
 (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16))
e3c29827
 
 #define FIRST_QUATERNIONS       \
32822438
         case _via1_: via1_CASE; \
 	case _from_: from_CASE; \
 	case _to12_: to12_CASE; \
 	case _cseq_: cseq_CASE; \
 	case _call_: call_CASE; \
 	case _cont_: cont_CASE; \
 	case _rout_: rout_CASE; \
 	case _max__: max_CASE;  \
 	case _reco_: reco_CASE; \
 	case _via2_: via2_CASE; \
 	case _auth_: auth_CASE; \
2f43c732
 	case _supp_: supp_CASE; \
32822438
 	case _expi_: expi_CASE; \
 	case _prox_: prox_CASE; \
 	case _allo_: allo_CASE; \
 	case _unsu_: unsu_CASE; \
71be0c4a
         case _even_: even_CASE; \
67386619
         case _sip_ : sip_CASE;  \
2f43c732
         case _acce_: acce_CASE; \
         case _orga_: orga_CASE; \
         case _prio_: prio_CASE; \
         case _subj_: subj_CASE; \
48862405
         case _subs_: subs_CASE; \
dccbcda9
         case _user_: user_CASE; \
fbac8f84
         case _serv_: serv_CASE; \
dccbcda9
         case _dive_: dive_CASE; \
8b482f1a
         case _remo_: remo_CASE; \
67386619
         case _refe_: refe_CASE; \
 	case _sess_: sess_CASE; \
 	case _reje_: reje_CASE; \
8a4f3a74
 	case _min__: min_CASE;  \
e696bf82
 	case _requ_: requ_CASE;  \
3ed13e77
 	case _www__: www_CASE; \
e7317b87
 	case _date_: date_CASE; \
 	case _iden_: iden_CASE; \
b861de9c
 	case _retr_: retr_CASE; \
67386619
 
e3c29827
 
 
 #define PARSE_COMPACT(id)          \
         switch(*(p + 1)) {         \
         case ' ':                  \
 	        hdr->type = id;    \
 	        p += 2;            \
 	        goto dc_end;       \
 	                           \
         case ':':                  \
 	        hdr->type = id;    \
 	        hdr->name.len = 1; \
 	        return (p + 2);    \
67386619
         }
e3c29827
 
 
3881f12c
 char* parse_hname2(char* begin, char* end, struct hdr_field* hdr)
 {
 	register char* p;
32822438
 	register unsigned int val;
3881f12c
 
 	if ((end - begin) < 4) {
5c28a534
 		hdr->type = HDR_ERROR_T;
3881f12c
 		return begin;
 	}
 
d615a5cd
 	p = begin;
 
32822438
 	val = LOWER_DWORD(READ(p));
 	hdr->name.s = begin;
d615a5cd
 
3881f12c
 	switch(val) {
e3c29827
 	FIRST_QUATERNIONS;
3881f12c
 
 	default:
32822438
 		switch(LOWER_BYTE(*p)) {
67386619
 		case 't':
 			switch(LOWER_BYTE(*(p + 1))) {
 			case 'o':
 			case ' ':
 				hdr->type = HDR_TO_T;
 				p += 2;
 				goto dc_end;
 
 			case ':':
 				hdr->type = HDR_TO_T;
 				hdr->name.len = 1;
 				return (p + 2);
 			}
3881f12c
 			break;
 
5c28a534
 		case 'v': PARSE_COMPACT(HDR_VIA_T);           break;
 		case 'f': PARSE_COMPACT(HDR_FROM_T);          break;
 		case 'i': PARSE_COMPACT(HDR_CALLID_T);        break;
 		case 'm': PARSE_COMPACT(HDR_CONTACT_T);       break;
 		case 'l': PARSE_COMPACT(HDR_CONTENTLENGTH_T); break;
 		case 'k': PARSE_COMPACT(HDR_SUPPORTED_T);     break;
 		case 'c': PARSE_COMPACT(HDR_CONTENTTYPE_T);   break;
 		case 'o': PARSE_COMPACT(HDR_EVENT_T);         break;
67386619
 		case 'x': PARSE_COMPACT(HDR_SESSIONEXPIRES_T);break;
 		case 'a': PARSE_COMPACT(HDR_ACCEPTCONTACT_T); break;
 		case 'u': PARSE_COMPACT(HDR_ALLOWEVENTS_T);   break;
 		case 'e': PARSE_COMPACT(HDR_CONTENTENCODING_T); break;
 		case 'b': PARSE_COMPACT(HDR_REFERREDBY_T);    break;
 		case 'j': PARSE_COMPACT(HDR_REJECTCONTACT_T); break;
 		case 'd': PARSE_COMPACT(HDR_REQUESTDISPOSITION_T); break;
 		case 's': PARSE_COMPACT(HDR_SUBJECT_T);       break;
 		case 'r': PARSE_COMPACT(HDR_REFER_TO_T);      break;
e7317b87
 		case 'y': PARSE_COMPACT(HDR_IDENTITY_T);      break;
 		case 'n': PARSE_COMPACT(HDR_IDENTITY_INFO_T); break;
3881f12c
 		}
32822438
 		goto other;
3881f12c
         }
 
 	     /* Double colon hasn't been found yet */
  dc_end:
        	p = skip_ws(p, end - p);
67386619
 	if (*p != ':') {
3881f12c
 	        goto other;
 	} else {
 		hdr->name.len = p - hdr->name.s;
 		return (p + 1);
 	}
 
 	     /* Unknown header type */
67386619
  other:
3881f12c
 	p = q_memchr(p, ':', end - p);
 	if (!p) {        /* No double colon found, error.. */
5c28a534
 		hdr->type = HDR_ERROR_T;
e3c29827
 		hdr->name.s = 0;
3881f12c
 		hdr->name.len = 0;
e3c29827
 		return 0;
3881f12c
 	} else {
5c28a534
 		hdr->type = HDR_OTHER_T;
3881f12c
 		hdr->name.len = p - hdr->name.s;
 		return (p + 1);
 	}
 }