瀏覽代碼

- epxerimental TMCB_LOCAL_REQUEST_IN callback: must be registered from mod_init (before forking) and is called each time a new local transaction is created
(e.g. t_uac called from fifo/rpc).

Andrei Pelinescu-Onciul 18 年之前
父節點
當前提交
5c953757db
共有 4 個文件被更改,包括 151 次插入51 次删除
  1. 12 7
      modules/tm/h_table.c
  2. 110 40
      modules/tm/t_hooks.c
  3. 26 4
      modules/tm/t_hooks.h
  4. 3 0
      modules/tm/uac.c

+ 12 - 7
modules/tm/h_table.c

@@ -266,32 +266,37 @@ struct cell*  build_cell( struct sip_msg* p_msg )
 	/* timers */
 	init_cell_timers(new_cell);
 
-	old = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI,  &new_cell->uri_avps_from );
+	old = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, 
+			&new_cell->uri_avps_from );
 	new_cell->uri_avps_from = *old;
 	*old = 0;
 
-	old = set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI,  &new_cell->uri_avps_to );
+	old = set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, 
+			&new_cell->uri_avps_to );
 	new_cell->uri_avps_to = *old;
 	*old = 0;
 
-	old = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER,  &new_cell->user_avps_from );
+	old = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, 
+			&new_cell->user_avps_from );
 	new_cell->user_avps_from = *old;
 	*old = 0;
 
-	old = set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER,  &new_cell->user_avps_to );
+	old = set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, 
+			&new_cell->user_avps_to );
 	new_cell->user_avps_to = *old;
 	*old = 0;
 
 	     /* We can just store pointer to domain avps in the transaction context,
 	      * because they are read-only
 	      */
-	new_cell->domain_avps_from = get_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN);
+	new_cell->domain_avps_from = get_avp_list(AVP_TRACK_FROM | 
+								AVP_CLASS_DOMAIN);
 	new_cell->domain_avps_to = get_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN);
 
 	/* enter callback, which may potentially want to parse some stuff,
 	 * before the request is shmem-ized */
-	if ( p_msg && has_reqin_tmcbs() )
-		run_reqin_callbacks( new_cell, p_msg, p_msg->REQ_METHOD);
+	if (p_msg && has_reqin_tmcbs())
+			run_reqin_callbacks( new_cell, p_msg, p_msg->REQ_METHOD);
 
 	if (p_msg) {
 		/* clean possible previous added vias/clen header or else they would 

+ 110 - 40
modules/tm/t_hooks.c

@@ -35,6 +35,7 @@
  *              available in callbacks (bogdan)
  * 2007-03-08  membar_write() used in insert_tmcb(...) (andrei)
  * 2007-03-14  added *_SENT callbacks (andrei)
+ * 2007-03-23  added local_req_in callbacks support (andrei)
  */
 
 #include "defs.h"
@@ -52,6 +53,7 @@
 
 
 struct tmcb_head_list* req_in_tmcb_hl = 0;
+struct tmcb_head_list* local_req_in_tmcb_hl = 0;
 
 
 
@@ -59,13 +61,27 @@ int init_tmcb_lists()
 {
 	req_in_tmcb_hl = (struct tmcb_head_list*)shm_malloc
 		( sizeof(struct tmcb_head_list) );
-	if (req_in_tmcb_hl==0) {
+	local_req_in_tmcb_hl = (struct tmcb_head_list*)shm_malloc
+		( sizeof(struct tmcb_head_list) );
+	if ((req_in_tmcb_hl==0) || (local_req_in_tmcb_hl==0)) {
 		LOG(L_CRIT,"ERROR:tm:init_tmcb_lists: no more shared mem\n");
-		return -1;
+		goto error;
 	}
 	req_in_tmcb_hl->first = 0;
 	req_in_tmcb_hl->reg_types = 0;
+	local_req_in_tmcb_hl->first = 0;
+	local_req_in_tmcb_hl->reg_types = 0;
 	return 1;
+error:
+	if (req_in_tmcb_hl){
+		shm_free(req_in_tmcb_hl);
+		req_in_tmcb_hl=0;
+	}
+	if(local_req_in_tmcb_hl){
+		shm_free(local_req_in_tmcb_hl);
+		local_req_in_tmcb_hl=0;
+	}
+	return -1;
 }
 
 
@@ -73,17 +89,26 @@ void destroy_tmcb_lists()
 {
 	struct tm_callback *cbp, *cbp_tmp;
 
-	if (!req_in_tmcb_hl)
-		return;
-
-	for( cbp=req_in_tmcb_hl->first; cbp ; ) {
-		cbp_tmp = cbp;
-		cbp = cbp->next;
-		if (cbp_tmp->param) shm_free( cbp_tmp->param );
-		shm_free( cbp_tmp );
+	if (req_in_tmcb_hl){
+		for( cbp=req_in_tmcb_hl->first; cbp ; ) {
+			cbp_tmp = cbp;
+			cbp = cbp->next;
+			if (cbp_tmp->param) shm_free( cbp_tmp->param );
+			shm_free( cbp_tmp );
+		}
+		shm_free(req_in_tmcb_hl);
+		req_in_tmcb_hl=0;
+	}
+	if(local_req_in_tmcb_hl){
+		for( cbp=local_req_in_tmcb_hl->first; cbp ; ) {
+			cbp_tmp = cbp;
+			cbp = cbp->next;
+			if (cbp_tmp->param) shm_free( cbp_tmp->param );
+			shm_free( cbp_tmp );
+		}
+		shm_free(local_req_in_tmcb_hl);
+		local_req_in_tmcb_hl=0;
 	}
-
-	shm_free(req_in_tmcb_hl);
 }
 
 
@@ -130,8 +155,8 @@ int insert_tmcb(struct tmcb_head_list *cb_list, int types,
  * (global or per transaction, depending of event type)
  * It _must_ be always called either with the REPLY_LOCK held, or before the
  *  branches are created.
- *  Special case: TMCB_REQUEST_IN - it must be called from mod_init
- *  (before forking!).
+ *  Special cases: TMCB_REQUEST_IN & TMCB_LOCAL_REQUEST_IN - must be called 
+ *                 from mod_init (before forking!).
 */
 int register_tmcb( struct sip_msg* p_msg, struct cell *t, int types,
 											transaction_cb f, void *param )
@@ -158,6 +183,14 @@ int register_tmcb( struct sip_msg* p_msg, struct cell *t, int types,
 			return E_BUG;
 		}
 		cb_list = req_in_tmcb_hl;
+	}else if (types & TMCB_LOCAL_REQUEST_IN) {
+		if (types!=TMCB_LOCAL_REQUEST_IN) {
+			LOG(L_CRIT, "BUG:tm:register_tmcb: callback type"
+					" TMCB_LOCAL_REQUEST_IN can't be register along with"
+					" other types\n");
+			return E_BUG;
+		}
+		cb_list = local_req_in_tmcb_hl;
 	} else {
 		if (!t) {
 			if (!p_msg) {
@@ -189,12 +222,18 @@ static void run_trans_callbacks_internal(int type, struct cell *trans,
 	struct tm_callback    *cbp;
 	avp_list_t* backup_from, *backup_to, *backup_dom_from, *backup_dom_to, *backup_uri_from, *backup_uri_to;
 
-	backup_uri_from = set_avp_list(AVP_CLASS_URI | AVP_TRACK_FROM, &trans->uri_avps_from );
-	backup_uri_to = set_avp_list(AVP_CLASS_URI | AVP_TRACK_TO, &trans->uri_avps_to );
-	backup_from = set_avp_list(AVP_CLASS_USER | AVP_TRACK_FROM, &trans->user_avps_from );
-	backup_to = set_avp_list(AVP_CLASS_USER | AVP_TRACK_TO, &trans->user_avps_to );
-	backup_dom_from = set_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_FROM, &trans->domain_avps_from);
-	backup_dom_to = set_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_TO, &trans->domain_avps_to);
+	backup_uri_from = set_avp_list(AVP_CLASS_URI | AVP_TRACK_FROM,
+			&trans->uri_avps_from );
+	backup_uri_to = set_avp_list(AVP_CLASS_URI | AVP_TRACK_TO, 
+			&trans->uri_avps_to );
+	backup_from = set_avp_list(AVP_CLASS_USER | AVP_TRACK_FROM, 
+			&trans->user_avps_from );
+	backup_to = set_avp_list(AVP_CLASS_USER | AVP_TRACK_TO, 
+			&trans->user_avps_to );
+	backup_dom_from = set_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_FROM, 
+			&trans->domain_avps_from);
+	backup_dom_to = set_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_TO, 
+			&trans->domain_avps_to);
 	for (cbp=trans->tmcb_hl.first; cbp; cbp=cbp->next)  {
 		if ( (cbp->types)&type ) {
 			DBG("DBG: trans=%p, callback type %d, id %d entered\n",
@@ -275,30 +314,31 @@ void run_onsend_callbacks2(int type , struct retr_buf* rbuf, char* buf,
 
 #endif
 
-void run_reqin_callbacks( struct cell *trans, struct sip_msg *req, int code )
+static void run_reqin_callbacks_internal(struct tmcb_head_list* hl,
+							struct cell *trans, struct tmcb_params* params)
 {
-	static struct tmcb_params params;
 	struct tm_callback    *cbp;
-	avp_list_t* backup_from, *backup_to, *backup_dom_from, *backup_dom_to, *backup_uri_from, *backup_uri_to;
-
-	if (req_in_tmcb_hl->first==0)
-		return;
-	memset (&params, 0, sizeof(params));
-	params.req = req;
-	params.code = code;
-
-
-	backup_uri_from = set_avp_list(AVP_CLASS_URI | AVP_TRACK_FROM, &trans->uri_avps_from );
-	backup_uri_to = set_avp_list(AVP_CLASS_URI | AVP_TRACK_TO, &trans->uri_avps_to );
-	backup_from = set_avp_list(AVP_CLASS_USER | AVP_TRACK_FROM, &trans->user_avps_from );
-	backup_to = set_avp_list(AVP_CLASS_USER | AVP_TRACK_TO, &trans->user_avps_to );
-	backup_dom_from = set_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_FROM, &trans->domain_avps_from);
-	backup_dom_to = set_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_TO, &trans->domain_avps_to);
-	for (cbp=req_in_tmcb_hl->first; cbp; cbp=cbp->next)  {
+	avp_list_t* backup_from, *backup_to, *backup_dom_from, *backup_dom_to,
+				*backup_uri_from, *backup_uri_to;
+
+	if (hl==0 || hl->first==0) return;
+	backup_uri_from = set_avp_list(AVP_CLASS_URI | AVP_TRACK_FROM,
+			&trans->uri_avps_from );
+	backup_uri_to = set_avp_list(AVP_CLASS_URI | AVP_TRACK_TO, 
+			&trans->uri_avps_to );
+	backup_from = set_avp_list(AVP_CLASS_USER | AVP_TRACK_FROM, 
+			&trans->user_avps_from );
+	backup_to = set_avp_list(AVP_CLASS_USER | AVP_TRACK_TO, 
+			&trans->user_avps_to );
+	backup_dom_from = set_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_FROM, 
+			&trans->domain_avps_from);
+	backup_dom_to = set_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_TO, 
+			&trans->domain_avps_to);
+	for (cbp=hl->first; cbp; cbp=cbp->next)  {
 		DBG("DBG: trans=%p, callback type %d, id %d entered\n",
 			trans, cbp->types, cbp->id );
-		params.param = &(cbp->param);
-		cbp->callback( trans, cbp->types, &params );
+		params->param = &(cbp->param);
+		cbp->callback( trans, cbp->types, params );
 	}
 	set_avp_list(AVP_CLASS_URI | AVP_TRACK_TO, backup_uri_to );
 	set_avp_list(AVP_CLASS_URI | AVP_TRACK_FROM, backup_uri_from );
@@ -307,3 +347,33 @@ void run_reqin_callbacks( struct cell *trans, struct sip_msg *req, int code )
 	set_avp_list(AVP_CLASS_USER | AVP_TRACK_TO, backup_to );
 	set_avp_list(AVP_CLASS_USER | AVP_TRACK_FROM, backup_from );
 }
+
+
+
+void run_reqin_callbacks( struct cell *trans, struct sip_msg *req, int code )
+{
+	static struct tmcb_params params;
+
+	if (req_in_tmcb_hl->first==0)
+		return;
+	memset (&params, 0, sizeof(params));
+	params.req = req;
+	params.code = code;
+	
+	run_reqin_callbacks_internal(req_in_tmcb_hl, trans, &params);
+}
+
+
+void run_local_reqin_callbacks( struct cell *trans, struct sip_msg *req,
+								int code )
+{
+	static struct tmcb_params params;
+
+	if (local_req_in_tmcb_hl->first==0)
+		return;
+	memset (&params, 0, sizeof(params));
+	params.req = req;
+	params.code = code;
+	
+	run_reqin_callbacks_internal(local_req_in_tmcb_hl, trans, &params);
+}

+ 26 - 4
modules/tm/t_hooks.h

@@ -34,6 +34,7 @@
  * 2007-03-14   added *_SENT callbacks (andrei)
  * 2007-03-17   added TMCB_NEG_ACK_IN, TMCB_REQ_RETR_IN & 
  *               TMCB_LOCAL_RESPONSE_IN (andrei)
+ * 2007-03-23   added TMCB_LOCAL_REQUEST_IN (andrei)
  */
 
 
@@ -67,12 +68,13 @@ struct cell;
 #define TMCB_ACK_NEG_IN_N       10
 #define TMCB_REQ_RETR_IN_N      11
 #define TMCB_LOCAL_RESPONSE_IN_N 12
+#define TMCB_LOCAL_REQUEST_IN_N  13
 #ifdef TMCB_ONSEND
-#define TMCB_REQUEST_SENT_N     13
-#define TMCB_RESPONSE_SENT_N    14
-#define TMCB_MAX_N              14
+#define TMCB_REQUEST_SENT_N     14
+#define TMCB_RESPONSE_SENT_N    15
+#define TMCB_MAX_N              15
 #else
-#define TMCB_MAX_N              12
+#define TMCB_MAX_N              13
 #endif
 
 #define TMCB_REQUEST_IN       (1<<TMCB_REQUEST_IN_N)
@@ -88,6 +90,7 @@ struct cell;
 #define TMCB_ACK_NEG_IN       (1<<TMCB_ACK_NEG_IN_N)
 #define TMCB_REQ_RETR_IN      (1<<TMCB_REQ_RETR_IN_N)
 #define TMCB_LOCAL_RESPONSE_IN (1<<TMCB_LOCAL_RESPONSE_IN_N)
+#define TMCB_LOCAL_REQUEST_IN (1<<TMCB_LOCAL_REQUEST_IN_N)
 #ifdef TMCB_ONSEND
 #define TMCB_REQUEST_SENT      (1<<TMCB_REQUEST_SENT_N)
 #define TMCB_RESPONSE_SENT     (1<<TMCB_RESPONSE_SENT_N)
@@ -239,6 +242,20 @@ struct cell;
  * transactions). It may or may not be a retransmission.
  * No lock is held here (yet). It's unsafe to register other TMCB callbacks.
  *
+ * TMCB_LOCAL_REQUEST_IN -- like TMCB_REQUEST_IN but for locally generated 
+ * request (e.g. via fifo/rpc):  a brand-new local request was 
+ * received/generated and a transaction for it is about to be created.
+ * It's called from HASH_LOCK, so be careful. It is guaranteed not to be
+ * a retransmission. The transactional context is mostly
+ * incomplete -- this callback is called in very early stage
+ * before the message is shmem-ized (so that you can work
+ * with it).
+ * It's safe to install other TMCB callbacks from here.
+ * Note: this callback MUST be installed before forking
+ * (the local_req_in_tmcb_hl callback list does not live in shmem and has no 
+ * access protection), i.e., at best from mod_init functions.
+ *
+ *
  *  All of the following callbacks are called immediately after or before 
  *  sending a message. All of them are read-only (no change can be made to
  * the message). These callbacks use the t_rbuf, send_buf, dst, is_retr
@@ -327,12 +344,15 @@ struct tmcb_head_list {
 
 
 extern struct tmcb_head_list*  req_in_tmcb_hl;
+extern struct tmcb_head_list*  local_req_in_tmcb_hl;
 
 
 #define has_tran_tmcbs(_T_, _types_) \
 	( ((_T_)->tmcb_hl.reg_types)|(_types_) )
 #define has_reqin_tmcbs() \
 	( req_in_tmcb_hl->first!=0 )
+#define has_local_reqin_tmcbs() \
+	( local_req_in_tmcb_hl->first!=0 )
 
 
 int init_tmcb_lists();
@@ -354,6 +374,8 @@ void run_trans_callbacks( int type , struct cell *trans,
 
 /* run all REQUEST_IN callbacks */
 void run_reqin_callbacks( struct cell *trans, struct sip_msg *req, int code );
+void run_local_reqin_callbacks( struct cell *trans, struct sip_msg *req, 
+		int code );
 
 #ifdef TMCB_ONSEND
 void run_onsend_callbacks(int type, struct retr_buf* rbuf, int retr);

+ 3 - 0
modules/tm/uac.c

@@ -54,6 +54,7 @@
  *               fixes 0 fr_timer bug (andrei)
  *  2006-08-11  t_uac uses dns failover until it finds a send socket (andrei)
  *  2007-03-15  TMCB_ONSEND callbacks support added (andrei)
+ *  2007-03-23  TMCB_LOCAL_REQUEST_IN callbacks support (andrei)
  */
 
 #include <string.h>
@@ -294,6 +295,8 @@ static inline int t_uac_prepare(str* method, str* headers, str* body,
 	request->buffer_len = buf_len;
 	new_cell->nr_of_outgoings++;
 	
+	if (has_local_reqin_tmcbs())
+			run_local_reqin_callbacks(new_cell, 0, 0);
 	if (dst_req) *dst_req = request;
 	if (dst_cell) *dst_cell = new_cell;