events.c
85acffe1
 /**
  * Copyright (C) 2009 SIP-Router.org
  *
6a0f4382
  * This file is part of Kamailio, a free SIP server.
85acffe1
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  * copyright notice and this permission notice appear in all copies.
  *
  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
1d0661db
 /*!
  * \file
88693a29
  * \brief Kamailio core :: event handling
1d0661db
  * \ingroup core
  * Module: \ref core
  */
 
85acffe1
 #include "dprint.h"
 #include "mem/mem.h"
2d826efb
 #include "route.h"
85acffe1
 #include "events.h"
 
 static sr_event_cb_t _sr_events_list;
 static int _sr_events_inited = 0;
 
2d826efb
 typedef struct _sr_core_ert {
 	int init_parse_error;
 } sr_core_ert_t;
 
 static sr_core_ert_t _sr_core_ert_list;
 
 /**
  *
  */
 void sr_core_ert_init(void)
 {
 	memset(&_sr_core_ert_list, 0, sizeof(sr_core_ert_t));
 	/* 0 - is not a valid index in event_route blocks list */
 	_sr_core_ert_list.init_parse_error = route_get(&event_rt,
 											"core:receive-parse-error");
86bdfaa3
 	if(_sr_core_ert_list.init_parse_error<=0
 				|| event_rt.rlist[_sr_core_ert_list.init_parse_error]==NULL) {
2d826efb
 		_sr_core_ert_list.init_parse_error = -1;
86bdfaa3
 	} else {
 		LM_DBG("event_route[core:receive-parse-error] is defined\n");
2d826efb
 	}
 }
 
 /**
  *
  */
 void sr_core_ert_run(sip_msg_t *msg, int e)
 {
fd68623b
 	struct run_act_ctx ctx;
 	int rtb;
 
2d826efb
 	switch(e) {
 		case SR_CORE_ERT_RECEIVE_PARSE_ERROR:
 			if(likely(_sr_core_ert_list.init_parse_error<=0))
 				return;
fd68623b
 			rtb = get_route_type();
 			set_route_type(REQUEST_ROUTE);
 			init_run_actions_ctx(&ctx);
 			run_top_route(event_rt.rlist[_sr_core_ert_list.init_parse_error],
 					msg, &ctx);
 			set_route_type(rtb);
2d826efb
 		break;
 	}
 }
 
70e7b570
 /**
  *
  */
85acffe1
 void sr_event_cb_init(void)
 {
 	if(_sr_events_inited == 0)
 	{
 		memset(&_sr_events_list, 0, sizeof(sr_event_cb_t));
 		_sr_events_inited = 1;
 	}
 }
 
70e7b570
 /**
  *
  */
85acffe1
 int sr_event_register_cb(int type, sr_event_cb_f f)
 {
1f1705a6
 	int i;
 
85acffe1
 	sr_event_cb_init();
 	switch(type) {
 		case SREV_NET_DATA_IN:
1f1705a6
 				for(i=0; i<SREV_CB_LIST_SIZE; i++) {
 					if(_sr_events_list.net_data_in[i]==0) {
 						_sr_events_list.net_data_in[i] = f;
 						break;
 					}
 				}
 				if(i==SREV_CB_LIST_SIZE) return -1;
85acffe1
 			break;
 		case SREV_NET_DATA_OUT:
1f1705a6
 				for(i=SREV_CB_LIST_SIZE-1; i>=0; i--) {
 					if(_sr_events_list.net_data_out[i]==0) {
 						_sr_events_list.net_data_out[i] = f;
 						break;
 					}
 				}
 				if(i<0) return -1;
85acffe1
 			break;
13959998
 		case SREV_CORE_STATS:
 				if(_sr_events_list.core_stats==0)
 					_sr_events_list.core_stats = f;
 				else return -1;
 			break;
1a7ef918
 		case SREV_CFG_RUN_ACTION:
 				if(_sr_events_list.run_action==0)
 					_sr_events_list.run_action = f;
 				else return -1;
 			break;
bccf5cd0
 		case SREV_PKG_UPDATE_STATS:
 				if(_sr_events_list.pkg_update_stats==0)
 					_sr_events_list.pkg_update_stats = f;
70e7b570
 				else return -1;
 			break;
178b21cc
 		case SREV_NET_DGRAM_IN:
 				if(_sr_events_list.net_dgram_in==0)
 					_sr_events_list.net_dgram_in = f;
 				else return -1;
 			break;
51655771
 		case SREV_TCP_HTTP_100C:
 				if(_sr_events_list.tcp_http_100c==0)
 					_sr_events_list.tcp_http_100c = f;
 				else return -1;
 			break;
 		case SREV_TCP_MSRP_FRAME:
 				if(_sr_events_list.tcp_msrp_frame==0)
 					_sr_events_list.tcp_msrp_frame = f;
 				else return -1;
 			break;
1f139814
 		case SREV_TCP_WS_FRAME_IN:
 				if(_sr_events_list.tcp_ws_frame_in==0)
 					_sr_events_list.tcp_ws_frame_in = f;
 				else return -1;
 			break;
 		case SREV_TCP_WS_FRAME_OUT:
 				if(_sr_events_list.tcp_ws_frame_out==0)
 					_sr_events_list.tcp_ws_frame_out = f;
3ec46961
 				else return -1;
 			break;
c573aa70
 		case SREV_STUN_IN:
 				if(_sr_events_list.stun_in==0)
 					_sr_events_list.stun_in = f;
 				else return -1;
 			break;
ac0bd379
 		case SREV_RCV_NOSIP:
 				if(_sr_events_list.rcv_nosip==0)
 					_sr_events_list.rcv_nosip = f;
 				else return -1;
 			break;
85acffe1
 		default:
 			return -1;
 	}
 	return 0;
 }
 
70e7b570
 /**
  *
  */
85acffe1
 int sr_event_exec(int type, void *data)
 {
 	int ret;
1f1705a6
 	int i;
e4a75063
 #ifdef EXTRA_DEBUG
85acffe1
 	str *p;
e4a75063
 #endif /* EXTRA_DEBUG */
85acffe1
 	switch(type) {
 		case SREV_NET_DATA_IN:
1f1705a6
 				if(unlikely(_sr_events_list.net_data_in[0]!=0))
85acffe1
 				{
da5d964b
 #ifdef EXTRA_DEBUG
e4a75063
 					p = (str*)data;
85acffe1
 					LM_DBG("PRE-IN ++++++++++++++++++++++++++++++++\n"
 							"%.*s\n+++++\n", p->len, p->s);
da5d964b
 #endif /* EXTRA_DEBUG */
1f1705a6
 					ret = 0;
 					for(i=0; i<SREV_CB_LIST_SIZE
6435d8a8
 							&& _sr_events_list.net_data_in[i]; i++) {
1f1705a6
 						ret |= _sr_events_list.net_data_in[i](data);
 					}
da5d964b
 #ifdef EXTRA_DEBUG
85acffe1
 					LM_DBG("POST-IN ++++++++++++++++++++++++++++++++\n"
 							"%.*s\n+++++\n", p->len, p->s);
da5d964b
 #endif /* EXTRA_DEBUG */
85acffe1
 					return ret;
 				} else return 1;
 			break;
 		case SREV_NET_DATA_OUT:
1f1705a6
 				if(unlikely(_sr_events_list.net_data_out[SREV_CB_LIST_SIZE-1]!=0))
85acffe1
 				{
da5d964b
 #ifdef EXTRA_DEBUG
e4a75063
 					p = (str*)data;
85acffe1
 					LM_DBG("PRE-OUT ++++++++++++++++++++\n"
 							"%.*s\n+++++++++++++++++++\n", p->len, p->s);
da5d964b
 #endif /* EXTRA_DEBUG */
1f1705a6
 					ret = 0;
3b159696
 					for(i=0; i<SREV_CB_LIST_SIZE; i++) {
 						if(_sr_events_list.net_data_out[i]) {
 							ret |= _sr_events_list.net_data_out[i](data);
 						}
1f1705a6
 					}
da5d964b
 #ifdef EXTRA_DEBUG
85acffe1
 					LM_DBG("POST-OUT ++++++++++++++++++++\n"
 							"%.*s\n+++++++++++++++++++\n", p->len, p->s);
da5d964b
 #endif /* EXTRA_DEBUG */
85acffe1
 					return ret;
 				} else return 1;
 			break;
13959998
 		case SREV_CORE_STATS:
 				if(unlikely(_sr_events_list.core_stats!=0))
 				{
 					ret = _sr_events_list.core_stats(data);
 					return ret;
 				} else return 1;
 			break;
1a7ef918
 		case SREV_CFG_RUN_ACTION:
 				if(unlikely(_sr_events_list.run_action!=0))
 				{
 					ret = _sr_events_list.run_action(data);
 					return ret;
 				} else return 1;
bccf5cd0
 		case SREV_PKG_UPDATE_STATS:
 				if(unlikely(_sr_events_list.pkg_update_stats!=0))
70e7b570
 				{
bccf5cd0
 					ret = _sr_events_list.pkg_update_stats(data);
70e7b570
 					return ret;
 				} else return 1;
178b21cc
 		case SREV_NET_DGRAM_IN:
 				if(unlikely(_sr_events_list.net_dgram_in!=0))
 				{
 					ret = _sr_events_list.net_dgram_in(data);
 					return ret;
 				} else return 1;
51655771
 		case SREV_TCP_HTTP_100C:
 				if(unlikely(_sr_events_list.tcp_http_100c!=0))
 				{
 					ret = _sr_events_list.tcp_http_100c(data);
 					return ret;
 				} else return 1;
 		case SREV_TCP_MSRP_FRAME:
 				if(unlikely(_sr_events_list.tcp_msrp_frame!=0))
 				{
 					ret = _sr_events_list.tcp_msrp_frame(data);
 					return ret;
 				} else return 1;
1f139814
 		case SREV_TCP_WS_FRAME_IN:
 				if(unlikely(_sr_events_list.tcp_ws_frame_in!=0))
 				{
 					ret = _sr_events_list.tcp_ws_frame_in(data);
 					return ret;
 				} else return 1;
 		case SREV_TCP_WS_FRAME_OUT:
 				if(unlikely(_sr_events_list.tcp_ws_frame_out!=0))
3ec46961
 				{
1f139814
 					ret = _sr_events_list.tcp_ws_frame_out(data);
3ec46961
 					return ret;
 				} else return 1;
c573aa70
 		case SREV_STUN_IN:
 				if(unlikely(_sr_events_list.stun_in!=0))
 				{
 					ret = _sr_events_list.stun_in(data);
 					return ret;
 				} else return 1;
ac0bd379
 		case SREV_RCV_NOSIP:
 				if(unlikely(_sr_events_list.rcv_nosip!=0))
 				{
 					ret = _sr_events_list.rcv_nosip(data);
 					return ret;
 				} else return 1;
85acffe1
 		default:
 			return -1;
 	}
 }
 
70e7b570
 /**
  *
  */
2ac66302
 int sr_event_enabled(int type)
 {
 	switch(type) {
 		case SREV_NET_DATA_IN:
1f1705a6
 				return (_sr_events_list.net_data_in[0]!=0)?1:0;
2ac66302
 		case SREV_NET_DATA_OUT:
1f1705a6
 				return (_sr_events_list.net_data_out[SREV_CB_LIST_SIZE-1]!=0)?1:0;
2ac66302
 		case SREV_CORE_STATS:
 				return (_sr_events_list.core_stats!=0)?1:0;
 		case SREV_CFG_RUN_ACTION:
 				return (_sr_events_list.run_action!=0)?1:0;
bccf5cd0
 		case SREV_PKG_UPDATE_STATS:
 				return (_sr_events_list.pkg_update_stats!=0)?1:0;
8958a14e
 		case SREV_NET_DGRAM_IN:
 				return (_sr_events_list.net_dgram_in!=0)?1:0;
51655771
 		case SREV_TCP_HTTP_100C:
 				return (_sr_events_list.tcp_http_100c!=0)?1:0;
 		case SREV_TCP_MSRP_FRAME:
 				return (_sr_events_list.tcp_msrp_frame!=0)?1:0;
1f139814
 		case SREV_TCP_WS_FRAME_IN:
 				return (_sr_events_list.tcp_ws_frame_in!=0)?1:0;
 		case SREV_TCP_WS_FRAME_OUT:
 				return (_sr_events_list.tcp_ws_frame_out!=0)?1:0;
c573aa70
 		case SREV_STUN_IN:
 				return (_sr_events_list.stun_in!=0)?1:0;
ac0bd379
 		case SREV_RCV_NOSIP:
 				return (_sr_events_list.rcv_nosip!=0)?1:0;
2ac66302
 	}
 	return 0;
 }