2
0
Эх сурвалжийг харах

evapi: evapi_relay() reduced to one parameter

- more flexibility in the format of full event data
- new function evapi_async_relay() - suspend request processing using tm
  before sending event out
Daniel-Constantin Mierla 11 жил өмнө
parent
commit
045a99c171

+ 30 - 11
modules/evapi/README

@@ -30,7 +30,8 @@ Daniel-Constantin Mierla
 
         4. Functions
 
-              4.1. evapi_relay(event, data)
+              4.1. evapi_relay(evdata)
+              4.2. evapi_async_relay(evdata)
 
    List of Examples
 
@@ -38,6 +39,7 @@ Daniel-Constantin Mierla
    1.2. Set bind_addr parameter
    1.3. evapi_relay usage
    1.4. TCP message
+   1.5. evapi_async_relay usage
 
 Chapter 1. Admin Guide
 
@@ -56,7 +58,8 @@ Chapter 1. Admin Guide
 
    4. Functions
 
-        4.1. evapi_relay(event, data)
+        4.1. evapi_relay(evdata)
+        4.2. evapi_async_relay(evdata)
 
 1. Overview
 
@@ -70,7 +73,7 @@ Chapter 1. Admin Guide
 2.1. Kamailio Modules
 
    The following modules must be loaded before this module:
-     * none
+     * tm - (optional) needed only by evapi_async_relay()
 
 2.2. External Libraries or Applications
 
@@ -108,26 +111,42 @@ modparam("evapi", "bind_addr", "1.2.3.4:8228")
 
 4. Functions
 
-   4.1. evapi_relay(event, data)
+   4.1. evapi_relay(evdata)
+   4.2. evapi_async_relay(evdata)
 
-4.1. evapi_relay(event, data)
+4.1. evapi_relay(evdata)
 
-   Relay the event to connected applications. The format is netstring with
-   json payload.
+   Relay the event data give as parameter to connected applications. The
+   format on the network is netstring with evdata payload.
 
    This function can be used from ANY_ROUTE.
 
    Example 1.3. evapi_relay usage
 ...
-evapi_relay("test", "{ \"fU\": \"$fU\" }");
+evapi_relay("{ \"event\": \"test\",\n \"data\": { \"fU\": \"$fU\" }\n}");
 ...
 
    The above exaple will send the following message over tcp:
 
    Example 1.4. TCP message
 ...
-45:{
- "event":"test",
- "data":{ "fU": "test" }
+47:{
+ "event": "test",
+ "data": { "fU": "test" }
 },
 ...
+
+4.2. evapi_async_relay(evdata)
+
+   Relay the event data give as parameter to connected applications. The
+   format on the network is netstring with evdata payload. Before
+   evaluating the parameter, the request processing is suspended using tm
+   module.
+
+   This function can be used from REQUEST_ROUTE.
+
+   Example 1.5. evapi_async_relay usage
+...
+evapi_relay("{ \"event\": \"suspend\",\n \"data\":"
+        " { \"index\": \"$T(id_index)\", \"label\": \"$T(id_label)\" }\n}");
+...

+ 34 - 9
modules/evapi/doc/evapi_admin.xml

@@ -29,7 +29,8 @@
 			<itemizedlist>
 			<listitem>
 			<para>
-				<emphasis>none</emphasis>
+				<emphasis>tm</emphasis> - (optional) needed only by
+				evapi_async_relay()
 			</para>
 			</listitem>
 			</itemizedlist>
@@ -95,13 +96,13 @@ modparam("evapi", "bind_addr", "1.2.3.4:8228")
 
 	<section>
 	<title>Functions</title>
-	<section>
+	<section id="evapi.f.evapi_relay">
 	    <title>
-		<function moreinfo="none">evapi_relay(event, data)</function>
+		<function moreinfo="none">evapi_relay(evdata)</function>
 	    </title>
 	    <para>
-		Relay the event to connected applications. The format is netstring
-		with json payload.
+		Relay the event data give as parameter to connected applications.
+		The format on the network is netstring with evdata payload.
 		</para>
 		<para>
 		This function can be used from ANY_ROUTE.
@@ -110,7 +111,7 @@ modparam("evapi", "bind_addr", "1.2.3.4:8228")
 		<title><function>evapi_relay</function> usage</title>
 		<programlisting format="linespecific">
 ...
-evapi_relay("test", "{ \"fU\": \"$fU\" }");
+evapi_relay("{ \"event\": \"test\",\n \"data\": { \"fU\": \"$fU\" }\n}");
 ...
 </programlisting>
 	    </example>
@@ -121,15 +122,39 @@ evapi_relay("test", "{ \"fU\": \"$fU\" }");
 		<title>TCP message</title>
 		<programlisting format="linespecific">
 ...
-45:{
- "event":"test",
- "data":{ "fU": "test" }
+47:{
+ "event": "test",
+ "data": { "fU": "test" }
 },
 ...
 </programlisting>
 	    </example>
 	</section>
 
+	<section id="evapi.f.evapi_async_relay">
+	    <title>
+		<function moreinfo="none">evapi_async_relay(evdata)</function>
+	    </title>
+	    <para>
+		Relay the event data give as parameter to connected applications.
+		The format on the network is netstring with evdata payload. Before
+		evaluating the parameter, the request processing is suspended using
+		tm module.
+		</para>
+		<para>
+		This function can be used from REQUEST_ROUTE.
+		</para>
+		<example>
+		<title><function>evapi_async_relay</function> usage</title>
+		<programlisting format="linespecific">
+...
+evapi_relay("{ \"event\": \"suspend\",\n \"data\":"
+        " { \"index\": \"$T(id_index)\", \"label\": \"$T(id_label)\" }\n}");
+...
+</programlisting>
+	    </example>
+	</section>
+
 	</section>
 </chapter>
 

+ 41 - 0
modules/evapi/evapi_dispatch.c

@@ -294,6 +294,46 @@ int evapi_run_worker(int prank)
 	}
 }
 
+/**
+ *
+ */
+int evapi_relay(str *evdata)
+{
+#define EVAPI_RELAY_FORMAT "%d:%.*s,"
+
+	int len;
+	int sbsize;
+	str *sbuf;
+
+	LM_DBG("relaying event data [%.*s]\n",
+			evdata->len, evdata->s);
+
+	sbsize = evdata->len;
+	sbuf = (str*)shm_malloc(sizeof(str) + ((sbsize+32) * sizeof(char)));
+	if(sbuf==NULL) {
+		LM_ERR("no more shared memory\n");
+		return -1;
+	}
+	sbuf->s = (char*)sbuf + sizeof(str);
+	sbuf->len = snprintf(sbuf->s, sbsize+32,
+			EVAPI_RELAY_FORMAT,
+			sbsize, evdata->len, evdata->s);
+	if(sbuf->len<=0 || sbuf->len>sbsize+32) {
+		shm_free(sbuf);
+		LM_ERR("cannot serialize event\n");
+		return -1;
+	}
+
+	len = write(_evapi_notify_sockets[1], &sbuf, sizeof(str*));
+	if(len<=0) {
+		LM_ERR("failed to pass the pointer to evapi dispatcher\n");
+		return -1;
+	}
+	LM_DBG("sent [%p] [%.*s] (%d)\n", sbuf, sbuf->len, sbuf->s, sbuf->len);
+	return 0;
+}
+
+#if 0
 /**
  *
  */
@@ -332,3 +372,4 @@ int evapi_relay(str *event, str *data)
 	LM_DBG("sent [%p] [%.*s] (%d)\n", sbuf, sbuf->len, sbuf->s, sbuf->len);
 	return 0;
 }
+#endif

+ 1 - 1
modules/evapi/evapi_dispatch.h

@@ -33,6 +33,6 @@ int evapi_run_dispatcher(char *laddr, int lport);
 
 int evapi_run_worker(int prank);
 
-int evapi_relay(str *event, str *data);
+int evapi_relay(str *evdata);
 
 #endif

+ 79 - 14
modules/evapi/evapi_mod.c

@@ -36,6 +36,8 @@
 #include "../../mod_fix.h"
 #include "../../cfg/cfg_struct.h"
 
+#include "../../modules/tm/tm_load.h"
+
 #include "evapi_dispatch.h"
 
 MODULE_VERSION
@@ -45,17 +47,21 @@ static char *_evapi_bind_addr = "127.0.0.1";
 static int   _evapi_bind_port = 8448;
 static char *_evapi_bind_param = NULL;
 
+static tm_api_t tmb;
 
 static int  mod_init(void);
 static int  child_init(int);
 static void mod_destroy(void);
 
-static int w_evapi_relay(struct sip_msg* msg, char* event, char* data);
+static int w_evapi_relay(struct sip_msg* msg, char* evdata, char* p2);
+static int w_evapi_async_relay(struct sip_msg* msg, char* evdata, char* p2);
 static int fixup_evapi_relay(void** param, int param_no);
 
 static cmd_export_t cmds[]={
-	{"evapi_relay", (cmd_function)w_evapi_relay, 2, fixup_evapi_relay,
+	{"evapi_relay",       (cmd_function)w_evapi_relay,       1, fixup_evapi_relay,
 		0, ANY_ROUTE},
+	{"evapi_async_relay", (cmd_function)w_evapi_async_relay, 1, fixup_evapi_relay,
+		0, REQUEST_ROUTE},
 	{0, 0, 0, 0, 0, 0}
 };
 
@@ -88,6 +94,12 @@ struct module_exports exports = {
 static int mod_init(void)
 {
 	char *p;
+
+	if(load_tm_api( &tmb ) < 0) {
+		LM_INFO("cannot load the TM-functions - async relay disabled\n");
+		memset(&tmb, 0, sizeof(tm_api_t));
+	}
+
 	if(_evapi_bind_param!=NULL) {
 		p = strchr(_evapi_bind_param, ':');
 		if(p!=NULL) {
@@ -175,25 +187,77 @@ static void mod_destroy(void)
 {
 }
 
-static int w_evapi_relay(sip_msg_t *msg, char *event, char *data)
+/**
+ *
+ */
+static int w_evapi_relay(sip_msg_t *msg, char *evdata, char *p2)
 {
-	str sevent;
 	str sdata;
 
-	if(event==0 || data==0) {
+	if(evdata==0) {
 		LM_ERR("invalid parameters\n");
 		return -1;
 	}
 
-	if(fixup_get_svalue(msg, (gparam_t*)event, &sevent)!=0) {
-		LM_ERR("unable to get event\n");
+	if(fixup_get_svalue(msg, (gparam_t*)evdata, &sdata)!=0) {
+		LM_ERR("unable to get data\n");
+		return -1;
+	}
+	if(sdata.s==NULL || sdata.len == 0) {
+		LM_ERR("invalid data parameter\n");
 		return -1;
 	}
-	if(sevent.s==NULL || sevent.len == 0) {
-		LM_ERR("invalid event parameter\n");
+	if(evapi_relay(&sdata)<0) {
+		LM_ERR("failed to relay event: %.*s\n", sdata.len, sdata.s);
 		return -1;
 	}
-	if(fixup_get_svalue(msg, (gparam_t*)data, &sdata)!=0) {
+	return 1;
+}
+
+/**
+ *
+ */
+static int w_evapi_async_relay(sip_msg_t *msg, char *evdata, char *p2)
+{
+	str sdata;
+	unsigned int tindex;
+	unsigned int tlabel;
+	tm_cell_t *t = 0;
+
+	if(evdata==0) {
+		LM_ERR("invalid parameters\n");
+		return -1;
+	}
+
+	if(tmb.t_suspend==NULL) {
+		LM_ERR("evapi async relay is disabled - tm module not loaded\n");
+		return -1;
+	}
+
+	t = tmb.t_gett();
+	if (t==NULL || t==T_UNDEFINED)
+	{
+		if(tmb.t_newtran(msg)<0)
+		{
+			LM_ERR("cannot create the transaction\n");
+			return -1;
+		}
+		t = tmb.t_gett();
+		if (t==NULL || t==T_UNDEFINED)
+		{
+			LM_ERR("cannot lookup the transaction\n");
+			return -1;
+		}
+	}
+	if(tmb.t_suspend(msg, &tindex, &tlabel)<0)
+	{
+		LM_ERR("failed to suppend request processing\n");
+		return -1;
+	}
+
+	LM_DBG("transaction suspended [%u:%u]\n", tindex, tlabel);
+
+	if(fixup_get_svalue(msg, (gparam_t*)evdata, &sdata)!=0) {
 		LM_ERR("unable to get data\n");
 		return -1;
 	}
@@ -201,14 +265,15 @@ static int w_evapi_relay(sip_msg_t *msg, char *event, char *data)
 		LM_ERR("invalid data parameter\n");
 		return -1;
 	}
-	if(evapi_relay(&sevent, &sdata)<0) {
-		LM_ERR("failed to relay event: %.*s\n", sevent.len, sevent.s);
-		return -1;
+
+	if(evapi_relay(&sdata)<0) {
+		LM_ERR("failed to relay event: %.*s\n", sdata.len, sdata.s);
+		return -2;
 	}
 	return 1;
 }
 
 static int fixup_evapi_relay(void** param, int param_no)
 {
-	return fixup_spve_spve(param, param_no);
+	return fixup_spve_null(param, param_no);
 }