Procházet zdrojové kódy

modules/websocket: WS module registering for WS messages and basic handler implementation

Peter Dunkley před 13 roky
rodič
revize
6d93ce1b8a

+ 28 - 0
modules/websocket/ws_frame.c

@@ -21,10 +21,38 @@
  *
  */
 
+#include "../../tcp_conn.h"
 #include "../../lib/kmi/tree.h"
 #include "ws_frame.h"
 #include "ws_mod.h"
 
+#define FRAME_BUF_SIZE 1024
+static char frame_buf[FRAME_BUF_SIZE];
+
+int ws_frame_received(void *data)
+{
+	int printed;
+	str output;
+	tcp_event_info_t *tev = (tcp_event_info_t *) data;
+
+	if (tev == NULL || tev->buf == NULL || tev->len <= 0)
+	{
+		LM_WARN("received bad frame\n");
+		return -1;
+	}
+
+	output.len = 0;
+	output.s = frame_buf;
+
+	for (printed = 0; printed < tev->len && output.len < FRAME_BUF_SIZE - 3;
+			printed++)
+		output.len += sprintf(output.s + output.len, "%02x ",
+				(unsigned char) tev->buf[printed]);
+	LM_INFO("Rx: %.*s\n", output.len, output.s);
+
+	return 0;
+}
+
 struct mi_root *ws_mi_close(struct mi_root *cmd, void *param)
 {
 	/* TODO close specified or all connections */

+ 1 - 0
modules/websocket/ws_frame.h

@@ -27,6 +27,7 @@
 #include "../../sr_module.h"
 #include "../../lib/kmi/tree.h"
 
+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);
 

+ 27 - 6
modules/websocket/ws_handshake.c

@@ -27,11 +27,13 @@
 #include "../../data_lump_rpl.h"
 #include "../../dprint.h"
 #include "../../locking.h"
+#include "../../tcp_conn.h"
 #include "../../lib/kcore/kstats_wrapper.h"
 #include "../../lib/kcore/cmpapi.h"
 #include "../../lib/kmi/tree.h"
 #include "../../parser/msg_parser.h"
 #include "../sl/sl.h"
+#include "../tls/tls_cfg.h"
 #include "ws_handshake.h"
 #include "ws_mod.h"
 
@@ -120,16 +122,31 @@ int ws_handle_handshake(struct sip_msg *msg)
 	str key = {0, 0}, headers = {0, 0}, reply_key = {0, 0};
 	unsigned char sha1[20];
 	unsigned int hdr_flags = 0;
-	int version;
+	int lifetime = 0, version;
 	struct hdr_field *hdr = msg->headers;
 
 	if (*ws_enabled == 0)
 	{
 		LM_INFO("disabled: bouncing handshake\n");
-		ws_send_reply(msg, 503, &str_status_service_unavailable, NULL);
+		ws_send_reply(msg, 503, &str_status_internal_server_error,
+				NULL);
+		return 0;
+	}
+
+	/* Check the protocol the request arrived over */
+	switch (msg->rcv.proto)
+	{
+	case PROTO_TCP:
+	case PROTO_TLS:
+		lifetime = cfg_get(tcp, tcp_cfg, con_lifetime);
+		break;
+	default:
+		LM_WARN("websocket handshake on unsupported protocol\n");
+		ws_send_reply(msg, 500, &str_status_service_unavailable, NULL);
 		return 0;
 	}
 
+	/* Process HTTP headers */
 	while (hdr != NULL)
 	{
 		/* Decode and validate Connection */
@@ -289,11 +306,15 @@ int ws_handle_handshake(struct sip_msg *msg)
 			str_hdr_sec_websocket_protocol.s, str_sip.len,
 			str_sip.s);
 
-	/* TODO: make sure Kamailio core sends future requests on this
-		 connection directly to this module */
-
 	/* Send reply */
-	ws_send_reply(msg, 101, &str_status_switching_protocols, &headers);
+	if (ws_send_reply(msg, 101,
+				&str_status_switching_protocols, &headers) < 0)
+		return 0;
+
+	/* Make sure Kamailio core sends future requests on this connection
+	   directly to this module */
+	tcpconn_get(msg->rcv.proto_reserved1, 0, 0, 0, lifetime)->flags
+		|= F_CONN_WS;
 
 	return 0;
 }

+ 7 - 0
modules/websocket/ws_mod.c

@@ -22,6 +22,7 @@
  */
 
 #include "../../dprint.h"
+#include "../../events.h"
 #include "../../locking.h"
 #include "../../sr_module.h"
 #include "../../lib/kcore/kstats_wrapper.h"
@@ -117,6 +118,12 @@ static int mod_init(void)
 		return -1;
 	}
 
+	if (sr_event_register_cb(SREV_TCP_WS_FRAME, ws_frame_received) != 0)
+	{
+		LM_ERR("registering WebSocket call-back\n");
+		return -1;
+	}
+
 	if (register_module_stats(exports.name, stats) != 0)
 	{
 		LM_ERR("registering core statistics\n");