Software /
code /
prosody
Annotate
net/websocket/frames.lua @ 10228:e77bf4222fae
net.server_epoll: Add support for opportunistic writes
This tries to flush data to the underlying sockets when receiving
writes. This should lead to fewer timer objects being around. On the
other hand, this leads to more and smaller writes which may translate to
more TCP/IP packets being sent, depending on how the kernel handles
this. This trades throughput for lower latency.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Wed, 28 Aug 2019 01:41:00 +0200 |
parent | 9692:affcbccc1dff |
child | 10241:48f7cda4174d |
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; |
9691
e11e076f0eb8
various: Don't rely on _G.unpack existing
Kim Alvefur <zash@zash.se>
parents:
9659
diff
changeset
|
19 local unpack = table.unpack or unpack; -- luacheck: ignore 113 |
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 t_concat = table.concat; |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
22 local s_byte = string.byte; |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
23 local s_char= string.char; |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
24 local s_sub = string.sub; |
9692
affcbccc1dff
lint: Remove use of the 143 error code
Kim Alvefur <zash@zash.se>
parents:
9691
diff
changeset
|
25 local s_pack = string.pack; |
affcbccc1dff
lint: Remove use of the 143 error code
Kim Alvefur <zash@zash.se>
parents:
9691
diff
changeset
|
26 local s_unpack = string.unpack; |
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
|
27 |
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 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
|
29 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
|
30 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
|
31 end |
6389
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
32 |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
33 local function read_uint16be(str, pos) |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
34 local l1, l2 = s_byte(str, pos, pos+1); |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
35 return l1*256 + l2; |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
36 end |
6395
e0164b0fcafd
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
37 -- FIXME: this may lose precision |
6389
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
38 local function read_uint64be(str, pos) |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
39 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
|
40 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
|
41 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
|
42 return h * 2^32 + l; |
6389
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
43 end |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
44 local function pack_uint16be(x) |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
45 return s_char(rshift(x, 8), band(x, 0xFF)); |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
46 end |
6395
e0164b0fcafd
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
47 local function get_byte(x, n) |
6389
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
48 return band(rshift(x, n), 0xFF); |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
49 end |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
50 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
|
51 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
|
52 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
|
53 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
|
54 end |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
55 |
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
|
56 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
|
57 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
|
58 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
|
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 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
|
61 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
|
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 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
|
64 |
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 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
|
66 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
|
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) |
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 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
|
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 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
|
73 |
6389
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
74 local function parse_frame_header(frame) |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
75 if #frame < 2 then return; end |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
76 |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
77 local byte1, byte2 = s_byte(frame, 1, 2); |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
78 local result = { |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
79 FIN = band(byte1, 0x80) > 0; |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
80 RSV1 = band(byte1, 0x40) > 0; |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
81 RSV2 = band(byte1, 0x20) > 0; |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
82 RSV3 = band(byte1, 0x10) > 0; |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
83 opcode = band(byte1, 0x0F); |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
84 |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
85 MASK = band(byte2, 0x80) > 0; |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
86 length = band(byte2, 0x7F); |
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 |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
89 local length_bytes = 0; |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
90 if result.length == 126 then |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
91 length_bytes = 2; |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
92 elseif result.length == 127 then |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
93 length_bytes = 8; |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
94 end |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
95 |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
96 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
|
97 if #frame < header_length then return; 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 if length_bytes == 2 then |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
100 result.length = read_uint16be(frame, 3); |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
101 elseif length_bytes == 8 then |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
102 result.length = read_uint64be(frame, 3); |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
103 end |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
104 |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
105 if result.MASK then |
6395
e0164b0fcafd
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
106 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
|
107 end |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
108 |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
109 return result, header_length; |
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 -- 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
|
113 -- TODO: optimize |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
114 local function apply_mask(str, key, from, to) |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
115 from = from or 1 |
8728
41c959c5c84b
Fix spelling throughout the codebase [codespell]
Kim Alvefur <zash@zash.se>
parents:
8442
diff
changeset
|
116 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
|
117 to = to or #str |
8728
41c959c5c84b
Fix spelling throughout the codebase [codespell]
Kim Alvefur <zash@zash.se>
parents:
8442
diff
changeset
|
118 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
|
119 local key_len = #key |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
120 local counter = 0; |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
121 local data = {}; |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
122 for i = from, to do |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
123 local key_index = counter%key_len + 1; |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
124 counter = counter + 1; |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
125 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
|
126 end |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
127 return t_concat(data); |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
128 end |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
129 |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
130 local function parse_frame_body(frame, header, pos) |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
131 if header.MASK then |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
132 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
|
133 else |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
134 return frame:sub(pos, pos + header.length - 1); |
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 end |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
137 |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
138 local function parse_frame(frame) |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
139 local result, pos = parse_frame_header(frame); |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
140 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
|
141 result.data = parse_frame_body(frame, result, pos+1); |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
142 return result, pos + result.length; |
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 function build_frame(desc) |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
146 local data = desc.data or ""; |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
147 |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
148 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
|
149 if desc.opcode >= 0x8 then |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
150 -- RFC 6455 5.5 |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
151 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
|
152 end |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
153 |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
154 local b1 = bor(desc.opcode, |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
155 desc.FIN and 0x80 or 0, |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
156 desc.RSV1 and 0x40 or 0, |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
157 desc.RSV2 and 0x20 or 0, |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
158 desc.RSV3 and 0x10 or 0); |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
159 |
6395
e0164b0fcafd
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
160 local b2 = #data; |
e0164b0fcafd
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
161 local length_extra; |
e0164b0fcafd
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
162 if b2 <= 125 then -- 7-bit length |
6389
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
163 length_extra = ""; |
6395
e0164b0fcafd
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
164 elseif b2 <= 0xFFFF then -- 2-byte length |
6389
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
165 b2 = 126; |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
166 length_extra = pack_uint16be(#data); |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
167 else -- 8-byte length |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
168 b2 = 127; |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
169 length_extra = pack_uint64be(#data); |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
170 end |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
171 |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
172 local key = "" |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
173 if desc.MASK then |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
174 local key_a = desc.key |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
175 if key_a then |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
176 key = s_char(unpack(key_a, 1, 4)); |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
177 else |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
178 key = random_bytes(4); |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
179 key_a = {key:byte(1,4)}; |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
180 end |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
181 b2 = bor(b2, 0x80); |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
182 data = apply_mask(data, key_a); |
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 |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
185 return s_char(b1, b2) .. length_extra .. key .. data |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
186 end |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
187 |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
188 local function parse_close(data) |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
189 local code, message |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
190 if #data >= 2 then |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
191 code = read_uint16be(data, 1); |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
192 if #data > 2 then |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
193 message = s_sub(data, 3); |
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 end |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
196 return code, message |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
197 end |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
198 |
6455
b6514e691a70
net.websocket: Make data masking configurable
Florian Zeitz <florob@babelmonkeys.de>
parents:
6398
diff
changeset
|
199 local function build_close(code, message, mask) |
6389
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
200 local data = pack_uint16be(code); |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
201 if message then |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
202 assert(#message<=123, "Close reason must be <=123 bytes"); |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
203 data = data .. message; |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
204 end |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
205 return build_frame({ |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
206 opcode = 0x8; |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
207 FIN = true; |
6455
b6514e691a70
net.websocket: Make data masking configurable
Florian Zeitz <florob@babelmonkeys.de>
parents:
6398
diff
changeset
|
208 MASK = mask; |
6389
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
209 data = data; |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
210 }); |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
211 end |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
212 |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
213 return { |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
214 parse_header = parse_frame_header; |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
215 parse_body = parse_frame_body; |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
216 parse = parse_frame; |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
217 build = build_frame; |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
218 parse_close = parse_close; |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
219 build_close = build_close; |
8eccd07b619c
net/websocket: Add new websocket client code
daurnimator <quae@daurnimator.com>
parents:
diff
changeset
|
220 }; |