OSDN Git Service

Add MS7619SE
[uclinux-h8/uClinux-dist.git] / user / ser / parser / parse_hname2.c
1 /* 
2  * $Id: parse_hname2.c,v 1.19 2004/12/03 17:11:36 jamey Exp $ 
3  *
4  * Fast 32-bit Header Field Name Parser
5  *
6  * Copyright (C) 2001-2003 FhG Fokus
7  *
8  * This file is part of ser, a free SIP server.
9  *
10  * ser is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version
14  *
15  * For a license to use the ser software under conditions
16  * other than those described here, or to purchase support for this
17  * software, please contact iptel.org by e-mail at the following addresses:
18  *    info@iptel.org
19  *
20  * ser is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License 
26  * along with this program; if not, write to the Free Software 
27  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28  *
29  * History:
30  * --------
31  * 2003-02-28 scratchpad compatibility abandoned (jiri)
32  * 2003-01-27 next baby-step to removing ZT - PRESERVE_ZT (jiri)
33  * 2003-05-01 added support for Accept HF (janakj)
34  */
35
36
37 #include "../comp_defs.h"
38 #include "parse_hname2.h"
39 #include "keys.h"
40 #include "../ut.h"  /* q_memchr */
41
42 #define LOWER_BYTE(b) ((b) | 0x20)
43 #define LOWER_DWORD(d) ((d) | 0x20202020)
44
45 /*
46  * Skip all white-chars and return position of the first
47  * non-white char
48  */
49 static inline char* skip_ws(char* p, unsigned int size)
50 {
51         char* end;
52         
53         end = p + size;
54         for(; p < end; p++) {
55                 if ((*p != ' ') && (*p != '\t')) return p;
56         }
57         return p;
58 }
59         
60 /*
61  * Parser macros
62  */
63 #include "case_via.h"      /* Via */
64 #include "case_from.h"     /* From */
65 #include "case_to.h"       /* To */
66 #include "case_cseq.h"     /* CSeq */
67 #include "case_call.h"     /* Call-ID */
68 #include "case_cont.h"     /* Contact, Content-Type, Content-Length, Content-Purpose, 
69                             * Content-Action, Content-Disposition */
70 #include "case_rout.h"     /* Route */
71 #include "case_max.h"      /* Max-Forwards */
72 #include "case_reco.h"     /* Record-Route */
73 #include "case_auth.h"     /* Authorization */
74 #include "case_expi.h"     /* Expires */
75 #include "case_prox.h"     /* Proxy-Authorization, Proxy-Require */
76 #include "case_allo.h"     /* Allow */
77 #include "case_unsu.h"     /* Unsupported */
78 #include "case_even.h"     /* Event */
79 #include "case_acce.h"     /* Accept, Accept-Language */
80 #include "case_orga.h"     /* Organization */
81 #include "case_prio.h"     /* Priority */
82 #include "case_subj.h"     /* Subject */
83 #include "case_user.h"     /* User-Agent */
84 #include "case_supp.h"     /* Supported */
85 #include "case_dive.h"     /* Diversion */
86 #include "case_remo.h"     /* Remote-Party-ID */
87
88
89 #define READ(val) \
90 (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16) + (*(val + 3) << 24))
91
92
93 #define FIRST_QUATERNIONS       \
94         case _via1_: via1_CASE; \
95         case _from_: from_CASE; \
96         case _to12_: to12_CASE; \
97         case _cseq_: cseq_CASE; \
98         case _call_: call_CASE; \
99         case _cont_: cont_CASE; \
100         case _rout_: rout_CASE; \
101         case _max__: max_CASE;  \
102         case _reco_: reco_CASE; \
103         case _via2_: via2_CASE; \
104         case _auth_: auth_CASE; \
105         case _supp_: supp_CASE; \
106         case _expi_: expi_CASE; \
107         case _prox_: prox_CASE; \
108         case _allo_: allo_CASE; \
109         case _unsu_: unsu_CASE; \
110         case _even_: even_CASE; \
111         case _acce_: acce_CASE; \
112         case _orga_: orga_CASE; \
113         case _prio_: prio_CASE; \
114         case _subj_: subj_CASE; \
115         case _user_: user_CASE; \
116         case _dive_: dive_CASE; \
117         case _remo_: remo_CASE;
118
119
120 #define PARSE_COMPACT(id)          \
121         switch(*(p + 1)) {         \
122         case ' ':                  \
123                 hdr->type = id;    \
124                 p += 2;            \
125                 goto dc_end;       \
126                                    \
127         case ':':                  \
128                 hdr->type = id;    \
129                 hdr->name.len = 1; \
130                 return (p + 2);    \
131         }                            
132
133
134 char* parse_hname2(char* begin, char* end, struct hdr_field* hdr)
135 {
136         register char* p;
137         register unsigned int val;
138
139         if ((end - begin) < 4) {
140                 hdr->type = HDR_ERROR;
141                 return begin;
142         }
143
144         p = begin;
145
146         val = LOWER_DWORD(READ(p));
147         hdr->name.s = begin;
148
149         switch(val) {
150         FIRST_QUATERNIONS;
151
152         default:
153                 switch(LOWER_BYTE(*p)) {
154                 case 't':                           
155                         switch(LOWER_BYTE(*(p + 1))) {          
156                         case 'o':                   
157                         case ' ':                   
158                                 hdr->type = HDR_TO; 
159                                 p += 2;             
160                                 goto dc_end;        
161                                 
162                         case ':':                   
163                                 hdr->type = HDR_TO; 
164                                 hdr->name.len = 1;  
165                                 return (p + 2);     
166                         }                           
167                         break;
168
169                 case 'v': PARSE_COMPACT(HDR_VIA);           break;
170                 case 'f': PARSE_COMPACT(HDR_FROM);          break;
171                 case 'i': PARSE_COMPACT(HDR_CALLID);        break;
172                 case 'm': PARSE_COMPACT(HDR_CONTACT);       break;
173                 case 'l': PARSE_COMPACT(HDR_CONTENTLENGTH); break;
174                 case 'k': PARSE_COMPACT(HDR_SUPPORTED);     break;
175                 case 'c': PARSE_COMPACT(HDR_CONTENTTYPE);   break;
176                 case 'o': PARSE_COMPACT(HDR_EVENT);         break;
177                 }
178                 goto other;
179         }
180
181              /* Double colon hasn't been found yet */
182  dc_end:
183         p = skip_ws(p, end - p);
184         if (*p != ':') {   
185                 goto other;
186         } else {
187                 hdr->name.len = p - hdr->name.s;
188                 return (p + 1);
189         }
190
191              /* Unknown header type */
192  other:    
193         p = q_memchr(p, ':', end - p);
194         if (!p) {        /* No double colon found, error.. */
195                 hdr->type = HDR_ERROR;
196                 hdr->name.s = 0;
197                 hdr->name.len = 0;
198                 return 0;
199         } else {
200                 hdr->type = HDR_OTHER;
201                 hdr->name.len = p - hdr->name.s;
202                 return (p + 1);
203         }
204 }