Ejemplo n.º 1
0
/*! \note WARNING: buf must be 0 terminated (buf[len]=0) or some things might
 * break (e.g.: modules/textops)
 */
int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info)
{
	struct sip_msg* msg;
	struct timeval start;
	int rc;
	char *tmp;
	str in_buff;

	in_buff.len = len;
	in_buff.s = buf;

	/* the raw processing callbacks can change the buffer,
	further use in_buff.s and at the end try to free in_buff.s
	if changed by callbacks */
	run_raw_processing_cb(PRE_RAW_PROCESSING,&in_buff);
	/* update the length for further processing */
	len = in_buff.len;

	msg=pkg_malloc(sizeof(struct sip_msg));
	if (msg==0) {
		LM_ERR("no pkg mem left for sip_msg\n");
		goto error;
	}
	msg_no++;
	/* number of vias parsed -- good for diagnostic info in replies */
	via_cnt=0;

	memset(msg,0, sizeof(struct sip_msg)); /* init everything to 0 */
	/* fill in msg */
	msg->buf=in_buff.s;
	msg->len=len;
	msg->rcv=*rcv_info;
	msg->id=msg_no;
	msg->set_global_address=default_global_address;
	msg->set_global_port=default_global_port;

	if (parse_msg(in_buff.s,len, msg)!=0){
		tmp=ip_addr2a(&(rcv_info->src_ip));
		LM_ERR("Unable to parse msg received from [%s:%d]\n", tmp, rcv_info->src_port);
		/* if a REQUEST msg was detected (first line was succesfully parsed) we
		   should trigger the error route */
		if ( msg->first_line.type==SIP_REQUEST && error_rlist.a!=NULL )
			run_error_route(msg, 1);
		goto parse_error;
	}
	LM_DBG("After parse_msg...\n");

	start_expire_timer(start,execmsgthreshold);

	/* ... clear branches from previous message */
	clear_branches();

	if (msg->first_line.type==SIP_REQUEST) {
		update_stat( rcv_reqs, 1);
		/* sanity checks */
		if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
			/* no via, send back error ? */
			LM_ERR("no via found in request\n");
			update_stat( err_reqs, 1);
			goto parse_error;
		}
		/* check if necessary to add receive?->moved to forward_req */
		/* check for the alias stuff */
#ifdef USE_TCP
		if (msg->via1->alias && tcp_accept_aliases &&
				(((rcv_info->proto==PROTO_TCP) && !tcp_disable)
#ifdef USE_TLS
					|| ((rcv_info->proto==PROTO_TLS) && !tls_disable)
#endif
				)
			){
			if (tcpconn_add_alias(rcv_info->proto_reserved1, msg->via1->port,
									rcv_info->proto)!=0){
				LM_ERR("tcp alias failed\n");
				/* continue */
			}
		}
#endif

		LM_DBG("preparing to run routing scripts...\n");
		/* set request route type --bogdan*/
		set_route_type( REQUEST_ROUTE );

		/* execute pre-script callbacks, if any;
		 * if some of the callbacks said not to continue with
		 * script processing, don't do so;
		 * if we are here basic sanity checks are already done
		 * (like presence of at least one via), so you can count
		 * on via1 being parsed in a pre-script callback --andrei
		 */
		rc = exec_pre_req_cb(msg);
		if (rc == SCB_DROP_MSG) {
			update_stat( drp_reqs, 1);
			goto end; /* drop the message */
		}

		/* exec the routing script */
		if (rc & SCB_RUN_TOP_ROUTE)
			run_top_route(rlist[DEFAULT_RT].a, msg);

		/* execute post request-script callbacks */
		if (rc & SCB_RUN_POST_CBS)
			exec_post_req_cb(msg);

	} else if (msg->first_line.type==SIP_REPLY) {
		update_stat( rcv_rpls, 1);
		/* sanity checks */
		if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
			/* no via, send back error ? */
			LM_ERR("no via found in reply\n");
			update_stat( err_rpls, 1);
			goto parse_error;
		}

		/* set reply route type --bogdan*/
		set_route_type( ONREPLY_ROUTE );

		/* execute pre-script callbacks, if any ;
		 * if some of the callbacks said not to continue with
		 * script processing, don't do so ;
		 * if we are here, basic sanity checks are already done
		 * (like presence of at least one via), so you can count
		 * on via1 being parsed in a pre-script callback --andrei
		 */
		rc = exec_pre_rpl_cb(msg);
		if (rc == SCB_DROP_MSG) {
			update_stat( drp_rpls, 1);
			goto end; /* drop the reply */
		}

		/* exec the onreply routing script */
		if (rc & SCB_RUN_TOP_ROUTE &&  onreply_rlist[DEFAULT_RT].a &&
		    (run_top_route(onreply_rlist[DEFAULT_RT].a,msg) & ACT_FL_DROP)
		    && msg->REPLY_STATUS < 200) {

			LM_DBG("dropping provisional reply %d\n", msg->REPLY_STATUS);
			update_stat( drp_rpls, 1);
			goto end; /* drop the message */
		} else {
			/* send the msg */
			forward_reply(msg);
			/* TODO - TX reply stat */
		}

		/* execute post reply-script callbacks */
		if (rc & SCB_RUN_POST_CBS)
			exec_post_rpl_cb(msg);
	}

end:
	stop_expire_timer( start, execmsgthreshold, "msg processing",
		msg->buf, msg->len, 0);
	reset_longest_action_list(execmsgthreshold);

	/* free possible loaded avps -bogdan */
	reset_avps();
	LM_DBG("cleaning up\n");
	free_sip_msg(msg);
	pkg_free(msg);
	if (in_buff.s != buf)
		pkg_free(in_buff.s);
	return 0;
parse_error:
	exec_parse_err_cb(msg);
	free_sip_msg(msg);
	pkg_free(msg);
error:
	if (in_buff.s != buf)
		pkg_free(in_buff.s);
	return -1;
}
Ejemplo n.º 2
0
/* WARNING: buf must be 0 terminated (buf[len]=0) or some things might 
 * break (e.g.: modules/textops)
 */
int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info) 
{
	struct sip_msg* msg;
	int ret;
#ifdef STATS
	int skipped = 1;
	struct timeval tvb, tve;	
	struct timezone tz;
	unsigned int diff;
#endif

	msg=pkg_malloc(sizeof(struct sip_msg));
	if (msg==0) {
		LOG(L_ERR, "ERROR: receive_msg: no mem for sip_msg\n");
		goto error00;
	}
	msg_no++;
	/* number of vias parsed -- good for diagnostic info in replies */
	via_cnt=0;

	memset(msg,0, sizeof(struct sip_msg)); /* init everything to 0 */
	/* fill in msg */
	msg->buf=buf;
	msg->len=len;
	/* zero termination (termination of orig message bellow not that
	   useful as most of the work is done with scratch-pad; -jiri  */
	/* buf[len]=0; */ /* WARNING: zero term removed! */
	msg->rcv=*rcv_info;
	msg->id=msg_no;
	msg->set_global_address=default_global_address;
	msg->set_global_port=default_global_port;
	
	if (parse_msg(buf,len, msg)!=0){
		LOG(L_ERR, "ERROR: receive_msg: parse_msg failed\n");
		goto error02;
	}
	DBG("After parse_msg...\n");


	/* ... clear branches from previous message */
	clear_branches();
	reset_static_buffer();

	if (msg->first_line.type==SIP_REQUEST){
		if (!IS_SIP(msg)){
			if (nonsip_msg_run_hooks(msg)!=NONSIP_MSG_ACCEPT);
				goto end; /* drop the message */
		}
		/* sanity checks */
		if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
			/* no via, send back error ? */
			LOG(L_ERR, "ERROR: receive_msg: no via found in request\n");
			goto error02;
		}
		/* check if necessary to add receive?->moved to forward_req */
		/* check for the alias stuff */
#ifdef USE_TCP
		if (msg->via1->alias && tcp_accept_aliases && 
				(((rcv_info->proto==PROTO_TCP) && !tcp_disable)
#ifdef USE_TLS
					|| ((rcv_info->proto==PROTO_TLS) && !tls_disable)
#endif
				)
			){
			if (tcpconn_add_alias(rcv_info->proto_reserved1, msg->via1->port,
									rcv_info->proto)!=0){
				LOG(L_ERR, " ERROR: receive_msg: tcp alias failed\n");
				/* continue */
			}
		}
#endif
			
	/*	skip: */
		DBG("preparing to run routing scripts...\n");
#ifdef  STATS
		gettimeofday( & tvb, &tz );
#endif
		/* execute pre-script callbacks, if any; -jiri */
		/* if some of the callbacks said not to continue with
		   script processing, don't do so
		   if we are here basic sanity checks are already done
		   (like presence of at least one via), so you can count
		   on via1 being parsed in a pre-script callback --andrei
		*/
		if (exec_pre_req_cb(msg)==0 )
			goto end; /* drop the request */

		/* exec the routing script */
		if (run_actions(main_rt.rlist[DEFAULT_RT], msg)<0){
			LOG(L_WARN, "WARNING: receive_msg: "
					"error while trying script\n");
			goto error_req;
		}

#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("successfully ran routing scripts...(%d usec)\n", diff);
		STATS_RX_REQUEST( msg->first_line.u.request.method_value );
#endif

		/* execute post request-script callbacks */
		exec_post_req_cb(msg);
	}else if (msg->first_line.type==SIP_REPLY){
		/* sanity checks */
		if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
			/* no via, send back error ? */
			LOG(L_ERR, "ERROR: receive_msg: no via found in reply\n");
			goto error02;
		}

#ifdef STATS
		gettimeofday( & tvb, &tz );
		STATS_RX_RESPONSE ( msg->first_line.u.reply.statuscode / 100 );
#endif
		
		/* execute pre-script callbacks, if any; -jiri */
		/* if some of the callbacks said not to continue with
		   script processing, don't do so
		   if we are here basic sanity checks are already done
		   (like presence of at least one via), so you can count
		   on via1 being parsed in a pre-script callback --andrei
		*/
		if (exec_pre_rpl_cb(msg)==0 )
			goto end; /* drop the request */
		/* exec the onreply routing script */
		if (onreply_rt.rlist[DEFAULT_RT]){
			ret=run_actions(onreply_rt.rlist[DEFAULT_RT], msg);
			if (ret<0){
				LOG(L_WARN, "WARNING: receive_msg: "
						"error while trying onreply script\n");
				goto error_rpl;
			}else if (ret==0) goto skip_send_reply; /* drop the message, 
													   no error */
		}
		/* send the msg */
		forward_reply(msg);
	skip_send_reply:
#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("successfully ran reply processing...(%d usec)\n", diff);
#endif

		/* execute post reply-script callbacks */
		exec_post_rpl_cb(msg);
	}

end:
#ifdef STATS
	skipped = 0;
#endif
	/* free possible loaded avps -bogdan */
	reset_avps();
	DBG("receive_msg: cleaning up\n");
	free_sip_msg(msg);
	pkg_free(msg);
#ifdef STATS
	if (skipped) STATS_RX_DROPS;
#endif
	return 0;
error_rpl:
	/* execute post reply-script callbacks */
	exec_post_rpl_cb(msg);
	reset_avps();
	goto error02;
error_req:
	DBG("receive_msg: error:...\n");
	/* execute post request-script callbacks */
	exec_post_req_cb(msg);
	/* free possible loaded avps -bogdan */
	reset_avps();
error02:
	free_sip_msg(msg);
	pkg_free(msg);
error00:
	STATS_RX_DROPS;
	return -1;
}