summaryrefslogtreecommitdiffhomepage
path: root/libs/lucid-rpc/luasrc/lucid/rpc/server.lua
diff options
context:
space:
mode:
Diffstat (limited to 'libs/lucid-rpc/luasrc/lucid/rpc/server.lua')
-rw-r--r--libs/lucid-rpc/luasrc/lucid/rpc/server.lua338
1 files changed, 0 insertions, 338 deletions
diff --git a/libs/lucid-rpc/luasrc/lucid/rpc/server.lua b/libs/lucid-rpc/luasrc/lucid/rpc/server.lua
deleted file mode 100644
index 18b004d8b8..0000000000
--- a/libs/lucid-rpc/luasrc/lucid/rpc/server.lua
+++ /dev/null
@@ -1,338 +0,0 @@
---[[
-LuCI - Lua Development Framework
-
-Copyright 2009 Steven Barth <steven@midlink.org>
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-$Id$
-]]
-
-local ipairs, pairs = ipairs, pairs
-local tostring, tonumber = tostring, tonumber
-local pcall, assert, type, unpack = pcall, assert, type, unpack
-
-local nixio = require "nixio"
-local json = require "luci.json"
-local util = require "luci.util"
-local table = require "table"
-local ltn12 = require "luci.ltn12"
-
---- RPC daemom.
--- @cstyle instance
-module "luci.lucid.rpc.server"
-
-RQLIMIT = 32 * nixio.const.buffersize
-VERSION = "1.0"
-
-ERRNO_PARSE = -32700
-ERRNO_INVALID = -32600
-ERRNO_UNKNOWN = -32001
-ERRNO_TIMEOUT = -32000
-ERRNO_NOTFOUND = -32601
-ERRNO_NOACCESS = -32002
-ERRNO_INTERNAL = -32603
-ERRNO_NOSUPPORT = -32003
-
-ERRMSG = {
- [ERRNO_PARSE] = "Parse error.",
- [ERRNO_INVALID] = "Invalid request.",
- [ERRNO_TIMEOUT] = "Connection timeout.",
- [ERRNO_UNKNOWN] = "Unknown error.",
- [ERRNO_NOTFOUND] = "Method not found.",
- [ERRNO_NOACCESS] = "Access denied.",
- [ERRNO_INTERNAL] = "Internal error.",
- [ERRNO_NOSUPPORT] = "Operation not supported."
-}
-
-
---- Create an RPC method wrapper.
--- @class function
--- @param method Lua function
--- @param description Method description
--- @return Wrapped RPC method
-Method = util.class()
-
---- Create an extended wrapped RPC method.
--- @class function
--- @param method Lua function
--- @param description Method description
--- @return Wrapped RPC method
-function Method.extended(...)
- local m = Method(...)
- m.call = m.xcall
- return m
-end
-
-function Method.__init__(self, method, description)
- self.description = description
- self.method = method
-end
-
---- Extended call the associated function.
--- @param session Session storage
--- @param argv Request parameters
--- @return function call response
-function Method.xcall(self, session, argv)
- return self.method(session, unpack(argv))
-end
-
---- Standard call the associated function.
--- @param session Session storage
--- @param argv Request parameters
--- @return function call response
-function Method.call(self, session, argv)
- return self.method(unpack(argv))
-end
-
---- Process a given request and create a JSON response.
--- @param session Session storage
--- @param request Requested method
--- @param argv Request parameters
-function Method.process(self, session, request, argv)
- local stat, result = pcall(self.call, self, session, argv)
-
- if stat then
- return { result=result }
- else
- return { error={
- code=ERRNO_UNKNOWN,
- message=ERRMSG[ERRNO_UNKNOWN],
- data=result
- } }
- end
-end
-
--- Remap IPv6-IPv4-compatibility addresses to IPv4 addresses
-local function remapipv6(adr)
- local map = "::ffff:"
- if adr:sub(1, #map) == map then
- return adr:sub(#map+1)
- else
- return adr
- end
-end
-
-
---- Create an RPC module.
--- @class function
--- @param description Method description
--- @return RPC module
-Module = util.class()
-
-function Module.__init__(self, description)
- self.description = description
- self.handler = {}
-end
-
---- Add a handler.
--- @param k key
--- @param v handler
-function Module.add(self, k, v)
- self.handler[k] = v
-end
-
---- Add an access restriction.
--- @param restriction Restriction specification
-function Module.restrict(self, restriction)
- if not self.restrictions then
- self.restrictions = {restriction}
- else
- self.restrictions[#self.restrictions+1] = restriction
- end
-end
-
---- Enforce access restrictions.
--- @param request Request object
--- @return nil or HTTP statuscode, table of headers, response source
-function Module.checkrestricted(self, session, request, argv)
- if not self.restrictions then
- return
- end
-
- for _, r in ipairs(self.restrictions) do
- local stat = true
- if stat and r.interface then -- Interface restriction
- if not session.localif then
- for _, v in ipairs(session.env.interfaces) do
- if v.addr == session.localaddr then
- session.localif = v.name
- break
- end
- end
- end
-
- if r.interface ~= session.localif then
- stat = false
- end
- end
-
- if stat and r.user and session.user ~= r.user then -- User restriction
- stat = false
- end
-
- if stat then
- return
- end
- end
-
- return {error={code=ERRNO_NOACCESS, message=ERRMSG[ERRNO_NOACCESS]}}
-end
-
---- Register a handler, submodule or function.
--- @param m entity
--- @param descr description
--- @return Module (self)
-function Module.register(self, m, descr)
- descr = descr or {}
- for k, v in pairs(m) do
- if util.instanceof(v, Method) then
- self.handler[k] = v
- elseif type(v) == "table" then
- self.handler[k] = Module()
- self.handler[k]:register(v, descr[k])
- elseif type(v) == "function" then
- self.handler[k] = Method(v, descr[k])
- end
- end
- return self
-end
-
---- Process a request.
--- @param session Session storage
--- @param request Request object
--- @param argv Request parameters
--- @return JSON response object
-function Module.process(self, session, request, argv)
- local first, last = request:match("^([^.]+).?(.*)$")
-
- local stat = self:checkrestricted(session, request, argv)
- if stat then -- Access Denied
- return stat
- end
-
- local hndl = first and self.handler[first]
- if not hndl then
- return {error={code=ERRNO_NOTFOUND, message=ERRMSG[ERRNO_NOTFOUND]}}
- end
-
- session.chain[#session.chain+1] = self
- return hndl:process(session, last, argv)
-end
-
-
---- Create a server object.
--- @class function
--- @param root Root module
--- @return Server object
-Server = util.class()
-
-function Server.__init__(self, root)
- self.root = root
-end
-
---- Get the associated root module.
--- @return Root module
-function Server.get_root(self)
- return self.root
-end
-
---- Set a new root module.
--- @param root Root module
-function Server.set_root(self, root)
- self.root = root
-end
-
---- Create a JSON reply.
--- @param jsonrpc JSON-RPC version
--- @param id Message id
--- @param res Result
--- @param err Error
--- @reutrn JSON response source
-function Server.reply(self, jsonrpc, id, res, err)
- id = id or json.null
-
- -- 1.0 compatibility
- if jsonrpc ~= "2.0" then
- jsonrpc = nil
- res = res or json.null
- err = err or json.null
- end
-
- return json.Encoder(
- {id=id, result=res, error=err, jsonrpc=jsonrpc}, BUFSIZE
- ):source()
-end
-
---- Handle a new client connection.
--- @param client client socket
--- @param env superserver environment
-function Server.process(self, client, env)
- local decoder
- local sinkout = client:sink()
- client:setopt("socket", "sndtimeo", 90)
- client:setopt("socket", "rcvtimeo", 90)
-
- local close = false
- local session = {server = self, chain = {}, client = client, env = env,
- localaddr = remapipv6(client:getsockname())}
- local req, stat, response, result, cb
-
- repeat
- local oldchunk = decoder and decoder.chunk
- decoder = json.ActiveDecoder(client:blocksource(nil, RQLIMIT))
- decoder.chunk = oldchunk
-
- result, response, cb = nil, nil, nil
-
- -- Read one request
- stat, req = pcall(decoder.get, decoder)
-
- if stat then
- if type(req) == "table" and type(req.method) == "string"
- and (not req.params or type(req.params) == "table") then
- req.params = req.params or {}
- result, cb = self.root:process(session, req.method, req.params)
- if type(result) == "table" then
- if req.id ~= nil then
- response = self:reply(req.jsonrpc, req.id,
- result.result, result.error)
- end
- close = result.close
- else
- if req.id ~= nil then
- response = self:reply(req.jsonrpc, req.id, nil,
- {code=ERRNO_INTERNAL, message=ERRMSG[ERRNO_INTERNAL]})
- end
- end
- else
- response = self:reply(req.jsonrpc, req.id,
- nil, {code=ERRNO_INVALID, message=ERRMSG[ERRNO_INVALID]})
- end
- else
- if nixio.errno() ~= nixio.const.EAGAIN then
- response = self:reply("2.0", nil,
- nil, {code=ERRNO_PARSE, message=ERRMSG[ERRNO_PARSE]})
- --[[else
- response = self:reply("2.0", nil,
- nil, {code=ERRNO_TIMEOUT, message=ERRMSG_TIMEOUT})]]
- end
- close = true
- end
-
- if response then
- ltn12.pump.all(response, sinkout)
- end
-
- if cb then
- close = cb(client, session, self) or close
- end
- until close
-
- client:shutdown()
- client:close()
-end