core: earlier execution of SREV_NET_DATA_RECV event
[sip-router] / receive.c
1 /* 
2  * Copyright (C) 2001-2003 FhG Fokus
3  *
4  * This file is part of Kamailio, a free SIP server.
5  *
6  * Kamailio is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version
10  *
11  * Kamailio is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License 
17  * along with this program; if not, write to the Free Software 
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 /*!
23  * \file
24  * \brief Kamailio core :: 
25  * \ingroup core
26  * Module: \ref core
27  */
28
29
30 #include <string.h>
31 #include <stdlib.h>
32 #include <sys/time.h>
33
34 #include "receive.h"
35 #include "globals.h"
36 #include "dprint.h"
37 #include "route.h"
38 #include "parser/msg_parser.h"
39 #include "forward.h"
40 #include "action.h"
41 #include "mem/mem.h"
42 #include "stats.h"
43 #include "ip_addr.h"
44 #include "script_cb.h"
45 #include "nonsip_hooks.h"
46 #include "dset.h"
47 #include "usr_avp.h"
48 #ifdef WITH_XAVP
49 #include "xavp.h"
50 #endif
51 #include "select_buf.h"
52
53 #include "tcp_server.h" /* for tcpconn_add_alias */
54 #include "tcp_options.h" /* for access to tcp_accept_aliases*/
55 #include "cfg/cfg.h"
56 #include "core_stats.h"
57
58 #ifdef DEBUG_DMALLOC
59 #include <mem/dmalloc.h>
60 #endif
61
62 unsigned int msg_no=0;
63 /* address preset vars */
64 str default_global_address={0,0};
65 str default_global_port={0,0};
66 str default_via_address={0,0};
67 str default_via_port={0,0};
68
69 /**
70  * increment msg_no and return the new value
71  */
72 unsigned int inc_msg_no(void)
73 {
74         return ++msg_no;
75 }
76
77 /**
78  *
79  */
80 int sip_check_fline(char* buf, unsigned int len)
81 {
82         char *p;
83         int m;
84
85         m = 0;
86         for(p=buf; p<buf+len; p++) {
87                 /* first check if is a reply - starts with SIP/2.0 */
88                 if(m==0) {
89                         if(*p==' ' || *p=='\t' || *p=='\r' || *p=='\n') continue;
90                         if(buf+len-p<10) return -1;
91                         if(strncmp(p, "SIP/2.0 ", 8)==0) {
92                                 LM_DBG("first line indicates a SIP reply\n");
93                                 return 0;
94                         }
95                         m=1;
96                 } else {
97                         /* check if a request - before end of first line is SIP/2.0 */
98                         if(*p!='\r' && *p!='\n') continue;
99                         if(p-10>=buf) {
100                                 if(strncmp(p-8, " SIP/2.0", 8)==0) {
101                                         LM_DBG("first line indicates a SIP request\n");
102                                         return 0;
103                                 }
104                         }
105                         return -1;
106                 }
107         }
108         return -1;
109 }
110
111 /** Receive message
112  *  WARNING: buf must be 0 terminated (buf[len]=0) or some things might 
113  * break (e.g.: modules/textops)
114  */
115 int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info) 
116 {
117         struct sip_msg* msg;
118         struct run_act_ctx ctx;
119         int ret;
120 #ifdef STATS
121         int skipped = 1;
122         struct timeval tvb, tve;        
123         struct timezone tz;
124         unsigned int diff;
125 #endif
126         str inb;
127         sr_net_info_t netinfo;
128
129         if(sr_event_enabled(SREV_NET_DATA_RECV)) {
130                 if(sip_check_fline(buf, len)==0) {
131                         memset(&netinfo, 0, sizeof(sr_net_info_t));
132                         netinfo.data.s = buf;
133                         netinfo.data.len = len;
134                         netinfo.rcv = rcv_info;
135                         sr_event_exec(SREV_NET_DATA_RECV, (void*)&netinfo);
136                 }
137         }
138
139         inb.s = buf;
140         inb.len = len;
141         sr_event_exec(SREV_NET_DATA_IN, (void*)&inb);
142         len = inb.len;
143
144         msg=pkg_malloc(sizeof(struct sip_msg));
145         if (msg==0) {
146                 LM_ERR("no mem for sip_msg\n");
147                 goto error00;
148         }
149         msg_no++;
150         /* number of vias parsed -- good for diagnostic info in replies */
151         via_cnt=0;
152
153         memset(msg,0, sizeof(struct sip_msg)); /* init everything to 0 */
154         /* fill in msg */
155         msg->buf=buf;
156         msg->len=len;
157         /* zero termination (termination of orig message bellow not that
158            useful as most of the work is done with scratch-pad; -jiri  */
159         /* buf[len]=0; */ /* WARNING: zero term removed! */
160         msg->rcv=*rcv_info;
161         msg->id=msg_no;
162         msg->pid=my_pid();
163         msg->set_global_address=default_global_address;
164         msg->set_global_port=default_global_port;
165         
166         if(likely(sr_msg_time==1)) msg_set_time(msg);
167
168         if (parse_msg(buf,len, msg)!=0){
169                 if(sr_event_exec(SREV_RCV_NOSIP, (void*)msg)!=0) {
170                         LOG(cfg_get(core, core_cfg, corelog),
171                                 "core parsing of SIP message failed (%s:%d/%d)\n",
172                                 ip_addr2a(&msg->rcv.src_ip), (int)msg->rcv.src_port,
173                                 (int)msg->rcv.proto);
174                         sr_core_ert_run(msg, SR_CORE_ERT_RECEIVE_PARSE_ERROR);
175                 }
176                 goto error02;
177         }
178         LM_DBG("After parse_msg...\n");
179
180         /* set log prefix */
181         log_prefix_set(msg);
182
183         /* ... clear branches from previous message */
184         clear_branches();
185
186         if (msg->first_line.type==SIP_REQUEST){
187                 ruri_mark_new(); /* ruri is usable for forking (not consumed yet) */
188                 if (!IS_SIP(msg)){
189                         if ((ret=nonsip_msg_run_hooks(msg))!=NONSIP_MSG_ACCEPT){
190                                 if (unlikely(ret==NONSIP_MSG_ERROR))
191                                         goto error03;
192                                 goto end; /* drop the message */
193                         }
194                 }
195                 /* sanity checks */
196                 if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
197                         /* no via, send back error ? */
198                         LM_ERR("no via found in request\n");
199                         STATS_BAD_MSG();
200                         goto error02;
201                 }
202                 /* check if necessary to add receive?->moved to forward_req */
203                 /* check for the alias stuff */
204 #ifdef USE_TCP
205                 if (msg->via1->alias && cfg_get(tcp, tcp_cfg, accept_aliases) && 
206                                 (((rcv_info->proto==PROTO_TCP) && !tcp_disable)
207 #ifdef USE_TLS
208                                         || ((rcv_info->proto==PROTO_TLS) && !tls_disable)
209 #endif
210                                 )
211                         ){
212                         if (tcpconn_add_alias(rcv_info->proto_reserved1, msg->via1->port,
213                                                                         rcv_info->proto)!=0){
214                                 LM_ERR("tcp alias failed\n");
215                                 /* continue */
216                         }
217                 }
218 #endif
219
220         /*      skip: */
221                 LM_DBG("preparing to run routing scripts...\n");
222 #ifdef  STATS
223                 gettimeofday( & tvb, &tz );
224 #endif
225                 /* execute pre-script callbacks, if any; -jiri */
226                 /* if some of the callbacks said not to continue with
227                    script processing, don't do so
228                    if we are here basic sanity checks are already done
229                    (like presence of at least one via), so you can count
230                    on via1 being parsed in a pre-script callback --andrei
231                 */
232                 if (exec_pre_script_cb(msg, REQUEST_CB_TYPE)==0 )
233                 {
234                         STATS_REQ_FWD_DROP();
235                         goto end; /* drop the request */
236                 }
237
238                 set_route_type(REQUEST_ROUTE);
239                 /* exec the routing script */
240                 if (run_top_route(main_rt.rlist[DEFAULT_RT], msg, 0)<0){
241                         LM_WARN("error while trying script\n");
242                         goto error_req;
243                 }
244
245 #ifdef STATS
246                 gettimeofday( & tve, &tz );
247                 diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
248                 stats->processed_requests++;
249                 stats->acc_req_time += diff;
250                 LM_DBG("successfully ran routing scripts...(%d usec)\n", diff);
251                 STATS_RX_REQUEST( msg->first_line.u.request.method_value );
252 #endif
253
254                 /* execute post request-script callbacks */
255                 exec_post_script_cb(msg, REQUEST_CB_TYPE);
256         }else if (msg->first_line.type==SIP_REPLY){
257                 /* sanity checks */
258                 if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
259                         /* no via, send back error ? */
260                         LM_ERR("no via found in reply\n");
261                         STATS_BAD_RPL();
262                         goto error02;
263                 }
264
265 #ifdef STATS
266                 gettimeofday( & tvb, &tz );
267                 STATS_RX_RESPONSE ( msg->first_line.u.reply.statuscode / 100 );
268 #endif
269                 
270                 /* execute pre-script callbacks, if any; -jiri */
271                 /* if some of the callbacks said not to continue with
272                    script processing, don't do so
273                    if we are here basic sanity checks are already done
274                    (like presence of at least one via), so you can count
275                    on via1 being parsed in a pre-script callback --andrei
276                 */
277                 if (exec_pre_script_cb(msg, ONREPLY_CB_TYPE)==0 )
278                 {
279                         STATS_RPL_FWD_DROP();
280                         goto end; /* drop the reply */
281                 }
282
283                 /* exec the onreply routing script */
284                 if (onreply_rt.rlist[DEFAULT_RT]){
285                         set_route_type(CORE_ONREPLY_ROUTE);
286                         ret=run_top_route(onreply_rt.rlist[DEFAULT_RT], msg, &ctx);
287 #ifndef NO_ONREPLY_ROUTE_ERROR
288                         if (unlikely(ret<0)){
289                                 LM_WARN("error while trying onreply script\n");
290                                 goto error_rpl;
291                         }else
292 #endif /* NO_ONREPLY_ROUTE_ERROR */
293                         if (unlikely(ret==0 || (ctx.run_flags&DROP_R_F))){
294                                 STATS_RPL_FWD_DROP();
295                                 goto skip_send_reply; /* drop the message, no error */
296                         }
297                 }
298                 /* send the msg */
299                 forward_reply(msg);
300         skip_send_reply:
301 #ifdef STATS
302                 gettimeofday( & tve, &tz );
303                 diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
304                 stats->processed_responses++;
305                 stats->acc_res_time+=diff;
306                 LM_DBG("successfully ran reply processing...(%d usec)\n", diff);
307 #endif
308
309                 /* execute post reply-script callbacks */
310                 exec_post_script_cb(msg, ONREPLY_CB_TYPE);
311         }
312
313 end:
314 #ifdef STATS
315         skipped = 0;
316 #endif
317         /* free possible loaded avps -bogdan */
318         reset_avps();
319 #ifdef WITH_XAVP
320         xavp_reset_list();
321 #endif
322         LM_DBG("cleaning up\n");
323         free_sip_msg(msg);
324         pkg_free(msg);
325 #ifdef STATS
326         if (skipped) STATS_RX_DROPS;
327 #endif
328         /* reset log prefix */
329         log_prefix_set(NULL);
330         return 0;
331
332 #ifndef NO_ONREPLY_ROUTE_ERROR
333 error_rpl:
334         /* execute post reply-script callbacks */
335         exec_post_script_cb(msg, ONREPLY_CB_TYPE);
336         reset_avps();
337 #ifdef WITH_XAVP
338         xavp_reset_list();
339 #endif
340         goto error02;
341 #endif /* NO_ONREPLY_ROUTE_ERROR */
342 error_req:
343         LM_DBG("error:...\n");
344         /* execute post request-script callbacks */
345         exec_post_script_cb(msg, REQUEST_CB_TYPE);
346 error03:
347         /* free possible loaded avps -bogdan */
348         reset_avps();
349 #ifdef WITH_XAVP
350         xavp_reset_list();
351 #endif
352 error02:
353         free_sip_msg(msg);
354         pkg_free(msg);
355 error00:
356         STATS_RX_DROPS;
357         /* reset log prefix */
358         log_prefix_set(NULL);
359         return -1;
360 }
361