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