Annotate

net/websocket/frames.lua @ 9659:86c431650dfd

net.websocket.frames: Prefer Lua 5.2 built-in bit module over LuaJIT version When running on Lua 5.2 this makes sense since bit32 is usually already loaded. It's sensible to prefer this going forward in case of incompatibilities between the two variants.
author Kim Alvefur <zash@zash.se>
date Thu, 29 Nov 2018 16:53:22 +0100
parent 8728:41c959c5c84b
child 9691:e11e076f0eb8
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
1 -- Prosody IM
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
2 -- Copyright (C) 2012 Florian Zeitz
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
3 -- Copyright (C) 2014 Daurnimator
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
4 --
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
5 -- This project is MIT/X11 licensed. Please see the
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
6 -- COPYING file in the source package for more information.
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
7 --
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
8
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
9 local softreq = require "util.dependencies".softreq;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
10 local random_bytes = require "util.random".bytes;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
11
9659
86c431650dfd net.websocket.frames: Prefer Lua 5.2 built-in bit module over LuaJIT version
Kim Alvefur <zash@zash.se>
parents: 8728
diff changeset
12 local bit = assert(softreq"bit32" or softreq"bit",
6897
8972b1a96526 net.websocket.frames: Link to documentation when bitop is missing
Kim Alvefur <zash@zash.se>
parents: 6896
diff changeset
13 "No bit module found. See https://prosody.im/doc/depends#bitop");
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
14 local band = bit.band;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
15 local bor = bit.bor;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
16 local bxor = bit.bxor;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
17 local lshift = bit.lshift;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
18 local rshift = bit.rshift;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
19
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
20 local t_concat = table.concat;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
21 local s_byte = string.byte;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
22 local s_char= string.char;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
23 local s_sub = string.sub;
8442
3a390fa561bf net.websocket.frames: Ignore Lua 5.3-only fields [luacheck]
Kim Alvefur <zash@zash.se>
parents: 7259
diff changeset
24 local s_pack = string.pack; -- luacheck: ignore 143
3a390fa561bf net.websocket.frames: Ignore Lua 5.3-only fields [luacheck]
Kim Alvefur <zash@zash.se>
parents: 7259
diff changeset
25 local s_unpack = string.unpack; -- luacheck: ignore 143
6899
5f3da8b00b9b net.websocket.frames: Use struct packing in Lua 5.3 or struct lib if available
Kim Alvefur <zash@zash.se>
parents: 6898
diff changeset
26
5f3da8b00b9b net.websocket.frames: Use struct packing in Lua 5.3 or struct lib if available
Kim Alvefur <zash@zash.se>
parents: 6898
diff changeset
27 if not s_pack and softreq"struct" then
5f3da8b00b9b net.websocket.frames: Use struct packing in Lua 5.3 or struct lib if available
Kim Alvefur <zash@zash.se>
parents: 6898
diff changeset
28 s_pack = softreq"struct".pack;
5f3da8b00b9b net.websocket.frames: Use struct packing in Lua 5.3 or struct lib if available
Kim Alvefur <zash@zash.se>
parents: 6898
diff changeset
29 s_unpack = softreq"struct".unpack;
5f3da8b00b9b net.websocket.frames: Use struct packing in Lua 5.3 or struct lib if available
Kim Alvefur <zash@zash.se>
parents: 6898
diff changeset
30 end
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
31
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
32 local function read_uint16be(str, pos)
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
33 local l1, l2 = s_byte(str, pos, pos+1);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
34 return l1*256 + l2;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
35 end
6395
e0164b0fcafd net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
36 -- FIXME: this may lose precision
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
37 local function read_uint64be(str, pos)
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
38 local l1, l2, l3, l4, l5, l6, l7, l8 = s_byte(str, pos, pos+7);
6898
d01254d5a825 net.websocket.frames: Pack and unpack 64bit ints without overflows (lua-bitop/bit32 are 32bit)
Kim Alvefur <zash@zash.se>
parents: 6897
diff changeset
39 local h = lshift(l1, 24) + lshift(l2, 16) + lshift(l3, 8) + l4;
d01254d5a825 net.websocket.frames: Pack and unpack 64bit ints without overflows (lua-bitop/bit32 are 32bit)
Kim Alvefur <zash@zash.se>
parents: 6897
diff changeset
40 local l = lshift(l5, 24) + lshift(l6, 16) + lshift(l7, 8) + l8;
d01254d5a825 net.websocket.frames: Pack and unpack 64bit ints without overflows (lua-bitop/bit32 are 32bit)
Kim Alvefur <zash@zash.se>
parents: 6897
diff changeset
41 return h * 2^32 + l;
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
42 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
43 local function pack_uint16be(x)
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
44 return s_char(rshift(x, 8), band(x, 0xFF));
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
45 end
6395
e0164b0fcafd net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
46 local function get_byte(x, n)
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
47 return band(rshift(x, n), 0xFF);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
48 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
49 local function pack_uint64be(x)
6898
d01254d5a825 net.websocket.frames: Pack and unpack 64bit ints without overflows (lua-bitop/bit32 are 32bit)
Kim Alvefur <zash@zash.se>
parents: 6897
diff changeset
50 local h = band(x / 2^32, 2^32-1);
6900
44a7e9152b9a net.websocket.frames: Fix syntax error due to code copy pasting
Kim Alvefur <zash@zash.se>
parents: 6899
diff changeset
51 return s_char(get_byte(h, 24), get_byte(h, 16), get_byte(h, 8), band(h, 0xFF),
44a7e9152b9a net.websocket.frames: Fix syntax error due to code copy pasting
Kim Alvefur <zash@zash.se>
parents: 6899
diff changeset
52 get_byte(x, 24), get_byte(x, 16), get_byte(x, 8), band(x, 0xFF));
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
53 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
54
6899
5f3da8b00b9b net.websocket.frames: Use struct packing in Lua 5.3 or struct lib if available
Kim Alvefur <zash@zash.se>
parents: 6898
diff changeset
55 if s_pack then
5f3da8b00b9b net.websocket.frames: Use struct packing in Lua 5.3 or struct lib if available
Kim Alvefur <zash@zash.se>
parents: 6898
diff changeset
56 function pack_uint16be(x)
5f3da8b00b9b net.websocket.frames: Use struct packing in Lua 5.3 or struct lib if available
Kim Alvefur <zash@zash.se>
parents: 6898
diff changeset
57 return s_pack(">I2", x);
5f3da8b00b9b net.websocket.frames: Use struct packing in Lua 5.3 or struct lib if available
Kim Alvefur <zash@zash.se>
parents: 6898
diff changeset
58 end
5f3da8b00b9b net.websocket.frames: Use struct packing in Lua 5.3 or struct lib if available
Kim Alvefur <zash@zash.se>
parents: 6898
diff changeset
59 function pack_uint64be(x)
5f3da8b00b9b net.websocket.frames: Use struct packing in Lua 5.3 or struct lib if available
Kim Alvefur <zash@zash.se>
parents: 6898
diff changeset
60 return s_pack(">I8", x);
5f3da8b00b9b net.websocket.frames: Use struct packing in Lua 5.3 or struct lib if available
Kim Alvefur <zash@zash.se>
parents: 6898
diff changeset
61 end
5f3da8b00b9b net.websocket.frames: Use struct packing in Lua 5.3 or struct lib if available
Kim Alvefur <zash@zash.se>
parents: 6898
diff changeset
62 end
5f3da8b00b9b net.websocket.frames: Use struct packing in Lua 5.3 or struct lib if available
Kim Alvefur <zash@zash.se>
parents: 6898
diff changeset
63
5f3da8b00b9b net.websocket.frames: Use struct packing in Lua 5.3 or struct lib if available
Kim Alvefur <zash@zash.se>
parents: 6898
diff changeset
64 if s_unpack then
5f3da8b00b9b net.websocket.frames: Use struct packing in Lua 5.3 or struct lib if available
Kim Alvefur <zash@zash.se>
parents: 6898
diff changeset
65 function read_uint16be(str, pos)
5f3da8b00b9b net.websocket.frames: Use struct packing in Lua 5.3 or struct lib if available
Kim Alvefur <zash@zash.se>
parents: 6898
diff changeset
66 return s_unpack(">I2", str, pos);
5f3da8b00b9b net.websocket.frames: Use struct packing in Lua 5.3 or struct lib if available
Kim Alvefur <zash@zash.se>
parents: 6898
diff changeset
67 end
5f3da8b00b9b net.websocket.frames: Use struct packing in Lua 5.3 or struct lib if available
Kim Alvefur <zash@zash.se>
parents: 6898
diff changeset
68 function read_uint64be(str, pos)
5f3da8b00b9b net.websocket.frames: Use struct packing in Lua 5.3 or struct lib if available
Kim Alvefur <zash@zash.se>
parents: 6898
diff changeset
69 return s_unpack(">I8", str, pos);
5f3da8b00b9b net.websocket.frames: Use struct packing in Lua 5.3 or struct lib if available
Kim Alvefur <zash@zash.se>
parents: 6898
diff changeset
70 end
5f3da8b00b9b net.websocket.frames: Use struct packing in Lua 5.3 or struct lib if available
Kim Alvefur <zash@zash.se>
parents: 6898
diff changeset
71 end
5f3da8b00b9b net.websocket.frames: Use struct packing in Lua 5.3 or struct lib if available
Kim Alvefur <zash@zash.se>
parents: 6898
diff changeset
72
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
73 local function parse_frame_header(frame)
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
74 if #frame < 2 then return; end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
75
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
76 local byte1, byte2 = s_byte(frame, 1, 2);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
77 local result = {
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
78 FIN = band(byte1, 0x80) > 0;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
79 RSV1 = band(byte1, 0x40) > 0;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
80 RSV2 = band(byte1, 0x20) > 0;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
81 RSV3 = band(byte1, 0x10) > 0;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
82 opcode = band(byte1, 0x0F);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
83
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
84 MASK = band(byte2, 0x80) > 0;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
85 length = band(byte2, 0x7F);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
86 };
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
87
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
88 local length_bytes = 0;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
89 if result.length == 126 then
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
90 length_bytes = 2;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
91 elseif result.length == 127 then
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
92 length_bytes = 8;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
93 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
94
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
95 local header_length = 2 + length_bytes + (result.MASK and 4 or 0);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
96 if #frame < header_length then return; end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
97
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
98 if length_bytes == 2 then
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
99 result.length = read_uint16be(frame, 3);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
100 elseif length_bytes == 8 then
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
101 result.length = read_uint64be(frame, 3);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
102 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
103
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
104 if result.MASK then
6395
e0164b0fcafd net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
105 result.key = { s_byte(frame, length_bytes+3, length_bytes+6) };
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
106 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
107
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
108 return result, header_length;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
109 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
110
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
111 -- XORs the string `str` with the array of bytes `key`
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
112 -- TODO: optimize
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
113 local function apply_mask(str, key, from, to)
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
114 from = from or 1
8728
41c959c5c84b Fix spelling throughout the codebase [codespell]
Kim Alvefur <zash@zash.se>
parents: 8442
diff changeset
115 if from < 0 then from = #str + from + 1 end -- negative indices
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
116 to = to or #str
8728
41c959c5c84b Fix spelling throughout the codebase [codespell]
Kim Alvefur <zash@zash.se>
parents: 8442
diff changeset
117 if to < 0 then to = #str + to + 1 end -- negative indices
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
118 local key_len = #key
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
119 local counter = 0;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
120 local data = {};
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
121 for i = from, to do
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
122 local key_index = counter%key_len + 1;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
123 counter = counter + 1;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
124 data[counter] = s_char(bxor(key[key_index], s_byte(str, i)));
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
125 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
126 return t_concat(data);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
127 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
128
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
129 local function parse_frame_body(frame, header, pos)
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
130 if header.MASK then
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
131 return apply_mask(frame, header.key, pos, pos + header.length - 1);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
132 else
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
133 return frame:sub(pos, pos + header.length - 1);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
134 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
135 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
136
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
137 local function parse_frame(frame)
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
138 local result, pos = parse_frame_header(frame);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
139 if result == nil or #frame < (pos + result.length) then return; end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
140 result.data = parse_frame_body(frame, result, pos+1);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
141 return result, pos + result.length;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
142 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
143
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
144 local function build_frame(desc)
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
145 local data = desc.data or "";
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
146
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
147 assert(desc.opcode and desc.opcode >= 0 and desc.opcode <= 0xF, "Invalid WebSocket opcode");
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
148 if desc.opcode >= 0x8 then
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
149 -- RFC 6455 5.5
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
150 assert(#data <= 125, "WebSocket control frames MUST have a payload length of 125 bytes or less.");
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
151 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
152
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
153 local b1 = bor(desc.opcode,
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
154 desc.FIN and 0x80 or 0,
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
155 desc.RSV1 and 0x40 or 0,
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
156 desc.RSV2 and 0x20 or 0,
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
157 desc.RSV3 and 0x10 or 0);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
158
6395
e0164b0fcafd net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
159 local b2 = #data;
e0164b0fcafd net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
160 local length_extra;
e0164b0fcafd net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
161 if b2 <= 125 then -- 7-bit length
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
162 length_extra = "";
6395
e0164b0fcafd net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
163 elseif b2 <= 0xFFFF then -- 2-byte length
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
164 b2 = 126;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
165 length_extra = pack_uint16be(#data);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
166 else -- 8-byte length
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
167 b2 = 127;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
168 length_extra = pack_uint64be(#data);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
169 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
170
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
171 local key = ""
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
172 if desc.MASK then
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
173 local key_a = desc.key
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
174 if key_a then
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
175 key = s_char(unpack(key_a, 1, 4));
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
176 else
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
177 key = random_bytes(4);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
178 key_a = {key:byte(1,4)};
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
179 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
180 b2 = bor(b2, 0x80);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
181 data = apply_mask(data, key_a);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
182 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
183
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
184 return s_char(b1, b2) .. length_extra .. key .. data
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
185 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
186
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
187 local function parse_close(data)
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
188 local code, message
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
189 if #data >= 2 then
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
190 code = read_uint16be(data, 1);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
191 if #data > 2 then
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
192 message = s_sub(data, 3);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
193 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
194 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
195 return code, message
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
196 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
197
6455
b6514e691a70 net.websocket: Make data masking configurable
Florian Zeitz <florob@babelmonkeys.de>
parents: 6398
diff changeset
198 local function build_close(code, message, mask)
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
199 local data = pack_uint16be(code);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
200 if message then
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
201 assert(#message<=123, "Close reason must be <=123 bytes");
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
202 data = data .. message;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
203 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
204 return build_frame({
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
205 opcode = 0x8;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
206 FIN = true;
6455
b6514e691a70 net.websocket: Make data masking configurable
Florian Zeitz <florob@babelmonkeys.de>
parents: 6398
diff changeset
207 MASK = mask;
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
208 data = data;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
209 });
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
210 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
211
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
212 return {
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
213 parse_header = parse_frame_header;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
214 parse_body = parse_frame_body;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
215 parse = parse_frame;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
216 build = build_frame;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
217 parse_close = parse_close;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
218 build_close = build_close;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
219 };