diff options
Diffstat (limited to 'libs/httpd/luasrc')
-rw-r--r-- | libs/httpd/luasrc/copas.lua | 439 | ||||
-rw-r--r-- | libs/httpd/luasrc/httpd.lua | 84 | ||||
-rw-r--r-- | libs/httpd/luasrc/httpd/FileHandler.lua | 24 |
3 files changed, 0 insertions, 547 deletions
diff --git a/libs/httpd/luasrc/copas.lua b/libs/httpd/luasrc/copas.lua deleted file mode 100644 index 262096ac00..0000000000 --- a/libs/httpd/luasrc/copas.lua +++ /dev/null @@ -1,439 +0,0 @@ -------------------------------------------------------------------------------- --- Copas - Coroutine Oriented Portable Asynchronous Services --- --- Offers a dispatcher and socket operations based on coroutines. --- Usage: --- copas.addserver(server, handler, timeout) --- copas.addthread(thread, ...) Create a new coroutine thread and run it with args --- copas.loop(timeout) - listens infinetely --- copas.step(timeout) - executes one listening step --- copas.receive(pattern or number) - receives data from a socket --- copas.settimeout(client, time) if time=0 copas.receive(bufferSize) - receives partial data from a socket were data<=bufferSize --- copas.send - sends data through a socket --- copas.wrap - wraps a LuaSocket socket with Copas methods --- copas.connect - blocks only the thread until connection completes --- copas.flush - *deprecated* do nothing --- --- Authors: Andre Carregal and Javier Guerra --- Contributors: Diego Nehab, Mike Pall, David Burgess, Leonardo Godinho, --- Thomas Harning Jr. and Gary NG --- --- Copyright 2005 - Kepler Project (www.keplerproject.org) --- --- $Id: copas.lua,v 1.31 2008/05/19 18:57:13 carregal Exp $ -------------------------------------------------------------------------------- -local socket = require "socket" - -require"luci.util" -local copcall = luci.util.copcall - - -local WATCH_DOG_TIMEOUT = 120 - --- Redefines LuaSocket functions with coroutine safe versions --- (this allows the use of socket.http from within copas) -local function statusHandler(status, ...) - if status then return ... end - return nil, ... -end -function socket.protect(func) - return function (...) - return statusHandler(copcall(func, ...)) - end -end - -function socket.newtry(finalizer) - return function (...) - local status = (...) or false - if (status==false)then - copcall(finalizer, select(2, ...) ) - error((select(2, ...)), 0) - end - return ... - end -end --- end of LuaSocket redefinitions - - -module ("copas", package.seeall) - --- Meta information is public even if begining with an "_" -_COPYRIGHT = "Copyright (C) 2005 Kepler Project" -_DESCRIPTION = "Coroutine Oriented Portable Asynchronous Services" -_VERSION = "Copas 1.1.3" - -------------------------------------------------------------------------------- --- Simple set implementation based on LuaSocket's tinyirc.lua example --- adds a FIFO queue for each value in the set -------------------------------------------------------------------------------- -local function newset() - local reverse = {} - local set = {} - local q = {} - setmetatable(set, { __index = { - insert = function(set, value) - if not reverse[value] then - set[#set + 1] = value - reverse[value] = #set - end - end, - - remove = function(set, value) - local index = reverse[value] - if index then - reverse[value] = nil - local top = set[#set] - set[#set] = nil - if top ~= value then - reverse[top] = index - set[index] = top - end - end - end, - - push = function (set, key, itm) - local qKey = q[key] - if qKey == nil then - q[key] = {itm} - else - qKey[#qKey + 1] = itm - end - end, - - pop = function (set, key) - local t = q[key] - if t ~= nil then - local ret = table.remove (t, 1) - if t[1] == nil then - q[key] = nil - end - return ret - end - end - }}) - return set -end - -local _servers = newset() -- servers being handled -local _reading_log = {} -local _writing_log = {} - -local _reading = newset() -- sockets currently being read -local _writing = newset() -- sockets currently being written - -------------------------------------------------------------------------------- --- Coroutine based socket I/O functions. -------------------------------------------------------------------------------- --- reads a pattern from a client and yields to the reading set on timeouts -function receive(client, pattern, part) - local s, err - pattern = pattern or "*l" - repeat - s, err, part = client:receive(pattern, part) - if s or err ~= "timeout" then - _reading_log[client] = nil - return s, err, part - end - _reading_log[client] = os.time() - coroutine.yield(client, _reading) - until false -end - --- same as above but with special treatment when reading chunks, --- unblocks on any data received. -function receivePartial(client, pattern) - local s, err, part - pattern = pattern or "*l" - repeat - s, err, part = client:receive(pattern) - if s or ( (type(pattern)=="number") and part~="" and part ~=nil ) or - err ~= "timeout" then - _reading_log[client] = nil - return s, err, part - end - _reading_log[client] = os.time() - coroutine.yield(client, _reading) - until false -end - --- sends data to a client. The operation is buffered and --- yields to the writing set on timeouts -function send(client,data, from, to) - local s, err,sent - from = from or 1 - local lastIndex = from - 1 - - repeat - s, err, lastIndex = client:send(data, lastIndex + 1, to) - -- adds extra corrotine swap - -- garantees that high throuput dont take other threads to starvation - if (math.random(100) > 90) then - _writing_log[client] = os.time() - coroutine.yield(client, _writing) - end - if s or err ~= "timeout" then - _writing_log[client] = nil - return s, err,lastIndex - end - _writing_log[client] = os.time() - coroutine.yield(client, _writing) - until false -end - --- waits until connection is completed -function connect(skt,host, port) - skt:settimeout(0) - local ret,err = skt:connect (host, port) - if ret or err ~= "timeout" then - return ret, err - end - _writing_log[skt] = os.time() - coroutine.yield(skt, _writing) - ret,err = skt:connect (host, port) - _writing_log[skt] = nil - if (err=="already connected") then - return 1 - end - return ret, err -end - --- flushes a client write buffer (deprecated) -function flush(client) -end - --- wraps a socket to use Copas methods (send, receive, flush and settimeout) -local _skt_mt = {__index = { - send = function (self, data, from, to) - return send (self.socket, data, from, to) - end, - - receive = function (self, pattern) - if (self.timeout==0) then - return receivePartial(self.socket, pattern) - end - return receive (self.socket, pattern) - end, - - flush = function (self) - return flush (self.socket) - end, - - settimeout = function (self,time) - self.timeout=time - return - end, -}} - -function wrap (skt) - return setmetatable ({socket = skt}, _skt_mt) -end - --------------------------------------------------- --- Error handling --------------------------------------------------- - -local _errhandlers = {} -- error handler per coroutine - -function setErrorHandler (err) - local co = coroutine.running() - if co then - _errhandlers [co] = err - end -end - -local function _deferror (msg, co, skt) - print (msg, co, skt) -end - -------------------------------------------------------------------------------- --- Thread handling -------------------------------------------------------------------------------- - -local function _doTick (co, skt, ...) - if not co then return end - - local ok, res, new_q = coroutine.resume(co, skt, ...) - - if ok and res and new_q then - new_q:insert (res) - new_q:push (res, co) - else - if not ok then copcall (_errhandlers [co] or _deferror, res, co, skt) end - if skt then skt:close() end - _errhandlers [co] = nil - end -end - --- accepts a connection on socket input -local function _accept(input, handler) - local client = input:accept() - if client then - client:settimeout(0) - local co = coroutine.create(handler) - _doTick (co, client) - --_reading:insert(client) - end - return client -end - --- handle threads on a queue -local function _tickRead (skt) - _doTick (_reading:pop (skt), skt) -end - -local function _tickWrite (skt) - _doTick (_writing:pop (skt), skt) -end - -------------------------------------------------------------------------------- --- Adds a server/handler pair to Copas dispatcher -------------------------------------------------------------------------------- -function addserver(server, handler, timeout) - server:settimeout(timeout or 0.1) - _servers[server] = handler - _reading:insert(server) -end - -------------------------------------------------------------------------------- --- Adds an new courotine thread to Copas dispatcher -------------------------------------------------------------------------------- -function addthread(thread, ...) - local co = coroutine.create(thread) - _doTick (co, nil, ...) -end - -------------------------------------------------------------------------------- --- tasks registering -------------------------------------------------------------------------------- - -local _tasks = {} - -local function addtaskRead (tsk) - -- lets tasks call the default _tick() - tsk.def_tick = _tickRead - - _tasks [tsk] = true -end - -local function addtaskWrite (tsk) - -- lets tasks call the default _tick() - tsk.def_tick = _tickWrite - - _tasks [tsk] = true -end - -local function tasks () - return next, _tasks -end - -------------------------------------------------------------------------------- --- main tasks: manage readable and writable socket sets -------------------------------------------------------------------------------- --- a task to check ready to read events -local _readable_t = { - events = function(self) - local i = 0 - return function () - i = i + 1 - return self._evs [i] - end - end, - - tick = function (self, input) - local handler = _servers[input] - if handler then - input = _accept(input, handler) - else - _reading:remove (input) - self.def_tick (input) - end - end -} - -addtaskRead (_readable_t) - - --- a task to check ready to write events -local _writable_t = { - events = function (self) - local i = 0 - return function () - i = i+1 - return self._evs [i] - end - end, - - tick = function (self, output) - _writing:remove (output) - self.def_tick (output) - end -} - -addtaskWrite (_writable_t) - -local last_cleansing = 0 -local function _select (timeout) - local err - local readable={} - local writable={} - local r={} - local w={} - local now = os.time() - local duration = os.difftime - - - _readable_t._evs, _writable_t._evs, err = socket.select(_reading, _writing, timeout) - local r_evs, w_evs = _readable_t._evs, _writable_t._evs - - if duration(now, last_cleansing) > WATCH_DOG_TIMEOUT then - last_cleansing = now - for k,v in pairs(_reading_log) do - if not r_evs[k] and duration(now, v) > WATCH_DOG_TIMEOUT then - _reading_log[k] = nil - r_evs[#r_evs + 1] = k - r_evs[k] = #r_evs - end - end - - for k,v in pairs(_writing_log) do - if not w_evs[k] and duration(now, v) > WATCH_DOG_TIMEOUT then - _writing_log[k] = nil - w_evs[#w_evs + 1] = k - w_evs[k] = #w_evs - end - end - end - - if err == "timeout" and #r_evs + #w_evs > 0 then return nil - else return err end -end - - -------------------------------------------------------------------------------- --- Dispatcher loop step. --- Listen to client requests and handles them -------------------------------------------------------------------------------- -function step(timeout) - local err = _select (timeout) - if err == "timeout" then return end - - if err then - error(err) - end - - for tsk in tasks() do - for ev in tsk:events () do - tsk:tick (ev) - end - end -end - -------------------------------------------------------------------------------- --- Dispatcher endless loop. --- Listen to client requests and handles them forever -------------------------------------------------------------------------------- -function loop(timeout) - while true do - step(timeout) - end -end diff --git a/libs/httpd/luasrc/httpd.lua b/libs/httpd/luasrc/httpd.lua deleted file mode 100644 index 773d3c873d..0000000000 --- a/libs/httpd/luasrc/httpd.lua +++ /dev/null @@ -1,84 +0,0 @@ ---[[ -LuCI - HTTPD -]]-- -module("luci.httpd", package.seeall) -require("luci.copas") -require("luci.http.protocol") -require("luci.sys") - - - -function run(config) - -- TODO: process config - local server = socket.bind("0.0.0.0", 8080) - copas.addserver(server, spawnworker) - - while true do - copas.step() - end -end - - -function spawnworker(socket) - socket = copas.wrap(socket) - local request = luci.http.protocol.parse_message_header(socket) - request.input = socket -- TODO: replace with streamreader - request.error = io.stderr - - - local output = socket -- TODO: replace with streamwriter - - -- TODO: detect matching handler - local h = luci.httpd.FileHandler.SimpleHandler(luci.sys.libpath() .. "/httpd/httest") - h:process(request, output) -end - - -Response = luci.util.class() -function Response.__init__(self, sourceout, headers, status) - self.sourceout = sourceout or function() end - self.headers = headers or {} - self.status = status or 200 -end - -function Response.addheader(self, key, value) - self.headers[key] = value -end - -function Response.setstatus(self, status) - self.status = status -end - -function Response.setsource(self, source) - self.sourceout = source -end - - -Handler = luci.util.class() -function Handler.__init__(self) - self.filter = {} -end - -function Handler.addfilter(self, filter) - table.insert(self.filter, filter) -end - -function Handler.process(self, request, output) - -- TODO: Process input filters - - local response = self:handle(request) - - -- TODO: Process output filters - - output:send("HTTP/1.0 " .. response.status .. " BLA\r\n") - for k, v in pairs(response.headers) do - output:send(k .. ": " .. v .. "\r\n") - end - - output:send("\r\n") - - for chunk in response.sourceout do - output:send(chunk) - end -end - diff --git a/libs/httpd/luasrc/httpd/FileHandler.lua b/libs/httpd/luasrc/httpd/FileHandler.lua deleted file mode 100644 index 1f3e948020..0000000000 --- a/libs/httpd/luasrc/httpd/FileHandler.lua +++ /dev/null @@ -1,24 +0,0 @@ -module("luci.httpd.FileHandler", package.seeall) -require("luci.util") -require("luci.fs") -require("ltn12") - -SimpleHandler = luci.util.class(luci.httpd.Handler) - -function SimpleHandler.__init__(self, docroot) - luci.httpd.Handler.__init__(self) - self.docroot = docroot -end - -function SimpleHandler.handle(self, request) - local response = luci.httpd.Response() - local f = self.docroot .. "/" .. request.request_uri:gsub("%.%./", "") - request.error:write("Requested " .. f .. "\n") - local s = luci.fs.stat(f, "size") - if s then - response:addheader("Content-Length", s) - response:setsource(ltn12.source.file(io.open(f))) - else - response:setstatus(404) - end -end
\ No newline at end of file |