Merge pull request #924 from linuxmaniac/vseva/fix_app_python
[sip-router] / src / core / 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 #include "kemi.h"
58
59 #ifdef DEBUG_DMALLOC
60 #include <mem/dmalloc.h>
61 #endif
62
63 int _sr_ip_free_bind = 0;
64
65 unsigned int msg_no=0;
66 /* address preset vars */
67 str default_global_address={0,0};
68 str default_global_port={0,0};
69 str default_via_address={0,0};
70 str default_via_port={0,0};
71
72 /**
73  * increment msg_no and return the new value
74  */
75 unsigned int inc_msg_no(void)
76 {
77         return ++msg_no;
78 }
79
80 /**
81  *
82  */
83 int sip_check_fline(char* buf, unsigned int len)
84 {
85         char *p;
86         int m;
87
88         m = 0;
89         for(p=buf; p<buf+len; p++) {
90                 /* first check if is a reply - starts with SIP/2.0 */
91                 if(m==0) {
92                         if(*p==' ' || *p=='\t' || *p=='\r' || *p=='\n') continue;
93                         if(buf+len-p<10) return -1;
94                         if(strncmp(p, "SIP/2.0 ", 8)==0) {
95                                 LM_DBG("first line indicates a SIP reply\n");
96                                 return 0;
97                         }
98                         m=1;
99                 } else {
100                         /* check if a request - before end of first line is SIP/2.0 */
101                         if(*p!='\r' && *p!='\n') continue;
102                         if(p-10>=buf) {
103                                 if(strncmp(p-8, " SIP/2.0", 8)==0) {
104                                         LM_DBG("first line indicates a SIP request\n");
105                                         return 0;
106                                 }
107                         }
108                         return -1;
109                 }
110         }
111         return -1;
112 }
113
114 /** Receive message
115  *  WARNING: buf must be 0 terminated (buf[len]=0) or some things might
116  * break (e.g.: modules/textops)
117  */
118 int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info)
119 {
120         struct sip_msg* msg;
121         struct run_act_ctx ctx;
122         struct run_act_ctx *bctx;
123         int ret;
124 #ifdef STATS
125         int skipped = 1;
126         int stats_on = 1;
127 #else
128         int stats_on = 0;
129 #endif
130         struct timeval tvb, tve;
131         struct timezone tz;
132         unsigned int diff = 0;
133         str inb;
134         sr_net_info_t netinfo;
135         sr_kemi_eng_t *keng = NULL;
136         sr_event_param_t evp = {0};
137
138         if(sr_event_enabled(SREV_NET_DATA_RECV)) {
139                 if(sip_check_fline(buf, len)==0) {
140                         memset(&netinfo, 0, sizeof(sr_net_info_t));
141                         netinfo.data.s = buf;
142                         netinfo.data.len = len;
143                         netinfo.rcv = rcv_info;
144                         evp.data = (void*)&netinfo;
145                         sr_event_exec(SREV_NET_DATA_RECV, &evp);
146                 }
147         }
148
149         inb.s = buf;
150         inb.len = len;
151         evp.data = (void*)&inb;
152         sr_event_exec(SREV_NET_DATA_IN, &evp);
153         len = inb.len;
154
155         msg=pkg_malloc(sizeof(struct sip_msg));
156         if (msg==0) {
157                 LM_ERR("no mem for sip_msg\n");
158                 goto error00;
159         }
160         msg_no++;
161         /* number of vias parsed -- good for diagnostic info in replies */
162         via_cnt=0;
163
164         memset(msg,0, sizeof(struct sip_msg)); /* init everything to 0 */
165         /* fill in msg */
166         msg->buf=buf;
167         msg->len=len;
168         /* zero termination (termination of orig message bellow not that
169          * useful as most of the work is done with scratch-pad; -jiri  */
170         /* buf[len]=0; */ /* WARNING: zero term removed! */
171         msg->rcv=*rcv_info;
172         msg->id=msg_no;
173         msg->pid=my_pid();
174         msg->set_global_address=default_global_address;
175         msg->set_global_port=default_global_port;
176
177         if(likely(sr_msg_time==1)) msg_set_time(msg);
178
179         if (parse_msg(buf,len, msg)!=0){
180                 evp.data = (void*)msg;
181                 if((ret=sr_event_exec(SREV_RCV_NOSIP, &evp))<NONSIP_MSG_DROP) {
182                         LOG(cfg_get(core, core_cfg, corelog),
183                                 "core parsing of SIP message failed (%s:%d/%d)\n",
184                                 ip_addr2a(&msg->rcv.src_ip), (int)msg->rcv.src_port,
185                                 (int)msg->rcv.proto);
186                         sr_core_ert_run(msg, SR_CORE_ERT_RECEIVE_PARSE_ERROR);
187                 }
188                 else if(ret == NONSIP_MSG_DROP) goto error02;
189         }
190
191         if(parse_headers(msg, HDR_FROM_F|HDR_TO_F|HDR_CALLID_F|HDR_CSEQ_F, 0)<0) {
192                 LM_WARN("parsing relevant headers failed\n");
193         }
194         LM_DBG("--- received sip message - %s - call-id: [%.*s] - cseq: [%.*s]\n",
195                         (msg->first_line.type==SIP_REQUEST)?"request":"reply",
196                         (msg->callid && msg->callid->body.s)?msg->callid->body.len:0,
197                         (msg->callid && msg->callid->body.s)?msg->callid->body.s:"",
198                         (msg->cseq && msg->cseq->body.s)?msg->cseq->body.len:0,
199                         (msg->cseq && msg->cseq->body.s)?msg->cseq->body.s:"");
200
201         /* set log prefix */
202         log_prefix_set(msg);
203
204         /* ... clear branches from previous message */
205         clear_branches();
206
207         if (msg->first_line.type==SIP_REQUEST){
208                 ruri_mark_new(); /* ruri is usable for forking (not consumed yet) */
209                 if (!IS_SIP(msg)){
210                         if ((ret=nonsip_msg_run_hooks(msg))!=NONSIP_MSG_ACCEPT){
211                                 if (unlikely(ret==NONSIP_MSG_ERROR))
212                                         goto error03;
213                                 goto end; /* drop the message */
214                         }
215                 }
216                 /* sanity checks */
217                 if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
218                         /* no via, send back error ? */
219                         LM_ERR("no via found in request\n");
220                         STATS_BAD_MSG();
221                         goto error02;
222                 }
223                 /* check if necessary to add receive?->moved to forward_req */
224                 /* check for the alias stuff */
225 #ifdef USE_TCP
226                 if (msg->via1->alias && cfg_get(tcp, tcp_cfg, accept_aliases) &&
227                                 (((rcv_info->proto==PROTO_TCP) && !tcp_disable)
228 #ifdef USE_TLS
229                                         || ((rcv_info->proto==PROTO_TLS) && !tls_disable)
230 #endif
231                                 )
232                         ){
233                         if (tcpconn_add_alias(rcv_info->proto_reserved1, msg->via1->port,
234                                                                         rcv_info->proto)!=0){
235                                 LM_ERR("tcp alias failed\n");
236                                 /* continue */
237                         }
238                 }
239 #endif
240
241         /*      skip: */
242                 LM_DBG("preparing to run routing scripts...\n");
243                 if(is_printable(cfg_get(core, core_cfg, latency_cfg_log))
244                                 || stats_on==1) {
245                         gettimeofday( & tvb, &tz );
246                 }
247                 /* execute pre-script callbacks, if any; -jiri */
248                 /* if some of the callbacks said not to continue with
249                  * script processing, don't do so
250                  * if we are here basic sanity checks are already done
251                  * (like presence of at least one via), so you can count
252                  * on via1 being parsed in a pre-script callback --andrei
253                 */
254                 if (exec_pre_script_cb(msg, REQUEST_CB_TYPE)==0 )
255                 {
256                         STATS_REQ_FWD_DROP();
257                         goto end; /* drop the request */
258                 }
259
260                 set_route_type(REQUEST_ROUTE);
261                 /* exec the routing script */
262                 if(unlikely(main_rt.rlist[DEFAULT_RT]==NULL)) {
263                         keng = sr_kemi_eng_get();
264                         if(keng==NULL) {
265                                 LM_ERR("no config routing engine registered\n");
266                                 goto error_req;
267                         }
268                         if(keng->froute(msg, REQUEST_ROUTE, NULL, NULL)<0) {
269                                 LM_NOTICE("negative return code from engine function\n");
270                         }
271                 } else {
272                         if (run_top_route(main_rt.rlist[DEFAULT_RT], msg, 0)<0){
273                                 LM_WARN("error while trying script\n");
274                                 goto error_req;
275                         }
276                 }
277
278                 if(is_printable(cfg_get(core, core_cfg, latency_cfg_log))
279                                 || stats_on==1) {
280                         gettimeofday( & tve, &tz );
281                         diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
282                         LOG(cfg_get(core, core_cfg, latency_cfg_log),
283                                         "request-route executed in: %d usec\n", diff);
284 #ifdef STATS
285                         stats->processed_requests++;
286                         stats->acc_req_time += diff;
287                         STATS_RX_REQUEST( msg->first_line.u.request.method_value );
288 #endif
289                 }
290
291                 /* execute post request-script callbacks */
292                 exec_post_script_cb(msg, REQUEST_CB_TYPE);
293         }else if (msg->first_line.type==SIP_REPLY){
294                 /* sanity checks */
295                 if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
296                         /* no via, send back error ? */
297                         LM_ERR("no via found in reply\n");
298                         STATS_BAD_RPL();
299                         goto error02;
300                 }
301
302                 if(is_printable(cfg_get(core, core_cfg, latency_cfg_log))
303                                 || stats_on==1) {
304                         gettimeofday( & tvb, &tz );
305                 }
306 #ifdef STATS
307                 STATS_RX_RESPONSE ( msg->first_line.u.reply.statuscode / 100 );
308 #endif
309
310                 /* execute pre-script callbacks, if any; -jiri */
311                 /* if some of the callbacks said not to continue with
312                  * script processing, don't do so
313                  * if we are here basic sanity checks are already done
314                  * (like presence of at least one via), so you can count
315                  * on via1 being parsed in a pre-script callback --andrei
316                 */
317                 if (exec_pre_script_cb(msg, ONREPLY_CB_TYPE)==0 )
318                 {
319                         STATS_RPL_FWD_DROP();
320                         goto end; /* drop the reply */
321                 }
322
323                 /* exec the onreply routing script */
324                 keng = sr_kemi_eng_get();
325                 if (onreply_rt.rlist[DEFAULT_RT]!=NULL || keng!=NULL){
326                         set_route_type(CORE_ONREPLY_ROUTE);
327                         ret = 1;
328                         if(unlikely(keng!=NULL)) {
329                                 bctx = sr_kemi_act_ctx_get();
330                                 init_run_actions_ctx(&ctx);
331                                 sr_kemi_act_ctx_set(&ctx);
332                                 ret = keng->froute(msg, CORE_ONREPLY_ROUTE, NULL, NULL);
333                                 sr_kemi_act_ctx_set(bctx);
334                         } else {
335                                 ret=run_top_route(onreply_rt.rlist[DEFAULT_RT], msg, &ctx);
336                         }
337 #ifndef NO_ONREPLY_ROUTE_ERROR
338                         if (unlikely(ret<0)){
339                                 LM_WARN("error while trying onreply script\n");
340                                 goto error_rpl;
341                         }else
342 #endif /* NO_ONREPLY_ROUTE_ERROR */
343                         if (unlikely(ret==0 || (ctx.run_flags&DROP_R_F))){
344                                 STATS_RPL_FWD_DROP();
345                                 goto skip_send_reply; /* drop the message, no error */
346                         }
347                 }
348                 /* send the msg */
349                 forward_reply(msg);
350         skip_send_reply:
351                 if(is_printable(cfg_get(core, core_cfg, latency_cfg_log))
352                                 || stats_on==1) {
353                         gettimeofday( & tve, &tz );
354                         diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
355                         LOG(cfg_get(core, core_cfg, latency_cfg_log),
356                                         "reply-route executed in: %d usec\n", diff);
357 #ifdef STATS
358                         stats->processed_responses++;
359                         stats->acc_res_time+=diff;
360 #endif
361                 }
362
363                 /* execute post reply-script callbacks */
364                 exec_post_script_cb(msg, ONREPLY_CB_TYPE);
365         }
366
367 end:
368 #ifdef STATS
369         skipped = 0;
370 #endif
371         ksr_msg_env_reset();
372         LM_DBG("cleaning up\n");
373         free_sip_msg(msg);
374         pkg_free(msg);
375 #ifdef STATS
376         if (skipped) STATS_RX_DROPS;
377 #endif
378         /* reset log prefix */
379         log_prefix_set(NULL);
380         return 0;
381
382 #ifndef NO_ONREPLY_ROUTE_ERROR
383 error_rpl:
384         /* execute post reply-script callbacks */
385         exec_post_script_cb(msg, ONREPLY_CB_TYPE);
386         goto error02;
387 #endif /* NO_ONREPLY_ROUTE_ERROR */
388 error_req:
389         LM_DBG("error:...\n");
390         /* execute post request-script callbacks */
391         exec_post_script_cb(msg, REQUEST_CB_TYPE);
392 error03:
393 error02:
394         free_sip_msg(msg);
395         pkg_free(msg);
396 error00:
397         ksr_msg_env_reset();
398         STATS_RX_DROPS;
399         /* reset log prefix */
400         log_prefix_set(NULL);
401         return -1;
402 }
403
404 /**
405  * clean up msg environment, such as avp and xavp lists
406  */
407 void ksr_msg_env_reset(void)
408 {
409         reset_avps();
410 #ifdef WITH_XAVP
411         xavp_reset_list();
412 #endif
413
414 }