Annotate

net/websocket/frames.lua @ 11540:1937b3c3efb5 0.11

mod_c2s, mod_s2s, mod_component, mod_bosh, mod_websockets: Set default stanza size limits c2s/bosh/ws streams will default to 256KB, s2s and components to 512KB. These values are aligned with ejabberd's default settings, which should reduce issues related to inconsistent size limits between servers on the XMPP network. The previous default (10MB) is excessive for any production server, and allows significant memory usage by even unauthenticated sessions.
author Matthew Wild <mwild1@gmail.com>
date Fri, 07 May 2021 17:03:49 +0100
parent 11164:4e5a2af9dd19
child 11166:51e5149ed0ad
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
6896
c11776f85552 net.websocket.frames: Throw an error if no bit lib is found
Kim Alvefur <zash@zash.se>
parents: 6895
diff changeset
12 local bit = assert(softreq"bit" or softreq"bit32",
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 lshift = bit.lshift;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
17 local rshift = bit.rshift;
11164
4e5a2af9dd19 net.websocket.frames: Use C string XOR implementation
Kim Alvefur <zash@zash.se>
parents: 11157
diff changeset
18 local sbit = require "util.strbitop";
4e5a2af9dd19 net.websocket.frames: Use C string XOR implementation
Kim Alvefur <zash@zash.se>
parents: 11157
diff changeset
19 local sxor = sbit.sxor;
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
20
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
21 local s_char= string.char;
11107
ddd0007e0f1b mod_websocket: Switch partial frame buffering to util.dbuffer
Matthew Wild <mwild1@gmail.com>
parents: 11106
diff changeset
22 local s_pack = string.pack; -- luacheck: ignore 143
ddd0007e0f1b mod_websocket: Switch partial frame buffering to util.dbuffer
Matthew Wild <mwild1@gmail.com>
parents: 11106
diff changeset
23 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
24
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
25 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
26 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
27 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
28 end
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
29
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
30 local function read_uint16be(str, pos)
11106
76f46c2579a2 net.websocket.frames: Allow all methods to work on non-string objects
Matthew Wild <mwild1@gmail.com>
parents: 8728
diff changeset
31 local l1, l2 = str:byte(pos, pos+1);
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
32 return l1*256 + l2;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
33 end
6395
e0164b0fcafd net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
34 -- FIXME: this may lose precision
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
35 local function read_uint64be(str, pos)
11106
76f46c2579a2 net.websocket.frames: Allow all methods to work on non-string objects
Matthew Wild <mwild1@gmail.com>
parents: 8728
diff changeset
36 local l1, l2, l3, l4, l5, l6, l7, l8 = str:byte(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
37 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
38 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
39 return h * 2^32 + l;
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
40 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
41 local function pack_uint16be(x)
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
42 return s_char(rshift(x, 8), band(x, 0xFF));
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
43 end
6395
e0164b0fcafd net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
44 local function get_byte(x, n)
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
45 return band(rshift(x, n), 0xFF);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
46 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
47 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
48 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
49 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
50 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
51 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
52
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
53 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
54 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
55 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
56 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
57 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
58 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
59 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
60 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
61
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 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
63 function read_uint16be(str, pos)
11106
76f46c2579a2 net.websocket.frames: Allow all methods to work on non-string objects
Matthew Wild <mwild1@gmail.com>
parents: 8728
diff changeset
64 if type(str) ~= "string" then
76f46c2579a2 net.websocket.frames: Allow all methods to work on non-string objects
Matthew Wild <mwild1@gmail.com>
parents: 8728
diff changeset
65 str, pos = str:sub(pos, pos+1), 1;
76f46c2579a2 net.websocket.frames: Allow all methods to work on non-string objects
Matthew Wild <mwild1@gmail.com>
parents: 8728
diff changeset
66 end
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
67 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
68 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
69 function read_uint64be(str, pos)
11106
76f46c2579a2 net.websocket.frames: Allow all methods to work on non-string objects
Matthew Wild <mwild1@gmail.com>
parents: 8728
diff changeset
70 if type(str) ~= "string" then
76f46c2579a2 net.websocket.frames: Allow all methods to work on non-string objects
Matthew Wild <mwild1@gmail.com>
parents: 8728
diff changeset
71 str, pos = str:sub(pos, pos+7), 1;
76f46c2579a2 net.websocket.frames: Allow all methods to work on non-string objects
Matthew Wild <mwild1@gmail.com>
parents: 8728
diff changeset
72 end
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
73 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
74 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
75 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
76
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
77 local function parse_frame_header(frame)
11157
413bd21ba449 net.websocket.frames: Read buffer length correctly in Lua 5.1 (fix #1598)
Kim Alvefur <zash@zash.se>
parents: 11112
diff changeset
78 if frame:len() < 2 then return; end
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
79
11106
76f46c2579a2 net.websocket.frames: Allow all methods to work on non-string objects
Matthew Wild <mwild1@gmail.com>
parents: 8728
diff changeset
80 local byte1, byte2 = frame:byte(1, 2);
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
81 local result = {
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
82 FIN = band(byte1, 0x80) > 0;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
83 RSV1 = band(byte1, 0x40) > 0;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
84 RSV2 = band(byte1, 0x20) > 0;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
85 RSV3 = band(byte1, 0x10) > 0;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
86 opcode = band(byte1, 0x0F);
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 MASK = band(byte2, 0x80) > 0;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
89 length = band(byte2, 0x7F);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
90 };
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
91
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
92 local length_bytes = 0;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
93 if result.length == 126 then
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
94 length_bytes = 2;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
95 elseif result.length == 127 then
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
96 length_bytes = 8;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
97 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
98
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
99 local header_length = 2 + length_bytes + (result.MASK and 4 or 0);
11157
413bd21ba449 net.websocket.frames: Read buffer length correctly in Lua 5.1 (fix #1598)
Kim Alvefur <zash@zash.se>
parents: 11112
diff changeset
100 if frame:len() < header_length then return; end
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
101
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
102 if length_bytes == 2 then
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
103 result.length = read_uint16be(frame, 3);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
104 elseif length_bytes == 8 then
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
105 result.length = read_uint64be(frame, 3);
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 if result.MASK then
11164
4e5a2af9dd19 net.websocket.frames: Use C string XOR implementation
Kim Alvefur <zash@zash.se>
parents: 11157
diff changeset
109 result.key = frame:sub(length_bytes+3, length_bytes+6);
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
110 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
111
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
112 return result, header_length;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
113 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
114
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
115 -- 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
116 -- TODO: optimize
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
117 local function apply_mask(str, key, from, to)
11164
4e5a2af9dd19 net.websocket.frames: Use C string XOR implementation
Kim Alvefur <zash@zash.se>
parents: 11157
diff changeset
118 return sxor(str:sub(from or 1, to or -1), key);
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
119 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
120
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
121 local function parse_frame_body(frame, header, pos)
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
122 if header.MASK then
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
123 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
124 else
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
125 return frame:sub(pos, pos + header.length - 1);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
126 end
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(frame)
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
130 local result, pos = parse_frame_header(frame);
11157
413bd21ba449 net.websocket.frames: Read buffer length correctly in Lua 5.1 (fix #1598)
Kim Alvefur <zash@zash.se>
parents: 11112
diff changeset
131 if result == nil or frame:len() < (pos + result.length) then return nil, nil, result; end
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
132 result.data = parse_frame_body(frame, result, pos+1);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
133 return result, pos + result.length;
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
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
136 local function build_frame(desc)
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
137 local data = desc.data or "";
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
138
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
139 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
140 if desc.opcode >= 0x8 then
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
141 -- RFC 6455 5.5
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
142 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
143 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
144
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
145 local b1 = bor(desc.opcode,
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
146 desc.FIN and 0x80 or 0,
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
147 desc.RSV1 and 0x40 or 0,
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
148 desc.RSV2 and 0x20 or 0,
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
149 desc.RSV3 and 0x10 or 0);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
150
6395
e0164b0fcafd net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
151 local b2 = #data;
e0164b0fcafd net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
152 local length_extra;
e0164b0fcafd net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
153 if b2 <= 125 then -- 7-bit length
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
154 length_extra = "";
6395
e0164b0fcafd net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
155 elseif b2 <= 0xFFFF then -- 2-byte length
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
156 b2 = 126;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
157 length_extra = pack_uint16be(#data);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
158 else -- 8-byte length
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
159 b2 = 127;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
160 length_extra = pack_uint64be(#data);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
161 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
162
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
163 local key = ""
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
164 if desc.MASK then
11164
4e5a2af9dd19 net.websocket.frames: Use C string XOR implementation
Kim Alvefur <zash@zash.se>
parents: 11157
diff changeset
165 key = desc.key
4e5a2af9dd19 net.websocket.frames: Use C string XOR implementation
Kim Alvefur <zash@zash.se>
parents: 11157
diff changeset
166 if not key then
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
167 key = random_bytes(4);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
168 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
169 b2 = bor(b2, 0x80);
11164
4e5a2af9dd19 net.websocket.frames: Use C string XOR implementation
Kim Alvefur <zash@zash.se>
parents: 11157
diff changeset
170 data = apply_mask(data, key);
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
171 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
172
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
173 return s_char(b1, b2) .. length_extra .. key .. data
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
174 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
175
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
176 local function parse_close(data)
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
177 local code, message
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
178 if #data >= 2 then
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
179 code = read_uint16be(data, 1);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
180 if #data > 2 then
11106
76f46c2579a2 net.websocket.frames: Allow all methods to work on non-string objects
Matthew Wild <mwild1@gmail.com>
parents: 8728
diff changeset
181 message = data:sub(3);
6389
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 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
184 return code, message
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
6455
b6514e691a70 net.websocket: Make data masking configurable
Florian Zeitz <florob@babelmonkeys.de>
parents: 6398
diff changeset
187 local function build_close(code, message, mask)
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
188 local data = pack_uint16be(code);
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
189 if message then
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
190 assert(#message<=123, "Close reason must be <=123 bytes");
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
191 data = data .. message;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
192 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
193 return build_frame({
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
194 opcode = 0x8;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
195 FIN = true;
6455
b6514e691a70 net.websocket: Make data masking configurable
Florian Zeitz <florob@babelmonkeys.de>
parents: 6398
diff changeset
196 MASK = mask;
6389
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
197 data = data;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
198 });
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
199 end
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
200
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
201 return {
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
202 parse_header = parse_frame_header;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
203 parse_body = parse_frame_body;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
204 parse = parse_frame;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
205 build = build_frame;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
206 parse_close = parse_close;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
207 build_close = build_close;
8eccd07b619c net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff changeset
208 };