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