01ed8fa9cec83fbd5fedf97fddb442544e048265
[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
28
29 #include <string.h>
30 #include <stdlib.h>
31 #include <sys/time.h>
32
33 #include "receive.h"
34 #include "globals.h"
35 #include "dprint.h"
36 #include "route.h"
37 #include "parser/msg_parser.h"
38 #include "forward.h"
39 #include "action.h"
40 #include "mem/mem.h"
41 #include "stats.h"
42 #include "ip_addr.h"
43 #include "script_cb.h"
44 #include "dset.h"
45
46
47 #ifdef DEBUG_DMALLOC
48 #include <mem/dmalloc.h>
49 #endif
50
51 unsigned int msg_no=0;
52
53 int receive_msg(char* buf, unsigned int len, union sockaddr_union* src_su)
54 {
55         struct sip_msg* msg;
56 #ifdef STATS
57         int skipped = 1;
58         struct timeval tvb, tve;        
59         struct timezone tz;
60         unsigned int diff;
61 #endif
62
63         msg=pkg_malloc(sizeof(struct sip_msg));
64         if (msg==0) {
65                 LOG(L_ERR, "ERROR: receive_msg: no mem for sip_msg\n");
66                 goto error00;
67         }
68         msg_no++;
69         /* number of vias parsed -- good for diagnostic info in replies */
70         via_cnt=0;
71
72         memset(msg,0, sizeof(struct sip_msg)); /* init everything to 0 */
73         /* fill in msg */
74         msg->buf=buf;
75         msg->len=len;
76         /* zero termination (termination of orig message bellow not that
77            useful as most of the work is done with scrath-pad; -jiri  */
78         /* buf[len]=0; */ /* WARNING: zero term removed! */
79         su2ip_addr(&msg->src_ip, src_su);
80         msg->dst_ip=bind_address->address; /* won't work if listening on 0.0.0.0 */
81         msg->id=msg_no;
82         /* make a copy of the message */
83         msg->orig=(char*) pkg_malloc(len+1);
84         if (msg->orig==0){
85                 LOG(L_ERR, "ERROR:receive_msg: memory allocation failure\n");
86                 goto error01;
87         }
88         memcpy(msg->orig, buf, len);
89         /* WARNING: zero term removed! */
90         /* msg->orig[len]=0; */ /* null terminate it,good for using str* functions
91                                                  on it*/
92         
93         if (parse_msg(buf,len, msg)!=0){
94                 LOG(L_ERR, "ERROR: receive_msg: parse_msg failed\n");
95                 goto error02;
96         }
97         DBG("After parse_msg...\n");
98
99         /* execute pre-script callbacks, if any; -jiri */
100         /* if some of the callbacks said not to continue with
101            script processing, don't do so
102         */
103         if (exec_pre_cb(msg)==0) goto error;
104
105         /* ... and clear branches from previous message */
106         clear_branches();
107
108         if (msg->first_line.type==SIP_REQUEST){
109                 /* sanity checks */
110                 if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
111                         /* no via, send back error ? */
112                         LOG(L_ERR, "ERROR: receive_msg: no via found in request\n");
113                         goto error;
114                 }
115                 /* check if neccesarry to add receive?->moved to forward_req */
116
117                 /* exec routing script */
118                 DBG("preparing to run routing scripts...\n");
119 #ifdef  STATS
120                 gettimeofday( & tvb, &tz );
121 #endif
122
123                 if (run_actions(rlist[0], msg)<0){
124
125                         LOG(L_WARN, "WARNING: receive_msg: "
126                                         "error while trying script\n");
127                         goto error;
128                 }
129
130
131 #ifdef STATS
132                 gettimeofday( & tve, &tz );
133                 diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
134                 stats->processed_requests++;
135                 stats->acc_req_time += diff;
136                 DBG("succesfully ran routing scripts...(%d usec)\n", diff);
137                 STATS_RX_REQUEST( msg->first_line.u.request.method_value );
138 #endif
139         }else if (msg->first_line.type==SIP_REPLY){
140                 /* sanity checks */
141                 if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
142                         /* no via, send back error ? */
143                         LOG(L_ERR, "ERROR: receive_msg: no via found in reply\n");
144                         goto error;
145                 }
146 #if 0
147                 if ((msg->via2==0) || (msg->via2->error!=PARSE_OK)){
148                         /* no second via => error? */
149                         LOG(L_ERR, "ERROR: receive_msg: no 2nd via found in reply\n");
150                         goto error;
151                 }
152                 /* check if via1 == us */
153 #endif
154
155 #ifdef STATS
156                 gettimeofday( & tvb, &tz );
157                 STATS_RX_RESPONSE ( msg->first_line.u.reply.statuscode / 100 );
158 #endif
159                 
160                 /* send the msg */
161                 forward_reply(msg);
162
163 #ifdef STATS
164                 gettimeofday( & tve, &tz );
165                 diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
166                 stats->processed_responses++;
167                 stats->acc_res_time+=diff;
168                 DBG("succesfully ran reply processing...(%d usec)\n", diff);
169 #endif
170         }
171 #ifdef STATS
172         skipped = 0;
173 #endif
174         /* execute post-script callbacks, if any; -jiri */
175         exec_post_cb(msg);
176         DBG("receive_msg: cleaning up\n");
177         free_sip_msg(msg);
178         pkg_free(msg);
179 #ifdef STATS
180         if (skipped) STATS_RX_DROPS;
181 #endif
182         return 0;
183 error:
184         DBG("error:...\n");
185         /* execute post-script callbacks, if any; -jiri */
186         exec_post_cb(msg);
187 error02:
188         free_sip_msg(msg);
189 error01:
190         pkg_free(msg);
191 error00:
192         STATS_RX_DROPS;
193         return -1;
194 }
195