2 *$Id: receive.c,v 1.50 2004/08/24 08:45:10 janakj Exp $
4 * Copyright (C) 2001-2003 FhG Fokus
6 * This file is part of ser, a free SIP server.
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
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:
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.
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
29 * 2003-02-28 scratchpad compatibility abandoned (jiri)
30 * 2003-01-29 transport-independent message zero-termination in
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 &
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)
51 #include "parser/msg_parser.h"
57 #include "script_cb.h"
62 #include "tcp_server.h" /* for tcpconn_add_alias */
66 #include <mem/dmalloc.h>
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};
78 /* WARNING: buf must be 0 terminated (buf[len]=0) or some things might
79 * break (e.g.: modules/textops)
81 int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info)
87 struct timeval tvb, tve;
92 msg=pkg_malloc(sizeof(struct sip_msg));
94 LOG(L_ERR, "ERROR: receive_msg: no mem for sip_msg\n");
98 /* number of vias parsed -- good for diagnostic info in replies */
101 memset(msg,0, sizeof(struct sip_msg)); /* init everything to 0 */
105 /* zero termination (termination of orig message bellow not that
106 useful as most of the work is done with scratch-pad; -jiri */
107 /* buf[len]=0; */ /* WARNING: zero term removed! */
110 msg->set_global_address=default_global_address;
111 msg->set_global_port=default_global_port;
113 if (parse_msg(buf,len, msg)!=0){
114 LOG(L_ERR, "ERROR: receive_msg: parse_msg failed\n");
117 DBG("After parse_msg...\n");
120 /* ... clear branches from previous message */
123 if (msg->first_line.type==SIP_REQUEST){
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");
130 /* check if necessary to add receive?->moved to forward_req */
131 /* check for the alias stuff */
133 if (msg->via1->alias && tcp_accept_aliases &&
134 (((rcv_info->proto==PROTO_TCP) && !tcp_disable)
136 || ((rcv_info->proto==PROTO_TLS) && !tls_disable)
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");
148 DBG("preparing to run routing scripts...\n");
150 gettimeofday( & tvb, &tz );
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
159 ret=exec_pre_cb(msg);
161 if (ret<0) goto error;
162 else goto end; /* drop the message -- no error -- andrei */
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");
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("successfully ran routing scripts...(%d usec)\n", diff);
177 STATS_RX_REQUEST( msg->first_line.u.request.method_value );
179 }else if (msg->first_line.type==SIP_REPLY){
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");
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");
192 /* check if via1 == us */
196 gettimeofday( & tvb, &tz );
197 STATS_RX_RESPONSE ( msg->first_line.u.reply.statuscode / 100 );
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
207 ret=exec_pre_cb(msg);
209 if (ret<0) goto error;
210 else goto end; /* drop the message -- no error -- andrei */
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("successfully ran reply processing...(%d usec)\n", diff);
228 /* execute post-script callbacks, if any; -jiri */
230 /* free possible loaded avps -bogdan */
232 DBG("receive_msg: cleaning up\n");
236 if (skipped) STATS_RX_DROPS;
241 /* execute post-script callbacks, if any; -jiri */
243 /* free possible loaded avps -bogdan */