Software /
code /
prosody
Comparison
net/websocket.lua @ 8892:fb38b2c77a72
net.websocket: Fix incompatibility with net.http changes
I was unable to pinpoint the exact revision that broke this.
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Fri, 08 Jun 2018 16:30:04 +0100 |
parent | 8189:a3565d7dd304 |
child | 8893:eb710675f7f8 |
comparison
equal
deleted
inserted
replaced
8891:d9b7db6f140f | 8892:fb38b2c77a72 |
---|---|
19 local close_timeout = 3; -- Seconds to wait after sending close frame until closing connection. | 19 local close_timeout = 3; -- Seconds to wait after sending close frame until closing connection. |
20 | 20 |
21 local websockets = {}; | 21 local websockets = {}; |
22 | 22 |
23 local websocket_listeners = {}; | 23 local websocket_listeners = {}; |
24 function websocket_listeners.ondisconnect(handler, err) | 24 function websocket_listeners.ondisconnect(conn, err) |
25 local s = websockets[handler]; | 25 local s = websockets[conn]; |
26 websockets[handler] = nil; | 26 websockets[conn] = nil; |
27 if s.close_timer then | 27 if s.close_timer then |
28 timer.stop(s.close_timer); | 28 timer.stop(s.close_timer); |
29 s.close_timer = nil; | 29 s.close_timer = nil; |
30 end | 30 end |
31 s.readyState = 3; | 31 s.readyState = 3; |
32 if s.close_code == nil and s.onerror then s:onerror(err); end | 32 if s.close_code == nil and s.onerror then s:onerror(err); end |
33 if s.onclose then s:onclose(s.close_code, s.close_message or err); end | 33 if s.onclose then s:onclose(s.close_code, s.close_message or err); end |
34 end | 34 end |
35 | 35 |
36 function websocket_listeners.ondetach(handler) | 36 function websocket_listeners.ondetach(conn) |
37 websockets[handler] = nil; | 37 websockets[conn] = nil; |
38 end | 38 end |
39 | 39 |
40 local function fail(s, code, reason) | 40 local function fail(s, code, reason) |
41 log("warn", "WebSocket connection failed, closing. %d %s", code, reason); | 41 log("warn", "WebSocket connection failed, closing. %d %s", code, reason); |
42 s:close(code, reason); | 42 s:close(code, reason); |
43 s.handler:close(); | 43 s.conn:close(); |
44 return false | 44 return false |
45 end | 45 end |
46 | 46 |
47 function websocket_listeners.onincoming(handler, buffer, err) -- luacheck: ignore 212/err | 47 function websocket_listeners.onincoming(conn, buffer, err) -- luacheck: ignore 212/err |
48 local s = websockets[handler]; | 48 local s = websockets[conn]; |
49 s.readbuffer = s.readbuffer..buffer; | 49 s.readbuffer = s.readbuffer..buffer; |
50 while true do | 50 while true do |
51 local frame, len = frames.parse(s.readbuffer); | 51 local frame, len = frames.parse(s.readbuffer); |
52 if frame == nil then break end | 52 if frame == nil then break end |
53 s.readbuffer = s.readbuffer:sub(len+1); | 53 s.readbuffer = s.readbuffer:sub(len+1); |
109 s:close(1000); | 109 s:close(1000); |
110 return true; | 110 return true; |
111 elseif frame.opcode == 0x9 then -- Ping frame | 111 elseif frame.opcode == 0x9 then -- Ping frame |
112 frame.opcode = 0xA; | 112 frame.opcode = 0xA; |
113 frame.MASK = true; -- RFC 6455 6.1.5: If the data is being sent by the client, the frame(s) MUST be masked | 113 frame.MASK = true; -- RFC 6455 6.1.5: If the data is being sent by the client, the frame(s) MUST be masked |
114 handler:write(frames.build(frame)); | 114 conn:write(frames.build(frame)); |
115 elseif frame.opcode == 0xA then -- Pong frame | 115 elseif frame.opcode == 0xA then -- Pong frame |
116 log("debug", "Received unexpected pong frame: " .. tostring(frame.data)); | 116 log("debug", "Received unexpected pong frame: " .. tostring(frame.data)); |
117 else | 117 else |
118 return fail(s, 1002, "Reserved opcode"); | 118 return fail(s, 1002, "Reserved opcode"); |
119 end | 119 end |
124 | 124 |
125 local websocket_methods = {}; | 125 local websocket_methods = {}; |
126 local function close_timeout_cb(now, timerid, s) -- luacheck: ignore 212/now 212/timerid | 126 local function close_timeout_cb(now, timerid, s) -- luacheck: ignore 212/now 212/timerid |
127 s.close_timer = nil; | 127 s.close_timer = nil; |
128 log("warn", "Close timeout waiting for server to close, closing manually."); | 128 log("warn", "Close timeout waiting for server to close, closing manually."); |
129 s.handler:close(); | 129 s.conn:close(); |
130 end | 130 end |
131 function websocket_methods:close(code, reason) | 131 function websocket_methods:close(code, reason) |
132 if self.readyState < 2 then | 132 if self.readyState < 2 then |
133 code = code or 1000; | 133 code = code or 1000; |
134 log("debug", "closing WebSocket with code %i: %s" , code , tostring(reason)); | 134 log("debug", "closing WebSocket with code %i: %s" , code , tostring(reason)); |
135 self.readyState = 2; | 135 self.readyState = 2; |
136 local handler = self.handler; | 136 local conn = self.conn; |
137 handler:write(frames.build_close(code, reason, true)); | 137 conn:write(frames.build_close(code, reason, true)); |
138 -- Do not close socket straight away, wait for acknowledgement from server. | 138 -- Do not close socket straight away, wait for acknowledgement from server. |
139 self.close_timer = timer.add_task(close_timeout, close_timeout_cb, self); | 139 self.close_timer = timer.add_task(close_timeout, close_timeout_cb, self); |
140 elseif self.readyState == 2 then | 140 elseif self.readyState == 2 then |
141 log("debug", "tried to close a closing WebSocket, closing the raw socket."); | 141 log("debug", "tried to close a closing WebSocket, closing the raw socket."); |
142 -- Stop timer | 142 -- Stop timer |
143 if self.close_timer then | 143 if self.close_timer then |
144 timer.stop(self.close_timer); | 144 timer.stop(self.close_timer); |
145 self.close_timer = nil; | 145 self.close_timer = nil; |
146 end | 146 end |
147 local handler = self.handler; | 147 local conn = self.conn; |
148 handler:close(); | 148 conn:close(); |
149 else | 149 else |
150 log("debug", "tried to close a closed WebSocket, ignoring."); | 150 log("debug", "tried to close a closed WebSocket, ignoring."); |
151 end | 151 end |
152 end | 152 end |
153 function websocket_methods:send(data, opcode) | 153 function websocket_methods:send(data, opcode) |
166 MASK = true; -- RFC 6455 6.1.5: If the data is being sent by the client, the frame(s) MUST be masked | 166 MASK = true; -- RFC 6455 6.1.5: If the data is being sent by the client, the frame(s) MUST be masked |
167 opcode = opcode; | 167 opcode = opcode; |
168 data = tostring(data); | 168 data = tostring(data); |
169 }; | 169 }; |
170 log("debug", "WebSocket sending frame: opcode=%0x, %i bytes", frame.opcode, #frame.data); | 170 log("debug", "WebSocket sending frame: opcode=%0x, %i bytes", frame.opcode, #frame.data); |
171 return self.handler:write(frames.build(frame)); | 171 return self.conn:write(frames.build(frame)); |
172 end | 172 end |
173 | 173 |
174 local websocket_metatable = { | 174 local websocket_metatable = { |
175 __index = websocket_methods; | 175 __index = websocket_methods; |
176 }; | 176 }; |
214 end | 214 end |
215 | 215 |
216 local s = setmetatable({ | 216 local s = setmetatable({ |
217 readbuffer = ""; | 217 readbuffer = ""; |
218 databuffer = nil; | 218 databuffer = nil; |
219 handler = nil; | 219 conn = nil; |
220 close_code = nil; | 220 close_code = nil; |
221 close_message = nil; | 221 close_message = nil; |
222 close_timer = nil; | 222 close_timer = nil; |
223 readyState = 0; | 223 readyState = 0; |
224 protocol = nil; | 224 protocol = nil; |
250 end | 250 end |
251 | 251 |
252 s.protocol = r.headers["sec-websocket-protocol"]; | 252 s.protocol = r.headers["sec-websocket-protocol"]; |
253 | 253 |
254 -- Take possession of socket from http | 254 -- Take possession of socket from http |
255 local conn = http_req.conn; | |
255 http_req.conn = nil; | 256 http_req.conn = nil; |
256 local handler = http_req.handler; | 257 s.conn = conn; |
257 s.handler = handler; | 258 websockets[conn] = s; |
258 websockets[handler] = s; | 259 conn:setlistener(websocket_listeners); |
259 handler:setlistener(websocket_listeners); | |
260 | 260 |
261 log("debug", "WebSocket connected successfully to %s", url); | 261 log("debug", "WebSocket connected successfully to %s", url); |
262 s.readyState = 1; | 262 s.readyState = 1; |
263 if s.onopen then s:onopen(); end | 263 if s.onopen then s:onopen(); end |
264 websocket_listeners.onincoming(handler, b); | 264 websocket_listeners.onincoming(conn, b); |
265 end); | 265 end); |
266 | 266 |
267 return s; | 267 return s; |
268 end | 268 end |
269 | 269 |