GSoC: Documentation #1

This commit is contained in:
Steven Barth 2009-06-13 18:16:34 +00:00
parent 120a7f558e
commit f9263e00c1
5 changed files with 174 additions and 3 deletions

View file

@ -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.

View file

@ -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.

75
libs/lucid/docs/OVERVIEW Normal file
View file

@ -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.

View file

@ -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

View file

@ -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