Module: sip-router
Branch: master
Commit: 9af456f292e25be2c5689212ed097177a5a16338
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=9af456f…
Author: Peter Dunkley <peter.dunkley(a)crocodile-rcs.com>
Committer: Peter Dunkley <peter.dunkley(a)crocodile-rcs.com>
Date: Fri May 10 20:04:02 2013 +0100
modules/websocket: Added ws_close() exported function
- Enables immediate closure of a WebSocket connection from the configuration
file.
---
modules/websocket/README | 36 ++++++++++++++--
modules/websocket/doc/websocket_admin.xml | 36 +++++++++++++++
modules/websocket/ws_frame.c | 67 +++++++++++++++++++++++++++++
modules/websocket/ws_frame.h | 3 +
modules/websocket/ws_mod.c | 26 +++++++++++
5 files changed, 164 insertions(+), 4 deletions(-)
diff --git a/modules/websocket/README b/modules/websocket/README
index ef1bbf0..5888d63 100644
--- a/modules/websocket/README
+++ b/modules/websocket/README
@@ -36,6 +36,7 @@ Peter Dunkley
5. Functions
5.1. ws_handle_handshake()
+ 5.2. ws_close([status, reason[, connection_id]])
6. MI Commands
@@ -62,7 +63,8 @@ Peter Dunkley
1.8. Set sub_protocols parameter
1.9. Set cors_mode parameter
1.10. ws_handle_handshake usage
- 1.11. event_route[websocket:closed] usage
+ 1.11. ws_close usage
+ 1.12. event_route[websocket:closed] usage
Chapter 1. Admin Guide
@@ -93,6 +95,7 @@ Chapter 1. Admin Guide
5. Functions
5.1. ws_handle_handshake()
+ 5.2. ws_close([status, reason[, connection_id]])
6. MI Commands
@@ -239,8 +242,7 @@ request_route {
fix_nated_register();
else {
if (!add_contact_alias()) {
- xlog("L_ERR", "Error aliasing contact
<$ct>\n")
-;
+ xlog("L_ERR", "Error aliasing contact
<$ct>\n");
sl_send_reply("400", "Bad Request");
exit;
}
@@ -433,6 +435,7 @@ modparam("websocket", "cors_mode", 2)
5. Functions
5.1. ws_handle_handshake()
+ 5.2. ws_close([status, reason[, connection_id]])
5.1. ws_handle_handshake()
@@ -453,6 +456,31 @@ Note
ws_handle_handshake();
...
+5.2. ws_close([status, reason[, connection_id]])
+
+ This function closes a WebSocket connection.
+
+ The function returns -1 if there is an error and 1 if it succeeds.
+
+ The meaning of the parameters is as follows:
+ * status - an integer indicating the reason for closure.
+ * reason - a string describing the reason for closure.
+ * connection_id - the connection to close. If not specified the
+ connection the current message arrived on will be closed.
+
+Note
+
+ status and reason values SHOULD correspond to the definitions in
+ section 7.4 of RFC 6455. If these parameters are not used the defaults
+ of "1000" and "Normal closure" will be used.
+
+ This function can be used from ANY_ROUTE.
+
+ Example 1.11. ws_close usage
+...
+ws_close(4000, "Because I say so");
+...
+
6. MI Commands
6.1. ws.dump
@@ -560,7 +588,7 @@ Note
connection closes. The connection may be identified using the the $si
and $sp pseudo-variables.
- Example 1.11. event_route[websocket:closed] usage
+ Example 1.12. event_route[websocket:closed] usage
...
event_route[websocket:closed] {
xlog("L_INFO", "WebSocket connection from $si:$sp has
closed\n");
diff --git a/modules/websocket/doc/websocket_admin.xml
b/modules/websocket/doc/websocket_admin.xml
index bbdc62b..cdc3372 100644
--- a/modules/websocket/doc/websocket_admin.xml
+++ b/modules/websocket/doc/websocket_admin.xml
@@ -457,6 +457,42 @@ ws_handle_handshake();
</programlisting>
</example>
</section>
+ <section id="websocket.f.ws_close">
+ <title>
+ <function moreinfo="none">ws_close([status,
+ reason[, connection_id]])</function>
+ </title>
+ <para>This function closes a WebSocket connection.</para>
+ <para>The function returns -1 if there is an error and 1 if
+ it succeeds.</para>
+ <para>The meaning of the parameters is as follows:</para>
+ <itemizedlist>
+ <listitem><para><emphasis>status</emphasis> - an
+ integer indicating the reason for closure.</para>
+ </listitem>
+ <listitem><para><emphasis>reason</emphasis> - a
+ string describing the reason for closure.</para>
+ </listitem>
+ <listitem><para><emphasis>connection_id</emphasis> - the
+ connection to close. If not specified the connection the
+ current message arrived on will be closed.</para>
+ </listitem>
+ </itemizedlist>
+ <note><para><emphasis>status</emphasis> and
+ <emphasis>reason</emphasis> values SHOULD correspond to the
+ definitions in section 7.4 of RFC 6455. If these parameters are
+ not used the defaults of "1000" and "Normal
+ closure" will be used.</para></note>
+ <para>This function can be used from ANY_ROUTE.</para>
+ <example>
+ <title><function>ws_close</function> usage</title>
+ <programlisting format="linespecific">
+...
+ws_close(4000, "Because I say so");
+...
+</programlisting>
+ </example>
+ </section>
</section>
<section>
diff --git a/modules/websocket/ws_frame.c b/modules/websocket/ws_frame.c
index b6be135..7b76bac 100644
--- a/modules/websocket/ws_frame.c
+++ b/modules/websocket/ws_frame.c
@@ -831,3 +831,70 @@ void ws_keepalive(unsigned int ticks, void *param)
}
}
+
+int ws_close(sip_msg_t *msg)
+{
+ ws_connection_t *wsc;
+
+ if ((wsc = wsconn_get(msg->rcv.proto_reserved1)) == NULL) {
+ LM_ERR("failed to retrieve WebSocket connection\n");
+ return -1;
+ }
+
+ return (close_connection(wsc, LOCAL_CLOSE, 1000,
+ str_status_normal_closure) == 0) ? 1: 0;
+}
+
+int ws_close2(sip_msg_t *msg, char *_status, char *_reason)
+{
+ int status;
+ str reason;
+ ws_connection_t *wsc;
+
+ if (get_int_fparam(&status, msg, (fparam_t *) _status) < 0) {
+ LM_ERR("failed to get status code\n");
+ return -1;
+ }
+
+ if (get_str_fparam(&reason, msg, (fparam_t *) _reason) < 0) {
+ LM_ERR("failed to get reason string\n");
+ return -1;
+ }
+
+ if ((wsc = wsconn_get(msg->rcv.proto_reserved1)) == NULL) {
+ LM_ERR("failed to retrieve WebSocket connection\n");
+ return -1;
+ }
+
+ return (close_connection(wsc, LOCAL_CLOSE, status, reason) == 0) ? 1: 0;
+}
+
+int ws_close3(sip_msg_t *msg, char *_status, char *_reason, char *_con)
+{
+ int status;
+ str reason;
+ int con;
+ ws_connection_t *wsc;
+
+ if (get_int_fparam(&status, msg, (fparam_t *) _status) < 0) {
+ LM_ERR("failed to get status code\n");
+ return -1;
+ }
+
+ if (get_str_fparam(&reason, msg, (fparam_t *) _reason) < 0) {
+ LM_ERR("failed to get reason string\n");
+ return -1;
+ }
+
+ if (get_int_fparam(&con, msg, (fparam_t *) _con) < 0) {
+ LM_ERR("failed to get connection ID\n");
+ return -1;
+ }
+
+ if ((wsc = wsconn_get(con)) == NULL) {
+ LM_ERR("failed to retrieve WebSocket connection\n");
+ return -1;
+ }
+
+ return (close_connection(wsc, LOCAL_CLOSE, status, reason) == 0) ? 1: 0;
+}
diff --git a/modules/websocket/ws_frame.h b/modules/websocket/ws_frame.h
index e10d584..1210c6c 100644
--- a/modules/websocket/ws_frame.h
+++ b/modules/websocket/ws_frame.h
@@ -73,5 +73,8 @@ struct mi_root *ws_mi_close(struct mi_root *cmd, void *param);
struct mi_root *ws_mi_ping(struct mi_root *cmd, void *param);
struct mi_root *ws_mi_pong(struct mi_root *cmd, void *param);
void ws_keepalive(unsigned int ticks, void *param);
+int ws_close(sip_msg_t *msg);
+int ws_close2(sip_msg_t *msg, char *_status, char *_reason);
+int ws_close3(sip_msg_t *msg, char *_status, char *_reason, char *_con);
#endif /* _WS_FRAME_H */
diff --git a/modules/websocket/ws_mod.c b/modules/websocket/ws_mod.c
index 9a6ae66..9b82dea 100644
--- a/modules/websocket/ws_mod.c
+++ b/modules/websocket/ws_mod.c
@@ -32,6 +32,7 @@
#include "../../lib/kcore/kstats_wrapper.h"
#include "../../lib/kmi/mi.h"
#include "../../mem/mem.h"
+#include "../../mod_fix.h"
#include "../../parser/msg_parser.h"
#include "ws_conn.h"
#include "ws_handshake.h"
@@ -47,6 +48,7 @@ MODULE_VERSION
static int mod_init(void);
static int child_init(int rank);
static void destroy(void);
+static int ws_close_fixup(void** param, int param_no);
sl_api_t ws_slb;
@@ -60,6 +62,17 @@ static int ws_keepalive_processes = DEFAULT_KEEPALIVE_PROCESSES;
static cmd_export_t cmds[]=
{
+ /* ws_frame.c */
+ { "ws_close", (cmd_function) ws_close,
+ 0, 0, 0,
+ ANY_ROUTE },
+ { "ws_close", (cmd_function) ws_close2,
+ 2, ws_close_fixup, 0,
+ ANY_ROUTE },
+ { "ws_close", (cmd_function) ws_close3,
+ 3, ws_close_fixup, 0,
+ ANY_ROUTE },
+
/* ws_handshake.c */
{ "ws_handle_handshake", (cmd_function) ws_handle_handshake,
0, 0, 0,
@@ -295,3 +308,16 @@ static void destroy(void)
{
wsconn_destroy();
}
+
+static int ws_close_fixup(void** param, int param_no)
+{
+ switch(param_no) {
+ case 1:
+ case 3:
+ return fixup_var_int_1(param, 1);
+ case 2:
+ return fixup_spve_null(param, 1);
+ default:
+ return 0;
+ }
+}