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