diff options
Diffstat (limited to 'libs')
-rw-r--r-- | libs/lucid-http/docs/OVERVIEW | 17 | ||||
-rw-r--r-- | libs/lucid-rpc/docs/OVERVIEW | 19 | ||||
-rw-r--r-- | libs/lucid/docs/OVERVIEW | 75 | ||||
-rw-r--r-- | libs/lucid/luasrc/lucid.lua | 47 | ||||
-rw-r--r-- | libs/lucid/luasrc/lucid/tcpserver.lua | 19 |
5 files changed, 174 insertions, 3 deletions
diff --git a/libs/lucid-http/docs/OVERVIEW b/libs/lucid-http/docs/OVERVIEW new file mode 100644 index 0000000000..74b499ca9f --- /dev/null +++ b/libs/lucid-http/docs/OVERVIEW @@ -0,0 +1,17 @@ + LuCId HTTP/1.1 Server Slave + +*** Abstract *** +The LuCId HTTP-Server Slave is an HTTP/1.1 implementation for the LuCId +superserver loosely based on the LuCI HTTP stack. It supports keep-alive, +pipelining, basic authentication, kernel-mode file transfer (sendfile() +through nixio), address and hostname based virtual hosts, custom 404 pages, +E-Tags, conditional headers, directory indexing and partial file transfers. + + +*** Workflow *** +After receiving an incoming connection from LuCId, the slave parses the request +and prepares the environment for the acion handler. After that the virtual host +will be dispatched and the request will be passed on to the respective handler. +The handler will enforce access restrictions if configured and then returns a +status code a set of response headers, as well as a content resource that will +be sent to the user.
\ No newline at end of file diff --git a/libs/lucid-rpc/docs/OVERVIEW b/libs/lucid-rpc/docs/OVERVIEW new file mode 100644 index 0000000000..9da870065e --- /dev/null +++ b/libs/lucid-rpc/docs/OVERVIEW @@ -0,0 +1,19 @@ + LuCId JSON-RPC Server Slave + +*** Abstract *** +The LuCId JSON-RPC server slave implements the JSON-RPC 1.0 and 2.0 protocol +to allow efficient light-weight remote procedure calling. +It provides notification support and several unofficial protocol extensions such +as: + * Close notifications + * Raw TCP switching to transfer BLOBs efficiently + * Client notification + + +*** Workflow *** +After receiving an incoming connection from LuCId, the slave analyses the +request and passes it to the matching handler. The handler will enforce +access restriction and deserialize the payload data and invokes the assigned +Lua function in a protected way. In case of a success the handler will serialize +the response and send it to the client - otherwise a detailed error message +will be returned.
\ No newline at end of file diff --git a/libs/lucid/docs/OVERVIEW b/libs/lucid/docs/OVERVIEW new file mode 100644 index 0000000000..ca742ddd68 --- /dev/null +++ b/libs/lucid/docs/OVERVIEW @@ -0,0 +1,75 @@ + LuCId Network Superserver in Lua + +*** Abstract *** +LuCId is a network superserver written in Lua based on the nixio POSIX library. +It supports IPv4, IPv6, TLS, asynchronous and synchronous IO and can be extended +to handle any kind of IO events on file descriptors. LuCId is also able to +generate RSA private keys and self-signed certificates on demand if the px5g +keymaster library is available. Both nixio and px5g are libraries created +by the LuCI developers. + + +*** Configuration *** +LuCId uses the UCI Universal Configuration Interface as configuration backend. + +There are 4 types of configuration sections and one named section defined: +The main section of type "lucid" defines the basic framework parameters of LuCId +These include: + * pollinterval: Internal polling interval + * threadlimit: Overall maximum number of child processes + * daemonize: Whether to daemonize at startup + * debug: Whether to enable debug output in syslog + + +The "tcpserver" section type provides the framework for TCP servers: +Parameters: + * entrypoint: Lua module entrypoint (provides a prepare_daemon function) + +The "daemon" sections define instances of servers. +Parameters may include: + * slave: Server slave + * publisher: Publishers to be served by this daemon + * enabled: Flag (0/1) whether this daemon should be started + * address: List of ports / addresses to be bound too, if applicable + * encryption: Flag (disabled/enabled) whether to enforce encryption + * tls: Reference to the TLS configuration section to use + +The "...Publisher" sections define services to be published through daemons. +Publishers definitions should be daemon and protocol independent whenever +possible. Publishers should also implement access restrictions for certain +network interfaces and for specified UNIX user accounts. +Publishers usually define but are not required to use the following Parameters: + * name: Published Name + * physical: Physical source path + * virtual: Virtual resource path + * domain: Any kind of domain or realm specification + * read: ACL containing entities allowed to read the given resource + * write: -"- + * exec: -"- + +The "tls" sections describe TLS security specifications for TCP servers. +Parameters: + * key: Private Key file + * cert: Certificate file + * type: Type of certificate and key files (pem, asn1) + * generate: Flag (0/1) to determine whether LuCId should generate + keys and self-signed certificates if the certificate is not available and + the px5g RSA Keymaster is available + + + +*** Workflow *** +In the preparation phase LuCId loads its configuration using the specification +given above and prepares its servers, daemons and publishers. It also allocates +resources such as binding sockets or preparing encryption credentials. +If everything could be setup correctly LuCId will daemonize - if requested. If +any errors occur in the preparation phase, LuCId will write to the system logger +and exit. + +After daemonizing the main process is responsible for keeping a list of +file descriptors that LuCId is polling regularly to handle incoming data events. +Data events are for example new TCP connection attempts which could cause the +superserver to fork a new process and invoke a registered handler. + +Whenever a sub-process is about to be generate LuCId checks if given resource +limits are still met.
\ No newline at end of file diff --git a/libs/lucid/luasrc/lucid.lua b/libs/lucid/luasrc/lucid.lua index 34452a5991..b10365579a 100644 --- a/libs/lucid/luasrc/lucid.lua +++ b/libs/lucid/luasrc/lucid.lua @@ -41,7 +41,7 @@ local UCINAME = UCINAME local SSTATE = "/tmp/.lucid_store" - +--- Starts a new LuCId superprocess. function start() prepare() @@ -60,6 +60,7 @@ function start() run() end +--- Stops any running LuCId superprocess. function stop() local pid = tonumber(state:get(UCINAME, "main", "pid")) if pid then @@ -68,6 +69,7 @@ function stop() return false end +--- Prepares the slaves, daemons and publishers, allocate resources. function prepare() local debug = tonumber((cursor:get(UCINAME, "main", "debug"))) @@ -104,6 +106,8 @@ function prepare() end) end +--- Run the superprocess if prepared before. +-- This main function of LuCId will wait for events on given file descriptors. function run() local pollint = tonumber((cursor:get(UCINAME, "main", "pollinterval"))) @@ -136,11 +140,20 @@ function run() end end +--- Add a file descriptor for the main loop and associate handler functions. +-- @param polle Table containing: {fd = FILE DESCRIPTOR, events = POLL EVENTS, +-- handler = EVENT HANDLER CALLBACK} +-- @see unregister_pollfd +-- @return boolean status function register_pollfd(polle) pollt[#pollt+1] = polle return true end +--- Unregister a file desciptor and associate handler from the main loop. +-- @param polle Poll descriptor +-- @see register_pollfd +-- @return boolean status function unregister_pollfd(polle) for k, v in ipairs(pollt) do if v == polle then @@ -151,6 +164,8 @@ function unregister_pollfd(polle) return false end +--- Close all registered file descriptors from main loop. +-- This is useful for forked child processes. function close_pollfds() for k, v in ipairs(pollt) do if v.fd and v.fd.close then @@ -159,11 +174,19 @@ function close_pollfds() end end +--- Register a tick function that will be called at each cycle of the main loop. +-- @param cb Callback +-- @see unregister_tick +-- @return boolean status function register_tick(cb) tickt[#tickt+1] = cb return true end +--- Unregister a tick function from the main loop. +-- @param cb Callback +-- @see register_tick +-- @return boolean status function unregister_tick(cb) for k, v in ipairs(tickt) do if v == cb then @@ -174,10 +197,14 @@ function unregister_tick(cb) return false end +--- Create a new child process from a Lua function and assign a destructor. +-- @param threadcb main function of the new process +-- @param waitcb destructor callback +-- @return process identifier or nil, error code, error message function create_process(threadcb, waitcb) local threadlimit = tonumber(cursor:get(UCINAME, "main", "threadlimit")) if threadlimit and tcount >= threadlimit then - nixio.syslog("warning", "Unable to create thread: process limit reached") + nixio.syslog("warning", "Cannot create thread: process limit reached") return nil end local pid, code, err = nixio.fork() @@ -193,6 +220,9 @@ function create_process(threadcb, waitcb) return pid, code, err end +--- Prepare a daemon from a given configuration table. +-- @param config Configuration data. +-- @return boolean status or nil, error code, error message function prepare_daemon(config) nixio.syslog("info", "Preparing daemon " .. config[".name"]) local modname = cursor:get(UCINAME, config.slave) @@ -210,6 +240,9 @@ function prepare_daemon(config) return module.prepare_daemon(config, _M) end +--- Prepare a slave. +-- @param name slave name +-- @return table containing slave module and configuration or nil, error message function prepare_slave(name) local slave = slaves[name] if not slave then @@ -228,16 +261,24 @@ function prepare_slave(name) end end +--- Return a list of available network interfaces on the host. +-- @return table returned by nixio.getifaddrs() function get_interfaces() return ifaddrs end +--- Revoke process privileges. +-- @param user new user name or uid +-- @param group new group name or gid +-- @return boolean status or nil, error code, error message function revoke_privileges(user, group) if nixio.getuid() == 0 then return nixio.setgid(group) and nixio.setuid(user) end end +--- Return a secure UCI cursor. +-- @return UCI cursor function securestate() local stat = nixio.fs.stat(SSTATE) or {} local uid = nixio.getuid() @@ -253,6 +294,8 @@ function securestate() return uci.cursor(nil, SSTATE) end +--- Daemonize the process. +-- @return boolean status or nil, error code, error message function daemonize() if nixio.getppid() == 1 then return diff --git a/libs/lucid/luasrc/lucid/tcpserver.lua b/libs/lucid/luasrc/lucid/tcpserver.lua index b1b95c1fb3..2897ec8eaa 100644 --- a/libs/lucid/luasrc/lucid/tcpserver.lua +++ b/libs/lucid/luasrc/lucid/tcpserver.lua @@ -28,7 +28,10 @@ local UCINAME = lucid.UCINAME local tcpsockets = {} - +--- Prepare a daemon and allocate its resources. (superserver callback) +-- @param config configuration table +-- @param server LuCId basemodule +-- @return binary data function prepare_daemon(config, server) nixio.syslog("info", "Preparing TCP-Daemon " .. config[".name"]) if type(config.address) ~= "table" then @@ -104,6 +107,9 @@ function prepare_daemon(config, server) end end +--- Accept a new TCP connection. (server callback) +-- @param polle Poll descriptor +-- @return handler process id or nil, error code, error message function accept(polle) local socket, host, port = polle.fd:accept() if not socket then @@ -133,6 +139,13 @@ function accept(polle) return unpack(stat) end +--- Prepare a TCP server socket. +-- @param family protocol family ["inetany", "inet6", "inet"] +-- @param host host +-- @param port port +-- @param opts table of socket options +-- @param backlog socket backlog +-- @return socket, final socket family function prepare_socket(family, host, port, opts, backlog) nixio.syslog("info", "Preparing socket for port " .. port) backlog = backlog or 1024 @@ -171,6 +184,10 @@ function prepare_socket(family, host, port, opts, backlog) return socket, family end +--- Prepare a TLS server context and load keys and certificates. +-- May invoke px5g to create keys and certificate on demand if available. +-- @param tlskey TLS configuration identifier +-- @return TLS server conext or nil function prepare_tls(tlskey) local tls if tlskey and cursor:get(UCINAME, tlskey) then |