Closed SinisterRectus closed 7 years ago
I think I've narrowed down the issue to somewhere in coro-wrapper by using the following test:
coroutine.wrap(function()
local ws = require('coro-websocket')
local options = ws.parseUrl("wss://gateway.discord.gg")
options.pathname = '/?v=7&encoding=json'
local res, read, write = ws.connect(options)
for msg in read do
write()
end
end)()
Looking at decoder
at line 71:
The final message in chunk
is nil
, which causes buffer
to become an empty string. When this is decoded, both item
and newIndex
come back as nil
. Because they are both nil
, the return item
line is never reached, so the while true do
loop never breaks. The process somehow manages to exit, though. Adding a special case before decoding seems to fix this, but I'm not sure if it will break anything else.
if buffer == '' then
return nil
end
local item, newIndex = decode(buffer, index)
Another option would be to add it to the final block:
if item or newIndex or buffer == '' then
Note: If I change write()
to res.socket:close()
, the issue persists. The loop never breaks, but the process exits. This also happens in 1.0.0-1, though, so it may not be related.
I also noticed that, according to the code, both buffer
and chunk
can be nil
. I don't know if this is ever possible in practice, but if it does happen, decode
will attempt to decode a nil buffer. It looks like the HTTP decoder will handle this, but the WebSocket decoder will error. It may be necessary to extend the buffer check:
if buffer == '' or buffer == nil then
... or you can return earlier when the buffer is cleared.
Let me know which fix you think is appropriate and I can PR it, or just let you fix it.
It looks like your head is more in this than mine. I'm super busy with another project for the next few weeks. Go ahead and PR the one you prefer. I'll try it against lit's unit tests and see if it breaks anything in there (they use coro websockets heavily).
Addressed with 84fe7b9
In coro-websocket 1.0.0-1, I wrote an empty message to close the socket:
This causes an opcode of 8 to be sent:
After this,
nil
was returned to signal an end of data:And the read loop breaks:
Similarly, if the server closed the connection,
nil
is returned and the loop breaks.While working with coro-websocket 3.0.0, I noticed that
nil
is not consistently returned.If the server closes the connection, I get a libuv error and the process hangs:
If
res.socket
is closed or ifwrite()
is called, the process appears to end (crash?) after one read loop or less; code after the loop is never executed.PR #207 would help with a server close, but I'm not sure what to do if the client wants to close the connection.