Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
srdgame committed Feb 21, 2024
2 parents c0fc8d4 + cea795e commit c7cdd5b
Show file tree
Hide file tree
Showing 29 changed files with 3,161 additions and 443 deletions.
22 changes: 22 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# EditorConfig is awesome: https://EditorConfig.org

# top-most EditorConfig file
root = true

# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true

# 4 space tab indentation for lua files
[*.lua]
indent_style = tab
indent_size = 4

# 2 space indentation for YAML files
[*.yaml]
indent_style = space
indent_size = 2
[*.yml]
indent_style = space
indent_size = 2
26 changes: 26 additions & 0 deletions .github/workflows/markdownlint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: validate (lint) markdown files
on: [push, pull_request]
jobs:
tests:
runs-on: ubuntu-latest
steps:
- name: check out repository code
uses: actions/checkout@v4

# NOTE: heavy node.js is used only to run markdownlint - the same tool as in my editor (Visual Studio Code)

# source: https://github.com/nodesource/distributions#debian-and-ubuntu-based-distributions
- name: add node.js deb source
run: |
sudo apt-get install -y ca-certificates curl gnupg && sudo mkdir -p /etc/apt/keyrings \
&& curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \
&& NODE_MAJOR=20 \
&& echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list
- name: install node.js
run: sudo apt-get update && sudo apt-get install nodejs -y

- name: install markdownlint-cli
run: sudo npm install -g markdownlint-cli

- name: validate all markdown files
run: cd "${{ github.workspace }}" && ./tests/run-markdownlint.sh
2 changes: 1 addition & 1 deletion .github/workflows/tests-and-coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: check out repository code
uses: actions/checkout@v2
uses: actions/checkout@v4

- name: run luacheck
run: sudo apt-get install -y lua-check && cd "${{ github.workspace }}" && ./tests/run-luacheck.sh -q
Expand Down
3 changes: 3 additions & 0 deletions .markdownlint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
default: true
single-title: false
line-length: false
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ This stage is optional and may be skipped if you don't need the secure network c
# Lua versions

It's tested to work on Debian 9 GNU/Linux with Lua versions:
* Lua 5.1 ... Lua 5.3 (**i.e. any modern Lua version**)

* Lua 5.1 ... Lua 5.4 (**i.e. any modern Lua version**)
* LuaJIT 2.0.0 ... LuaJIT 2.1.0 beta3
* It may also work on other Lua versions without any guarantees

Expand All @@ -72,7 +73,7 @@ As the luamqtt is almost zero-dependency you have to install required Lua librar

```sh
luarocks install luasocket # optional if you will use your own connectors (see below)
luarocks install luabitop # you don't need this for lua 5.3
luarocks install luabitop # you don't need this for lua 5.3 and above
luarocks install luasec # you don't need this if you don't want to use SSL connections
```

Expand All @@ -83,6 +84,7 @@ luarocks install luamqtt
```

Or for development purposes;

```sh
# development branch:
luarocks install luamqtt --dev
Expand Down Expand Up @@ -204,6 +206,7 @@ Standard MIT License, see LICENSE file for full text
* in file `./openwrt/Makefile`: change `PKG_VERSION:=X.Y.Z` and maybe `PKG_RELEASE:=1`
* copy file `./luamqtt-scm-1.rockspec` to `./rockspecs/luamqtt-X.Y.Z-1.rockspec` change `local package_version = "scm"`, `local package_version = "X.Y.Z"`
* run `./tests/run-luacheck.sh` and check output for errors
* run `./tests/run-markdownlint.sh` and check output for errors
* run `./tests/run-for-all-lua-versions.sh` and check output for errors
* run `./openwrt/make-package-without-openwrt-sources.sh` and check output for errors
* run `git commit`, `git tag vX.Y.Z`
Expand Down
2 changes: 1 addition & 1 deletion docs/modules/mqtt.client.html
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ <h3>Parameters:</h3>
</li>
<li><span class="parameter">callback</span>
<span class="types"><span class="type">function</span></span>
callback to call when publihsed message will be acknowledged
callback to call when published message will be acknowledged
(<em>optional</em>)
</li>
</li></ul>
Expand Down
4 changes: 3 additions & 1 deletion examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@
The simplest example are in `examples/simple.lua` file.

It's performing all basic MQTT actions:

1. connecting to broker
2. subscribing to topic
3. publishing message after subscription creation
4. receiving self-published message
5. disconnecting from MQTT broker

Here is an expected output of such script:
```

```console
created MQTT client mqtt.client{id="luamqtt-v2-0-0-5807dc7"}
running ioloop for it
connected: CONNACK{rc=0, sp=false, type=2}
Expand Down
2 changes: 1 addition & 1 deletion examples/copas-example.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ local mqtt_ioloop = require("mqtt.ioloop")

local num_pings = 10 -- total number of ping-pongs
local timeout = 1 -- timeout between ping-pongs
local suffix = tostring(math.random(1000000)) -- mqtt topic suffix to distinct simultaneous rinning of this script
local suffix = tostring(math.random(1000000)) -- mqtt topic suffix to distinct simultaneous running of this script

-- NOTE: more about flespi tokens: https://flespi.com/kb/tokens-access-keys-to-flespi-platform
local token = "stPwSVV73Eqw5LSv0iMXbc4EguS7JyuZR9lxU5uLxI5tiNM8ToTVqNpu85pFtJv9"
Expand Down
4 changes: 2 additions & 2 deletions examples/last-will/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ To reproduce you have to start `client-1.lua` and then `client-2.lua`.

Here is an example output of both scripts:

```
```console
$ lua examples/last-will/client-1.lua
connected: CONNACK{rc=0, type=2, sp=false}
subscribed to luamqtt/close, waiting for connection close command from client-2
received: PUBLISH{qos=1, retain=false, topic="luamqtt/close", payload="Dear client-1, please close your connection", packet_id=1, type=3, dup=false}
closing connection without DISCONNECT and stopping client-1
```

```
```console
$ lua examples/last-will/client-2.lua
connected: CONNACK{rc=0, sp=false, type=2}
subscribed to luamqtt/lost
Expand Down
2 changes: 1 addition & 1 deletion examples/openresty/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ There is a two ways to run MQTT client in openresty:

Started MQTT client is connecting, subscribing and waiting for incoming MQTT publications as you code it, without any magic asynchronous work.

**Caveats**: The keep_alive feature will not work as there is no way for MQTT client to break its receive() operation in keep_alive interval and send PINGREQ packet to MQTT broker to maintain connection. It may lead to disconnects from MQTT broker side in absense traffic in opened MQTT connection. After disconnecting from broker there is a way to reconnect using openresty's timer.
**Caveats**: The keep_alive feature will not work as there is no way for MQTT client to break its receive() operation in keep_alive interval and send PINGREQ packet to MQTT broker to maintain connection. It may lead to disconnects from MQTT broker side in absence of traffic in opened MQTT connection. After disconnecting from broker there is a way to reconnect using openresty's timer.

# ioloop mode

Expand Down
8 changes: 4 additions & 4 deletions mqtt/client.lua
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ function client_mt:__init(args)
self._to_remove_handlers = {}

-- state
self.first_connect = true -- contains true to perform one network connection attemt after client creation
self.first_connect = true -- contains true to perform one network connection attempt after client creation
self._last_in_time = 0 -- time of the last network received from client side

-- packet creation/parse functions according version
Expand Down Expand Up @@ -420,7 +420,7 @@ end
-- @tparam[opt=false] boolean args.dup dup message publication flag
-- @tparam[opt] table args.properties properties for publishing message
-- @tparam[opt] table args.user_properties user properties for publishing message
-- @tparam[opt] function args.callback callback to call when publihsed message will be acknowledged
-- @tparam[opt] function args.callback callback to call when published message will be acknowledged
-- @return true or packet id on success or false and error message on failure
function client_mt:publish(args)
-- fetch and validate args
Expand Down Expand Up @@ -723,8 +723,8 @@ function client_mt:open_connection()
-- create connection table
local conn = {
uri = args.uri,
wait_for_pubrec = {}, -- a table with packet_id of parially acknowledged sent packets in QoS 2 exchange process
wait_for_pubrel = {}, -- a table with packet_id of parially acknowledged received packets in QoS 2 exchange process
wait_for_pubrec = {}, -- a table with packet_id of partially acknowledged sent packets in QoS 2 exchange process
wait_for_pubrel = {}, -- a table with packet_id of partially acknowledged received packets in QoS 2 exchange process
}
client_mt._parse_uri(args, conn)
client_mt._apply_secure(args, conn)
Expand Down
4 changes: 3 additions & 1 deletion mqtt/const.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ local const = {
_VERSION = "3.4.3",
}

return const
return const

-- vim: ts=4 sts=4 sw=4 noet ft=lua
27 changes: 17 additions & 10 deletions mqtt/protocol.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
Here is a generic implementation of MQTT protocols of all supported versions.
MQTT v3.1.1 documentation (DOCv3.1.1):
http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/errata01/os/mqtt-v3.1.1-errata01-os-complete.html
DOC[1]: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/errata01/os/mqtt-v3.1.1-errata01-os-complete.html
MQTT v5.0 documentation (DOCv5.0):
http://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.html
DOC[2]: http://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.html
CONVENTIONS:
Expand Down Expand Up @@ -56,6 +56,7 @@ local rshift = bit.rshift

local tools = require("mqtt.tools")
local div = tools.div
local sortedpairs = tools.sortedpairs

--- Create bytes of the uint8 value
-- @tparam number val - integer value to convert to bytes
Expand Down Expand Up @@ -157,20 +158,20 @@ function protocol.make_var_length_nonzero(value)
return make_var_length(value)
end

--- Read string using given read_func function
--- Read string (or bytes) using given read_func function
-- @tparam function read_func - function to read some bytes from the network layer
-- @treturn string parsed string on success
-- @treturn string parsed string (or bytes) on success
-- @return OR false and error message on failure
function protocol.parse_string(read_func)
assert(type(read_func) == "function", "expecting read_func to be a function")
local len, err = read_func(2)
if not len then
return false, "failed to read string length: "..err
end
-- convert len string from 2-byte integer
-- convert string length from 2 bytes
local byte1, byte2 = str_byte(len, 1, 2)
len = bor(lshift(byte1, 8), byte2)
-- and return string if parsed length
-- and return string/bytes of the parsed length
return read_func(len)
end
local parse_string = protocol.parse_string
Expand Down Expand Up @@ -262,6 +263,8 @@ local max_mult = 128 * 128 * 128
-- @treturn number parser value
-- @return OR false and error message on failure
function protocol.parse_var_length(read_func)
-- DOC[1]: 2.2.3 Remaining Length
-- DOC[2]: 1.5.5 Variable Byte Integer
assert(type(read_func) == "function", "expecting read_func to be a function")
local mult = 1
local val = 0
Expand Down Expand Up @@ -476,7 +479,7 @@ combined_packet_mt.__index = function(_, key)
end

--- Combine several data parts into one
-- @tparam combined_packet_mt/string ... any amout of strings of combined_packet_mt tables to combine into one packet
-- @tparam combined_packet_mt/string ... any amount of strings of combined_packet_mt tables to combine into one packet
-- @treturn combined_packet_mt table suitable to append packet parts or to stringify it into raw packet bytes
function protocol.combine(...)
return setmetatable({...}, combined_packet_mt)
Expand All @@ -489,7 +492,7 @@ local function value_tostring(value)
return str_format("%q", value)
elseif t == "table" then
local res = {}
for k, v in pairs(value) do
for k, v in sortedpairs(value) do
if type(k) == "number" then
res[#res + 1] = value_tostring(v)
else
Expand All @@ -511,7 +514,7 @@ end
-- @treturn string human-readable string representation of the packet
function protocol.packet_tostring(packet)
local res = {}
for k, v in pairs(packet) do
for k, v in sortedpairs(packet) do
res[#res + 1] = str_format("%s=%s", k, value_tostring(v))
end
return str_format("%s{%s}", tostring(packet_type[packet.type]), tbl_concat(res, ", "))
Expand All @@ -527,7 +530,11 @@ protocol.packet_mt = {
protocol.connack_packet_mt = {
__tostring = packet_tostring, -- packet-to-human-readable-string conversion metamethod using protocol.packet_tostring()
reason_string = function(self) -- Returns reason string for the CONNACK packet according to its rc field
return connack_rc[self.rc]
local reason_string = connack_rc[self.rc]
if not reason_string then
reason_string = "Unknown: "..self.rc
end
return reason_string
end,
}
protocol.connack_packet_mt.__index = protocol.connack_packet_mt
Expand Down
Loading

0 comments on commit c7cdd5b

Please sign in to comment.