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