* libs/httpd: Prepared HTTPD dispatching model

This commit is contained in:
Steven Barth 2008-06-21 19:41:17 +00:00
parent 16dfa697e4
commit 90aef16aea
3 changed files with 87 additions and 30 deletions

View file

@ -15,27 +15,31 @@ $Id$
require("ltn12") require("ltn12")
require("socket") require("socket")
require("luci.util") require("luci.util")
require("luci.http.protocol")
require("luci.httpd.server")
local srv = luci.httpd.server Daemon = luci.util.class()
local host = "0.0.0.0"
local port = 50000
function Daemon.__init__(self, threadlimit)
self.reading = {}
self.running = {}
self.handler = {}
self.threadlimit = threadlimit
end
server = socket.bind(host, port) function Daemon.register(self, socket, clhandler, errhandler)
server:settimeout( 0, "t" ) table.insert( self.reading, socket )
self.handler[socket] = { clhandler = clhandler, errhandler = errhandler }
end
reading = { server } function Daemon.run(self)
running = { } while true do
self:step()
end
end
function Daemon.step(self)
while true do local input = socket.select( self.reading, nil, 0 )
local input = socket.select( reading, nil, 0.1 )
-- accept new connections -- accept new connections
for i, connection in ipairs(input) do for i, connection in ipairs(input) do
@ -43,25 +47,29 @@ while true do
local sock = connection:accept() local sock = connection:accept()
-- check capacity -- check capacity
if #running < srv.MAX_CLIENTS then if self.threadlimit and #running < self.threadlimit then
table.insert( running, { table.insert( self.running, {
coroutine.create( srv.client_handler ), coroutine.create( self.handler[connection].clhandler ),
sock sock
} ) } )
-- reject client -- reject client
else else
srv.error503( sock ) if self.handler[connection].errhandler then
self.handler[connection].errhandler( sock )
end
sock:close()
end end
end end
-- create client handler -- create client handler
for i, client in ipairs( running ) do for i, client in ipairs( self.running ) do
-- reap dead clients -- reap dead clients
if coroutine.status( client[1] ) == "dead" then if coroutine.status( client[1] ) == "dead" then
table.remove( running, i ) table.remove( self.running, i )
end end
coroutine.resume( client[1], client[2] ) coroutine.resume( client[1], client[2] )

View file

@ -13,6 +13,7 @@ $Id$
]]-- ]]--
module("luci.httpd.module", package.seeall) module("luci.httpd.module", package.seeall)
require("luci.util") require("luci.util")
require("luci.http.protocol")
require("ltn12") require("ltn12")
@ -90,7 +91,7 @@ function Handler.process(self, request, sourcein, sinkout, sinkerr)
end end
end end
luci.http.protocol.push_response(request,response, sourceout, sinkout, sinkerr) luci.http.protocol.push_response(request, response, sourceout, sinkout, sinkerr)
end end

View file

@ -14,13 +14,58 @@ $Id$
]]-- ]]--
module("luci.httpd.server", package.seeall) module("luci.httpd.server", package.seeall)
require("luci.util")
MAX_CLIENTS = 15
READ_BUFSIZE = 1024 READ_BUFSIZE = 1024
VHost = luci.util.class()
function error400( client, msg ) function VHost.__init__(self, handler)
self.handler = handler
self.dhandler = {}
end
function VHost.process(self, ...)
-- TODO: Dispatch handler
end
function VHost.sethandler(self, handler, match)
if match then
self.dhandler[match] = handler
else
self.handler = handler
end
end
Server = luci.util.class()
function Server.__init__(self, ip, port, base)
self.socket = socket.bind(ip, port)
self.socket:settimeout(0, "t")
self.clhandler = client_handler
self.errhandler = error503
self.host = nil
self.vhosts = {}
-- Clone another server
if base then
getmetatable(self).__index = base
end
end
-- Sets a vhost
function Server.setvhost(self, vhost, name)
if name then
self.vhosts[name] = vhost
else
self.host = vhost
end
end
function Server.error400(self, client, msg)
client:send( "HTTP/1.0 400 Bad request\r\n" ) client:send( "HTTP/1.0 400 Bad request\r\n" )
client:send( "Content-Type: text/plain\r\n\r\n" ) client:send( "Content-Type: text/plain\r\n\r\n" )
@ -31,15 +76,18 @@ function error400( client, msg )
client:close() client:close()
end end
function error503( client ) function Server.error503(self, client)
client:send( "HTTP/1.0 503 Server unavailable\r\n" ) client:send( "HTTP/1.0 503 Server unavailable\r\n" )
client:send( "Content-Type: text/plain\r\n\r\n" ) client:send( "Content-Type: text/plain\r\n\r\n" )
client:send( "There are too many clients connected, try again later\r\n" ) client:send( "There are too many clients connected, try again later\r\n" )
client:close() end
function Server.process(self, ...)
-- TODO: Dispatch vhost
end end
function client_handler(client) function Server.client_handler(self, client)
client:settimeout( 0 ) client:settimeout( 0 )
@ -114,12 +162,12 @@ function client_handler(client)
luci.util.dumptable( message ) luci.util.dumptable( message )
if not s and e then if not s and e then
error400( client, e ) self:error400( client, e )
end end
else else
error400( client, err ) self:error400( client, err )
end end
-- send response -- send response
error400( client, "Dummy response" ) self:error400( client, "Dummy response" )
end end