- added special callbacks for non-sip msg (e.g http), They are called every
[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 #define IS_SIP(req)                                                \
105     ((req)->first_line.u.request.version.len >= SIP_VERSION_LEN && \
106     !strncasecmp((req)->first_line.u.request.version.s,             \
107                 SIP_VERSION, SIP_VERSION_LEN))
108
109 /*
110  * Return a URI to which the message should be really sent (not what should
111  * be in the Request URI. The following fields are tried in this order:
112  * 1) dst_uri
113  * 2) new_uri
114  * 3) first_line.u.request.uri
115  */
116 #define GET_NEXT_HOP(m) \
117 (((m)->dst_uri.s && (m)->dst_uri.len) ? (&(m)->dst_uri) : \
118 (((m)->new_uri.s && (m)->new_uri.len) ? (&(m)->new_uri) : (&(m)->first_line.u.request.uri)))
119
120
121 /*
122  * Return the Reqeust URI of a message.
123  * The following fields are tried in this order:
124  * 1) new_uri
125  * 2) first_line.u.request.uri
126  */
127 #define GET_RURI(m) \
128 (((m)->new_uri.s && (m)->new_uri.len) ? (&(m)->new_uri) : (&(m)->first_line.u.request.uri))
129
130
131 #if 0
132         /* old version */
133 struct sip_uri {
134         str user;     /* Username */
135         str passwd;   /* Password */
136         str host;     /* Host name */
137         str port;     /* Port number */
138         str params;   /* Parameters */
139         str headers;
140         unsigned short port_no;
141 };
142 #endif
143
144 enum _uri_type{ERROR_URI_T=0, SIP_URI_T, SIPS_URI_T, TEL_URI_T, TELS_URI_T};
145 typedef enum _uri_type uri_type;
146
147 struct sip_uri {
148         str user;     /* Username */
149         str passwd;   /* Password */
150         str host;     /* Host name */
151         str port;     /* Port number */
152         str params;   /* Parameters */
153         str headers;
154         unsigned short port_no;
155         unsigned short proto; /* from transport */
156         uri_type type; /* uri scheme */
157 #ifdef USE_COMP
158         unsigned short comp;
159 #endif
160         /* parameters */
161         str transport;
162         str ttl;
163         str user_param;
164         str maddr;
165         str method;
166         str lr;
167         str r2; /* ser specific rr parameter */
168         /* values */
169         str transport_val;
170         str ttl_val;
171         str user_param_val;
172         str maddr_val;
173         str method_val;
174         str lr_val; /* lr value placeholder for lr=on a.s.o*/
175         str r2_val;
176 };
177
178
179 struct sip_msg {
180         unsigned int id;               /* message id, unique/process*/
181         struct msg_start first_line;   /* Message first line */
182         struct via_body* via1;         /* The first via */
183         struct via_body* via2;         /* The second via */
184         struct hdr_field* headers;     /* All the parsed headers*/
185         struct hdr_field* last_header; /* Pointer to the last parsed header*/
186         hdr_flags_t parsed_flag;    /* Already parsed header field types */
187
188              /* Via, To, CSeq, Call-Id, From, end of header*/
189              /* pointers to the first occurrences of these headers;
190                   * everything is also saved in 'headers'
191                   * (WARNING: do not deallocate them twice!)*/
192
193         struct hdr_field* h_via1;
194         struct hdr_field* h_via2;
195         struct hdr_field* callid;
196         struct hdr_field* to;
197         struct hdr_field* cseq;
198         struct hdr_field* from;
199         struct hdr_field* contact;
200         struct hdr_field* maxforwards;
201         struct hdr_field* route;
202         struct hdr_field* record_route;
203         struct hdr_field* content_type;
204         struct hdr_field* content_length;
205         struct hdr_field* authorization;
206         struct hdr_field* expires;
207         struct hdr_field* proxy_auth;
208         struct hdr_field* supported;
209         struct hdr_field* require;
210         struct hdr_field* proxy_require;
211         struct hdr_field* unsupported;
212         struct hdr_field* allow;
213         struct hdr_field* event;
214         struct hdr_field* accept;
215         struct hdr_field* accept_language;
216         struct hdr_field* organization;
217         struct hdr_field* priority;
218         struct hdr_field* subject;
219         struct hdr_field* user_agent;
220         struct hdr_field* content_disposition;
221         struct hdr_field* accept_disposition;
222         struct hdr_field* diversion;
223         struct hdr_field* rpid;
224         struct hdr_field* refer_to;
225         struct hdr_field* session_expires;
226         struct hdr_field* min_se;
227         struct hdr_field* sipifmatch;
228         struct hdr_field* subscription_state;
229
230         char* eoh;        /* pointer to the end of header (if found) or null */
231         char* unparsed;   /* here we stopped parsing*/
232
233         struct receive_info rcv; /* source & dest ip, ports, proto a.s.o*/
234
235         char* buf;        /* scratch pad, holds a modified message,
236                                            *  via, etc. point into it */
237         unsigned int len; /* message len (orig) */
238
239              /* modifications */
240
241         str new_uri; /* changed first line uri, when you change this
242                         don't forget to set parsed_uri_ok to 0*/
243
244         str dst_uri; /* Destination URI, must be forwarded to this URI if len != 0 */
245
246         /* current uri */
247         int parsed_uri_ok; /* 1 if parsed_uri is valid, 0 if not, set if to 0
248                               if you modify the uri (e.g change new_uri)*/
249         struct sip_uri parsed_uri; /* speed-up > keep here the parsed uri*/
250         /* the same for original uri */
251         int parsed_orig_ruri_ok;
252         struct sip_uri parsed_orig_ruri;
253
254         struct lump* add_rm;       /* used for all the forwarded requests/replies */
255         struct lump* body_lumps;     /* Lumps that update Content-Length */
256         struct lump_rpl *reply_lump; /* only for localy generated replies !!!*/
257
258         /* str add_to_branch;
259            whatever whoever want to append to branch comes here
260         */
261         char add_to_branch_s[MAX_BRANCH_PARAM_LEN];
262         int add_to_branch_len;
263
264              /* index to TM hash table; stored in core to avoid unnecessary calculations */
265         unsigned int  hash_index;
266         unsigned int msg_flags; /* flags used by core */
267              /* allows to set various flags on the message; may be used for
268               * simple inter-module communication or remembering processing state
269               * reached
270               */
271         flag_t flags;
272         str set_global_address;
273         str set_global_port;
274         struct socket_info* force_send_socket; /* force sending on this socket,
275                                                                                           if ser */
276 };
277
278 /* pointer to a fakes message which was never received ;
279    (when this message is "relayed", it is generated out
280     of the original request)
281 */
282 #define FAKED_REPLY     ((struct sip_msg *) -1)
283
284 extern int via_cnt;
285
286 int parse_msg(char* buf, unsigned int len, struct sip_msg* msg);
287
288 int parse_headers(struct sip_msg* msg, hdr_flags_t flags, int next);
289
290 char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr);
291
292 void free_sip_msg(struct sip_msg* msg);
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
298
299 /* make sure all HFs needed for transaction identification have been
300    parsed; return 0 if those HFs can't be found
301 */
302 inline static int check_transaction_quadruple( struct sip_msg* msg )
303 {
304         if ( parse_headers(msg, HDR_FROM_F|HDR_TO_F|HDR_CALLID_F|HDR_CSEQ_F,0)!=-1
305                 && msg->from && msg->to && msg->callid && msg->cseq ) {
306                 return 1;
307         } else {
308                 ser_error=E_BAD_TUPEL;
309                 return 0;
310         }
311 }
312
313
314
315 /* calculate characteristic value of a message -- this value
316    is used to identify a transaction during the process of
317    reply matching
318  */
319 inline static int char_msg_val( struct sip_msg *msg, char *cv )
320 {
321         str src[8];
322
323         if (!check_transaction_quadruple(msg)) {
324                 LOG(L_ERR, "ERROR: can't calculate char_value due "
325                         "to a parsing error\n");
326                 memset( cv, '0', MD5_LEN );
327                 return 0;
328         }
329
330         src[0]= msg->from->body;
331         src[1]= msg->to->body;
332         src[2]= msg->callid->body;
333         src[3]= msg->first_line.u.request.uri;
334         src[4]= get_cseq( msg )->number;
335
336         /* topmost Via is part of transaction key as well ! */
337         src[5]= msg->via1->host;
338         src[6]= msg->via1->port_str;
339         if (msg->via1->branch) {
340                 src[7]= msg->via1->branch->value;
341                 MDStringArray ( cv, src, 8 );
342         } else {
343                 MDStringArray( cv, src, 7 );
344         }
345         return 1;
346 }
347
348
349 /* returns a pointer to the begining of the msg's body
350  */
351 inline static char* get_body(struct sip_msg *msg)
352 {
353         int offset;
354         unsigned int len;
355
356         if ( parse_headers(msg, HDR_EOH_F, 0)==-1 )
357                 return 0;
358
359         if (msg->unparsed){
360                 len=(unsigned int)(msg->unparsed-msg->buf);
361         }else return 0;
362         if ((len+2<=msg->len) && (strncmp(CRLF,msg->unparsed,CRLF_LEN)==0) )
363                 offset = CRLF_LEN;
364         else if ( (len+1<=msg->len) &&
365                                 (*(msg->unparsed)=='\n' || *(msg->unparsed)=='\r' ) )
366                 offset = 1;
367         else
368                 return 0;
369
370         return msg->unparsed + offset;
371 }
372
373
374 /*
375  * Make a private copy of the string and assign it to dst_uri
376  */
377 int set_dst_uri(struct sip_msg* msg, str* uri);
378
379
380 #endif