Files
NodeMCU_Lua/Websocket/nodemcu-webide/bin/httpserver-websocket.lua
Christian Zufferey 8abc823276 - commencé à bosser sur les websocket, ce n'est pas en yaka :-(
- essayé d'installer webide sur NodeMCU, il y a justement un exemple de websocker server, je n'arrive pas encore à comprendre comment cela marche
- donc il y a encore pas mal de taf
2018-11-02 23:02:02 +01:00

136 lines
3.7 KiB
Lua
Executable File

--rewrite from https://github.com/creationix/nodemcu-webide
local function decode(chunk)
if #chunk < 2 then return end
local second = string.byte(chunk, 2)
local len = bit.band(second, 0x7f)
local offset
if len == 126 then
if #chunk < 4 then return end
len = bit.bor(
bit.lshift(string.byte(chunk, 3), 8),
string.byte(chunk, 4))
offset = 4
elseif len == 127 then
if #chunk < 10 then return end
len = bit.bor(
-- Ignore lengths longer than 32bit
bit.lshift(string.byte(chunk, 7), 24),
bit.lshift(string.byte(chunk, 8), 16),
bit.lshift(string.byte(chunk, 9), 8),
string.byte(chunk, 10))
offset = 10
else
offset = 2
end
local mask = bit.band(second, 0x80) > 0
if mask then
offset = offset + 4
end
if #chunk < offset + len then return end
local first = string.byte(chunk, 1)
local payload = string.sub(chunk, offset + 1, offset + len)
assert(#payload == len, "Length mismatch")
if mask then
payload = crypto.mask(payload, string.sub(chunk, offset - 3, offset))
end
local extra = string.sub(chunk, offset + len + 1)
local opcode = bit.band(first, 0xf)
return extra, payload, opcode
end
local function encode(payload, opcode)
opcode = opcode or 2
assert(type(opcode) == "number", "opcode must be number")
assert(type(payload) == "string", "payload must be string")
local len = #payload
local head = string.char(
bit.bor(0x80, opcode),
bit.bor(len < 126 and len or len < 0x10000 and 126 or 127)
)
if len >= 0x10000 then
head = head .. string.char(
0,0,0,0, -- 32 bit length is plenty, assume zero for rest
bit.band(bit.rshift(len, 24), 0xff),
bit.band(bit.rshift(len, 16), 0xff),
bit.band(bit.rshift(len, 8), 0xff),
bit.band(len, 0xff)
)
elseif len >= 126 then
head = head .. string.char(bit.band(bit.rshift(len, 8), 0xff), bit.band(len, 0xff))
end
return head .. payload
end
local guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
local function acceptKey(key)
return crypto.toBase64(crypto.hash("sha1", key .. guid))
end
return function (connection, payload)
local buffer = false
local socket = {}
local queue = {}
local waiting = false
local function onSend()
if queue[1] then
local data = table.remove(queue, 1)
return connection:send(data, onSend)
end
waiting = false
end
function socket.send(...)
local data = encode(...)
if not waiting then
waiting = true
connection:send(data, onSend)
else
queue[#queue + 1] = data
end
collectgarbage()
print(node.heap())
end
connection:on("receive", function(_, chunk)
if buffer then
buffer = buffer .. chunk
while true do
local extra, payload, opcode = decode(buffer)
if not extra then return end
buffer = extra
socket.onmessage(payload, opcode)
end
end
end)
connection:on("sent", function(_, _)
if socket.onsent ~= nil then
socket.onsent()
end
end)
connection:on("disconnection", function(_, _)
if socket.onclose ~= nil then
socket.onclose()
end
end)
local req = dofile("httpserver-request.lc")(payload)
local key = payload:match("Sec%-WebSocket%-Key: ([A-Za-z0-9+/=]+)")
local fileExists = file.open(req.uri.file, "r")
file.close()
if req.method == "GET" and key and fileExists then
connection:send(
"HTTP/1.1 101 Switching Protocols\r\n" ..
"Upgrade: websocket\r\nConnection: Upgrade\r\n" ..
"Sec-WebSocket-Accept: " .. acceptKey(key) .. "\r\n\r\n",
function () dofile(req.uri.file)(socket) end)
buffer = ""
else
connection:send(
"HTTP/1.1 404 Not Found\r\nConnection: Close\r\n\r\n",
connection.close)
end
end