diff --git a/lib/config.lua b/lib/config.lua index 262f0e1..8e99b33 100644 --- a/lib/config.lua +++ b/lib/config.lua @@ -30,6 +30,7 @@ local storeConfigs = { local wiolaConf = { socketTimeout = 100, maxPayloadLen = 65536, + pingInterval = 1000, -- interval in ms for sending ping frames. set to 0 for disabling realms = {}, store = "redis", storeConfig = { @@ -103,6 +104,10 @@ function _M.config(config) wiolaConf.maxPayloadLen = config.maxPayloadLen end + if config.pingInterval then + wiolaConf.pingInterval = config.pingInterval + end + if config.realms then wiolaConf.realms = config.realms end diff --git a/lib/raw-handler.lua b/lib/raw-handler.lua index 7e53bfc..59d6fff 100644 --- a/lib/raw-handler.lua +++ b/lib/raw-handler.lua @@ -26,33 +26,33 @@ local wiola = require "wiola" local config = require("wiola.config").config() local wiola_max_payload_len = WAMP_PAYLOAD_LENGTHS[config.maxPayloadLen] or 65536 local bit = require "bit" -local tcpSocket, wampServer, cliMaxLength, serializer, serializerStr, data, err, ok, cliData +local tcpSocket, wampServer, cliMaxLength, serializer, serializerStr, data, err, ok, cliData, pingCo tcpSocket, err = ngx.req.socket(true) if not tcpSocket then - return ngx.exit(444) + return ngx.exit(ngx.ERROR) end -tcpSocket:settimeout(config.socketTimeout) +tcpSocket:settimeouts(config.socketTimeout, config.socketTimeout, config.socketTimeout) wampServer, err = wiola:new() if not wampServer then - return ngx.exit(444) + return ngx.exit(ngx.ERROR) end data, err = tcpSocket:receive(4) if data == nil then - return ngx.exit(444) -- tcpSocket:close() + return ngx.exit(ngx.ERROR) end if string.byte(data) ~= 0x7F then - return ngx.exit(444) + return ngx.exit(ngx.ERROR) elseif string.byte(data, 3) ~= 0x0 or string.byte(data, 4) ~= 0x0 then cliData = string.char(0x7F, bit.bor(bit.lshift(3, 4), 0), 0, 0) tcpSocket:send(cliData) - return ngx.exit(444) + return ngx.exit(ngx.ERROR) end cliMaxLength = math.pow(2, 9 + bit.rshift(string.byte(data, 2), 4)) @@ -65,7 +65,7 @@ elseif serializer == 2 then else cliData = string.char(0x7F, bit.bor(bit.lshift(1, 4), 0), 0, 0) tcpSocket:send(cliData) - return ngx.exit(444) + return ngx.exit(ngx.ERROR) end local sessionId, dataType = wampServer:addConnection(ngx.var.connection, serializerStr) @@ -74,7 +74,7 @@ cliData = string.char(0x7F, bit.bor(bit.lshift(wiola_max_payload_len, 4), serial data, err = tcpSocket:send(cliData) if not data then - return ngx.exit(444) + return ngx.exit(ngx.ERROR) end local function removeConnection(_, sessId) @@ -95,7 +95,7 @@ end ok, err = ngx.on_abort(removeConnectionWrapper) if not ok then - ngx.exit(444) + ngx.exit(ngx.ERROR) end local function getLenBytes(len) @@ -107,28 +107,33 @@ local function getLenBytes(len) return string.char(b1, b2, b3) end -while true do - local hflags, msgType, msgLen +if config.pingInterval > 0 then + local pinger = function (period) + local pingData + coroutine.yield() - hflags = wampServer:getHandlerFlags(sessionId) - if hflags ~= nil then - if hflags.sendLast == true then - cliData = wampServer:getPendingData(sessionId, true) + while true do - data, err = tcpSocket:send(cliData) + pingData = string.char(1) .. getLenBytes(1) .. 'p' + data, err = tcpSocket:send(pingData) if not data then + ngx.timer.at(0, removeConnection, sessionId) + ngx.exit(ngx.ERROR) end - end - - if hflags.close == true then - ngx.timer.at(0, removeConnection, sessionId) - return ngx.exit(444) + ngx.sleep(period) end end - cliData = wampServer:getPendingData(sessionId) - while cliData ~= ngx.null do + pingCo = ngx.thread.spawn(pinger, config.pingInterval / 1000) +end + +while true do + local hflags, msgType, msgLen + hflags = wampServer:getHandlerFlags(sessionId) + cliData = wampServer:getPendingData(sessionId, hflags.sendLast) + + if cliData ~= ngx.null and cliData then msgLen = string.len(cliData) @@ -141,50 +146,52 @@ while true do end -- TODO Handle exceeded message length situation - - cliData = wampServer:getPendingData(sessionId) end - data, err = tcpSocket:receive(4) - - if data == nil then + if hflags.close == true then + if pingCo then + ngx.thread.kill(pingCo) + end + tcpSocket:shutdown("send") ngx.timer.at(0, removeConnection, sessionId) - return ngx.exit(444) + ngx.exit(ngx.OK) end - msgType = bit.band(string.byte(data), 0xff) - msgLen = bit.lshift(string.byte(data, 2), 16) + - bit.lshift(string.byte(data, 3), 8) + - string.byte(data, 4) + data, err = tcpSocket:receive(4) - if msgType == 0 then -- regular WAMP message + if data ~= nil then + msgType = bit.band(string.byte(data), 0xff) + msgLen = bit.lshift(string.byte(data, 2), 16) + + bit.lshift(string.byte(data, 3), 8) + + string.byte(data, 4) - data, err = tcpSocket:receive(msgLen) + if msgType == 0 then -- regular WAMP message - if data == nil then - ngx.timer.at(0, removeConnection, sessionId) - return ngx.exit(444) - end + data, err = tcpSocket:receive(msgLen) - wampServer:receiveData(sessionId, data) + if data == nil then + ngx.timer.at(0, removeConnection, sessionId) + ngx.exit(ngx.ERROR) + end + wampServer:receiveData(sessionId, data) - elseif msgType == 1 then -- PING + elseif msgType == 1 then -- PING - data, err = tcpSocket:receive(msgLen) + data, err = tcpSocket:receive(msgLen) - if data == nil then - ngx.timer.at(0, removeConnection, sessionId) - return ngx.exit(444) - end + if data == nil then + ngx.timer.at(0, removeConnection, sessionId) + ngx.exit(ngx.ERROR) + end - cliData = string.char(2) .. msgLen .. data - data, err = tcpSocket:send(cliData) + cliData = string.char(2) .. msgLen .. data + data, err = tcpSocket:send(cliData) - if not data then + if not data then + end end - --- elseif msgType == 2 then -- PONG - -- TODO Implement server initiated ping - + elseif err == 'closed' then + ngx.timer.at(0, removeConnection, sessionId) + ngx.exit(ngx.ERROR) end end diff --git a/lib/redis.lua b/lib/redis.lua index a0bc470..9f7a0c9 100644 --- a/lib/redis.lua +++ b/lib/redis.lua @@ -348,7 +348,7 @@ function _M:getHandlerFlags(regId) return fl else - return nil + return {} end end diff --git a/lib/wiola.lua b/lib/wiola.lua index 30a1072..cf3d4c8 100644 --- a/lib/wiola.lua +++ b/lib/wiola.lua @@ -7,7 +7,7 @@ local _M = { - _VERSION = '0.9.1', + _VERSION = '0.10.0', } _M.__index = _M @@ -292,7 +292,7 @@ function _M:_publishMetaEvent(part, eventUri, session, ...) argsL[1].authprovider = parameters[1].authprovider end -- TODO Add information about transport - elseif eventUri == 'wamp.session.on_leave' then + --elseif eventUri == 'wamp.session.on_leave' then -- nothing to add :) elseif eventUri == 'wamp.subscription.on_create' then local details = { diff --git a/lib/ws-handler.lua b/lib/ws-handler.lua index fb4f9ca..79495a8 100644 --- a/lib/ws-handler.lua +++ b/lib/ws-handler.lua @@ -6,7 +6,7 @@ local wsServer = require "resty.websocket.server" local wiola = require "wiola" local config = require("wiola.config").config() -local webSocket, wampServer, ok, err, bytes +local webSocket, wampServer, ok, err, bytes, pingCo webSocket, err = wsServer:new({ timeout = config.socketTimeout, @@ -14,12 +14,12 @@ webSocket, err = wsServer:new({ }) if not webSocket then - return ngx.exit(444) + return ngx.exit(ngx.ERROR) end wampServer, err = wiola:new() if not wampServer then - return ngx.exit(444) + return ngx.exit(ngx.ERROR) end local sessionId, dataType = wampServer:addConnection(ngx.var.connection, ngx.header["Sec-WebSocket-Protocol"]) @@ -42,35 +42,32 @@ end ok, err = ngx.on_abort(removeConnectionWrapper) if not ok then - ngx.exit(444) + ngx.exit(ngx.ERROR) end -while true do - local cliData, data, typ, hflags - - hflags = wampServer:getHandlerFlags(sessionId) - if hflags ~= nil then - if hflags.sendLast == true then - cliData = wampServer:getPendingData(sessionId, true) - - if dataType == 'binary' then - bytes, err = webSocket:send_binary(cliData) - else - bytes, err = webSocket:send_text(cliData) - end +if config.pingInterval > 0 then + local pinger = function (period) + coroutine.yield() + while true do + bytes, err = webSocket:send_ping() if not bytes then + ngx.timer.at(0, removeConnection, sessionId) + ngx.exit(ngx.ERROR) end - end - - if hflags.close == true then - ngx.timer.at(0, removeConnection, sessionId) - return ngx.exit(444) + ngx.sleep(period) end end - cliData = wampServer:getPendingData(sessionId) - while cliData ~= ngx.null do + pingCo = ngx.thread.spawn(pinger, config.pingInterval / 1000) +end + +while true do + local cliData, data, typ, hflags + hflags = wampServer:getHandlerFlags(sessionId) + cliData = wampServer:getPendingData(sessionId, hflags.sendLast) + + if cliData ~= ngx.null and cliData then if dataType == 'binary' then bytes, err = webSocket:send_binary(cliData) else @@ -79,32 +76,31 @@ while true do if not bytes then end + end - cliData = wampServer:getPendingData(sessionId) + if hflags.close == true then + if pingCo then + ngx.thread.kill(pingCo) + end + webSocket:send_close(1000, "Closing connection") + ngx.timer.at(0, removeConnection, sessionId) + ngx.exit(ngx.OK) end if webSocket.fatal then ngx.timer.at(0, removeConnection, sessionId) - return ngx.exit(444) + ngx.exit(ngx.ERROR) end data, typ = webSocket:recv_frame() - if not data then - - bytes, err = webSocket:send_ping() - if not bytes then - ngx.timer.at(0, removeConnection, sessionId) - return ngx.exit(444) + if typ == "close" then + if pingCo then + ngx.thread.kill(pingCo) end - - elseif typ == "close" then - bytes, err = webSocket:send_close(1000, "Closing connection") - if not bytes then - return - end + webSocket:send_close(1000, "Closing connection") ngx.timer.at(0, removeConnection, sessionId) - webSocket:send_close() + ngx.exit(ngx.OK) break elseif typ == "ping" then @@ -112,7 +108,7 @@ while true do bytes, err = webSocket:send_pong() if not bytes then ngx.timer.at(0, removeConnection, sessionId) - return ngx.exit(444) + ngx.exit(ngx.ERROR) end -- elseif typ == "pong" then diff --git a/src/wiola/wiola.lua b/src/wiola/wiola.lua index 9e997bf..df2a642 100644 --- a/src/wiola/wiola.lua +++ b/src/wiola/wiola.lua @@ -7,7 +7,7 @@ --local getdump = require("debug.vardump").getdump local _M = { - _VERSION = '0.9.1', + _VERSION = '0.10.0', } _M.__index = _M diff --git a/wiola-0.9.1-2.rockspec b/wiola-0.10.0-1.rockspec similarity index 97% rename from wiola-0.9.1-2.rockspec rename to wiola-0.10.0-1.rockspec index 6182753..3852dc6 100644 --- a/wiola-0.9.1-2.rockspec +++ b/wiola-0.10.0-1.rockspec @@ -1,9 +1,9 @@ package = "Wiola" -version = "0.9.1-2" +version = "0.10.0-1" source = { url = "git://github.com/KSDaemon/wiola.git", - tag = "v0.9.1" + tag = "v0.10.0" } description = {