Software /
code /
prosody
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 |
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 }; |