Module: sip-router
Branch: pd/websocket
Commit: d3e770533b908acf73b359ba556a972c1330a118
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=d3e7705…
Author: Peter Dunkley <peter.dunkley(a)crocodile-rcs.com>
Committer: Peter Dunkley <peter.dunkley(a)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=