mame/plugins/weblit/websocket.lua

82 lines
2.2 KiB
Lua

local websocketCodec = require('websocket-codec')
local function websocketHandler(options, handler)
return function (req, res, go)
-- Websocket connections must be GET requests
-- with 'Upgrade: websocket'
-- and 'Connection: Upgrade' headers
local headers = req.headers
local connection = headers.connection
local upgrade = headers.upgrade
if not (
req.method == "GET" and
upgrade and upgrade:lower():find("websocket", 1, true) and
connection and connection:lower():find("upgrade", 1, true)
) then
return go()
end
if options.filter and not options.filter(req) then
return go()
end
-- If there is a sub-protocol specified, filter on it.
local protocol = options.protocol
if protocol then
local list = headers["sec-websocket-protocol"]
local foundProtocol
if list then
for item in list:gmatch("[^, ]+") do
if item == protocol then
foundProtocol = true
break
end
end
end
if not foundProtocol then
return go()
end
end
-- Make sure it's a new client speaking v13 of the protocol
assert(tonumber(headers["sec-websocket-version"]) >= 13, "only websocket protocol v13 supported")
-- Get the security key
local key = assert(headers["sec-websocket-key"], "websocket security required")
res.code = 101
headers = res.headers
headers.Upgrade = "websocket"
headers.Connection = "Upgrade"
headers["Sec-WebSocket-Accept"] = websocketCodec.acceptKey(key)
if protocol then
headers["Sec-WebSocket-Protocol"] = protocol
end
function res.upgrade(read, write, updateDecoder, updateEncoder)
updateDecoder(websocketCodec.decode)
updateEncoder(websocketCodec.encode)
local success, err = pcall(handler, req, read, write)
if not success then
print(err)
write({
opcode = 1,
payload = err,
})
return write()
end
end
end
end
local server = require('weblit-app')
function server.websocket(options, handler)
server.route({
method = "GET",
path = options.path,
host = options.host,
}, websocketHandler(options, handler))
return server
end
return websocketHandler