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
, reproduced for convenience in
Section Lua Language Binding Interface Specification.
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.
Lua Language Binding Interface Specification
1--[[
2
3 SWUpdate IPC Lua Module Interface.
4
5 Interface specification for the Lua IPC module.
6 See: bindings/lua_swupdate.c
7
8 Copyright (C) 2022, Siemens AG
9 Author: Christian Storm <christian.storm@siemens.com>
10
11 SPDX-License-Identifier: GPL-2.0-or-later
12
13--]]
14
15---@diagnostic disable: missing-return
16---@diagnostic disable: unused-local
17-- luacheck: no unused args
18
19
20--- SWUpdate IPC Lua Module.
21--- @class lua_swupdate
22local lua_swupdate = {}
23
24
25--- Get local IPv4 network interface(s) information.
26--
27-- The returned Table contains the network interface names
28-- as keys and a space-separated IP address and subnet mask
29-- as values, e.g., {['eth0']="192.168.1.1 255.255.255.0"}.
30--
31--- @return table<string, string>
32lua_swupdate.ipv4 = function() end
33
34
35--- @enum lua_swupdate.RECOVERY_STATUS
36--- Lua equivalent of `RECOVERY_STATUS` as in `include/swupdate_status.h`.
37lua_swupdate.RECOVERY_STATUS = {
38 IDLE = 0,
39 START = 1,
40 RUN = 2,
41 SUCCESS = 3,
42 FAILURE = 4,
43 DOWNLOAD = 5,
44 DONE = 6,
45 SUBPROCESS = 7,
46 PROGRESS = 8
47}
48
49
50--- @enum lua_swupdate.sourcetype
51--- Lua equivalent of `sourcetype` as in `include/swupdate_status.h`.
52lua_swupdate.sourcetype = {
53 SOURCE_UNKNOWN = 0,
54 SOURCE_WEBSERVER = 1,
55 SOURCE_SURICATTA = 2,
56 SOURCE_DOWNLOADER = 3,
57 SOURCE_LOCAL = 4,
58 SOURCE_CHUNKS_DOWNLOADER = 5
59}
60
61
62--- Lua equivalent of `struct progress_msg` as in `include/progress_ipc.h`.
63--- @class lua_swupdate.progress_msg
64--- @field status lua_swupdate.RECOVERY_STATUS Update status, one of `lua_swupdate.RECOVERY_STATUS`'s values
65--- @field download number Downloaded data percentage
66--- @field source lua_swupdate.sourcetype Interface that triggered the update, one of `lua_swupdate.sourcetype`'s values
67--- @field nsteps number Total number of steps
68--- @field step number Current step
69--- @field percent number Percentage done in current step
70--- @field artifact string Name of image to be installed
71--- @field handler string Name of running Handler
72--- @field info string Additional information about installation
73
74
75--- SWUpdate progress socket binding.
76--
77-- The returned Class Table contains methods to
78-- interact with SWUpdate's progress socket.
79--
80lua_swupdate.progress = function()
81 return {
82 --- Connect to SWUpdate's progress socket.
83 --
84 --- @param self table This `lua_swupdate.progress` instance
85 --- @return number | nil # The connection handle or nil in case of error
86 --- @return nil | string # nil or an error message in case of error
87 connect = function(self) end,
88
89 --- Receive data from SWUpdate's progress socket.
90 --
91 --- @param self table This `lua_swupdate.progress` instance
92 --- @return table | lua_swupdate.progress_msg # This `lua_swupdate.progress` instance on error or the received progress message
93 --- @return nil # nil in case of error
94 receive = function(self) end,
95
96 --- Close connection to SWUpdate's progress socket.
97 --
98 --- @param self table This `lua_swupdate.progress` instance
99 --- @return table # This `lua_swupdate.progress` instance
100 close = function(self) end,
101 }
102end
103
104
105--- SWUpdate control socket binding.
106--
107-- The returned Class Table contains methods to
108-- interact with SWUpdate's control socket.
109--
110lua_swupdate.control = function()
111 return {
112 --- Connect to SWUpdate's control socket.
113 --
114 --- @param self table This `lua_swupdate.control` instance
115 --- @return number | nil # Connection handle or nil in case of error
116 --- @return nil | string # nil or an error message in case of error
117 connect = function(self) end,
118
119 --- Write to connected SWUpdate control socket.
120 --
121 --- @param self table This `lua_swupdate.control` instance
122 --- @param data string Chunk data to write to SWUpdate's control socket
123 --- @return boolean | nil # true or nil in case of error
124 --- @return nil | string # nil or an error message in case of error
125 write = function(self, data) end,
126
127 --- Close connection to SWUpdate's control socket.
128 --
129 --- @param self table This `lua_swupdate.control` instance
130 --- @return boolean | nil # true or nil in case of error
131 --- @return nil | string # nil or an error message in case of error
132 close = function(self) end,
133 }
134end
135
136
137return lua_swupdate