Module: sip-router Branch: master Commit: 9af456f292e25be2c5689212ed097177a5a16338 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=9af456f2...
Author: Peter Dunkley peter.dunkley@crocodile-rcs.com Committer: Peter Dunkley peter.dunkley@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; + } +}