- avp core replaced with .14 version
[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
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 scrath-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
123         if (msg->first_line.type==SIP_REQUEST){
124                 /* sanity checks */
125                 if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
126                         /* no via, send back error ? */
127                         LOG(L_ERR, "ERROR: receive_msg: no via found in request\n");
128                         goto error;
129                 }
130                 /* check if neccesarry to add receive?->moved to forward_req */
131                 /* check for the alias stuff */
132 #ifdef USE_TCP
133                 if (msg->via1->alias && tcp_accept_aliases && 
134                                 (((rcv_info->proto==PROTO_TCP) && !tcp_disable)
135 #ifdef USE_TLS
136                                         || ((rcv_info->proto==PROTO_TLS) && !tls_disable)
137 #endif
138                                 )
139                         ){
140                         if (tcpconn_add_alias(rcv_info->proto_reserved1, msg->via1->port,
141                                                                         rcv_info->proto)!=0){
142                                 LOG(L_ERR, " ERROR: receive_msg: tcp alias failed\n");
143                                 /* continue */
144                         }
145                 }
146 #endif
147
148                 DBG("preparing to run routing scripts...\n");
149 #ifdef  STATS
150                 gettimeofday( & tvb, &tz );
151 #endif
152                 /* execute pre-script callbacks, if any; -jiri */
153                 /* if some of the callbacks said not to continue with
154                    script processing, don't do so
155                    if we are here basic sanity checks are already done
156                    (like presence of at least one via), so you can count
157                    on via1 being parsed in a pre-script callback --andrei
158                 */
159                 ret=exec_pre_cb(msg);
160                 if (ret<=0){
161                         if (ret<0) goto error;
162                         else goto end; /* drop the message -- no error -- andrei */
163                 }
164                 /* exec the routing script */
165                 if (run_actions(rlist[0], msg)<0) {
166                         LOG(L_WARN, "WARNING: receive_msg: "
167                                         "error while trying script\n");
168                         goto error;
169                 }
170
171 #ifdef STATS
172                 gettimeofday( & tve, &tz );
173                 diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
174                 stats->processed_requests++;
175                 stats->acc_req_time += diff;
176                 DBG("succesfully ran routing scripts...(%d usec)\n", diff);
177                 STATS_RX_REQUEST( msg->first_line.u.request.method_value );
178 #endif
179         }else if (msg->first_line.type==SIP_REPLY){
180                 /* sanity checks */
181                 if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
182                         /* no via, send back error ? */
183                         LOG(L_ERR, "ERROR: receive_msg: no via found in reply\n");
184                         goto error;
185                 }
186 #if 0
187                 if ((msg->via2==0) || (msg->via2->error!=PARSE_OK)){
188                         /* no second via => error? */
189                         LOG(L_ERR, "ERROR: receive_msg: no 2nd via found in reply\n");
190                         goto error;
191                 }
192                 /* check if via1 == us */
193 #endif
194
195 #ifdef STATS
196                 gettimeofday( & tvb, &tz );
197                 STATS_RX_RESPONSE ( msg->first_line.u.reply.statuscode / 100 );
198 #endif
199                 
200                 /* execute pre-script callbacks, if any; -jiri */
201                 /* if some of the callbacks said not to continue with
202                    script processing, don't do so
203                    if we are here basic sanity checks are already done
204                    (like presence of at least one via), so you can count
205                    on via1 being parsed in a pre-script callback --andrei
206                 */
207                 ret=exec_pre_cb(msg);
208                 if (ret<=0){
209                         if (ret<0) goto error;
210                         else goto end; /* drop the message -- no error -- andrei */
211                 }
212
213                 /* send the msg */
214                 forward_reply(msg);
215
216 #ifdef STATS
217                 gettimeofday( & tve, &tz );
218                 diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
219                 stats->processed_responses++;
220                 stats->acc_res_time+=diff;
221                 DBG("succesfully ran reply processing...(%d usec)\n", diff);
222 #endif
223         }
224 end:
225 #ifdef STATS
226         skipped = 0;
227 #endif
228         /* execute post-script callbacks, if any; -jiri */
229         exec_post_cb(msg);
230         /* free possible loaded avps -bogdan */
231         reset_avps();
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         /* free possible loaded avps -bogdan */
244         reset_avps();
245 error02:
246         free_sip_msg(msg);
247         pkg_free(msg);
248 error00:
249         STATS_RX_DROPS;
250         return -1;
251 }
252