b74a1578162080f2a61b4555acc4a21fc92bb58d
[sip-router] / parser / msg_parser.h
1 /*
2  * $Id$
3  *
4  * Copyright (C) 2001-2003 FhG Fokus
5  *
6  * This file is part of ser, a free SIP server.
7  *
8  * ser is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version
12  *
13  * For a license to use the ser software under conditions
14  * other than those described here, or to purchase support for this
15  * software, please contact iptel.org by e-mail at the following addresses:
16  *    info@iptel.org
17  *
18  * ser is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  *
27  * History
28  * -------
29  *  2003-01-28  removed scratchpad (jiri)
30  *  2003-02-28  scratchpad compatibility abandoned (jiri)
31  *  2003-03-06  enum_request_method changed to begin with 1;
32  *               0 reserved for invalid values; (jiri)
33  *  2003-03-31  removed sip_msg->repl_add_rm (andrei)
34  *  2003-04-01  2 macros added: GET_NEXT_HOP and GET_RURI (janakj)
35  *  2003-04-04  structure for parsed inbound uri added (jiri)
36  *  2003-04-11  updated the  sip_uri structure (lots of fields added) (andrei)
37  *  2003-04-12  added msg_flags to sip_msg (andrei)
38  *  2003-11-02  added diversion header field to sip_msg (jh)
39  *  2004-11-08  added force_send_socket (andrei)
40  *  2005-02-25  uri types added (sip, sips & tel)  (andrei)
41  *  2006-04-20  uri comp member (only if USE_COMP is defined) (andrei)
42  *  2006-11-10  check_transaction_quadruple inlined (andrei)
43  */
44
45
46 #ifndef msg_parser_h
47 #define msg_parser_h
48
49
50 #include "../comp_defs.h"
51 #include "../str.h"
52 #include "../lump_struct.h"
53 #include "../flags.h"
54 #include "../ip_addr.h"
55 #include "../md5utils.h"
56 #include "../config.h"
57 #include "parse_def.h"
58 #include "parse_cseq.h"
59 #include "parse_to.h"
60 #include "parse_via.h"
61 #include "parse_fline.h"
62 #include "hf.h"
63 #include "../error.h"
64
65
66 /* convenience short-cut macros */
67 #define REQ_LINE(_msg) ((_msg)->first_line.u.request)
68 #define REQ_METHOD first_line.u.request.method_value
69 #define REPLY_STATUS first_line.u.reply.statuscode
70 #define REPLY_CLASS(_reply) ((_reply)->REPLY_STATUS/100)
71
72 /* number methods as power of two to allow bitmap matching */
73 enum request_method { METHOD_UNDEF=0, METHOD_INVITE=1, METHOD_CANCEL=2, METHOD_ACK=4,
74         METHOD_BYE=8, METHOD_INFO=16, METHOD_REGISTER=32, METHOD_SUBSCRIBE=64,
75         METHOD_NOTIFY=128, METHOD_OTHER=256 };
76
77 #define FL_FORCE_RPORT 1   /* force rport */
78 #define FL_FORCE_ACTIVE 2  /* force active SDP */
79 #define FL_SDP_IP_AFS 4    /* SDP IP rewritten */
80 #define FL_SDP_PORT_AFS 8  /* SDP port rewritten */
81 #define FL_SHM_CLONE   16  /* msg cloned in SHM as a single chunk */
82 #define FL_TIMEOUT     32  /* message belongs to an "expired" branch
83                                (for failure route use) */
84 #define FL_REPLIED     64  /* message branch received at least one reply
85                                 (for failure route use) */
86 #define FL_HASH_INDEX  128 /* msg->hash_index contains a valid value (tm use)*/
87
88
89 #define IFISMETHOD(methodname,firstchar)                                  \
90 if (  (*tmp==(firstchar) || *tmp==((firstchar) | 32)) &&                  \
91         strncasecmp( tmp+1, #methodname +1, methodname##_LEN-1)==0 &&     \
92         *(tmp+methodname##_LEN)==' ') {                                   \
93                 fl->type=SIP_REQUEST;                                     \
94                 fl->u.request.method.len=methodname##_LEN;                \
95                 fl->u.request.method_value=METHOD_##methodname;           \
96                 tmp=buffer+methodname##_LEN;                              \
97 }
98
99 #define IS_HTTP(req)                                                \
100     ((req)->first_line.u.request.version.len >= HTTP_VERSION_LEN && \
101     !strncasecmp((req)->first_line.u.request.version.s,             \
102                 HTTP_VERSION, HTTP_VERSION_LEN))
103
104 /*
105  * Return a URI to which the message should be really sent (not what should
106  * be in the Request URI. The following fields are tried in this order:
107  * 1) dst_uri
108  * 2) new_uri
109  * 3) first_line.u.request.uri
110  */
111 #define GET_NEXT_HOP(m) \
112 (((m)->dst_uri.s && (m)->dst_uri.len) ? (&(m)->dst_uri) : \
113 (((m)->new_uri.s && (m)->new_uri.len) ? (&(m)->new_uri) : (&(m)->first_line.u.request.uri)))
114
115
116 /*
117  * Return the Reqeust URI of a message.
118  * The following fields are tried in this order:
119  * 1) new_uri
120  * 2) first_line.u.request.uri
121  */
122 #define GET_RURI(m) \
123 (((m)->new_uri.s && (m)->new_uri.len) ? (&(m)->new_uri) : (&(m)->first_line.u.request.uri))
124
125
126 #if 0
127         /* old version */
128 struct sip_uri {
129         str user;     /* Username */
130         str passwd;   /* Password */
131         str host;     /* Host name */
132         str port;     /* Port number */
133         str params;   /* Parameters */
134         str headers;
135         unsigned short port_no;
136 };
137 #endif
138
139 enum _uri_type{ERROR_URI_T=0, SIP_URI_T, SIPS_URI_T, TEL_URI_T, TELS_URI_T};
140 typedef enum _uri_type uri_type;
141
142 struct sip_uri {
143         str user;     /* Username */
144         str passwd;   /* Password */
145         str host;     /* Host name */
146         str port;     /* Port number */
147         str params;   /* Parameters */
148         str headers;
149         unsigned short port_no;
150         unsigned short proto; /* from transport */
151         uri_type type; /* uri scheme */
152 #ifdef USE_COMP
153         unsigned short comp;
154 #endif
155         /* parameters */
156         str transport;
157         str ttl;
158         str user_param;
159         str maddr;
160         str method;
161         str lr;
162         str r2; /* ser specific rr parameter */
163         /* values */
164         str transport_val;
165         str ttl_val;
166         str user_param_val;
167         str maddr_val;
168         str method_val;
169         str lr_val; /* lr value placeholder for lr=on a.s.o*/
170         str r2_val;
171 };
172
173
174 struct sip_msg {
175         unsigned int id;               /* message id, unique/process*/
176         struct msg_start first_line;   /* Message first line */
177         struct via_body* via1;         /* The first via */
178         struct via_body* via2;         /* The second via */
179         struct hdr_field* headers;     /* All the parsed headers*/
180         struct hdr_field* last_header; /* Pointer to the last parsed header*/
181         hdr_flags_t parsed_flag;    /* Already parsed header field types */
182
183              /* Via, To, CSeq, Call-Id, From, end of header*/
184              /* pointers to the first occurrences of these headers;
185                   * everything is also saved in 'headers'
186                   * (WARNING: do not deallocate them twice!)*/
187
188         struct hdr_field* h_via1;
189         struct hdr_field* h_via2;
190         struct hdr_field* callid;
191         struct hdr_field* to;
192         struct hdr_field* cseq;
193         struct hdr_field* from;
194         struct hdr_field* contact;
195         struct hdr_field* maxforwards;
196         struct hdr_field* route;
197         struct hdr_field* record_route;
198         struct hdr_field* content_type;
199         struct hdr_field* content_length;
200         struct hdr_field* authorization;
201         struct hdr_field* expires;
202         struct hdr_field* proxy_auth;
203         struct hdr_field* supported;
204         struct hdr_field* require;
205         struct hdr_field* proxy_require;
206         struct hdr_field* unsupported;
207         struct hdr_field* allow;
208         struct hdr_field* event;
209         struct hdr_field* accept;
210         struct hdr_field* accept_language;
211         struct hdr_field* organization;
212         struct hdr_field* priority;
213         struct hdr_field* subject;
214         struct hdr_field* user_agent;
215         struct hdr_field* content_disposition;
216         struct hdr_field* accept_disposition;
217         struct hdr_field* diversion;
218         struct hdr_field* rpid;
219         struct hdr_field* refer_to;
220         struct hdr_field* session_expires;
221         struct hdr_field* min_se;
222         struct hdr_field* sipifmatch;
223         struct hdr_field* subscription_state;
224
225         char* eoh;        /* pointer to the end of header (if found) or null */
226         char* unparsed;   /* here we stopped parsing*/
227
228         struct receive_info rcv; /* source & dest ip, ports, proto a.s.o*/
229
230         char* buf;        /* scratch pad, holds a modified message,
231                                            *  via, etc. point into it */
232         unsigned int len; /* message len (orig) */
233
234              /* modifications */
235
236         str new_uri; /* changed first line uri, when you change this
237                         don't forget to set parsed_uri_ok to 0*/
238
239         str dst_uri; /* Destination URI, must be forwarded to this URI if len != 0 */
240
241         /* current uri */
242         int parsed_uri_ok; /* 1 if parsed_uri is valid, 0 if not, set if to 0
243                               if you modify the uri (e.g change new_uri)*/
244         struct sip_uri parsed_uri; /* speed-up > keep here the parsed uri*/
245         /* the same for original uri */
246         int parsed_orig_ruri_ok;
247         struct sip_uri parsed_orig_ruri;
248
249         struct lump* add_rm;       /* used for all the forwarded requests/replies */
250         struct lump* body_lumps;     /* Lumps that update Content-Length */
251         struct lump_rpl *reply_lump; /* only for localy generated replies !!!*/
252
253         /* str add_to_branch;
254            whatever whoever want to append to branch comes here
255         */
256         char add_to_branch_s[MAX_BRANCH_PARAM_LEN];
257         int add_to_branch_len;
258
259              /* index to TM hash table; stored in core to avoid unnecessary calculations */
260         unsigned int  hash_index;
261         unsigned int msg_flags; /* flags used by core */
262              /* allows to set various flags on the message; may be used for
263               * simple inter-module communication or remembering processing state
264               * reached
265               */
266         flag_t flags;
267         str set_global_address;
268         str set_global_port;
269         struct socket_info* force_send_socket; /* force sending on this socket,
270                                                                                           if ser */
271 };
272
273 /* pointer to a fakes message which was never received ;
274    (when this message is "relayed", it is generated out
275     of the original request)
276 */
277 #define FAKED_REPLY     ((struct sip_msg *) -1)
278
279 extern int via_cnt;
280
281 int parse_msg(char* buf, unsigned int len, struct sip_msg* msg);
282
283 int parse_headers(struct sip_msg* msg, hdr_flags_t flags, int next);
284
285 char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr);
286
287 void free_sip_msg(struct sip_msg* msg);
288
289 /* make sure all HFs needed for transaction identification have been
290    parsed; return 0 if those HFs can't be found
291  */
292
293
294 /* make sure all HFs needed for transaction identification have been
295    parsed; return 0 if those HFs can't be found
296 */
297 inline static int check_transaction_quadruple( struct sip_msg* msg )
298 {
299         if ( parse_headers(msg, HDR_FROM_F|HDR_TO_F|HDR_CALLID_F|HDR_CSEQ_F,0)!=-1
300                 && msg->from && msg->to && msg->callid && msg->cseq ) {
301                 return 1;
302         } else {
303                 ser_error=E_BAD_TUPEL;
304                 return 0;
305         }
306 }
307
308
309
310 /* calculate characteristic value of a message -- this value
311    is used to identify a transaction during the process of
312    reply matching
313  */
314 inline static int char_msg_val( struct sip_msg *msg, char *cv )
315 {
316         str src[8];
317
318         if (!check_transaction_quadruple(msg)) {
319                 LOG(L_ERR, "ERROR: can't calculate char_value due "
320                         "to a parsing error\n");
321                 memset( cv, '0', MD5_LEN );
322                 return 0;
323         }
324
325         src[0]= msg->from->body;
326         src[1]= msg->to->body;
327         src[2]= msg->callid->body;
328         src[3]= msg->first_line.u.request.uri;
329         src[4]= get_cseq( msg )->number;
330
331         /* topmost Via is part of transaction key as well ! */
332         src[5]= msg->via1->host;
333         src[6]= msg->via1->port_str;
334         if (msg->via1->branch) {
335                 src[7]= msg->via1->branch->value;
336                 MDStringArray ( cv, src, 8 );
337         } else {
338                 MDStringArray( cv, src, 7 );
339         }
340         return 1;
341 }
342
343
344 /* returns a pointer to the begining of the msg's body
345  */
346 inline static char* get_body(struct sip_msg *msg)
347 {
348         int offset;
349         unsigned int len;
350
351         if ( parse_headers(msg, HDR_EOH_F, 0)==-1 )
352                 return 0;
353
354         if (msg->unparsed){
355                 len=(unsigned int)(msg->unparsed-msg->buf);
356         }else return 0;
357         if ((len+2<=msg->len) && (strncmp(CRLF,msg->unparsed,CRLF_LEN)==0) )
358                 offset = CRLF_LEN;
359         else if ( (len+1<=msg->len) &&
360                                 (*(msg->unparsed)=='\n' || *(msg->unparsed)=='\r' ) )
361                 offset = 1;
362         else
363                 return 0;
364
365         return msg->unparsed + offset;
366 }
367
368
369 /*
370  * Make a private copy of the string and assign it to dst_uri
371  */
372 int set_dst_uri(struct sip_msg* msg, str* uri);
373
374
375 #endif