Răsfoiți Sursa

Merge pull request #504 from kamailio/co/tcp_closed_event_enhancements

tcp:closed event enhancements
Daniel-Constantin Mierla 9 ani în urmă
părinte
comite
326adcfa3f

+ 80 - 17
modules/tcpops/README

@@ -8,9 +8,9 @@ Olle E. Johansson
 
 
    Edvina AB
    Edvina AB
 
 
-   Copyright © 2015 Orange
+   Copyright © 2015 Orange
 
 
-   Copyright © 2015 Edvina AB, Sollentuna, Sweden
+   Copyright © 2015 Edvina AB, Sollentuna, Sweden
      __________________________________________________________________
      __________________________________________________________________
 
 
    Table of Contents
    Table of Contents
@@ -19,6 +19,9 @@ Olle E. Johansson
 
 
         1. Overview
         1. Overview
         2. Parameters
         2. Parameters
+
+              2.1. closed_event (int)
+
         3. Functions
         3. Functions
 
 
               3.1. tcp_conid_alive(conid)
               3.1. tcp_conid_alive(conid)
@@ -26,14 +29,17 @@ Olle E. Johansson
               3.3. tcp_keepalive_enable([conid], idle, count, interval)
               3.3. tcp_keepalive_enable([conid], idle, count, interval)
               3.4. tcp_keepalive_disable([conid])
               3.4. tcp_keepalive_disable([conid])
               3.5. tcp_set_connection_lifetime([conid], lifetime)
               3.5. tcp_set_connection_lifetime([conid], lifetime)
+              3.6. tcp_enable_closed_event([conid])
 
 
    List of Examples
    List of Examples
 
 
-   1.1. tcp_conid_alive usage
-   1.2. tcp_conid_state usage
-   1.3. tcp_keepalive_enable usage
-   1.4. tcp_keepalive_disable usage
-   1.5. tcp_set_connection_lifetime usage
+   1.1. Set closed_event parameter
+   1.2. tcp_conid_alive usage
+   1.3. tcp_conid_state usage
+   1.4. tcp_keepalive_enable usage
+   1.5. tcp_keepalive_disable usage
+   1.6. tcp_set_connection_lifetime usage
+   1.7. tcp_set_closed_event usage
 
 
 Chapter 1. Admin Guide
 Chapter 1. Admin Guide
 
 
@@ -41,6 +47,9 @@ Chapter 1. Admin Guide
 
 
    1. Overview
    1. Overview
    2. Parameters
    2. Parameters
+
+        2.1. closed_event (int)
+
    3. Functions
    3. Functions
 
 
         3.1. tcp_conid_alive(conid)
         3.1. tcp_conid_alive(conid)
@@ -48,6 +57,7 @@ Chapter 1. Admin Guide
         3.3. tcp_keepalive_enable([conid], idle, count, interval)
         3.3. tcp_keepalive_enable([conid], idle, count, interval)
         3.4. tcp_keepalive_disable([conid])
         3.4. tcp_keepalive_disable([conid])
         3.5. tcp_set_connection_lifetime([conid], lifetime)
         3.5. tcp_set_connection_lifetime([conid], lifetime)
+        3.6. tcp_enable_closed_event([conid])
 
 
 1. Overview
 1. Overview
 
 
@@ -61,6 +71,27 @@ Chapter 1. Admin Guide
 
 
 2. Parameters
 2. Parameters
 
 
+   2.1. closed_event (int)
+
+2.1. closed_event (int)
+
+   If set to 0 (gloabbly disabled), the "tcp:closed" event route will
+   never be called on TCP disconnections.
+
+   If set to 1 (globally enabled), the "tcp:closed" event route will
+   always be called on TCP disconnections.
+
+   If set to 2 ("manual" mode), the "tcp:closed" event route will only be
+   called on TCP connections for which tcp_enable_closed_event() has been
+   applied, when a disconnection occurs.
+
+   Default value is 1 (globally enabled).
+
+   Example 1.1. Set closed_event parameter
+...
+modparam("tcpops", "closed_event", 0)
+...
+
 3. Functions
 3. Functions
 
 
    3.1. tcp_conid_alive(conid)
    3.1. tcp_conid_alive(conid)
@@ -68,8 +99,9 @@ Chapter 1. Admin Guide
    3.3. tcp_keepalive_enable([conid], idle, count, interval)
    3.3. tcp_keepalive_enable([conid], idle, count, interval)
    3.4. tcp_keepalive_disable([conid])
    3.4. tcp_keepalive_disable([conid])
    3.5. tcp_set_connection_lifetime([conid], lifetime)
    3.5. tcp_set_connection_lifetime([conid], lifetime)
+   3.6. tcp_enable_closed_event([conid])
 
 
-3.1. tcp_conid_alive(conid)
+3.1.  tcp_conid_alive(conid)
 
 
    Check the state of a TCP or WS connection ID
    Check the state of a TCP or WS connection ID
 
 
@@ -83,7 +115,7 @@ Chapter 1. Admin Guide
 
 
    -1: Connection has errors, does not exist or is about to be closed)
    -1: Connection has errors, does not exist or is about to be closed)
 
 
-   Example 1.1. tcp_conid_alive usage
+   Example 1.2. tcp_conid_alive usage
 ...
 ...
         $var(conid) = $conid;
         $var(conid) = $conid;
         if(!tcp_conid_alive("$var(conid)")) {
         if(!tcp_conid_alive("$var(conid)")) {
@@ -91,7 +123,7 @@ Chapter 1. Admin Guide
         }
         }
 ...
 ...
 
 
-3.2. tcp_conid_state(conid)
+3.2.  tcp_conid_state(conid)
 
 
    Check the state of a TCP or WS connection ID
    Check the state of a TCP or WS connection ID
 
 
@@ -115,14 +147,14 @@ Chapter 1. Admin Guide
 
 
    -4: Socket is in unknow bad state. Connection will likely close.
    -4: Socket is in unknow bad state. Connection will likely close.
 
 
-   Example 1.2. tcp_conid_state usage
+   Example 1.3. tcp_conid_state usage
 ...
 ...
         if(!tcp_conid_state("$var(conid)")) {
         if(!tcp_conid_state("$var(conid)")) {
                 xlog("L_ERR", "Connection $conid is closed or malfunctional\n");
                 xlog("L_ERR", "Connection $conid is closed or malfunctional\n");
         }
         }
 ...
 ...
 
 
-3.3. tcp_keepalive_enable([conid], idle, count, interval)
+3.3.  tcp_keepalive_enable([conid], idle, count, interval)
 
 
    Enables keepalive on a TCP connection.
    Enables keepalive on a TCP connection.
 
 
@@ -138,7 +170,7 @@ Chapter 1. Admin Guide
 
 
    Retuns 1 on success, -1 on failure.
    Retuns 1 on success, -1 on failure.
 
 
-   Example 1.3. tcp_keepalive_enable usage
+   Example 1.4. tcp_keepalive_enable usage
 request_route {
 request_route {
         if (is_method("INVITE")) {
         if (is_method("INVITE")) {
                 $avp(caller_conid) = $conid;
                 $avp(caller_conid) = $conid;
@@ -157,7 +189,7 @@ onreply_route[foo] {
         ...
         ...
 }
 }
 
 
-3.4. tcp_keepalive_disable([conid])
+3.4.  tcp_keepalive_disable([conid])
 
 
    Disables keepalive on a TCP connection.
    Disables keepalive on a TCP connection.
 
 
@@ -169,7 +201,7 @@ onreply_route[foo] {
 
 
    Retuns 1 on success, -1 on failure.
    Retuns 1 on success, -1 on failure.
 
 
-   Example 1.4. tcp_keepalive_disable usage
+   Example 1.5. tcp_keepalive_disable usage
 request_route {
 request_route {
         ...
         ...
         if (is_method("BYE")) {
         if (is_method("BYE")) {
@@ -188,7 +220,7 @@ onreply_route[foo] {
         ...
         ...
 }
 }
 
 
-3.5. tcp_set_connection_lifetime([conid], lifetime)
+3.5.  tcp_set_connection_lifetime([conid], lifetime)
 
 
    Sets the connection lifetime of a connection (TCP).
    Sets the connection lifetime of a connection (TCP).
 
 
@@ -200,7 +232,7 @@ onreply_route[foo] {
 
 
    Retuns 1 on success, -1 on failure.
    Retuns 1 on success, -1 on failure.
 
 
-   Example 1.5. tcp_set_connection_lifetime usage
+   Example 1.6. tcp_set_connection_lifetime usage
 ...
 ...
 # use 10s as default lifetime
 # use 10s as default lifetime
 tcp_connection_lifetime=10
 tcp_connection_lifetime=10
@@ -214,3 +246,34 @@ request_route {
         }
         }
         ...
         ...
 }
 }
+
+3.6.  tcp_enable_closed_event([conid])
+
+   Explicitly enables the "tcp:closed" event route on a TCP connection.
+
+   Meaning of the parameters is as follows:
+     * conid (optionnal): the kamailio internal connection id. If no
+       parameter is given, it will be enabled on the current message
+       source connection.
+
+   Retuns 1 on success, -1 on failure.
+
+   Example 1.7. tcp_set_closed_event usage
+...
+# "tcp:closed" event route is "manual" mode
+modparam("tcpops", "closed_event", 2)
+...
+
+request_route {
+        ...
+        if (is_method("REGISTER") && pv_www_authenticate("$td", "xxx", "0")) {
+                # it will be called for this specific connection
+                tcp_enable_closed_event();
+        }
+        ...
+
+}
+
+event_route[tcp:closed] {
+        xlog("connection $conid was closed");
+}

+ 43 - 0
modules/tcpops/doc/functions.xml

@@ -211,4 +211,47 @@ request_route {
                         ]]></programlisting>
                         ]]></programlisting>
                 </example>
                 </example>
         </section>
         </section>
+
+        <section id="tcpops.f.tcp_enable_closed_event">
+                <title>
+                        <function>tcp_enable_closed_event([conid])</function>
+                </title>
+                <para>
+                                Explicitly enables the "tcp:closed" event route
+                                on a TCP connection.
+                </para>
+                <para>Meaning of the parameters is as follows:</para>
+                <itemizedlist>
+                        <listitem>
+                                <para><emphasis>conid</emphasis> (optionnal): the kamailio internal
+                                connection id. If no parameter
+                                is given, it will be enabled on the current message source connection.
+                                </para>
+                        </listitem>
+                </itemizedlist>
+                <para>Retuns 1 on success, -1 on failure.</para>
+                <example>
+                        <title><function>tcp_set_closed_event</function> usage</title>
+                        <programlisting><![CDATA[
+...
+# "tcp:closed" event route is "manual" mode
+modparam("tcpops", "closed_event", 2)
+...
+
+request_route {
+	...
+	if (is_method("REGISTER") && pv_www_authenticate("$td", "xxx", "0")) {
+		# it will be called for this specific connection
+		tcp_enable_closed_event();
+	}
+	...
+
+}
+
+event_route[tcp:closed] {
+	xlog("connection $conid was closed");
+}
+]]></programlisting>
+                </example>
+        </section>
 </section>
 </section>

+ 29 - 0
modules/tcpops/doc/params.xml

@@ -7,6 +7,35 @@
     </sectioninfo>
     </sectioninfo>
 
 
     <title>Parameters</title>
     <title>Parameters</title>
+		<section>
+		<title><varname>closed_event</varname> (int)</title>
+		<para>
+			If set to 0 (gloabbly disabled), the "tcp:closed" event route will never be called on TCP
+			disconnections.
+		</para>
+		<para>
+			If set to 1 (globally enabled), the "tcp:closed" event route will always be called on TCP
+			disconnections.
+		</para>
+		<para>
+			If set to 2 ("manual" mode), the "tcp:closed" event route will only be called on TCP
+			connections for which <literal>tcp_enable_closed_event()</literal> has
+			been applied, when a disconnection occurs.
+		</para>
+		<para>
+		<emphasis>
+			Default value is 1 (globally enabled).
+		</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>closed_event</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("tcpops", "closed_event", 0)
+...
+</programlisting>
+		</example>
+	</section>
 
 
 
 
 
 

+ 9 - 1
modules/tcpops/tcpops.c

@@ -34,6 +34,10 @@
 #include "../../fmsg.h"
 #include "../../fmsg.h"
 #include "../../sr_module.h"
 #include "../../sr_module.h"
 
 
+
+/* globally enabled by default */
+int tcp_closed_event = 1;
+
 /**
 /**
  * gets the fd of the current message source connection
  * gets the fd of the current message source connection
  *
  *
@@ -193,6 +197,7 @@ static void tcpops_tcp_closed_run_route(struct tcp_connection *con)
 	int rt, backup_rt;
 	int rt, backup_rt;
 	struct run_act_ctx ctx;
 	struct run_act_ctx ctx;
 	sip_msg_t *fmsg;
 	sip_msg_t *fmsg;
+
 	LM_DBG("tcp_closed_run_route event_route[tcp:closed]\n");
 	LM_DBG("tcp_closed_run_route event_route[tcp:closed]\n");
 
 
 	rt = route_get(&event_rt, "tcp:closed");
 	rt = route_get(&event_rt, "tcp:closed");
@@ -226,7 +231,10 @@ int tcpops_handle_tcp_closed(void *data)
 		return -1;
 		return -1;
 	}
 	}
 
 
-	tcpops_tcp_closed_run_route(tev->con);
+	/* run event route if tcp_closed_event == 1 or if the
+	 * F_CONN_CLOSE_EV flag is explicitly set */
+	if (tcp_closed_event == 1 || (tev->con->flags & F_CONN_CLOSE_EV))
+		tcpops_tcp_closed_run_route(tev->con);
 
 
 	return 0;
 	return 0;
 }
 }

+ 2 - 0
modules/tcpops/tcpops.h

@@ -27,6 +27,8 @@
 #include "../../tcp_conn.h"
 #include "../../tcp_conn.h"
 #include "../../events.h"
 #include "../../events.h"
 
 
+extern int tcp_closed_event;
+
 int tcpops_get_current_fd(int conid, int *fd);
 int tcpops_get_current_fd(int conid, int *fd);
 int tcpops_acquire_fd_from_tcpmain(int conid, int *fd);
 int tcpops_acquire_fd_from_tcpmain(int conid, int *fd);
 int tcpops_keepalive_enable(int fd, int idle, int count, int interval, int closefd);
 int tcpops_keepalive_enable(int fd, int idle, int count, int interval, int closefd);

+ 62 - 2
modules/tcpops/tcpops_mod.c

@@ -50,6 +50,8 @@ static int w_tcp_keepalive_disable1(sip_msg_t* msg, char* con);
 static int w_tcp_keepalive_disable0(sip_msg_t* msg);
 static int w_tcp_keepalive_disable0(sip_msg_t* msg);
 static int w_tcpops_set_connection_lifetime2(sip_msg_t* msg, char* con, char* time);
 static int w_tcpops_set_connection_lifetime2(sip_msg_t* msg, char* con, char* time);
 static int w_tcpops_set_connection_lifetime1(sip_msg_t* msg, char* time);
 static int w_tcpops_set_connection_lifetime1(sip_msg_t* msg, char* time);
+static int w_tcpops_enable_closed_event1(sip_msg_t* msg, char* con, char* foo);
+static int w_tcpops_enable_closed_event0(sip_msg_t* msg, char* foo);
 static int w_tcp_conid_state(sip_msg_t* msg, char* con, char *p2);
 static int w_tcp_conid_state(sip_msg_t* msg, char* con, char *p2);
 static int w_tcp_conid_alive(sip_msg_t* msg, char* con, char *p2);
 static int w_tcp_conid_alive(sip_msg_t* msg, char* con, char *p2);
 
 
@@ -69,6 +71,10 @@ static cmd_export_t cmds[]={
 		0, ANY_ROUTE},
 		0, ANY_ROUTE},
 	{"tcp_set_connection_lifetime", (cmd_function)w_tcpops_set_connection_lifetime1, 1, fixup_numpv,
 	{"tcp_set_connection_lifetime", (cmd_function)w_tcpops_set_connection_lifetime1, 1, fixup_numpv,
 		0, REQUEST_ROUTE|ONREPLY_ROUTE},
 		0, REQUEST_ROUTE|ONREPLY_ROUTE},
+	{"tcp_enable_closed_event", (cmd_function)w_tcpops_enable_closed_event1, 1, fixup_numpv,
+		0, ANY_ROUTE},
+	{"tcp_enable_closed_event", (cmd_function)w_tcpops_enable_closed_event0, 0, 0,
+		0, REQUEST_ROUTE|ONREPLY_ROUTE},
 	{"tcp_conid_state", (cmd_function)w_tcp_conid_state, 1, fixup_numpv,
 	{"tcp_conid_state", (cmd_function)w_tcp_conid_state, 1, fixup_numpv,
 		0, ANY_ROUTE},
 		0, ANY_ROUTE},
 	{"tcp_conid_alive", (cmd_function)w_tcp_conid_alive, 1, fixup_numpv,
 	{"tcp_conid_alive", (cmd_function)w_tcp_conid_alive, 1, fixup_numpv,
@@ -76,13 +82,18 @@ static cmd_export_t cmds[]={
 	{0, 0, 0, 0, 0, 0}
 	{0, 0, 0, 0, 0, 0}
 };
 };
 
 
+static param_export_t params[] = {
+	{"closed_event",    PARAM_INT,    &tcp_closed_event},
+	{0, 0, 0}
+};
+
 
 
 
 
 struct module_exports exports = {
 struct module_exports exports = {
 	"tcpops",
 	"tcpops",
 	DEFAULT_DLFLAGS, /* dlopen flags */
 	DEFAULT_DLFLAGS, /* dlopen flags */
 	cmds,            /* exported functions to config */
 	cmds,            /* exported functions to config */
-	0,          /* exported parameters to config */
+	params,          /* exported parameters to config */
 	0,               /* exported statistics */
 	0,               /* exported statistics */
 	0,              /* exported MI functions */
 	0,              /* exported MI functions */
 	0,        /* exported pseudo-variables */
 	0,        /* exported pseudo-variables */
@@ -102,7 +113,14 @@ static int mod_init(void)
 {
 {
 	LM_DBG("TCP keepalive module loaded.\n");
 	LM_DBG("TCP keepalive module loaded.\n");
 
 
-	if (sr_event_register_cb(SREV_TCP_CLOSED, tcpops_handle_tcp_closed) != 0) {
+	if (tcp_closed_event < 0 || tcp_closed_event > 2) {
+		LM_ERR("invalid \"closed_event\" value: %d, must be 0 (disabled), 1 (enabled) or 2 (manual)\n", tcp_closed_event);
+		return -1;
+	}
+
+	if (tcp_closed_event /* register event only if tcp_closed_event != 0 */
+		&& (sr_event_register_cb(SREV_TCP_CLOSED, tcpops_handle_tcp_closed) != 0))
+	{
 		LM_ERR("problem registering tcpops_handle_tcp_closed call-back\n");
 		LM_ERR("problem registering tcpops_handle_tcp_closed call-back\n");
 		return -1;
 		return -1;
 	}
 	}
@@ -334,6 +352,48 @@ static int w_tcpops_set_connection_lifetime1(sip_msg_t* msg, char* time)
 	return ret;
 	return ret;
 }
 }
 
 
+static int w_tcpops_enable_closed_event1(sip_msg_t* msg, char* conid, char* foo)
+{
+	struct tcp_connection *s_con;
+
+	_IVALUE (conid)
+
+	if (unlikely((s_con = tcpconn_get(i_conid, 0, 0, 0, 0)) == NULL)) {
+		LM_ERR("invalid connection id %d, (must be a TCP conid)\n", i_conid);
+		return 0;
+	} else {
+		s_con->flags |= F_CONN_CLOSE_EV;
+		tcpconn_put(s_con);
+	}
+	return 1;
+}
+
+
+static int w_tcpops_enable_closed_event0(sip_msg_t* msg, char* foo)
+{
+	struct tcp_connection *s_con;
+
+	if (unlikely(tcp_closed_event != 2)) {
+		LM_WARN("tcp_enable_closed_event() can only be used if"
+				" the \"closed_event\" modparam is set to 2\n");
+		return -1;
+	}
+
+	if(unlikely(msg->rcv.proto != PROTO_TCP && msg->rcv.proto != PROTO_TLS && msg->rcv.proto != PROTO_WS && msg->rcv.proto != PROTO_WSS))
+	{
+		LM_ERR("the current message does not come from a TCP connection\n");
+		return -1;
+	}
+
+	if (unlikely((s_con = tcpconn_get(msg->rcv.proto_reserved1, 0, 0, 0, 0)) == NULL)) {
+		return -1;
+	} else {
+		s_con->flags |= F_CONN_CLOSE_EV;
+		tcpconn_put(s_con);
+	}
+	return 1;
+}
+
 /**
 /**
  *
  *
  */
  */

+ 1 - 0
tcp_conn.h

@@ -55,6 +55,7 @@
 #define F_CONN_WANTS_RD  4096  /* conn. should be watched for READ */
 #define F_CONN_WANTS_RD  4096  /* conn. should be watched for READ */
 #define F_CONN_WANTS_WR  8192  /* conn. should be watched for WRITE */
 #define F_CONN_WANTS_WR  8192  /* conn. should be watched for WRITE */
 #define F_CONN_PASSIVE  16384 /* conn. created via accept() and not connect()*/
 #define F_CONN_PASSIVE  16384 /* conn. created via accept() and not connect()*/
+#define F_CONN_CLOSE_EV 32768 /* explicitely call tcpops ev route when closed */
 
 
 #ifndef NO_READ_HTTP11
 #ifndef NO_READ_HTTP11
 #define READ_HTTP11
 #define READ_HTTP11