mod_websocket: Switch partial frame buffering to util.dbuffer 0.11
authorMatthew Wild <mwild1@gmail.com>
Thu, 17 Sep 2020 13:04:46 +0100
branch0.11
changeset 11111 ddd0007e0f1b
parent 11110 76f46c2579a2
child 11112 fa1821b56f75
mod_websocket: Switch partial frame buffering to util.dbuffer This improves performance and enforces stanza size limits earlier in the pipeline.
net/websocket/frames.lua
plugins/mod_websocket.lua
--- a/net/websocket/frames.lua	Thu Sep 17 13:00:19 2020 +0100
+++ b/net/websocket/frames.lua	Thu Sep 17 13:04:46 2020 +0100
@@ -20,8 +20,8 @@
 
 local t_concat = table.concat;
 local s_char= string.char;
-local s_pack = string.pack;
-local s_unpack = string.unpack;
+local s_pack = string.pack; -- luacheck: ignore 143
+local s_unpack = string.unpack; -- luacheck: ignore 143
 
 if not s_pack and softreq"struct" then
 	s_pack = softreq"struct".pack;
--- a/plugins/mod_websocket.lua	Thu Sep 17 13:00:19 2020 +0100
+++ b/plugins/mod_websocket.lua	Thu Sep 17 13:04:46 2020 +0100
@@ -18,6 +18,7 @@
 local portmanager = require "core.portmanager";
 local sm_destroy_session = require"core.sessionmanager".destroy_session;
 local log = module._log;
+local dbuffer = require "util.dbuffer";
 
 local websocket_frames = require"net.websocket.frames";
 local parse_frame = websocket_frames.parse;
@@ -27,6 +28,8 @@
 
 local t_concat = table.concat;
 
+local stanza_size_limit = module:get_option_number("c2s_stanza_size_limit", 10 * 1024 * 1024);
+local frame_fragment_limit = module:get_option_number("websocket_frame_fragment_limit", 8);
 local stream_close_timeout = module:get_option_number("c2s_close_timeout", 5);
 local consider_websocket_secure = module:get_option_boolean("consider_websocket_secure");
 local cross_domain = module:get_option_set("cross_domain_websocket", {});
@@ -269,14 +272,16 @@
 	session.open_stream = session_open_stream;
 	session.close = session_close;
 
-	local frameBuffer = "";
+	-- max frame header is 22 bytes
+	local frameBuffer = dbuffer.new(stanza_size_limit + 22, frame_fragment_limit);
 	add_filter(session, "bytes/in", function(data)
+		frameBuffer:write(data);
+
 		local cache = {};
-		frameBuffer = frameBuffer .. data;
 		local frame, length = parse_frame(frameBuffer);
 
 		while frame do
-			frameBuffer = frameBuffer:sub(length + 1);
+			frameBuffer:discard(length);
 			local result = handle_frame(frame);
 			if not result then return; end
 			cache[#cache+1] = filter_open_close(result);