Skip to content

Commit 6705bca

Browse files
authored
Merge pull request #606 from david-cermak/feat/mosquitto
[mosq]: Support for TCP listener mode of mosquitto broker on ESP32
2 parents 2208e76 + e2392c3 commit 6705bca

35 files changed

+1479
-1
lines changed

.github/workflows/mosq__build.yml

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
name: "mosq: build-tests"
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
pull_request:
8+
types: [opened, synchronize, reopened, labeled]
9+
10+
jobs:
11+
build_mosq:
12+
if: contains(github.event.pull_request.labels.*.name, 'mosquitto') || github.event_name == 'push'
13+
name: Mosquitto build
14+
strategy:
15+
matrix:
16+
idf_ver: ["latest", "release-v5.3"]
17+
runs-on: ubuntu-22.04
18+
container: espressif/idf:${{ matrix.idf_ver }}
19+
env:
20+
TEST_DIR: components/mosquitto/examples/broker
21+
TARGET_TEST_DIR: build_esp32_default
22+
steps:
23+
- name: Checkout esp-protocols
24+
uses: actions/checkout@v4
25+
with:
26+
submodules: recursive
27+
- name: Build with IDF-${{ matrix.idf_ver }}
28+
shell: bash
29+
run: |
30+
. ${IDF_PATH}/export.sh
31+
pip install idf-component-manager idf-build-apps --upgrade
32+
python ci/build_apps.py ${TEST_DIR}
33+
cd ${TEST_DIR}
34+
${GITHUB_WORKSPACE}/ci/clean_build_artifacts.sh `pwd`/${TARGET_TEST_DIR}
35+
zip -qur artifacts.zip ${TARGET_TEST_DIR}
36+
- uses: actions/upload-artifact@v4
37+
with:
38+
name: mosq_target_esp32_${{ matrix.idf_ver }}
39+
path: ${{ env.TEST_DIR }}/artifacts.zip
40+
if-no-files-found: error
41+
42+
test_mosq:
43+
# Skip running on forks since it won't have access to secrets
44+
if: |
45+
github.repository == 'espressif/esp-protocols' &&
46+
( contains(github.event.pull_request.labels.*.name, 'mosquitto') || github.event_name == 'push' )
47+
name: Mosquitto target test
48+
needs: build_mosq
49+
strategy:
50+
matrix:
51+
idf_ver: ["latest", "release-v5.3"]
52+
runs-on:
53+
- self-hosted
54+
- ESP32-ETHERNET-KIT
55+
env:
56+
TEST_DIR: components/mosquitto/examples/broker
57+
TARGET_TEST_DIR: build_esp32_default
58+
steps:
59+
- uses: actions/checkout@v4
60+
- uses: actions/download-artifact@v4
61+
with:
62+
name: mosq_target_esp32_${{ matrix.idf_ver }}
63+
path: ${{ env.TEST_DIR }}/ci/
64+
- name: Run Test
65+
working-directory: ${{ env.TEST_DIR }}
66+
run: |
67+
unzip ci/artifacts.zip -d ci
68+
for dir in `ls -d ci/build_*`; do
69+
rm -rf build sdkconfig.defaults
70+
mv $dir build
71+
python -m pytest --log-cli-level DEBUG --junit-xml=./results_esp32_${{ matrix.idf_ver }}_${dir#"ci/build_"}.xml --target=esp32
72+
done

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
[submodule "components/asio/asio"]
22
path = components/asio/asio
33
url = https://github.com/espressif/asio
4+
[submodule "components/mosq/mosquitto"]
5+
path = components/mosquitto/mosquitto
6+
url = https://github.com/eclipse/mosquitto

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ repos:
6262
hooks:
6363
- id: commit message scopes
6464
name: "commit message must be scoped with: mdns, modem, websocket, asio, mqtt_cxx, console, common, eppp, wifi_remote, tls_cxx"
65-
entry: '\A(?!(feat|fix|ci|bump|test|docs)\((mdns|modem|common|console|websocket|asio|mqtt_cxx|examples|eppp|wifi_remote|tls_cxx)\)\:)'
65+
entry: '\A(?!(feat|fix|ci|bump|test|docs)\((mdns|modem|common|console|websocket|asio|mqtt_cxx|examples|eppp|wifi_remote|tls_cxx|mosq)\)\:)'
6666
language: pygrep
6767
args: [--multiline]
6868
stages: [commit-msg]

ci/check_copyright_config.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ asio_component:
4747
- Apache-2.0
4848
- BSL-1.0
4949

50+
mosquitto_component:
51+
include:
52+
- 'components/mosquitto/port/**'
53+
allowed_licenses:
54+
- EPL-2.0
55+
- Apache-2.0
56+
5057
slim_modem_examples:
5158
include:
5259
- 'examples/esp_netif/slip_custom_netif/**'

components/mosquitto/.cz.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
commitizen:
2+
bump_message: 'bump(mosq): $current_version -> $new_version'
3+
pre_bump_hooks: python ../../ci/changelog.py mosq
4+
tag_format: mosq-v$version
5+
version: 2.0.27
6+
version_files:
7+
- idf_component.yml

components/mosquitto/CMakeLists.txt

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
set(m_dir mosquitto)
2+
set(m_src_dir ${m_dir}/src)
3+
set(m_incl_dir ${m_dir}/include)
4+
set(m_lib_dir ${m_dir}/lib)
5+
set(m_deps_dir ${m_dir}/deps)
6+
7+
set(m_srcs
8+
${m_lib_dir}/memory_mosq.c
9+
${m_lib_dir}/util_mosq.c
10+
${m_lib_dir}/net_mosq.c
11+
${m_lib_dir}/will_mosq.c
12+
${m_lib_dir}/alias_mosq.c
13+
${m_lib_dir}/send_mosq.c
14+
${m_lib_dir}/strings_mosq.c
15+
${m_lib_dir}/packet_mosq.c
16+
${m_lib_dir}/packet_datatypes.c
17+
${m_lib_dir}/property_mosq.c
18+
${m_lib_dir}/util_topic.c
19+
${m_lib_dir}/send_publish.c
20+
${m_lib_dir}/send_disconnect.c
21+
${m_lib_dir}/handle_pubackcomp.c
22+
${m_lib_dir}/handle_pubrec.c
23+
${m_lib_dir}/handle_pubrel.c
24+
${m_lib_dir}/handle_ping.c
25+
${m_lib_dir}/time_mosq.c
26+
${m_lib_dir}/utf8_mosq.c
27+
28+
${m_src_dir}/bridge.c
29+
${m_src_dir}/bridge_topic.c
30+
${m_src_dir}/conf_includedir.c
31+
${m_src_dir}/context.c
32+
${m_src_dir}/control.c
33+
${m_src_dir}/database.c
34+
${m_src_dir}/handle_auth.c
35+
${m_src_dir}/handle_connack.c
36+
${m_src_dir}/handle_connect.c
37+
${m_src_dir}/handle_disconnect.c
38+
${m_src_dir}/handle_publish.c
39+
${m_src_dir}/handle_subscribe.c
40+
${m_src_dir}/handle_unsubscribe.c
41+
${m_src_dir}/keepalive.c
42+
${m_src_dir}/logging.c
43+
${m_src_dir}/loop.c
44+
${m_src_dir}/memory_public.c
45+
${m_src_dir}/mosquitto.c
46+
${m_src_dir}/mux.c
47+
${m_src_dir}/mux_epoll.c
48+
${m_src_dir}/mux_poll.c
49+
${m_src_dir}/net.c
50+
${m_src_dir}/password_mosq.c
51+
${m_src_dir}/persist_read.c
52+
${m_src_dir}/persist_read_v234.c
53+
${m_src_dir}/persist_read_v5.c
54+
${m_src_dir}/persist_write.c
55+
${m_src_dir}/persist_write_v5.c
56+
${m_src_dir}/property_broker.c
57+
${m_src_dir}/read_handle.c
58+
${m_src_dir}/retain.c
59+
${m_src_dir}/security.c
60+
${m_src_dir}/security_default.c
61+
${m_src_dir}/send_auth.c
62+
${m_src_dir}/send_connack.c
63+
${m_src_dir}/send_suback.c
64+
${m_src_dir}/send_unsuback.c
65+
${m_src_dir}/service.c
66+
${m_src_dir}/session_expiry.c
67+
${m_src_dir}/signals.c
68+
${m_src_dir}/subs.c
69+
${m_src_dir}/sys_tree.c
70+
${m_src_dir}/topic_tok.c
71+
${m_src_dir}/websockets.c
72+
${m_src_dir}/will_delay.c
73+
${m_src_dir}/xtreport.c)
74+
75+
idf_component_register(SRCS ${m_srcs}
76+
port/callbacks.c port/config.c port/signals.c port/ifaddrs.c port/broker.c port/files.c
77+
PRIV_INCLUDE_DIRS port/priv_include port/priv_include/sys ${m_dir} ${m_src_dir}
78+
${m_incl_dir} ${m_lib_dir} ${m_deps_dir}
79+
INCLUDE_DIRS ${m_incl_dir} port/include
80+
PRIV_REQUIRES newlib
81+
)
82+
83+
target_compile_definitions(${COMPONENT_LIB} PRIVATE "WITH_BROKER")
84+
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
85+
86+
# Some mosquittos source unconditionally define `_GNU_SOURCE` which collides with IDF build system
87+
# producing warning: "_GNU_SOURCE" redefined
88+
# This workarounds this issue by undefining the macro for the selected files
89+
set(sources_that_define_gnu_source ${m_lib_dir}/net_mosq.c ${m_src_dir}/loop.c ${m_src_dir}/mux_poll.c)
90+
foreach(offending_src ${sources_that_define_gnu_source})
91+
set_source_files_properties(${offending_src} PROPERTIES COMPILE_OPTIONS "-U_GNU_SOURCE")
92+
endforeach()

components/mosquitto/Doxyfile

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Set this to the include directory of your component
2+
INPUT = port/include
3+
STRIP_FROM_PATH = ./port/include
4+
5+
# Output goes into doxygen directory, which is added to gitignore
6+
OUTPUT_DIRECTORY = doxygen
7+
8+
# Warning-related settings, it's recommended to keep them enabled
9+
WARN_AS_ERROR = YES
10+
11+
# Other common settings
12+
RECURSIVE = YES
13+
FULL_PATH_NAMES = YES
14+
ENABLE_PREPROCESSING = YES
15+
MACRO_EXPANSION = YES
16+
EXPAND_ONLY_PREDEF = YES
17+
PREDEFINED = $(ENV_DOXYGEN_DEFINES)
18+
HAVE_DOT = NO
19+
GENERATE_XML = YES
20+
XML_OUTPUT = xml
21+
GENERATE_HTML = NO
22+
HAVE_DOT = NO
23+
GENERATE_LATEX = NO
24+
QUIET = YES
25+
MARKDOWN_SUPPORT = YES

components/mosquitto/LICENSE.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
This project is dual licensed under the Eclipse Public License 2.0 and the
2+
Eclipse Distribution License 1.0 as described in the epl-v20 and edl-v10 files.

components/mosquitto/README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# ESP32 Mosquitto Port
2+
3+
This is a lightweight port of the Mosquitto broker designed to run on the ESP32. It currently supports a single listener and TCP transport only.
4+
5+
## Supported Options
6+
7+
The Espressif port supports a limited set of options (with plans to add more in future releases). These options can be configured through a structure passed to the `mosq_broker_start()` function. For detailed information on available configuration options, refer to the [API documentation](api.md).
8+
9+
## API
10+
11+
### Starting the Broker
12+
13+
To start the broker, call the `mosq_broker_start()` function with a properly configured settings structure. The broker operates in the context of the calling task and does not create a separate task.
14+
15+
It's recommended to analyze the stack size needed for the task, but in general, the broker requires at least 4 kB of stack size.
16+
17+
```c
18+
mosq_broker_start(&config);
19+
```
20+
21+
## Memory Footprint Considerations
22+
23+
The broker primarily uses the heap for internal data, with minimal use of static/BSS memory. It consumes approximately 60 kB of program memory.
24+
25+
- **Initial Memory Usage**: ~2 kB of heap on startup
26+
- **Per Client Memory Usage**: ~4 kB of heap for each connected client
27+
28+
When using the broker with multiple clients, ensure sufficient heap space is available to handle scenarios where clients disconnect abruptly and reconnect. In cases of clean disconnections, the broker releases the memory immediately. However, when a client loses connection abruptly, the broker retains its connection information for some time before eventually freeing this memory. If the client reconnects during this period, an additional 4 kB of heap is allocated for the new connection while the memory for the previous connection is still being retained. Therefore, extra heap space is necessary to manage these abrupt reconnections smoothly.
29+
30+
## Testing
31+
32+
Extensive long-term tests have been conducted with the broker handling 5 clients simultaneously. Each client publishes messages every second to a different topic, while all clients subscribe to all topics. The test also included abrupt disconnections, where clients were suspended and reconnected after 10 seconds, to simulate real-world network instability.

components/mosquitto/api.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# API Reference
2+
3+
## Header files
4+
5+
- [mosq_broker.h](#file-mosq_brokerh)
6+
7+
## File mosq_broker.h
8+
9+
10+
11+
12+
13+
## Structures and Types
14+
15+
| Type | Name |
16+
| ---: | :--- |
17+
| struct | [**mosq\_broker\_config**](#struct-mosq_broker_config) <br>_Mosquitto configuration structure._ |
18+
19+
## Functions
20+
21+
| Type | Name |
22+
| ---: | :--- |
23+
| int | [**mosq\_broker\_start**](#function-mosq_broker_start) (struct [**mosq\_broker\_config**](#struct-mosq_broker_config) \*config) <br>_Start mosquitto broker._ |
24+
25+
26+
## Structures and Types Documentation
27+
28+
### struct `mosq_broker_config`
29+
30+
_Mosquitto configuration structure._
31+
32+
ESP port of mosquittto supports only the options in this configuration structure.
33+
34+
Variables:
35+
36+
- char \* host <br>Address on which the broker is listening for connections
37+
38+
- int port <br>Port number of the broker to listen to
39+
40+
41+
## Functions Documentation
42+
43+
### function `mosq_broker_start`
44+
45+
_Start mosquitto broker._
46+
```c
47+
int mosq_broker_start (
48+
struct mosq_broker_config *config
49+
)
50+
```
51+
52+
53+
This API runs the broker in the calling thread and blocks until the mosquitto exits.
54+
55+
56+
57+
**Parameters:**
58+
59+
60+
* `config` Mosquitto configuration structure
61+
62+
63+
**Returns:**
64+
65+
int Exit code (0 on success)

0 commit comments

Comments
 (0)