Module: sip-router Branch: pd/websocket Commit: d3e770533b908acf73b359ba556a972c1330a118 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=d3e77053...
Author: Peter Dunkley peter.dunkley@crocodile-rcs.com Committer: Peter Dunkley peter.dunkley@crocodile-rcs.com Date: Sun Jun 17 14:29:44 2012 +0100
modules/websocket: more work on WebSocket framing and base-protocol
---
modules/websocket/ws_frame.c | 75 +++++++++++++++++++++++++++++++++++++----- modules/websocket/ws_frame.h | 1 + modules/websocket/ws_mod.c | 45 +++++++++++++------------ 3 files changed, 90 insertions(+), 31 deletions(-)
diff --git a/modules/websocket/ws_frame.c b/modules/websocket/ws_frame.c index bce0a09..0b0b474 100644 --- a/modules/websocket/ws_frame.c +++ b/modules/websocket/ws_frame.c @@ -22,6 +22,7 @@ */
#include "../../tcp_conn.h" +#include "../../lib/kcore/kstats_wrapper.h" #include "../../lib/kmi/tree.h" #include "ws_frame.h" #include "ws_mod.h" @@ -177,10 +178,10 @@ static int decode_and_validate_ws_frame(ws_frame_t *frame) frame->masking_key[3] = (buf[mask_start + 3] & 0xff);
/* Decode and unmask payload */ - if (len < frame->payload_len + mask_start) + if (len != frame->payload_len + mask_start + 4) { - LM_WARN("message not complete payload_len = %u but only " - "received %u\n", frame->payload_len, len); + LM_WARN("message not complete frame size %u but received %u\n", + frame->payload_len + mask_start + 4, len); return -1; } frame->payload_data = &buf[mask_start + 4]; @@ -197,27 +198,75 @@ static int decode_and_validate_ws_frame(ws_frame_t *frame) return frame->opcode; }
-static int handle_sip_message(ws_frame_t *msg) +static int encode_and_send_ws_frame(ws_frame_t *frame) +{ + /* TODO: convert ws_frame_t into a binary WebSocket frame and send over + TCP/TLS */ + + update_stat(ws_transmitted_frames, 1); + + return 0; +} + +static int handle_sip_message(ws_frame_t *frame) { LM_INFO("Received SIP message\n"); + + /* TODO: drop SIP message into route {} for processing */ + return 0; }
-static int handle_close(ws_frame_t *msg) +static int handle_close(ws_frame_t *frame) { + unsigned short code = 0; + str reason = {0, 0}; + + update_stat(ws_remote_closed_connections, 1); + update_stat(ws_current_connections, -1); LM_INFO("Received Close\n"); + + if (frame->payload_len >= 2) + code = ((frame->payload_data[0] & 0xff) << 8) + | ((frame->payload_data[1] & 0xff) << 0); + + if (frame->payload_len > 2) + { + reason.s = &frame->payload_data[2]; + reason.len = frame->payload_len - 2; + } + + LM_INFO("Close: %hu %.*s\n", code, reason.len, reason.s); + + /* TODO: cleanly close TCP/TLS connection */ + return 0; }
-static int handle_ping(ws_frame_t *msg) +static int handle_ping(ws_frame_t *frame) { + ws_frame_t ws_frame; + LM_INFO("Received Ping\n"); + + memset(&ws_frame, 0, sizeof(ws_frame_t)); + ws_frame.fin = 1; + ws_frame.opcode = OPCODE_PONG; + ws_frame.payload_len = frame->payload_len; + ws_frame.payload_data = frame->payload_data; + ws_frame.tcpinfo = frame->tcpinfo; + + encode_and_send_ws_frame(&ws_frame); + return 0; }
-static int handle_pong(ws_frame_t *msg) +static int handle_pong(ws_frame_t *frame) { LM_INFO("Received Pong\n"); + + LM_INFO("Pong: %.*s\n", frame->payload_len, frame->payload_data); + return 0; }
@@ -226,6 +275,8 @@ int ws_frame_received(void *data) ws_frame_t ws_frame; tcp_event_info_t *tev = (tcp_event_info_t *) data;
+ update_stat(ws_received_frames, 1); + if (tev == NULL || tev->buf == NULL || tev->len <= 0) { LM_WARN("received bad frame\n"); @@ -278,12 +329,18 @@ int ws_frame_received(void *data)
struct mi_root *ws_mi_close(struct mi_root *cmd, void *param) { - /* TODO close specified or all connections */ + /* TODO Close specified or all connections */ return init_mi_tree(200, MI_OK_S, MI_OK_LEN); }
struct mi_root *ws_mi_ping(struct mi_root *cmd, void *param) { - /* TODO ping specified connection */ + /* TODO Ping specified connection */ + return init_mi_tree(200, MI_OK_S, MI_OK_LEN); +} + +struct mi_root *ws_mi_pong(struct mi_root *cmd, void *param) +{ + /* TODO Pong specified connection */ return init_mi_tree(200, MI_OK_S, MI_OK_LEN); } diff --git a/modules/websocket/ws_frame.h b/modules/websocket/ws_frame.h index 782367f..aef04e0 100644 --- a/modules/websocket/ws_frame.h +++ b/modules/websocket/ws_frame.h @@ -30,5 +30,6 @@ int ws_frame_received(void *data); 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);
#endif /* _WS_FRAME_H */ diff --git a/modules/websocket/ws_mod.c b/modules/websocket/ws_mod.c index 4ca1758..302e0db 100644 --- a/modules/websocket/ws_mod.c +++ b/modules/websocket/ws_mod.c @@ -58,40 +58,41 @@ static struct mi_root *mi_dump(struct mi_root *cmd, void *param);
static cmd_export_t cmds[]= { - {"ws_handle_handshake", (cmd_function)ws_handle_handshake, 0, - 0, 0, - ANY_ROUTE}, - {0, 0, 0, 0, 0, 0} + { "ws_handle_handshake", (cmd_function)ws_handle_handshake, + 0, 0, 0, + ANY_ROUTE }, + { 0, 0, 0, 0, 0, 0 } };
static param_export_t params[]= { - {"ping_interval", INT_PARAM, &ws_ping_interval}, - {0, 0} + { "ping_interval", INT_PARAM, &ws_ping_interval }, + { 0, 0 } };
static stat_export_t stats[] = { - {"ws_current_connections", 0, &ws_current_connections }, - {"ws_failed_connections", 0, &ws_failed_connections }, - {"ws_failed_handshakes", 0, &ws_failed_handshakes }, - {"ws_local_closed_connections", 0, &ws_local_closed_connections }, - {"ws_max_concurrent_connections",0, &ws_max_concurrent_connections }, - {"ws_received_frames", 0, &ws_received_frames }, - {"ws_remote_closed_connections", 0, &ws_remote_closed_connections }, - {"ws_successful_handshakes", 0, &ws_successful_handshakes }, - {"ws_transmitted_frames", 0, &ws_transmitted_frames }, - {0, 0, 0} + { "ws_current_connections", 0, &ws_current_connections }, + { "ws_failed_connections", 0, &ws_failed_connections }, + { "ws_failed_handshakes", 0, &ws_failed_handshakes }, + { "ws_local_closed_connections", 0, &ws_local_closed_connections }, + { "ws_max_concurrent_connections",0, &ws_max_concurrent_connections }, + { "ws_received_frames", 0, &ws_received_frames }, + { "ws_remote_closed_connections", 0, &ws_remote_closed_connections }, + { "ws_successful_handshakes", 0, &ws_successful_handshakes }, + { "ws_transmitted_frames", 0, &ws_transmitted_frames }, + { 0, 0, 0 } };
static mi_export_t mi_cmds[] = { - { "ws_close", ws_mi_close, 0, 0, 0}, - { "ws_disable", ws_mi_disable, 0, 0, 0}, - { "ws_dump", mi_dump, 0, 0, 0}, - { "ws_enable", ws_mi_enable, 0, 0, 0}, - { "ws_ping", ws_mi_ping, 0, 0, 0}, - { 0, 0, 0, 0, 0} + { "ws_close", ws_mi_close, 0, 0, 0 }, + { "ws_disable", ws_mi_disable, 0, 0, 0 }, + { "ws_dump", mi_dump, 0, 0, 0 }, + { "ws_enable", ws_mi_enable, 0, 0, 0 }, + { "ws_ping", ws_mi_ping, 0, 0, 0 }, + { "ws_pong", ws_mi_pong, 0, 0, 0 }, + { 0, 0, 0, 0, 0 } };
struct module_exports exports=