diff options
author | 2016-03-12 12:31:13 +0100 | |
---|---|---|
committer | 2016-03-12 12:31:13 +0100 | |
commit | a026a582f1a0ea8c1ede3acaddacef506ef3f3b0 (patch) | |
tree | e31573822f2359677de519f9f3b600d98e8764cd /plugins/websocket-codec/init.lua | |
parent | 477d2abd43984f076b7e45f5527591fa8fd0d241 (diff) | |
parent | dcab55bf53b94713a6f72e9633f5101c8dd6c08c (diff) |
Merge pull request #15 from mamedev/master
Sync to base master
Diffstat (limited to 'plugins/websocket-codec/init.lua')
-rw-r--r-- | plugins/websocket-codec/init.lua | 261 |
1 files changed, 0 insertions, 261 deletions
diff --git a/plugins/websocket-codec/init.lua b/plugins/websocket-codec/init.lua deleted file mode 100644 index 8a7da7f9190..00000000000 --- a/plugins/websocket-codec/init.lua +++ /dev/null @@ -1,261 +0,0 @@ -local exports = {} - -exports.name = "creationix/websocket-codec" -exports.version = "1.0.7" -exports.homepage = "https://github.com/luvit/lit/blob/master/deps/websocket-codec.lua" -exports.description = "A codec implementing websocket framing and helpers for handshakeing" -exports.tags = {"http", "websocket", "codec"} -exports.license = "MIT" -exports.author = { name = "Tim Caswell" } - -local digest = require('openssl').digest.digest -local base64 = require('openssl').base64 -local random = require('openssl').random -local bit = require('bit') - -local band = bit.band -local bor = bit.bor -local bxor = bit.bxor -local rshift = bit.rshift -local lshift = bit.lshift -local char = string.char -local byte = string.byte -local sub = string.sub -local gmatch = string.gmatch -local lower = string.lower -local gsub = string.gsub -local concat = table.concat - -local function applyMask(data, mask) - local bytes = { - [0] = byte(mask, 1), - [1] = byte(mask, 2), - [2] = byte(mask, 3), - [3] = byte(mask, 4) - } - local out = {} - for i = 1, #data do - out[i] = char( - bxor(byte(data, i), bytes[(i - 1) % 4]) - ) - end - return concat(out) -end - -function exports.decode(chunk) - if #chunk < 2 then return end - local second = byte(chunk, 2) - local len = band(second, 0x7f) - local offset - if len == 126 then - if #chunk < 4 then return end - len = bor( - lshift(byte(chunk, 3), 8), - byte(chunk, 4)) - offset = 4 - elseif len == 127 then - if #chunk < 10 then return end - len = bor( - lshift(byte(chunk, 3), 56), - lshift(byte(chunk, 4), 48), - lshift(byte(chunk, 5), 40), - lshift(byte(chunk, 6), 32), - lshift(byte(chunk, 7), 24), - lshift(byte(chunk, 8), 16), - lshift(byte(chunk, 9), 8), - byte(chunk, 10)) - offset = 10 - else - offset = 2 - end - local mask = band(second, 0x80) > 0 - if mask then - offset = offset + 4 - end - if #chunk < offset + len then return end - - local first = byte(chunk, 1) - local payload = sub(chunk, offset + 1, offset + len) - assert(#payload == len, "Length mismatch") - if mask then - payload = applyMask(payload, sub(chunk, offset - 3, offset)) - end - local extra = sub(chunk, offset + len + 1) - return { - fin = band(first, 0x80) > 0, - rsv1 = band(first, 0x40) > 0, - rsv2 = band(first, 0x20) > 0, - rsv3 = band(first, 0x10) > 0, - opcode = band(first, 0xf), - mask = mask, - len = len, - payload = payload - }, extra -end - -function exports.encode(item) - if type(item) == "string" then - item = { - opcode = 2, - payload = item - } - end - local payload = item.payload - assert(type(payload) == "string", "payload must be string") - local len = #payload - local fin = item.fin - if fin == nil then fin = true end - local rsv1 = item.rsv1 - local rsv2 = item.rsv2 - local rsv3 = item.rsv3 - local opcode = item.opcode or 2 - local mask = item.mask - local chars = { - char(bor( - fin and 0x80 or 0, - rsv1 and 0x40 or 0, - rsv2 and 0x20 or 0, - rsv3 and 0x10 or 0, - opcode - )), - char(bor( - mask and 0x80 or 0, - len < 126 and len or (len < 0x10000) and 126 or 127 - )) - } - if len >= 0x10000 then - chars[3] = char(band(rshift(len, 56), 0xff)) - chars[4] = char(band(rshift(len, 48), 0xff)) - chars[5] = char(band(rshift(len, 40), 0xff)) - chars[6] = char(band(rshift(len, 32), 0xff)) - chars[7] = char(band(rshift(len, 24), 0xff)) - chars[8] = char(band(rshift(len, 16), 0xff)) - chars[9] = char(band(rshift(len, 8), 0xff)) - chars[10] = char(band(len, 0xff)) - elseif len >= 126 then - chars[3] = char(band(rshift(len, 8), 0xff)) - chars[4] = char(band(len, 0xff)) - end - if mask then - local key = random(4) - return concat(chars) .. key .. applyMask(payload, key) - end - return concat(chars) .. payload -end - -local websocketGuid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" - -function exports.acceptKey(key) - return gsub(base64(digest("sha1", key .. websocketGuid, true)), "\n", "") -end -local acceptKey = exports.acceptKey - --- Make a client handshake connection -function exports.handshake(options, request) - local key = gsub(base64(random(20)), "\n", "") - local host = options.host - local path = options.path or "/" - local protocol = options.protocol - local req = { - method = "GET", - path = path, - {"Connection", "Upgrade"}, - {"Upgrade", "websocket"}, - {"Sec-WebSocket-Version", "13"}, - {"Sec-WebSocket-Key", key}, - } - for i = 1, #options do - req[#req + 1] = options[i] - end - if host then - req[#req + 1] = {"Host", host} - end - if protocol then - req[#req + 1] = {"Sec-WebSocket-Protocol", protocol} - end - local res = request(req) - if not res then - return nil, "Missing response from server" - end - -- Parse the headers for quick reading - if res.code ~= 101 then - return nil, "response must be code 101" - end - - local headers = {} - for i = 1, #res do - local name, value = unpack(res[i]) - headers[lower(name)] = value - end - - if not headers.connection or lower(headers.connection) ~= "upgrade" then - return nil, "Invalid or missing connection upgrade header in response" - end - if headers["sec-websocket-accept"] ~= acceptKey(key) then - return nil, "challenge key missing or mismatched" - end - if protocol and headers["sec-websocket-protocol"] ~= protocol then - return nil, "protocol missing or mistmatched" - end - return true -end - -function exports.handleHandshake(head, protocol) - - -- WebSocket connections must be GET requests - if not head.method == "GET" then return end - - -- Parse the headers for quick reading - local headers = {} - for i = 1, #head do - local name, value = unpack(head[i]) - headers[lower(name)] = value - end - - -- Must have 'Upgrade: websocket' and 'Connection: Upgrade' headers - if not (headers.connection and headers.upgrade and - headers.connection:lower():find("upgrade", 1, true) and - headers.upgrade:lower():find("websocket", 1, true)) then return end - - -- Make sure it's a new client speaking v13 of the protocol - if tonumber(headers["sec-websocket-version"]) < 13 then - return nil, "only websocket protocol v13 supported" - end - - local key = headers["sec-websocket-key"] - if not key then - return nil, "websocket security key missing" - end - - -- If the server wants a specified protocol, check for it. - if protocol then - local foundProtocol = false - local list = headers["sec-websocket-protocol"] - if list then - for item in gmatch(list, "[^, ]+") do - if item == protocol then - foundProtocol = true - break - end - end - end - if not foundProtocol then - return nil, "specified protocol missing in request" - end - end - - local accept = acceptKey(key) - - local res = { - code = 101, - {"Upgrade", "websocket"}, - {"Connection", "Upgrade"}, - {"Sec-WebSocket-Accept", accept}, - } - if protocol then - res[#res + 1] = {"Sec-WebSocket-Protocol", protocol} - end - - return res -end -return exports |