Language Bindings
Overview
In general, SWUpdate is agnostic to a particular language it is operated from, thanks to SWUpdate’s socket-based control and progress APIs for external programs. As long as the language of choice has proper socket (library) support, SWUpdate can be operated with it.
However, for convenience, a Lua language binding in terms of a shared library,
currently lua_swupdate.so.0.1
, is provided.
Lua Language Binding
The Lua language binding is realized in terms of the lua_swupdate
module
that defines three bindings, namely for the control interface, the progress
interface, and a convenience function yielding a table holding all local
network interfaces including their IP addresses and submasks.
The lua_swupdate
Lua module interface specification that details what
functionality is made available by bindings/lua_swupdate.c
is found
in bindings/lua_swupdate.lua
. It serves as reference, for mocking
purposes, and type checking thanks to the EmmyLua-inspired annotations.
Note that, depending on the filesystem location of the Lua binding’s shared
library, Lua’s package.cpath
may have to be adapted by setting the
environment variable LUA_CPATH
, modifying package.cpath
prior to
a require('lua_swupdate')
, or , as last resort, using package.loadlib()
instead of require('lua_swupdate')
.
Control Interface
The lua_swupdate
module’s control interface binding conveniently makes
SWUpdate’s socket-based control API available to pure Lua.
The binding is captured in the swupdate_control
object that is returned
by a call to swupdate.control()
. This object offers the three methods
connect()
, write(<chunkdata>)
, and close()
:
The connect()
method initializes the connection to SWUpdate’s control
socket, sends REQ_INSTALL
, and waits for ACK
or NACK
, returning the
socket connection file descriptor, mostly for information purposes, or, in case
of an error, nil
plus an error message.
The artifact’s data can then be sent to SWUpdate via the write(<chunkdata>)
method, returning true
, or, in case of errors, nil
plus an error message.
Finally, the close()
method closes the connection to SWUpdate’s control
socket after which it waits for SWUpdate to complete the update transaction and
executes the post-install command, if given.
The following example snippet illustrates how to use the control interface binding:
local artifact = io.open("/some/path/to/artifact.swu", "rb" )
swupdate = require('lua_swupdate')
local ctrl = swupdate.control()
if not ctrl:connect() then
-- Deliberately neglecting error message.
io.stderr:write("Error connecting to SWUpdate control socket.\n")
return
end
while true do
local chunk = artifact:read(1024)
if not chunk then break end
if not ctrl:write(chunk) then
-- Deliberately neglecting error message.
io.stderr:write("Error writing to SWUpdate control socket.\n")
break
end
end
local res, msg = ctrl:close()
if not res then
io.stderr:write(string.format("Error finalizing update: %s\n", msg))
end
Progress Interface
The lua_swupdate
module’s progress interface binding conveniently makes
SWUpdate’s socket-based progress API available to pure Lua.
The binding is captured in the swupdate_progress
object that is returned
by a call to swupdate.progress()
. This object offers the three methods
connect()
, receive()
, and close()
:
The connect()
method connects to SWUpdate’s progress socket, waiting until
the connection has been established. Note that it is only really required to
explicitly call connect()
to reestablish a broken connection as the
swupdate_progress
object’s instantiation already initiates the connection.
The receive()
method returns a table representation of the struct
progress_msg
described in the progress interface’s API description.
The close()
method deliberately closes the connection to SWUpdate’s progress
socket.
IPv4 Interface
For convenience, the lua_swupdate
module provides the ipv4()
method
returning a table holding the local network interfaces as the table’s keys and
their space-separated IP addresses plus subnet masks as respective values.