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