Comparison

net/websocket.lua @ 6396:17b54f523796

Check Sec-WebSocket-Protocol header
author Florian Zeitz <florob@babelmonkeys.de>
date Fri, 05 Sep 2014 02:14:04 +0200
parent 6395:e0164b0fcafd
child 6398:ad434f47bfc0
comparison
equal deleted inserted replaced
6395:e0164b0fcafd 6396:17b54f523796
4 -- 4 --
5 -- This project is MIT/X11 licensed. Please see the 5 -- This project is MIT/X11 licensed. Please see the
6 -- COPYING file in the source package for more information. 6 -- COPYING file in the source package for more information.
7 -- 7 --
8 8
9 local t_concat = table.concat;
10
9 local http = require "net.http"; 11 local http = require "net.http";
10 local frames = require "net.websocket.frames"; 12 local frames = require "net.websocket.frames";
11 local base64 = require "util.encodings".base64; 13 local base64 = require "util.encodings".base64;
12 local sha1 = require "util.hashes".sha1; 14 local sha1 = require "util.hashes".sha1;
13 local random_bytes = require "util.random".bytes; 15 local random_bytes = require "util.random".bytes;
74 return fail(s, 1002, "Reserved opcode"); 76 return fail(s, 1002, "Reserved opcode");
75 end 77 end
76 if frame.FIN then 78 if frame.FIN then
77 s.databuffer = nil; 79 s.databuffer = nil;
78 if s.onmessage then 80 if s.onmessage then
79 s:onmessage(table.concat(databuffer), databuffer.type); 81 s:onmessage(t_concat(databuffer), databuffer.type);
80 end 82 end
81 end 83 end
82 else -- Control frame 84 else -- Control frame
83 if frame.length > 125 then -- Control frame with too much payload 85 if frame.length > 125 then -- Control frame with too much payload
84 return fail(s, 1002, "Payload too large"); 86 return fail(s, 1002, "Payload too large");
185 ]] 187 ]]
186 local key = base64.encode(random_bytes(16)); 188 local key = base64.encode(random_bytes(16));
187 189
188 -- Either a single protocol string or an array of protocol strings. 190 -- Either a single protocol string or an array of protocol strings.
189 local protocol = ex.protocol; 191 local protocol = ex.protocol;
190 if type(protocol) == "table" then 192 if type(protocol) == "string" then
191 protocol = table.concat(protocol, ", "); 193 protocol = { protocol };
194 end
195 for _, v in ipairs(protocol) do
196 protocol[v] = true;
192 end 197 end
193 198
194 local headers = { 199 local headers = {
195 ["Upgrade"] = "websocket"; 200 ["Upgrade"] = "websocket";
196 ["Connection"] = "Upgrade"; 201 ["Connection"] = "Upgrade";
197 ["Sec-WebSocket-Key"] = key; 202 ["Sec-WebSocket-Key"] = key;
198 ["Sec-WebSocket-Protocol"] = protocol; 203 ["Sec-WebSocket-Protocol"] = t_concat(protocol, ", ");
199 ["Sec-WebSocket-Version"] = "13"; 204 ["Sec-WebSocket-Version"] = "13";
200 ["Sec-WebSocket-Extensions"] = ex.extensions; 205 ["Sec-WebSocket-Extensions"] = ex.extensions;
201 } 206 }
202 if ex.headers then 207 if ex.headers then
203 for k,v in pairs(ex.headers) do 208 for k,v in pairs(ex.headers) do
231 }, function(b, c, r, http_req) 236 }, function(b, c, r, http_req)
232 if c ~= 101 237 if c ~= 101
233 or r.headers["connection"]:lower() ~= "upgrade" 238 or r.headers["connection"]:lower() ~= "upgrade"
234 or r.headers["upgrade"] ~= "websocket" 239 or r.headers["upgrade"] ~= "websocket"
235 or r.headers["sec-websocket-accept"] ~= base64.encode(sha1(key .. "258EAFA5-E914-47DA-95CA-C5AB0DC85B11")) 240 or r.headers["sec-websocket-accept"] ~= base64.encode(sha1(key .. "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"))
236 -- TODO: check "Sec-WebSocket-Protocol" 241 or not protocol[r.headers["sec-websocket-protocol"]]
237 then 242 then
238 s.readyState = 3; 243 s.readyState = 3;
239 log("warn", "WebSocket connection to %s failed: %s", url, tostring(b)); 244 log("warn", "WebSocket connection to %s failed: %s", url, tostring(b));
240 if s.onerror then s:onerror("connecting-failed"); end 245 if s.onerror then s:onerror("connecting-failed"); end
241 return; 246 return;