receive.c
888ca09d
 /* 
  *$Id$
7dd0b342
  *
  * Copyright (C) 2001-2003 Fhg Fokus
  *
  * This file is part of ser, a free SIP server.
  *
  * ser is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
  * For a license to use the ser software under conditions
  * other than those described here, or to purchase support for this
  * software, please contact iptel.org by e-mail at the following addresses:
  *    info@iptel.org
  *
  * ser is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License 
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
049f64c2
  *
  * History:
  * ---------
18dbc018
  * 2003-02-28 scratchpad compatibility abandoned (jiri)
049f64c2
  * 2003-01-29 transport-independent message zero-termination in
  *            receive_msg (jiri)
ab130758
  * 2003-02-07 undoed jiri's zero term. changes (they break tcp) (andrei)
8fc80c33
  * 2003-02-10 moved zero-term in the calling functions (udp_receive &
  *            tcp_read_req)
43888875
  * 2003-08-01 fixed exec_pre_cb returning 0 (drop, not an error!) (andrei)
888ca09d
  */
 
7dd0b342
 
888ca09d
 #include <string.h>
3e429f5c
 #include <stdlib.h>
4f3faaaf
 #include <sys/time.h>
888ca09d
 
 #include "receive.h"
4e2fdd79
 #include "globals.h"
888ca09d
 #include "dprint.h"
 #include "route.h"
3881f12c
 #include "parser/msg_parser.h"
888ca09d
 #include "forward.h"
3e429f5c
 #include "action.h"
dda9dab1
 #include "mem/mem.h"
 #include "stats.h"
4e2fdd79
 #include "ip_addr.h"
caf80ae6
 #include "script_cb.h"
 #include "dset.h"
888ca09d
 
5b253cc6
 
03150098
 #ifdef DEBUG_DMALLOC
dda9dab1
 #include <mem/dmalloc.h>
0a974a1d
 #endif
5b253cc6
 
e72b5b50
 unsigned int msg_no=0;
 
8fc80c33
 
 /* WARNING: buf must be 0 terminated (buf[len]=0) or some things might 
  * break (e.g.: modules/textops)
  */
f2f969dd
 int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info) 
888ca09d
 {
22d4aa5d
 	struct sip_msg* msg;
43888875
 	int ret;
985f6f0f
 #ifdef STATS
 	int skipped = 1;
4f3faaaf
 	struct timeval tvb, tve;	
 	struct timezone tz;
 	unsigned int diff;
985f6f0f
 #endif
e72b5b50
 
6fa79282
 	msg=pkg_malloc(sizeof(struct sip_msg));
caf80ae6
 	if (msg==0) {
 		LOG(L_ERR, "ERROR: receive_msg: no mem for sip_msg\n");
 		goto error00;
 	}
e72b5b50
 	msg_no++;
caf80ae6
 	/* number of vias parsed -- good for diagnostic info in replies */
 	via_cnt=0;
5b253cc6
 
22d4aa5d
 	memset(msg,0, sizeof(struct sip_msg)); /* init everything to 0 */
4ac74c03
 	/* fill in msg */
22d4aa5d
 	msg->buf=buf;
 	msg->len=len;
9b47a45c
 	/* zero termination (termination of orig message bellow not that
 	   useful as most of the work is done with scrath-pad; -jiri  */
6ee62314
 	/* buf[len]=0; */ /* WARNING: zero term removed! */
f2f969dd
 	msg->rcv=*rcv_info;
22d4aa5d
 	msg->id=msg_no;
888ca09d
 	
22d4aa5d
 	if (parse_msg(buf,len, msg)!=0){
caf80ae6
 		LOG(L_ERR, "ERROR: receive_msg: parse_msg failed\n");
 		goto error02;
888ca09d
 	}
e72b5b50
 	DBG("After parse_msg...\n");
caf80ae6
 
 	/* execute pre-script callbacks, if any; -jiri */
a50f3f89
 	/* if some of the callbacks said not to continue with
 	   script processing, don't do so
 	*/
43888875
 	ret=exec_pre_cb(msg);
 	if (ret<=0){
 		if (ret<0) goto error;
 		else goto end; /* drop the message -- no error -- andrei */
 	}
a50f3f89
 
caf80ae6
 	/* ... and clear branches from previous message */
 	clear_branches();
 
22d4aa5d
 	if (msg->first_line.type==SIP_REQUEST){
888ca09d
 		/* sanity checks */
34af87af
 		if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
888ca09d
 			/* no via, send back error ? */
e72b5b50
 			LOG(L_ERR, "ERROR: receive_msg: no via found in request\n");
 			goto error;
888ca09d
 		}
f8d46776
 		/* check if neccesarry to add receive?->moved to forward_req */
0a6afa42
 
f20a56a2
 		/* exec routing script */
f8d46776
 		DBG("preparing to run routing scripts...\n");
4f3faaaf
 #ifdef  STATS
 		gettimeofday( & tvb, &tz );
 #endif
caf80ae6
 
22d4aa5d
 		if (run_actions(rlist[0], msg)<0){
caf80ae6
 
4ac74c03
 			LOG(L_WARN, "WARNING: receive_msg: "
f20a56a2
 					"error while trying script\n");
4ac74c03
 			goto error;
 		}
caf80ae6
 
 
4f3faaaf
 #ifdef STATS
 		gettimeofday( & tve, &tz );
 		diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
 		stats->processed_requests++;
 		stats->acc_req_time += diff;
 		DBG("succesfully ran routing scripts...(%d usec)\n", diff);
dda9dab1
 		STATS_RX_REQUEST( msg->first_line.u.request.method_value );
4f3faaaf
 #endif
22d4aa5d
 	}else if (msg->first_line.type==SIP_REPLY){
888ca09d
 		/* sanity checks */
34af87af
 		if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
888ca09d
 			/* no via, send back error ? */
e72b5b50
 			LOG(L_ERR, "ERROR: receive_msg: no via found in reply\n");
 			goto error;
888ca09d
 		}
e22bbdb8
 #if 0
34af87af
 		if ((msg->via2==0) || (msg->via2->error!=PARSE_OK)){
e22bbdb8
 			/* no second via => error? */
e72b5b50
 			LOG(L_ERR, "ERROR: receive_msg: no 2nd via found in reply\n");
 			goto error;
e22bbdb8
 		}
888ca09d
 		/* check if via1 == us */
caf80ae6
 #endif
5b253cc6
 
4f3faaaf
 #ifdef STATS
 		gettimeofday( & tvb, &tz );
9598488f
 		STATS_RX_RESPONSE ( msg->first_line.u.reply.statuscode / 100 );
4f3faaaf
 #endif
888ca09d
 		
 		/* send the msg */
b908cdeb
 		forward_reply(msg);
 
4f3faaaf
 #ifdef STATS
 		gettimeofday( & tve, &tz );
 		diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
 		stats->processed_responses++;
 		stats->acc_res_time+=diff;
 		DBG("succesfully ran reply processing...(%d usec)\n", diff);
 #endif
888ca09d
 	}
43888875
 end:
f571aa35
 #ifdef STATS
 	skipped = 0;
 #endif
caf80ae6
 	/* execute post-script callbacks, if any; -jiri */
 	exec_post_cb(msg);
7f858173
 	DBG("receive_msg: cleaning up\n");
22d4aa5d
 	free_sip_msg(msg);
6fa79282
 	pkg_free(msg);
f571aa35
 #ifdef STATS
dda9dab1
 	if (skipped) STATS_RX_DROPS;
f571aa35
 #endif
888ca09d
 	return 0;
 error:
e72b5b50
 	DBG("error:...\n");
caf80ae6
 	/* execute post-script callbacks, if any; -jiri */
 	exec_post_cb(msg);
 error02:
22d4aa5d
 	free_sip_msg(msg);
6fa79282
 	pkg_free(msg);
caf80ae6
 error00:
dda9dab1
 	STATS_RX_DROPS;
888ca09d
 	return -1;
 }