[sr-dev] git:pd/websocket: modules/websocket: more work on WebSocket framing and base-protocol

Peter Dunkley peter.dunkley at crocodile-rcs.com
Sun Jun 17 15:30:30 CEST 2012


Module: sip-router
Branch: pd/websocket
Commit: d3e770533b908acf73b359ba556a972c1330a118
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=d3e770533b908acf73b359ba556a972c1330a118

Author: Peter Dunkley <peter.dunkley at crocodile-rcs.com>
Committer: Peter Dunkley <peter.dunkley at 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= 




More information about the sr-dev mailing list