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 apiversion number API Version for compatibility check
65--- @field status lua_swupdate.RECOVERY_STATUS Update status, one of `lua_swupdate.RECOVERY_STATUS`'s values
66--- @field download number Downloaded data percentage
67--- @field source lua_swupdate.sourcetype Interface that triggered the update, one of `lua_swupdate.sourcetype`'s values
68--- @field nsteps number Total number of steps
69--- @field step number Current step
70--- @field percent number Percentage done in current step
71--- @field artifact string Name of image to be installed
72--- @field handler string Name of running Handler
73--- @field info string Additional information about installation
74
75
76--- SWUpdate progress socket binding.
77--
78-- The returned Class Table contains methods to
79-- interact with SWUpdate's progress socket.
80--
81lua_swupdate.progress = function()
82 return {
83 --- Connect to SWUpdate's progress socket.
84 --
85 --- @param self table This `lua_swupdate.progress` instance
86 --- @return number | nil # The connection handle or nil in case of error
87 --- @return nil | string # nil or an error message in case of error
88 connect = function(self) end,
89
90 --- Receive data from SWUpdate's progress socket.
91 --
92 --- @param self table This `lua_swupdate.progress` instance
93 --- @return table | lua_swupdate.progress_msg # This `lua_swupdate.progress` instance on error or the received progress message
94 --- @return nil # nil in case of error
95 receive = function(self) end,
96
97 --- Close connection to SWUpdate's progress socket.
98 --
99 --- @param self table This `lua_swupdate.progress` instance
100 --- @return table # This `lua_swupdate.progress` instance
101 close = function(self) end,
102 }
103end
104
105
106--- SWUpdate control socket binding.
107--
108-- The returned Class Table contains methods to
109-- interact with SWUpdate's control socket.
110--
111lua_swupdate.control = function()
112 return {
113 --- Connect to SWUpdate's control socket.
114 --
115 --- @param self table This `lua_swupdate.control` instance
116 --- @return number | nil # Connection handle or nil in case of error
117 --- @return nil | string # nil or an error message in case of error
118 connect = function(self) end,
119
120 --- Write to connected SWUpdate control socket.
121 --
122 --- @param self table This `lua_swupdate.control` instance
123 --- @param data string Chunk data to write to SWUpdate's control socket
124 --- @return boolean | nil # true or nil in case of error
125 --- @return nil | string # nil or an error message in case of error
126 write = function(self, data) end,
127
128 --- Close connection to SWUpdate's control socket.
129 --
130 --- @param self table This `lua_swupdate.control` instance
131 --- @return boolean | nil # true or nil in case of error
132 --- @return nil | string # nil or an error message in case of error
133 close = function(self) end,
134 }
135end
136
137
138return lua_swupdate