Comparison

net/websocket/frames.lua @ 11164:4e5a2af9dd19 0.11

net.websocket.frames: Use C string XOR implementation
author Kim Alvefur <zash@zash.se>
date Wed, 14 Oct 2020 19:41:42 +0200
parent 11157:413bd21ba449
child 11166:51e5149ed0ad
comparison
equal deleted inserted replaced
11163:37a6a535343e 11164:4e5a2af9dd19
11 11
12 local bit = assert(softreq"bit" or softreq"bit32", 12 local bit = assert(softreq"bit" or softreq"bit32",
13 "No bit module found. See https://prosody.im/doc/depends#bitop"); 13 "No bit module found. See https://prosody.im/doc/depends#bitop");
14 local band = bit.band; 14 local band = bit.band;
15 local bor = bit.bor; 15 local bor = bit.bor;
16 local bxor = bit.bxor;
17 local lshift = bit.lshift; 16 local lshift = bit.lshift;
18 local rshift = bit.rshift; 17 local rshift = bit.rshift;
19 local unpack = table.unpack or unpack; -- luacheck: ignore 113 18 local sbit = require "util.strbitop";
20 19 local sxor = sbit.sxor;
21 local t_concat = table.concat; 20
22 local s_char= string.char; 21 local s_char= string.char;
23 local s_pack = string.pack; -- luacheck: ignore 143 22 local s_pack = string.pack; -- luacheck: ignore 143
24 local s_unpack = string.unpack; -- luacheck: ignore 143 23 local s_unpack = string.unpack; -- luacheck: ignore 143
25 24
26 if not s_pack and softreq"struct" then 25 if not s_pack and softreq"struct" then
105 elseif length_bytes == 8 then 104 elseif length_bytes == 8 then
106 result.length = read_uint64be(frame, 3); 105 result.length = read_uint64be(frame, 3);
107 end 106 end
108 107
109 if result.MASK then 108 if result.MASK then
110 result.key = { frame:byte(length_bytes+3, length_bytes+6) }; 109 result.key = frame:sub(length_bytes+3, length_bytes+6);
111 end 110 end
112 111
113 return result, header_length; 112 return result, header_length;
114 end 113 end
115 114
116 -- XORs the string `str` with the array of bytes `key` 115 -- XORs the string `str` with the array of bytes `key`
117 -- TODO: optimize 116 -- TODO: optimize
118 local function apply_mask(str, key, from, to) 117 local function apply_mask(str, key, from, to)
119 from = from or 1 118 return sxor(str:sub(from or 1, to or -1), key);
120 if from < 0 then from = #str + from + 1 end -- negative indices
121 to = to or #str
122 if to < 0 then to = #str + to + 1 end -- negative indices
123 local key_len = #key
124 local counter = 0;
125 local data = {};
126 for i = from, to do
127 local key_index = counter%key_len + 1;
128 counter = counter + 1;
129 data[counter] = s_char(bxor(key[key_index], str:byte(i)));
130 end
131 return t_concat(data);
132 end 119 end
133 120
134 local function parse_frame_body(frame, header, pos) 121 local function parse_frame_body(frame, header, pos)
135 if header.MASK then 122 if header.MASK then
136 return apply_mask(frame, header.key, pos, pos + header.length - 1); 123 return apply_mask(frame, header.key, pos, pos + header.length - 1);
173 length_extra = pack_uint64be(#data); 160 length_extra = pack_uint64be(#data);
174 end 161 end
175 162
176 local key = "" 163 local key = ""
177 if desc.MASK then 164 if desc.MASK then
178 local key_a = desc.key 165 key = desc.key
179 if key_a then 166 if not key then
180 key = s_char(unpack(key_a, 1, 4));
181 else
182 key = random_bytes(4); 167 key = random_bytes(4);
183 key_a = {key:byte(1,4)};
184 end 168 end
185 b2 = bor(b2, 0x80); 169 b2 = bor(b2, 0x80);
186 data = apply_mask(data, key_a); 170 data = apply_mask(data, key);
187 end 171 end
188 172
189 return s_char(b1, b2) .. length_extra .. key .. data 173 return s_char(b1, b2) .. length_extra .. key .. data
190 end 174 end
191 175