Merge branch kamailio/trunk/db_flatstore into sip-router/janakj/db_flatstore.
[sip-router] / receive.c
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-02-28 scratchpad compatibility abandoned (jiri)
30  * 2003-01-29 transport-independent message zero-termination in
31  *            receive_msg (jiri)
32  * 2003-02-07 undoed jiri's zero term. changes (they break tcp) (andrei)
33  * 2003-02-10 moved zero-term in the calling functions (udp_receive &
34  *            tcp_read_req)
35  * 2003-08-13 fixed exec_pre_cb returning 0 (backported from stable) (andrei)
36  * 2004-02-06 added user preferences support - destroy_avps() (bogdan)
37  * 2004-04-30 exec_pre_cb is called after basic sanity checks (at least one
38  *            via present & parsed ok)  (andrei)
39  * 2004-08-23 avp core changed - destroy_avp-> reset_avps (bogdan)
40  * 2006-11-29 nonsip_msg hooks called for non-sip msg (e.g HTTP) (andrei)
41  */
42
43
44 #include <string.h>
45 #include <stdlib.h>
46 #include <sys/time.h>
47
48 #include "receive.h"
49 #include "globals.h"
50 #include "dprint.h"
51 #include "route.h"
52 #include "parser/msg_parser.h"
53 #include "forward.h"
54 #include "action.h"
55 #include "mem/mem.h"
56 #include "stats.h"
57 #include "ip_addr.h"
58 #include "script_cb.h"
59 #include "nonsip_hooks.h"
60 #include "dset.h"
61 #include "usr_avp.h"
62 #include "select_buf.h"
63
64 #include "tcp_server.h" /* for tcpconn_add_alias */
65
66
67 #ifdef DEBUG_DMALLOC
68 #include <mem/dmalloc.h>
69 #endif
70
71 unsigned int msg_no=0;
72 /* address preset vars */
73 str default_global_address={0,0};
74 str default_global_port={0,0};
75 str default_via_address={0,0};
76 str default_via_port={0,0};
77
78
79
80 /* WARNING: buf must be 0 terminated (buf[len]=0) or some things might 
81  * break (e.g.: modules/textops)
82  */
83 int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info) 
84 {
85         struct sip_msg* msg;
86         int ret;
87         struct run_act_ctx ra_ctx;
88 #ifdef STATS
89         int skipped = 1;
90         struct timeval tvb, tve;        
91         struct timezone tz;
92         unsigned int diff;
93 #endif
94
95         msg=pkg_malloc(sizeof(struct sip_msg));
96         if (msg==0) {
97                 LOG(L_ERR, "ERROR: receive_msg: no mem for sip_msg\n");
98                 goto error00;
99         }
100         msg_no++;
101         /* number of vias parsed -- good for diagnostic info in replies */
102         via_cnt=0;
103
104         memset(msg,0, sizeof(struct sip_msg)); /* init everything to 0 */
105         /* fill in msg */
106         msg->buf=buf;
107         msg->len=len;
108         /* zero termination (termination of orig message bellow not that
109            useful as most of the work is done with scratch-pad; -jiri  */
110         /* buf[len]=0; */ /* WARNING: zero term removed! */
111         msg->rcv=*rcv_info;
112         msg->id=msg_no;
113         msg->set_global_address=default_global_address;
114         msg->set_global_port=default_global_port;
115         
116         if (parse_msg(buf,len, msg)!=0){
117                 LOG(L_ERR, "ERROR: receive_msg: parse_msg failed\n");
118                 goto error02;
119         }
120         DBG("After parse_msg...\n");
121
122
123         /* ... clear branches from previous message */
124         clear_branches();
125         reset_static_buffer();
126
127         if (msg->first_line.type==SIP_REQUEST){
128                 if (!IS_SIP(msg)){
129                         if (nonsip_msg_run_hooks(msg)!=NONSIP_MSG_ACCEPT);
130                                 goto end; /* drop the message */
131                 }
132                 /* sanity checks */
133                 if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
134                         /* no via, send back error ? */
135                         LOG(L_ERR, "ERROR: receive_msg: no via found in request\n");
136                         goto error02;
137                 }
138                 /* check if necessary to add receive?->moved to forward_req */
139                 /* check for the alias stuff */
140 #ifdef USE_TCP
141                 if (msg->via1->alias && tcp_accept_aliases && 
142                                 (((rcv_info->proto==PROTO_TCP) && !tcp_disable)
143 #ifdef USE_TLS
144                                         || ((rcv_info->proto==PROTO_TLS) && !tls_disable)
145 #endif
146                                 )
147                         ){
148                         if (tcpconn_add_alias(rcv_info->proto_reserved1, msg->via1->port,
149                                                                         rcv_info->proto)!=0){
150                                 LOG(L_ERR, " ERROR: receive_msg: tcp alias failed\n");
151                                 /* continue */
152                         }
153                 }
154 #endif
155                         
156         /*      skip: */
157                 DBG("preparing to run routing scripts...\n");
158 #ifdef  STATS
159                 gettimeofday( & tvb, &tz );
160 #endif
161                 /* execute pre-script callbacks, if any; -jiri */
162                 /* if some of the callbacks said not to continue with
163                    script processing, don't do so
164                    if we are here basic sanity checks are already done
165                    (like presence of at least one via), so you can count
166                    on via1 being parsed in a pre-script callback --andrei
167                 */
168                 if (exec_pre_req_cb(msg)==0 )
169                         goto end; /* drop the request */
170
171                 /* exec the routing script */
172                 init_run_actions_ctx(&ra_ctx);
173                 if (run_actions(&ra_ctx, main_rt.rlist[DEFAULT_RT], msg)<0){
174                         LOG(L_WARN, "WARNING: receive_msg: "
175                                         "error while trying script\n");
176                         goto error_req;
177                 }
178
179 #ifdef STATS
180                 gettimeofday( & tve, &tz );
181                 diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
182                 stats->processed_requests++;
183                 stats->acc_req_time += diff;
184                 DBG("successfully ran routing scripts...(%d usec)\n", diff);
185                 STATS_RX_REQUEST( msg->first_line.u.request.method_value );
186 #endif
187
188                 /* execute post request-script callbacks */
189                 exec_post_req_cb(msg);
190         }else if (msg->first_line.type==SIP_REPLY){
191                 /* sanity checks */
192                 if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
193                         /* no via, send back error ? */
194                         LOG(L_ERR, "ERROR: receive_msg: no via found in reply\n");
195                         goto error02;
196                 }
197
198 #ifdef STATS
199                 gettimeofday( & tvb, &tz );
200                 STATS_RX_RESPONSE ( msg->first_line.u.reply.statuscode / 100 );
201 #endif
202                 
203                 /* execute pre-script callbacks, if any; -jiri */
204                 /* if some of the callbacks said not to continue with
205                    script processing, don't do so
206                    if we are here basic sanity checks are already done
207                    (like presence of at least one via), so you can count
208                    on via1 being parsed in a pre-script callback --andrei
209                 */
210                 if (exec_pre_rpl_cb(msg)==0 )
211                         goto end; /* drop the request */
212                 /* exec the onreply routing script */
213                 if (onreply_rt.rlist[DEFAULT_RT]){
214                         init_run_actions_ctx(&ra_ctx);
215                         ret=run_actions(&ra_ctx, onreply_rt.rlist[DEFAULT_RT], msg);
216                         if (ret<0){
217                                 LOG(L_WARN, "WARNING: receive_msg: "
218                                                 "error while trying onreply script\n");
219                                 goto error_rpl;
220                         }else if (ret==0) goto skip_send_reply; /* drop the message, 
221                                                                                                            no error */
222                 }
223                 /* send the msg */
224                 forward_reply(msg);
225         skip_send_reply:
226 #ifdef STATS
227                 gettimeofday( & tve, &tz );
228                 diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
229                 stats->processed_responses++;
230                 stats->acc_res_time+=diff;
231                 DBG("successfully ran reply processing...(%d usec)\n", diff);
232 #endif
233
234                 /* execute post reply-script callbacks */
235                 exec_post_rpl_cb(msg);
236         }
237
238 end:
239 #ifdef STATS
240         skipped = 0;
241 #endif
242         /* free possible loaded avps -bogdan */
243         reset_avps();
244         DBG("receive_msg: cleaning up\n");
245         free_sip_msg(msg);
246         pkg_free(msg);
247 #ifdef STATS
248         if (skipped) STATS_RX_DROPS;
249 #endif
250         return 0;
251 error_rpl:
252         /* execute post reply-script callbacks */
253         exec_post_rpl_cb(msg);
254         reset_avps();
255         goto error02;
256 error_req:
257         DBG("receive_msg: error:...\n");
258         /* execute post request-script callbacks */
259         exec_post_req_cb(msg);
260         /* free possible loaded avps -bogdan */
261         reset_avps();
262 error02:
263         free_sip_msg(msg);
264         pkg_free(msg);
265 error00:
266         STATS_RX_DROPS;
267         return -1;
268 }
269