mirror of
https://github.com/rxi/lovebird.git
synced 2024-11-15 22:54:21 +00:00
Changed connection handling to use coroutines
This commit is contained in:
parent
04facfb00f
commit
991a723c5b
68
lovebird.lua
68
lovebird.lua
@ -16,6 +16,7 @@ lovebird.inited = false
|
|||||||
lovebird.host = "*"
|
lovebird.host = "*"
|
||||||
lovebird.buffer = ""
|
lovebird.buffer = ""
|
||||||
lovebird.lines = {}
|
lovebird.lines = {}
|
||||||
|
lovebird.connections = {}
|
||||||
lovebird.pages = {}
|
lovebird.pages = {}
|
||||||
|
|
||||||
lovebird.wrapprint = true
|
lovebird.wrapprint = true
|
||||||
@ -614,23 +615,56 @@ function lovebird.onrequest(req, client)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function lovebird.receive(client, pattern)
|
||||||
|
while 1 do
|
||||||
|
local data, msg = client:receive(pattern)
|
||||||
|
if not data then
|
||||||
|
if msg == "timeout" then
|
||||||
|
-- Wait for more data
|
||||||
|
coroutine.yield(true)
|
||||||
|
else
|
||||||
|
-- Disconnected -- yielding nil means we're done
|
||||||
|
coroutine.yield(nil)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return data
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function lovebird.send(client, data)
|
||||||
|
local idx = 1
|
||||||
|
while idx < #data do
|
||||||
|
local res, msg = client:send(data, idx)
|
||||||
|
if not res and msg == "closed" then
|
||||||
|
-- Handle disconnect
|
||||||
|
coroutine.yield(nil)
|
||||||
|
else
|
||||||
|
idx = idx + res
|
||||||
|
coroutine.yield(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
function lovebird.onconnect(client)
|
function lovebird.onconnect(client)
|
||||||
-- Create request table
|
-- Create request table
|
||||||
local requestptn = "(%S*)%s*(%S*)%s*(%S*)"
|
local requestptn = "(%S*)%s*(%S*)%s*(%S*)"
|
||||||
local req = {}
|
local req = {}
|
||||||
req.socket = client
|
req.socket = client
|
||||||
req.addr, req.port = client:getsockname()
|
req.addr, req.port = client:getsockname()
|
||||||
req.request = client:receive()
|
req.request = lovebird.receive(client, "*l")
|
||||||
req.method, req.url, req.proto = req.request:match(requestptn)
|
req.method, req.url, req.proto = req.request:match(requestptn)
|
||||||
req.headers = {}
|
req.headers = {}
|
||||||
while 1 do
|
while 1 do
|
||||||
local line = client:receive()
|
local line, msg = lovebird.receive(client, "*l")
|
||||||
if not line or #line == 0 then break end
|
if not line or #line == 0 then break end
|
||||||
local k, v = line:match("(.-):%s*(.*)$")
|
local k, v = line:match("(.-):%s*(.*)$")
|
||||||
req.headers[k] = v
|
req.headers[k] = v
|
||||||
end
|
end
|
||||||
if req.headers["Content-Length"] then
|
if req.headers["Content-Length"] then
|
||||||
req.body = client:receive(req.headers["Content-Length"])
|
req.body = lovebird.receive(client, req.headers["Content-Length"])
|
||||||
end
|
end
|
||||||
-- Parse body
|
-- Parse body
|
||||||
req.parsedbody = {}
|
req.parsedbody = {}
|
||||||
@ -641,12 +675,9 @@ function lovebird.onconnect(client)
|
|||||||
end
|
end
|
||||||
-- Parse request line's url
|
-- Parse request line's url
|
||||||
req.parsedurl = lovebird.parseurl(req.url)
|
req.parsedurl = lovebird.parseurl(req.url)
|
||||||
-- Handle request; get data to send
|
-- Handle request; get data to send and send
|
||||||
local data, index = lovebird.onrequest(req), 0
|
local data = lovebird.onrequest(req)
|
||||||
-- Send data
|
lovebird.send(client, data)
|
||||||
while index < #data do
|
|
||||||
index = index + client:send(data, index)
|
|
||||||
end
|
|
||||||
-- Clear up
|
-- Clear up
|
||||||
client:close()
|
client:close()
|
||||||
end
|
end
|
||||||
@ -654,18 +685,33 @@ end
|
|||||||
|
|
||||||
function lovebird.update()
|
function lovebird.update()
|
||||||
if not lovebird.inited then lovebird.init() end
|
if not lovebird.inited then lovebird.init() end
|
||||||
|
-- Handle new connections
|
||||||
while 1 do
|
while 1 do
|
||||||
|
-- Accept new connections
|
||||||
local client = lovebird.server:accept()
|
local client = lovebird.server:accept()
|
||||||
if not client then break end
|
if not client then break end
|
||||||
client:settimeout(2)
|
client:settimeout(0)
|
||||||
local addr = client:getsockname()
|
local addr = client:getsockname()
|
||||||
if lovebird.checkwhitelist(addr) then
|
if lovebird.checkwhitelist(addr) then
|
||||||
xpcall(function() lovebird.onconnect(client) end, function() end)
|
-- Connection okay -- create and add coroutine to set
|
||||||
|
local conn = coroutine.wrap(function()
|
||||||
|
xpcall(function() lovebird.onconnect(client) end, function() end)
|
||||||
|
end)
|
||||||
|
lovebird.connections[conn] = true
|
||||||
else
|
else
|
||||||
|
-- Reject connection not on whitelist
|
||||||
lovebird.trace("got non-whitelisted connection attempt: ", addr)
|
lovebird.trace("got non-whitelisted connection attempt: ", addr)
|
||||||
client:close()
|
client:close()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
-- Handle existing connections
|
||||||
|
for conn in pairs(lovebird.connections) do
|
||||||
|
-- Resume coroutine, remove if it has finished
|
||||||
|
local status = conn()
|
||||||
|
if status == nil then
|
||||||
|
lovebird.connections[conn] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user