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