Compare commits

...

472 Commits

Author SHA1 Message Date
b43d93c82d fix: Fix host test for github ci. 2024-04-17 14:35:34 +02:00
aa6f889fb4 Merge branch 'fix/error_codes' into 'master'
fix: regard reason codes greater than 0x80 as failures.

See merge request espressif/esp-mqtt!205
2024-04-05 17:09:50 +08:00
1edd167dcb Merge branch 'fix/calloc_failure' into 'master'
PR: Return on allocation failure

See merge request espressif/esp-mqtt!204
2024-04-03 15:29:51 +08:00
c06f1540fe set last_retransmit to now when first connected
when published before connected, the msg will be always retransmitted immediately even it is  send right now
2024-04-02 10:48:45 +02:00
37478a9c00 add return to faile_message, avoid segment fault
should not use response_topic when calloc failed
2024-04-02 10:48:45 +02:00
fd21b27a83 Merge branch 'fix/unused_variable_warning' into 'master'
Minor warning of unused variable

See merge request espressif/esp-mqtt!203
2024-04-02 14:41:47 +08:00
e7b9aa5e6a fix: regard reason codes greater than 0x80 as failures. 2024-04-01 10:37:42 +08:00
726e5f2fce fix: Minor warning of unused variable
In case of hardcoded id mac array was unused.
2024-03-28 14:16:34 +01:00
14f5fa079f Merge branch 'fix/cliend_id' into 'master'
Cover the case for SOC without MAC address

See merge request espressif/esp-mqtt!202
2024-03-28 20:37:54 +08:00
5e3abd4b8c fix: Cover the case for SOC without MAC address
We need to cover for the case where the available MAC isn't defined in
soc caps. E.g. A new target is being introduced but the support isn't
complete yet.
2024-03-28 12:40:07 +01:00
37cb056c5f Merge branch 'feature/atomic_state' into 'master'
Make state and size atomic

See merge request espressif/esp-mqtt!199
2024-03-22 15:26:15 +08:00
74481cbbf4 Merge branch 'fix/log_level_on_timeout' into 'master'
fix: Adjust the log level on few messages to avoid cluthering the logs

See merge request espressif/esp-mqtt!201
2024-03-22 15:05:49 +08:00
c33a0c8e44 Merge branch 'fix/detect_mac_type' into 'master'
fix: Make automatic client_id soc dependent

See merge request espressif/esp-mqtt!200
2024-03-22 15:05:21 +08:00
5c17fc4a1a fix: Adjust the log level on few messages to avoid cluthering the logs 2024-03-21 14:11:57 +01:00
657a2aea77 fix: Make automatic client_id soc dependent
When creating the client_id for user, the library uses the device MAC.
For some of our devices WIFI isn't available and the library needs to select
a different MAC to use.
2024-03-14 07:31:37 +01:00
891380bdf5 feat: Make state and size atomic
This makes the mqtt client state atomic to reduce the scope of locking in
some parts of the code.
2024-03-12 08:49:36 +01:00
fa88da5282 Merge branch 'lifetime_clarification' into 'master'
Clarify data that users need to take care of lifetime.

See merge request espressif/esp-mqtt!197
2024-01-26 19:10:50 +08:00
5a35782272 Merge branch 'fix/subscribe_macro_type' into 'master'
Update mqtt_client.h

See merge request espressif/esp-mqtt!198
2024-01-26 18:54:42 +08:00
acdb66d5c6 add const char * to esp_mqtt_client_subscribe() generic macros 2024-01-25 15:35:32 +07:00
d3e3c4e7ad Merge branch 'bugfix/consolidate_err_messages' into 'master'
client: Report failure on timeout in mid-message timeout (GitHub PR)

See merge request espressif/esp-mqtt!165
2024-01-24 22:23:04 +08:00
371f594cce docs: Clarify data that users need to take care of lifetime.
- Adds to field that the mqtt client doesn't copy a note about it.
2024-01-24 09:38:37 +01:00
ddde502782 client: Report failure on timeout in mid-message timeout
Fixes error processing on network reads:

1) Treat EOF as an error, since the connection is closed (FIN) from the
server side. If we didn't we would try to read (in the next iteration)
from the same socket that has been already closed and get an error
ENOTCONN.
Before the fix:
D (13760) mqtt_client: esp_mqtt_handle_transport_read_error: transport_read(): EOF
E (13800) transport_base: tcp_read error, errno=Socket is not connected
E (13800) mqtt_client: esp_mqtt_handle_transport_read_error: transport_read() error: errno=128
D (13810) esp_mqtt_demo: Event dispatched from event loop base=MQTT_EVENTS, event_id=0
I (13820) esp_mqtt_demo: MQTT_EVENT_ERROR
E (13830) esp_mqtt_demo: Last error reported from esp-tls: 0x8008
E (13830) esp_mqtt_demo: Last error captured as transport's socket errno: 0x80
I (13840) esp_mqtt_demo: Last errno string (Socket is not connected)
E (13850) mqtt_client: mqtt_process_receive: mqtt_message_receive() returned -1
D (13860) mqtt_client: Reconnect after 10000 ms
D (13860) esp_mqtt_demo: Event dispatched from event loop base=MQTT_EVENTS, event_id=2
I (13870) esp_mqtt_demo: MQTT_EVENT_DISCONNECTED
After the fix:
E (12420) mqtt_client: esp_mqtt_handle_transport_read_error: transport_read(): EOF
E (12420) mqtt_client: esp_mqtt_handle_transport_read_error: transport_read() error: errno=128
D (12430) esp_mqtt_demo: Event dispatched from event loop base=MQTT_EVENTS, event_id=0
I (12440) esp_mqtt_demo: MQTT_EVENT_ERROR
E (12450) esp_mqtt_demo: Last error reported from esp-tls: 0x8008
I (12450) esp_mqtt_demo: Last errno string (Success)
E (12460) mqtt_client: mqtt_process_receive: mqtt_message_receive() returned -1
D (12470) mqtt_client: Reconnect after 10000 ms
D (12470) esp_mqtt_demo: Event dispatched from event loop base=MQTT_EVENTS, event_id=2
I (12480) esp_mqtt_demo: MQTT_EVENT_DISCONNECTED

2) Treat timeouts in the middle of MQTT message reading as errors (if
timeouted for the second time and didn't read a byte)
Before the fix:
D (9160) mqtt_client: mqtt_message_receive: read "remaining length" byte: 0x2
D (9170) mqtt_client: mqtt_message_receive: total message length: 4 (already read: 2)
D (19190) mqtt_client: mqtt_message_receive: read_len=0
D (19190) mqtt_client: esp_mqtt_handle_transport_read_error: transport_read(): call timed out before data was ready!
E (19200) mqtt_client: esp_mqtt_connect: mqtt_message_receive() returned 0
E (19210) mqtt_client: MQTT connect failed
D (19220) mqtt_client: Reconnect after 10000 ms
D (19220) esp_mqtt_demo: Event dispatched from event loop base=MQTT_EVENTS, event_id=2
I (19230) esp_mqtt_demo: MQTT_EVENT_DISCONNECTED
After the fix:
D (19190) mqtt_client: mqtt_message_receive: read_len=0
E (19190) mqtt_client: Network timeout while reading MQTT message
E (19200) mqtt_client: esp_mqtt_handle_transport_read_error: transport_read() error: errno=119
D (19210) esp_mqtt_demo: Event dispatched from event loop base=MQTT_EVENTS, event_id=0
I (19220) esp_mqtt_demo: MQTT_EVENT_ERROR
I (19220) esp_mqtt_demo: Last errno string (Success)
E (19230) mqtt_client: esp_mqtt_connect: mqtt_message_receive() returned -1
E (19240) mqtt_client: MQTT connect failed
D (19240) mqtt_client: Reconnect after 10000 ms
D (19240) esp_mqtt_demo: Event dispatched from event loop base=MQTT_EVENTS, event_id=2
I (19250) esp_mqtt_demo: MQTT_EVENT_DISCONNECTED
(Note that the above log is from mid-message timeout of CONNECT message,
which was hadled before the fix. If the mid-message timeout ocurs with
for example SUBACK, the current version would repeatably resend
susbscribe message)

Merges https://github.com/espressif/esp-mqtt/pull/232
2023-11-10 15:40:44 +01:00
7894dd0ace Merge branch 'fix/buffer_creation_in_set_config' into 'master'
fix: Move buffer initialization to set config

See merge request espressif/esp-mqtt!194
2023-10-25 16:16:35 +08:00
ea0df31e00 fix: Move buffer initialization to set config
When calling set config message buffers were not affected because the
creation was handled on init.

Closes https://github.com/espressif/esp-mqtt/issues/267
2023-10-25 07:47:05 +00:00
abd8b6cadc Merge branch 'fix/qos0publishdispatch' into 'master'
Fix check for message creation when processing publish

See merge request espressif/esp-mqtt!195
2023-10-10 16:25:20 +08:00
67800569de fix: Deliver publish verifies if message was created only for QoS >0
The previous version depends on a sucessful message being created prior
to that check. The check only makes sense for the case where puback or
pubrec messages should be created.
2023-10-10 06:47:07 +00:00
e6afdb4025 Merge branch 'fix/check_asprintf_return_value' into 'master'
fix: using return value of asprintf now

See merge request espressif/esp-mqtt!192
2023-09-14 19:46:26 +08:00
c0b40b1293 fix: using return value of asprintf now 2023-09-14 19:46:26 +08:00
dc93367bd5 Merge branch 'fix/outbox_memory_destination' into 'master'
fix: Uses caps allocation for data buffer instead of item struct

See merge request espressif/esp-mqtt!193
2023-09-14 13:47:33 +08:00
00ee059bf8 fix: Uses caps allocation for data buffer instead of item struct
Once introduced the memory destination for outbox was incorrectly
allocating the outbox data structuture instead of data buffer to the
selected memory.
2023-09-13 08:04:38 +02:00
05b347643f Merge branch 'bugfix/mock_tests_include_idf_additions' into 'master'
Fix: Mock test should include idf_additions.h

See merge request espressif/esp-mqtt!191
2023-09-04 20:01:22 +08:00
f35aaa1577 fix: Mock tests include idf_additions.h
A number of IDF specific FreeRTOS API additions will be moved to
`#include "freertos/idf_additions.h". Mock tests need to include these to
properly use them as mock functions.
2023-09-04 15:05:03 +08:00
4b28192d00 Merge branch 'docs/outbox_doxygen' into 'master'
Adds missing documentation to outbox configuration.

See merge request espressif/esp-mqtt!190
2023-08-31 22:22:04 +08:00
c355e0b5ae docs: Adds missing documentation to outbox configuration. 2023-08-31 22:22:04 +08:00
301bd9e028 Merge branch 'fix/big_messages' into 'master'
fix: Added missing update to message data

See merge request espressif/esp-mqtt!189
2023-08-25 15:38:48 +08:00
cc41d1b852 fix: Added missing update to message data
When handling big messages the refactoring introduced a regression when
handling big messages, messages larger than the message buffer.
2023-08-24 09:52:00 +02:00
1ca73479cb Merge branch 'mqtt5_fixing_typo' into 'master'
PR: fixing typos in `mqtt5_error_reason_code`

See merge request espressif/esp-mqtt!188
2023-08-18 14:43:10 +08:00
90b4a4538e feat: Add enum definition with typo to keep backwards compatibility
Added initial enum definitions with deprecated attribute.
Should be removed with a new version that can introduce a breaking
change.
2023-08-17 14:58:49 +02:00
dc775bb52e fixing typos in mqtt5_error_reason_code 2023-07-24 23:23:32 +08:00
fe32d8f224 Merge branch 'docs/clarify_keepalive_timeout' into 'master'
docs: Clarify keepalive timeout

See merge request espressif/esp-mqtt!186
2023-07-11 05:34:46 +08:00
cb1e6cf218 docs: Clarify keepalive timeout
Adds information on the behavior of the PINGREQ message timeout and some
reasoning behind the choice.
2023-07-11 05:34:46 +08:00
cd81773bd1 Merge branch 'fix/format_log_messages' into 'master'
fix: LOG format strings

See merge request espressif/esp-mqtt!187
2023-07-10 17:28:55 +08:00
395aa141c8 Merge branch 'fix/stop_only_if_started' into 'master'
Fix: Stop client only if it's running.

See merge request espressif/esp-mqtt!183
2023-07-10 15:55:33 +08:00
8d98103013 Merge branch 'fix/account_for_failure_in_make_publish' into 'master'
fix: Error on publish message creation was ignored.

See merge request espressif/esp-mqtt!185
2023-06-30 20:42:28 +08:00
a3b04f2d0a fix: LOG format strings
Fix log format strings and remove no-format warning configuration.
2023-06-30 10:17:32 +02:00
585e3ba2e0 fix: Error on publish message creation was ignored.
In the case of make_publish failure the client would just continue and
the error was ignored and not propagated to caller.
2023-06-27 15:13:54 +02:00
36eec6f625 Fix: Stop client only if it's running.
Check for client run instead of lock to call esp_mqtt_client_stop
when destroying the client.
2023-06-21 09:39:42 +02:00
effd1e6705 Merge branch 'bugfix/connection_buffer_allocation' into 'master'
Fix: Allocation for connection buffer was incorrectly done.

See merge request espressif/esp-mqtt!182
2023-06-21 14:57:11 +08:00
6c849c62ef Fix: Allocation for connection buffer was incorrectly done.
By mistake calloc parameters were incorrect.
2023-06-21 08:24:46 +02:00
ee3ea29d52 Merge branch 'fix/host_test' into 'master'
Adds mqtt host tests to Ci

See merge request espressif/esp-mqtt!181
2023-06-20 13:27:02 +08:00
4050df4caf Adds mqtt host tests to Ci
- New job to run host tests
- Fix leak in case of usage of interface name
- Fix host tests to expect a call to `transport_destroy` and add an
  extra case
2023-06-19 10:34:18 +02:00
aee82c7ba8 Merge branch 'bugfix/outbox_init_failure' into 'master'
Fix: Outbox was leaked in case of initialization failure

See merge request espressif/esp-mqtt!180
2023-06-14 21:46:04 +08:00
5896e259ad Merge branch 'feat/bind_interface' into 'master'
feat: Add option to bind interface of use

See merge request espressif/esp-mqtt!179
2023-06-14 21:43:34 +08:00
363fbf7dab feat: Add option to bind interface of use
Enable user to set which interface should be used for client network,
allowing client to be binded to the interface selected by user forcing
it to go through the selected interface.

Closes https://github.com/espressif/esp-mqtt/issues/253
2023-06-14 14:48:44 +02:00
5d491a45ce Fix: Outbox was leaked in case of initialization failure
If the the list allocation fail, outbox must be freed.
2023-06-14 13:36:42 +02:00
63cfec799c Merge branch 'feature/configurable_max_outbox' into 'master'
Add outbox size control feature

See merge request espressif/esp-mqtt!141
2023-06-14 01:02:34 +08:00
372ab7b374 feat: Introduces outbox limit
A memory limit for the outbox can be configured.
User will not be able to publish or enqueue if the new message goes
beyond the configured limit.
2023-06-13 15:59:55 +02:00
21a5491d53 Removes unused outbox functions. 2023-06-13 11:56:11 +02:00
122875bf8a refactor: Group access to output buffer in mqtt_connection_t
- Moves mqtt_connect_info to mqtt_connection_t.
  - Removes outbound_message in favor of accessing it trough connection.
2023-06-13 11:56:05 +02:00
ed628098a1 Merge branch 'feature/custom_transport' into 'master'
Add custom transport configuration

See merge request espressif/esp-mqtt!169
2023-06-13 14:30:24 +08:00
6438676b66 Merge branch 'fix/removed_unused_handler_field' into 'master'
Removes leftover calls to event_handler

See merge request espressif/esp-mqtt!178
2023-06-13 14:29:49 +08:00
a492935951 Removes leftover calls to event_handler
The possibility to add a callback as custom handler was removed from
the client in favor of esp_event. These removes the older alternative
that wasn't possible to use.
2023-06-09 10:44:50 +02:00
a89af4bf8d Merge branch 'cfg-common-name' into 'master'
PR: Added support to set server common name.

See merge request espressif/esp-mqtt!173
2023-06-08 15:08:22 +08:00
6195762d28 Added support to set server common name. 2023-06-08 08:46:41 +02:00
a5c1b441dc feat: Add custom transport configuration
Today there is no way to add a new transport without applying
modifications to the transport list. This impose limitations on the
client usage. Adding the custom configuration we enable user defined
transports.
2023-06-08 06:38:53 +00:00
ffd7d4df6c Fix: Prevent sync verififcation from running on master
Removes the verification in case the pipeline is running on master.
2023-06-08 08:15:38 +02:00
4c2ed1676f CI: Add check for Gitlab/Github remotes in sync
To avoid merging on Gitlab with Github remote out of sync while we are
moving to Github development.
2023-06-08 08:15:38 +02:00
5b8a541939 Merge pull request #258 from euripedesrocha/feature/github_actions
feat: Adds github action
2023-06-05 03:26:25 -03:00
6c3cbdd195 feat: Adds github action
- Initial support for github actions
2023-06-01 13:55:48 +02:00
63ebf8b1a2 Merge branch 'cherry-pick-fa40f446' into 'master'
Merge branch 'bugfix/return_on_qos0_disconnected' into 'master'

See merge request espressif/esp-mqtt!175
2023-06-01 18:51:58 +08:00
89981b7277 Merge branch 'cherry-pick-88413ec3' into 'master'
Merge branch 'bugfix/cpp_compilation' into 'master'

See merge request espressif/esp-mqtt!174
2023-06-01 18:31:40 +08:00
5bd9724c69 Merge branch 'bugfix/return_on_qos0_disconnected' into 'master'
bug: Incorrect return on disconnect qos0 publish

See merge request espressif/esp-mqtt!172

(cherry picked from commit fa40f44695fc4a0cde14a31a01b8a03da14dd702)

58c25577 bug: Incorrect return on disconnect qos0 publish
2023-06-01 17:03:03 +08:00
70cbaca728 Merge branch 'bugfix/cpp_compilation' into 'master'
Fix: Compilation in C++ with multiple subscribe

See merge request espressif/esp-mqtt!171

(cherry picked from commit 88413ec3f27102daa805ae1992dd145b42d4690d)

47da99fb Fix: Compilation in C++ with multiple subscribe
2023-06-01 17:02:05 +08:00
b2bd8e5f49 Merge pull request #257 from gabsuren/feature/mqtt_host_tests
feature: added host tests
2023-05-26 13:40:28 +04:00
77372e81f9 feature: added host tests 2023-05-26 13:21:44 +04:00
fe622fc77a Merge pull request #259 from espressif/fix/jira_sync_action
ci: Test for Jira sync action fix (IDFGH-10224)
2023-05-24 16:12:38 +02:00
490bde044f ci: Fix Jira sync action (action setting based on standard boilerplate) 2023-05-24 15:23:21 +02:00
0e4cec9497 Merge branch 'ci/fix_qemu_build' into 'master'
ci: Fix qemu build against 5.1

See merge request espressif/esp-mqtt!170
2023-05-04 16:01:19 +08:00
94defb867e ci: Fix qemu build against 5.1
Also adds build against v5.1 and master separetely
2023-05-03 15:48:41 +02:00
14b11ad07e Merge branch 'merge_enqueue' into 'master'
Minor cleanups on mqtt client

See merge request espressif/esp-mqtt!168
2023-04-21 15:11:48 +08:00
da6d38a17e Removes pending message count
The information was used only to log remaining messages on debug log.
It was checked on writing but updated prior to every call making the
verification meaningless.
2023-04-21 08:40:12 +02:00
5729048683 Bugfix: Dispatch transport error on all write operations
- During connect the error wasn't dispatched.
- Merged esp_mqtt_write with mqtt_write_data since the only difference
  was the error dispatched.
2023-04-20 09:29:33 +02:00
72833c7f8a Merge enqueue functions
- enqueue and oversized enqueue did the same work with small differences
  this clean up the extra unnecessary function
2023-04-20 09:29:33 +02:00
0b315a01b1 Merge branch 'feature/outbox_memory_selection' into 'master'
Adds a configuration for outbox data destination

See merge request espressif/esp-mqtt!166
2023-04-13 15:20:43 +08:00
2c71f9e69b feat: Adds a configuration for outbox data destination
Allow user to move outbox data to external SPI RAM.
2023-04-12 08:43:40 +00:00
6bcd906b8a Merge branch 'ci/fix_qemu_test' into 'master'
CI: Add configuration for ttfw

See merge request espressif/esp-mqtt!167
2023-04-12 16:43:06 +08:00
d71dcf372a CI: Add configuration for ttfw
File was removed from idf. Adding it here to fix CI before we move the
tests to pytest embedded
2023-04-12 08:49:23 +02:00
9c1826d152 Merge branch 'bugfix/fix_mqtt5_flow_control' into 'master'
mqtt5: Fix flow control will increase count when send fragmented packet

See merge request espressif/esp-mqtt!164
2023-03-29 20:36:13 +08:00
5cce2c4f35 mqtt5: Fix flow control will increase count when send fragmented packet
Closes https://github.com/espressif/esp-mqtt/issues/255
2023-03-17 16:55:25 +08:00
9f2db7b4b6 Merge branch 'bugfix/queue_license' into 'master'
Add license information to queue

See merge request espressif/esp-mqtt!163
2023-03-09 14:37:30 +08:00
36f0faa80d Add license information to queue
File was copied from BSD header without the license information.
2023-03-02 08:02:57 +01:00
7089fac9c0 Merge branch 'prs/mqtt5_fixes' into 'master'
MQTTv5: Fixes and additions from GitHub PRs

See merge request espressif/esp-mqtt!162
2023-02-28 16:25:53 +08:00
65a4fdaff5 fix: Allow MQTT v5 zero length payload
Merges https://github.com/espressif/esp-mqtt/pull/250
2023-02-27 12:46:22 +01:00
1011e63cbe feature: Include subscribe_id in esp_mqtt5_event_property_t 2023-02-09 18:44:47 +00:00
5a156f56b4 Merge branch 'feature/multiple_subscribe' into 'master'
Feature:  Enable SUBSCRIBE to multiple topics

See merge request espressif/esp-mqtt!156
2023-02-08 15:35:31 +08:00
32102558d3 Feature: Enable SUBSCRIBE to multiple topics
- Adds an api for multiple topics on SUBSCRIBE message.

Apply 2 suggestion(s) to 1 file(s)

Removing headers

y
2023-02-03 14:19:24 +01:00
5adbe11aaf Merge branch 'feature/config_read_poll' into 'master'
Adds Kconfig option to configure poll read timeout

See merge request espressif/esp-mqtt!159
2023-02-02 20:52:02 +08:00
2fa945d0b8 Adds Kconfig option to configure poll read timeout
A new Kconfig option was added to allow users to configure poll read
timeout.

Closes: https://github.com/espressif/esp-mqtt/issues/245
2023-02-02 20:52:02 +08:00
86d21e4902 Merge branch 'bugfix/nano_printf_format' into 'master'
Fix formatting when using printf nano

See merge request espressif/esp-mqtt!160
2023-02-02 20:24:24 +08:00
e9b865eb9d Fix formatting when using printf nano 2023-02-02 20:24:24 +08:00
acab02f2c5 Merge branch 'bugfix/fix_mqtt5_flow_control' into 'master'
mqtt5: Fix flow control will regard the DUP packet and not consider PUBCOMP packet

See merge request espressif/esp-mqtt!158
2023-01-18 16:03:31 +08:00
ed76036744 mqtt5: Fix flow control will regard the DUP packet and not consider PUBCOMP packet
Closes https://github.com/espressif/esp-mqtt/issues/243
2023-01-18 14:16:28 +08:00
c96f6f804c Merge branch 'bugfix/coverity_fix' into 'master'
Remove possible null pointer dereferences

See merge request espressif/esp-mqtt!157
2023-01-04 20:26:27 +08:00
dffabb067f Merge branch 'feature/esp_mqtt_as_managed_component' into 'master'
Moves mqtt build files to esp-mqtt and adds a component file

See merge request espressif/esp-mqtt!149
2022-12-17 01:46:11 +08:00
159b1638b2 Reorganize mqtt build structure
- Integrate build definitions from idf
- Changes CMakeLists to allow import
- Added host test from idf
- Added test code from idf
2022-12-16 08:52:54 +01:00
f27cb47c0f [MQTT] Simplifies MQTT CMakeLists file
- Uses mocks from tools instead of creating them.
- Move host based definition to test code.
2022-12-16 08:38:48 +01:00
ee9b52b7d2 build system: re-add -Wno-format as private flag for some components 2022-12-16 08:38:48 +01:00
01d0f34654 test: Add mqtt5 unit-test 2022-12-16 08:38:48 +01:00
0b98c63247 mqtt: Add mqtt5 Kconfig 2022-12-16 08:38:48 +01:00
94ecca2073 esp_netif/lwip: Fix deps cycles to "lwip -> esp_netif -> phy-drivers"
Fix dependency tree so that lwip doesn't depend on any specific network
interface component.
Network interface drivers shall depend on esp_netif.
esp_netif shall depend on lwip (but not on any specific interface
driver) -- it optionally depends on vfs and esp_eth (need ethernet
header for L2/bridge mode)
2022-12-16 08:38:48 +01:00
1e598b071b [MQTT] - Updates esp_mqtt configuration struct
- Layered config struct
- Fix examples.
2022-12-16 08:38:48 +01:00
d4ee31f627 docs: changes docs supported targets tables 2022-12-16 08:38:48 +01:00
411ea65ec7 [MQTT] - Adds esp-timer as dependency and change version.
- Current time is now from esp_timer.
2022-12-16 08:38:48 +01:00
bc30b9a8e3 mqtt: Update tests to start with valid transport 2022-12-16 08:38:48 +01:00
d372bbf09e mqtt: Fix client_enqueue(len=0), Improve transport memory
* Update submodule: git log --oneline 64f88b4412ea6649dbf207a07370c2617160d044..a21c387d6280260894981c22494017c893d505b9

Detailed description of the changes:
* mqtt_client: Added checks for cleanly-closed connection and timeout
  - See merge request espressif/esp-mqtt!118
  - Added checks for cleanly-closed connection and timeout (espressif/esp-mqtt@e05d873)
* mqtt_client: fix esp_mqtt_client_enqueue for len=0 (GitHub PR)
  - See merge request espressif/esp-mqtt!135
  - mqtt_client: fix esp_mqtt_client_enqueue for len=0 (espressif/esp-mqtt@69b6493)
* Fix implicit malloc/free inclusion
  - See merge request espressif/esp-mqtt!134
  - See commit https://github.com/espressif/esp-mqtt/commit/9299f54
* feat(mqtt): Optimize mqtt transport list and remove unused transport
  - See merge request espressif/esp-mqtt!131
  - See commit https://github.com/espressif/esp-mqtt/commit/647e0ef
* Fix WSS default port selection through menuconfig.
  - See merge request espressif/esp-mqtt!132
  - - Closes https://github.com/espressif/esp-mqtt/issues/223
  - See commit https://github.com/espressif/esp-mqtt/commit/f6caaff
2022-12-16 08:38:48 +01:00
610db7b934 mqtt: Fix and add mqtt host test to CI 2022-12-16 08:38:48 +01:00
62c5545f2d esp-netif: Make dependency on esp-eth optional
* esp-netif to optionally depend on esp-eth (only for l2tap config)
* esp_eth.h now includes the original ethernet header and the
ethernet-netif glue layer
* Updated examples and test to explicitely use esp-eth dependency if
needed
2022-12-16 08:38:48 +01:00
b80d4d468c tools: Increase the minimal supported CMake version to 3.16
This updates the minimal supported version of CMake to 3.16, which in turn enables us to use more CMake features and have a cleaner build system.
This is the version that provides most new features and also the one we use in our latest docker image for CI.
2022-12-16 08:38:48 +01:00
5539c83c0a mqtt: Fix incorrect reads on error; Update ping processing
* Update submodule: git log --oneline 4874bab35659bd2301e65fd849f6559d7380d4f1..64f88b4412ea6649dbf207a07370c2617160d044

Detailed description of the changes:
* Fix documentation of config struct
  - See merge request espressif/esp-mqtt!129
  - See commit https://github.com/espressif/esp-mqtt/commit/e31834c
* Changes the moment we update keepalive_tick.
  - See merge request espressif/esp-mqtt!127
  - See commit https://github.com/espressif/esp-mqtt/commit/2c2e6f3
* MQTT: Fix signature matching for some integer values
  - See merge request espressif/esp-mqtt!128
  - Closes https://github.com/espressif/esp-idf/issues/8482
  - MQTT: Fix signature matching for integer values (espressif/esp-mqtt@6b794e4)
* Make the mqtt submodule logging tags lower case
  - See merge request espressif/esp-mqtt!122
  - See commit https://github.com/espressif/esp-mqtt/commit/fb3184c

Closes https://github.com/espressif/esp-idf/issues/8482
Closes https://github.com/espressif/esp-idf/issues/8550
2022-12-16 08:38:48 +01:00
0a507f1205 build system: remove lwip from common requirements
lwip was added to common requirements list to provide "sys/socket.h"
header to all components without additional requirements specified.

However, lwip pulls in a lot of dependencies on other components.
This commit removes lwip from common requirements to reduce the number
of components in G1-only apps.

To compensate for this removal, the following changes are made:
- newlib (which is a common requirement) has a public dependency on
  lwip if lwip is present in the build. This ensures that sys/socket.h
  is available as long as lwip component is included into the build.
- lwip is now a public requirement of esp-tls since esp_tls.h includes
  sys/socket.h header.
- lwip is now a public requirement o esp_http_client because
  sys/socket.h is included from esp_http_client.h
- lwip is now a private requirement of esp_wifi for "smartconfig_ack"
- lwip is now a private requirement of mqtt for socket functions
- lwip is now a public requirement of tcp_transport because
  esp_transport_tcp.h includes sys/socket.h header.
- mbedtls checks if lwip component is present in the build. If yes,
  net_sockets.c is added to the build, along with the dependency on
  lwip. Previously lwip was a public requirement of mbedtls
  unconditionally.

system/g1_components test app is updated to reflect the changes

Default public dependencies of a component before and after this
change, except common requirements:

- esp_timer (public dependency of freertos)
- bootloader_support (public dependency of esp_hw_support)
- vfs (public dependency of lwip)
- esp_wifi (public dependency of lwip)
- esp_event (public dependency of esp_wifi)
- esp_netif (public dependency of esp_event)
- esp_eth (public dependency of esp_netif)
- esp_phy (public dependency of esp_wifi)

After:

- esp_timer (public dependency of freertos)
- bootloader_support (public dependency of esp_hw_support)

Altogether, the following components have been always added as
public requirements to all other components, and are not added now
([breaking-change]):

- lwip
- vfs
- esp_wifi
- esp_event
- esp_netif
- esp_eth
- esp_phy

Application components now need to explicitly declare dependencies on
these components.
2022-12-16 08:38:48 +01:00
77e41479d7 components: correct printf() placeholder for time_t
Using C99 %jd, https://en.cppreference.com/w/c/chrono/time_t
2022-12-16 08:38:48 +01:00
a88eaebad9 esp-mqtt: fix warnings 2022-12-16 08:38:48 +01:00
8dc8e5ae0b kconfig: Changed default values of bool configs
- Some bool configs were using default values true and false,
  instead of y and n.
2022-12-16 08:38:48 +01:00
933da9efed Remove legacy system event framework. 2022-12-16 08:38:48 +01:00
a840bcf274 esp_hw_support/esp_system: Re-evaluate header inclusions and include directories
This commit updates the visibility of various header files and cleans up
some unnecessary inclusions. Also, this commit removes certain header
include paths which were maintained for backward compatibility.
2022-12-16 08:38:48 +01:00
fcd548daab freertos: Remove legacy hooks
This commit refactors the legacy hooks as follows:

- Removed CONFIG_FREERTOS_LEGACY_HOOKS
- FreeRTOS hooks are now enabled via:
    - CONFIG_FREERTOS_USE_IDLE_HOOK
    - CONFIG_FREERTOS_USE_TICK_HOOK
- Update IDF hooks documentation
2022-12-16 08:38:48 +01:00
23e5c5a02c esp_eth: Update esp32's EMAC API to decouple driver and vendor config 2022-12-16 08:38:48 +01:00
71d9236275 mqtt: Fix sending log data; dup flag after queue
* Fix sending mqtt message longer than Tx buffer size
* Fix enqueue API to send data with correct dup flag
* Update submodule: git log --oneline b86d42c130ac64a916ce6cf299d99f9756692394..985078affa8a2d2b56b87c8e6455252850f895c6

Detailed description of the changes:
* Isolate IDF env for v4.4 and v5.0(master)
  - See merge request espressif/esp-mqtt!111
  - ci: Isolate IDF env for v4.4 and v5.0(master) (espressif/esp-mqtt@4c5a65c)
* Client: Remove usage of legacy FreeRTOS types
  - See merge request espressif/esp-mqtt!120
  - ci: Fix build issues with IDF-4.4 against master (espressif/esp-mqtt@c28a56d)
  - See commit https://github.com/espressif/esp-mqtt/commit/6ef98d6
* mqtt_client: Fix mqtt send long data error
  - See merge request espressif/esp-mqtt!117
  - Closes https://github.com/espressif/esp-mqtt/issues/214
  - See commit https://github.com/espressif/esp-mqtt/commit/372b323
* Client: Fix use esp_mqtt_client_enqueue API to send data, data dup flag will be set 1
  - See merge request espressif/esp-mqtt!116
  - See commit https://github.com/espressif/esp-mqtt/commit/df8dc92
2022-12-16 08:38:48 +01:00
f8cb9f7286 mqtt: Add docs on MQTT_CUSTOM_OUTBOX implentation
Closes https://github.com/espressif/esp-mqtt/issues/217
2022-12-16 08:38:48 +01:00
47ac29b1e2 mqtt: replace nghttp with http_parser references 2022-12-16 08:38:48 +01:00
174c6781de refactor (test_utils)!: separate file for memory check functions
Memory check (leaks and heap tracing) functions for unit tests
now have a separate file now and are renamed for more consistency.

BREAKING CHANGE: renamed memory check function names which may be used
                 in unit tests outside IDF.
2022-12-16 08:38:48 +01:00
1766fd4d5b MQTT: Fix disconnect/reconnect, Adds empty client id, ...
Updated MQTT submodule: git log --oneline 89894bd0c611b1392967fe90bb49682eba858383...b86d42c130ac64a916ce6cf299d99f9756692394
* Added support for client with empty id
* Fixed user requested disconnect to correctly send MQTT disconnection message
* Fixed reconnection request with disabled autoreconnect
* Added qos and dup flags to data events
* Added Support for suback massage payload in mqtt events

Detailed description of the changes (89894bd0c6...b86d42c130):
* Adds the possibility of client with empty id
    - See merge request esp-mqtt!114
    - esp_mqtt commit 09287a1156
    - esp_mqtt commit 1fd50dd2cb
    - Related IDF-4124
* Client: Disconnect/Reconnect improvements
    - See merge request esp-mqtt!113
    - esp_mqtt commit 3f05b1aedc
    - esp_mqtt commit 86e40f8615
    - Related https://github.com/espressif/esp-mqtt/issues/206
    - Related https://github.com/espressif/esp-mqtt/issues/208
* Events: Support qos/dup flags and suback payload in mqtt events (GitHub PR)
    - See merge request esp-mqtt!112
    - esp_mqtt commit de47f1c341
    - esp_mqtt commit e1d5a9402f
    - Related https://github.com/espressif/esp-mqtt/issues/200
    - Related https://github.com/espressif/esp-mqtt/pull/203
2022-12-16 08:38:48 +01:00
4afe71b132 MQTT: Add more tests 2022-12-16 08:38:48 +01:00
74882b18f0 MQTT: Add more unit tests with actual broker 2022-12-16 08:38:48 +01:00
ff8a93585f freertos: Add portTRY_ENTRY_CRITICAL() and deprecate legacy spinlock fucntions
Add TRY_ENTRY_CRITICAL() API to all for timeouts when entering critical sections.
The following port API were added:
- portTRY_ENTER_CRITICAL()
- portTRY_ENTER_CRITICAL_ISR()
- portTRY_ENTER_CRITICAL_SAFE()

Deprecated legacy spinlock API in favor of spinlock.h. The following API were deprecated:
- vPortCPUInitializeMutex()
- vPortCPUAcquireMutex()
- vPortCPUAcquireMutexTimeout()
- vPortCPUReleaseMutex()

Other Changes:
- Added portMUX_INITIALIZE() to replace vPortCPUInitializeMutex()
- The assembly of the critical section functions ends up being about 50 instructions longer,
  thus the spinlock test pass threshold had to be increased to account for the extra runtime.

Closes https://github.com/espressif/esp-idf/issues/5301
2022-12-16 08:38:48 +01:00
b4474ac16d Build & config: Remove leftover files from the unsupported "make" build system 2022-12-16 08:38:48 +01:00
3c764f0fc1 freertos: update freertos folder structure to match upstream
The following changes have been made:
1. All FreeRTOS kernel source files are now placed in the
   freertos/FreeRTOS-Kernel folder to match with the upstream folder structure.
2. All kernel include files are now placed in freertos/FreeRTOS-Kernel/include.
3. All port files are now placed in freertos/FreeRTOS-Kernel/portable.
4. All additions/customizations are placed in freertos/esp_additions.
5. All other miscellaneous files (README, License files etc.) are moved to
   freertos/FreeRTOS-Kernel folder to match with the upstream.
6. Updated esp-cryptoauthlib to latest commit to resolve FreeRTOS
   include dependencies.

Signed-off-by: Sudeep Mohanty <sudeep.mohanty@espressif.com>
2022-12-16 08:38:48 +01:00
c03353333b MQTT: Fix build if CONFIG_WS_TRANSPORT is not set and client cleanups
Updated MQTT submodule: git log --oneline f10321a53b53a146ee299cfecc320b89c0cf6611...89894bd0c611b1392967fe90bb49682eba858383
* Fix build issue if cert bundle disabled
* Fix build issue if ws transport disabled
* Add config to set retransmission interval

Detailed description of the changes (f10321a53b...89894bd0c6):
* Added config option to configure custom retransmission interval
    - See merge request espressif/esp-mqtt!110
    - esp_mqtt commit 1b009c840b
    - Related https://github.com/espressif/esp-mqtt/pull/199
* Configuration conflicts were verified, logged but not reported to the user.
    - See merge request espressif/esp-mqtt!102
    - esp_mqtt commit 88f4b8ed50
* Fixed build issue if cert bundle disabled
    - See merge request espressif/esp-mqtt!109
    - esp_mqtt commit 4a89bff610
    - esp_mqtt commit 1b71980575
    - esp_mqtt commit 5b3c81ee48
    - Related https://github.com/espressif/esp-mqtt/pull/198
    - Related https://github.com/espressif/esp-idf/issues/7535
* Removes unnecessary outbox_cleanup
    - This function were used on old version to handle QoS 2 messages. It's no longer necessary in current implementation.
    - See merge request espressif/esp-mqtt!108
    - esp_mqtt commit ebef896b00
* Fixed return an error when fail to enqueue
    - The functions that enqueue messages didn't had a return for the handler, with this the error was only logged instead of returned whichmay cause the user to have an ID for a message that was not published.
    - See merge request espressif/esp-mqtt!103
    - esp_mqtt commit 7471177fe7
* CI: Use qemu image based on esp-env:v4.4-1
    - Replaced the temporary qemu image with the official qemu:v4.4-1-20210517 derived from the esp-env:v4.4-1 test environment
    - See merge request espressif/esp-mqtt!107
    - esp_mqtt commit 231b274962

Closes https://github.com/espressif/esp-idf/issues/7535
2022-12-16 08:38:48 +01:00
382caedbbb upgrade freertos version and history 2022-12-16 08:38:48 +01:00
93158d5d18 mqtt: Adds host tests for mqtt client 2022-12-16 08:38:48 +01:00
a8b0f474ec MQTT: Support for certificate bundle; Client clean-up
* Closes https://github.com/espressif/esp-idf/issues/7040
* Merges https://github.com/espressif/esp-idf/pull/7041
* Update submodule: git log --oneline 9fdf7b61385633075d5c3b84803f2dd0578d7869..f10321a53b53a146ee299cfecc320b89c0cf6611

Detailed description of the changes:
* Remove unnecessary parentheses
  - esp-mqtt commit: db13533904
  - esp-mqtt MR: espressif/esp-mqtt!101
* outbox: Cleanup all items when connection closes
  - esp-mqtt commit: 1a94efe8b9
  - esp-mqtt MR: espressif/esp-mqtt!104
* Outbox: Removes unnecessary calls to outbox_set_pending
  - esp-mqtt commit: 36a3990404
  - esp-mqtt MR: espressif/esp-mqtt!105
* MQTT: Makes abort connection function void.
  - esp-mqtt commit: 67553aba45
  - esp-mqtt MR: espressif/esp-mqtt!106
* Client: Removes unused defines
  - esp-mqtt commit: eec6f0e17d
  - esp-mqtt MR: espressif/esp-mqtt!100
  - Closes https://github.com/espressif/esp-mqtt/issues/194
* Config: Added support for certificate bundle
  - esp-mqtt commit: 06157be118
  - esp-mqtt MR: espressif/esp-mqtt!98
  - Closes https://github.com/espressif/esp-mqtt/issues/190
* Config: Adds missing field at config struct (path field)
  - esp-mqtt commit: 5b27d1896e
  - esp-mqtt MR: espressif/esp-mqtt!96
* Client: Add support for partial transport writes
  - esp-mqtt commit: d8c9c7a9e7
  - esp-mqtt MR: espressif/esp-mqtt!99
  - Partially addresses https://github.com/espressif/esp-idf/issues/6940
* Client: Add support for Retain flag in messages posted by events
  - esp-mqtt commit: a00a3134c6
  - esp-mqtt MR: espressif/esp-mqtt!99
  - Closes https://github.com/espressif/esp-mqtt/issues/193
* esp-mqtt: Added nullchecks for public APIs
  - esp-mqtt commit: 2f57985c0b
  - esp-mqtt MR: espressif/esp-mqtt!94
  - Closes https://github.com/espressif/esp-mqtt/issues/185
* esp-mqtt: Reduce the includes used in all files
  - esp-mqtt commit: 87fcce72c9
  - esp-mqtt MR: espressif/esp-mqtt!93
* mqtt_outbox: Use STAILQ_FOREACH for outbox_delete_single_expired
  - esp-mqtt commit: ff8e64839a
  - esp-mqtt MR: espressif/esp-mqtt!97
  - Merges https://github.com/espressif/esp-mqtt/pull/187
* Client: Add optimize for depend on ssl
  - esp-mqtt commit: 8f3cac8c36
  - esp-mqtt MR: espressif/esp-mqtt!95
2022-12-16 08:38:48 +01:00
0fda7d7062 transport: Add CONFI_WS_TRANSPORT for optimize the code size 2022-12-16 08:38:48 +01:00
128be3f402 mqtt: Moved weekend tests to test apps 2022-12-16 08:38:48 +01:00
f2f30baec0 esp-mqtt: Remove __FILE__ macro from error logs 2022-12-16 08:38:48 +01:00
f072c9f753 style: format python files with isort and double-quote-string-fixer 2022-12-16 08:38:48 +01:00
3883bde0b0 ci: Add MQTT publish test to standard test apps 2022-12-16 08:38:48 +01:00
40fdf32793 ci: Extend the MQTT weekend test to check mqtt-enqueue api 2022-12-16 08:38:48 +01:00
2c3363e23a MQTT: Add new config modes (outbox related, incremental id) 2022-12-16 08:38:48 +01:00
6756e62387 MQTT: Update submodule reference to support new config modes
* Queueing publish messages to outbox when the client is not connected (default=off -> messages are queued if disconnected)
* Use of incremental msg-id instead of random id (default=off -> msg-id uses platform_random())
* Posting a new event-id if a queued message gets deleted from the outbox (default=off -> events are not posted)

Detailed description of included `esp-mqtt` changes
(da850b0add1e71b3659bfac5d797cc834dc3e89b...9ea804e0ab5368d5ab53ae2301a5fec9d1f12f1a)
* mqtt: Remove unused mqtt_header_state_t
  - esp-mqtt commit: b7158a4aea
  - esp-mqtt MR: espressif/esp-mqtt!84
  - Merges https://github.com/espressif/esp-mqtt/pull/180
* Cleanup public include dirs
  - esp-mqtt commit: f65d5d05db
  - esp-mqtt MR: espressif/esp-mqtt!85
* Config: Add a new option to use incremental message id
  - esp-mqtt commit: 8bb4a26f46
  - esp-mqtt MR: espressif/esp-mqtt!85
  - Closes https://github.com/espressif/esp-mqtt/issues/176
* Publish: Add new API to enqueue qos>0 messages
  - esp-mqtt commit: dc7fd5c0b1
  - esp-mqtt MR: espressif/esp-mqtt!85
  - Closes https://github.com/espressif/esp-mqtt/issues/155
* Config: Add a new option to disable publishing when disconnected
  - esp-mqtt commit: f44dcb1c26
  - esp-mqtt MR: espressif/esp-mqtt!85
  - Related https://github.com/espressif/esp-mqtt/issues/177
* Events: Add new event to report deleted messages from outbox
  - esp-mqtt commit: 2e35d4d4d5
  - esp-mqtt MR: espressif/esp-mqtt!85
* Publish: Allow for qos=0 messages to be stored using esp_mqtt_client_enqueue()
  - esp-mqtt commit: e2de0f3e3e
  - esp-mqtt MR: espressif/esp-mqtt!85
2022-12-16 08:38:48 +01:00
10bba73d21 MQTT: Update submodule reference: config, error handle, minor fixes
Updates esp-mqtt reference to include fixes below related mainly to:
* configuration update (disable keepalive, network timeout)
* minor fixes (size_t for all sizes, unbalanced lock, api for
  outbox-size)
* extended error handle to include socket's errno

Closes https://github.com/espressif/esp-idf/issues/5906

Config: Added config value to disable keepalive mechanism
esp-mqtt commit: 8562437c8a
Related https://github.com/espressif/esp-mqtt/issues/179

Added esp_mqtt_client_get_outbox_size API
esp-mqtt commit: 0a1d9d0300
Related https://github.com/espressif/esp-mqtt/pull/178

mqtt_outbox: Removed unused retry_count field from outbox_item_t
esp-mqtt commit: 673086e13a

config: Fixed typo for configuring OUTBOX_EXPIRED_TIMEOUT_MS
esp-mqtt commit: 259baaec96

Fixed missing MQTT_API_UNLOCK in esp_mqtt_client_stop error path
esp-mqtt commit: 845c2a3a1e
Related https://github.com/espressif/esp-mqtt/issues/173
Related https://github.com/espressif/esp-mqtt/pull/174

Extended mqtt error handle to capture transport's socket errno (IDF
v4.3+)
esp-mqtt commit: 23c8e1ecf5

Config: Added configuration value to set network timeout
esp-mqtt commit: a03228ac46
Related https://github.com/espressif/esp-mqtt/pull/166

Used size_t for all lengths to allow for other architectures
esp-mqtt commit: b9db8d9020
2022-12-16 08:38:48 +01:00
b342444746 riscv: Add new arch-level component
Changes come from internal branch commit a6723fc
2022-12-16 08:38:48 +01:00
5facf78673 MQTT: Restore default MQTT_OUTBOX_EXPIRED_TIMEOUT_MS to 30 sec
The OUTBOX_EXPIRED_TIMEOUT_MS was 30*1000 in original esp-mqtt code.
Don't change the default OUTBOX_EXPIRED_TIMEOUT_MS without good reason,
which may has impact on memory usage for existing applications.

Fixes: e931168ed695 ("MQTT: add configurable msg expired timeout")
Signed-off-by: Axel Lin <axel.lin@gmail.com>
2022-12-16 08:38:48 +01:00
6c55757f70 Whitespace: Automated whitespace fixes (large commit)
Apply the pre-commit hook whitespace fixes to all files in the repo.

(Line endings, blank lines at end of file, trailing whitespace)
2022-12-16 08:38:48 +01:00
87d698cbc7 cmock: added cmock as component
* changing dependencies from unity->cmock
* added component.mk and Makefile.projbuild
* ignore test dir in gen_esp_err_to_name.py
* added some brief introduction of CMock in IDF
2022-12-16 08:38:48 +01:00
25b661c8ea MQTT: add configurable msg expired timeout 2022-12-16 08:38:48 +01:00
8b3d3db10b MQTT: Update submodule reference
SSL: add config option for skipping common name check
esp-mqtt commit: 5e8950e681)
Closes https://github.com/espressif/esp-mqtt/issues/158

SSL: add support for tls with secure element (ATECC608A)
esp-mqtt commit: a7ff9afa3f)
Closes https://github.com/espressif/esp-mqtt/issues/156

Websocket: Allow the query part of the uri to be a part of the path
esp-mqtt commit: 40b06deb10)
Closes https://github.com/espressif/esp-mqtt/issues/161

Config: Add check for consistency between config settings
esp-mqtt commit: 8a412c147d)

Add IDF version check for secure element feature
esp-mqtt commit: db4bce01ab)

Fix esp_mqtt_client_stop deadlock
esp-mqtt commit: 5e17dcaeb2)
Closes https://github.com/espressif/esp-mqtt/issues/163

Add dispatch error event for read errors
esp-mqtt commit: d4aaec08ff
Closes https://github.com/espressif/esp-idf/issues/5704

Cleanup expired messages when offline
esp-mqtt commit: bdadd77c6e
Closes https://github.com/espressif/esp-idf/issues/5668

esp_mqtt_client_publish now returns msg id for QoS > 0 when offline
esp-mqtt commit: f7325bfa10

Add support for Digital Signature through ESP-TLS
esp-mqtt commit: 7d8e59de00
2022-12-16 08:38:48 +01:00
691e7bca88 mqtt: clenaup logs and docs
esp_mqtt: Change an error print to use ESP_LOGE instead of ESP_LOGI
Move Sending MQTT connect message log from Info to Debug level
docs: Makes clear that publish API could block
Change the message printed after MQTT connection failure

Closes https://github.com/espressif/esp-idf/issues/5077
(by means of referencing commit 615aeae0c2)
2022-12-16 08:38:48 +01:00
9b79fe3d00 esp_mqtt_abort_connection: Fixed an issue which could result in a race condition and subsequent crash 2022-12-16 08:38:48 +01:00
cb782cae1e mqtt-tests: rename tests to match the actual group 2022-12-16 08:38:48 +01:00
9db10b5b7b mqtt: reenable outbox unit tests for esp32s2 2022-12-16 08:38:48 +01:00
29ce3c5869 esp_mqtt: add option to configure mqtt task priority.
Merges https://github.com/espressif/esp-idf/pull/4947
2022-12-16 08:38:48 +01:00
605352c1c5 MQTT: Reference latest mqtt addressing c++ build and qos1/2 resend
Closes https://github.com/espressif/esp-idf/issues/4787
2022-12-16 08:38:48 +01:00
5ba36d511f ci: disable failed cases for s2 temporarily 2022-12-16 08:38:48 +01:00
650328b021 mqtt: example test to check connection with different ssl parameters 2022-12-16 08:38:48 +01:00
5be3f7b5d4 mqtt: add basic set of unit tests 2022-12-16 08:38:48 +01:00
0178bafba8 mqtt: update submodule to point to latest commit.
Adds bugfixes for:
 - Too early publishing
 - Potential mutex memory leak
 - CI related issues.
 - Wait for entire connack message
 - Event loop not getting cleaned up

Adds support for ALPN, configurable reconnect time, QEMU CI tests and password
protected client key.

MQTT MR: https://gitlab.espressif.cn:6688/espressif/esp-mqtt/merge_requests/46
Closes IDF-1162
Closes https://github.com/espressif/esp-mqtt/issues/137

MQTT MR: https://gitlab.espressif.cn:6688/espressif/esp-mqtt/merge_requests/47
Closes IDF-1126

MQTT MR: https://gitlab.espressif.cn:6688/espressif/esp-mqtt/merge_requests/48
Closes IDFGH-2197
Closes https://github.com/espressif/esp-idf/issues/4349
Closes https://github.com/espressif/esp-mqtt/issues/140

MQTT MR: https://gitlab.espressif.cn:6688/espressif/esp-mqtt/merge_requests/48
Closes IDFGH-2235
Closes https://github.com/espressif/esp-idf/issues/4384

MQTT MR: https://gitlab.espressif.cn:6688/espressif/esp-mqtt/merge_requests/49
Closes https://github.com/espressif/esp-idf/issues/4433
Closes IDFGH-2293

MQTT MR: https://gitlab.espressif.cn:6688/espressif/esp-mqtt/merge_requests/50
Closes FCS-254

MQTT MR: https://gitlab.espressif.cn:6688/espressif/esp-mqtt/merge_requests/53
Closes FCS-267
2022-12-16 08:38:48 +01:00
8a24bebbc0 ci: updated mqtt weekend test for qemu support
Added default sdkconfig for qemu build for the mqtt publish example,
Added environment configuration for running the same test on target
or in qemu
Updated missing example tests per latest ttfw refactoring
2022-12-16 08:38:48 +01:00
62f3dc4705 mqtt: updated to latest version to include latest fixes, support for global CA store, extended error structure to receive mqtt specific errors. updated idf ssl example to use this error struct
https://github.com/espressif/esp-mqtt/issues/135
2022-12-16 08:38:48 +01:00
6cadfe519b MQTT: update default broker URL for examples
The MQTT broker URL used as default in the examples has ceased operation. All examples and documention have been updated to point to the new domain mqtt.eclipse.org.
This also required an update of the python example test scripts to use TLS 1.2
2022-12-16 08:38:48 +01:00
37e511bef1 ci: fix weekend test confguration update per latest refactoring of
grouping tests
2022-12-16 08:38:48 +01:00
b4ba09ce38 esp_wifi: wifi support new event mechanism
1. WiFi support new event mechanism
2. Update examples to use new event mechanism
2022-12-16 08:38:48 +01:00
25f423d69b ci: limit example test to ESP32s 2022-12-16 08:38:48 +01:00
5a50fc0812 esp_tls: enable psk verification mode, added mqtt example using psk authentication 2022-12-16 08:38:48 +01:00
bef4fce9c1 mqtt: referenced esp-mqtt master to close disconnection issues and fix static analysis warnings
closes https://github.com/espressif/esp-idf/issues/3619 including mqtt commit 7223302deb
closes https://github.com/espressif/esp-idf/issues/3215 including mqtt commit caf5007b99
2022-12-16 08:38:48 +01:00
49296d851d esp-tls: extending error handle to contain error descriptors with last mbedtls failure and latest certificate verification result flags, reworked tcp_transport to use this error handle 2022-12-16 08:38:48 +01:00
a903e5e3a9 esp-tls: capturing specific errors to be available in tcp_transport and then in application code 2022-12-16 08:38:48 +01:00
63b3f29ffc components: use new component registration api 2022-12-16 08:38:48 +01:00
332fadfea6 esp_websocket_client: Add websocket client component
Closes https://github.com/espressif/esp-idf/issues/2829
2022-12-16 08:38:48 +01:00
3a2e82ec0f mqtt: added support for esp event loop, updating examples to register and use event loop handler 2022-12-16 08:38:48 +01:00
7f77ad063d mqtt_tests: add weekend test for sending and receiving empty payload messages, update config options per new naming convetions 2022-12-16 08:38:48 +01:00
6809fcb2df tcp_transport: modified ws_read to read payload directly to the read buffer and separately from header bytes
Previous version read all data to the buffer including header which reduced maximum payload read. This version uses a local array to receive header and reads payload bytes to the buffer
2022-12-16 08:38:48 +01:00
6b70e14236 mqtt tests: adding weekend test for mqtt library to exercise publishing/receiving different data and references esp-mqtt commits to pass these tests
testing conditions:
transports (tcp, ssl, ws..)
qos (0, 1, 2)
short repeated messages (packed packets)
oversized messages (fragmented packets)
publish from a different thread

Closes https://github.com/espressif/esp-idf/issues/2870 by means of including commit 815623dfe5 from esp-mqtt
Closes https://github.com/espressif/esp-idf/issues/2975 by means of including commit 752953dc3b from esp-mqtt
Closes https://github.com/espressif/esp-idf/issues/2850 by means of including commits df455d2a5f 17fd713bce from esp-mqtt
2022-12-16 08:38:48 +01:00
e19b9aa2df separate rom from esp32 component to esp_rom
1. separate rom include files and linkscript to esp_rom
2. modefiy "include rom/xxx.h" to "include esp32/rom/xxx.h"
3. Forward compatible
4. update mqtt
2022-12-16 08:38:48 +01:00
9726859fa3 Correct Kconfigs according to the coding style 2022-12-16 08:38:48 +01:00
7437dce403 mqtt: support for BEFORE_CONNECT event in idf
Updated examples to use new event id, idf to use mqtt with fixed retained, oversized messages
2022-12-16 08:38:48 +01:00
60e39865e6 mqtt: ssl mutual authentication example added per PR from github, corrected cmake build, updated per idf style
Merges https://github.com/espressif/esp-idf/pull/2490
2022-12-16 08:38:48 +01:00
14e9df14ff tcp_transport: Remove the ignore warning because we had idf/esp-idf!3359 2022-12-16 08:38:48 +01:00
a31ede754f tcp_transport: transport set handle refactoring, web socket client name updated 2022-12-16 08:38:48 +01:00
229167f48a tcp_transport: renamed possibly generic function names to be esp_ prefixed and not to colide with user namespace 2022-12-16 08:38:48 +01:00
71d6861d6a tcp_transport: renamed transport related header files to esp_ prefixed to avoid collisions
tcp_transport component used public header files such as 'transport.h', etc. which are too generic and might collide with user or user libraries headers
This change closes #2417
2022-12-16 08:38:48 +01:00
78233fe7de doc: Re-add summaries of what children each menu item has
Slightly different to the original version of this, but same goal.
2022-12-16 08:38:48 +01:00
1d49ac3249 mqtt: silence a format warning 2022-12-16 08:38:48 +01:00
20dda12b88 mqtt: list files manually in component cmake file 2022-12-16 08:38:48 +01:00
24b656ca4b MQTT: Moved Kconfig from esp-mqtt submodule to esp-idf to support docs genration in RTD 2022-12-16 08:38:48 +01:00
c5069977a4 MQTT: Integrate esp-mqtt library into idf
added docs and tests for mqtt library, small fixes (removed warnings, option for custom outbox, websocket bug fixed for longer transports). refactored to use common tcp_transport component, support for CMake build system.
Closes #2108
2022-12-16 08:38:48 +01:00
f80772b8d7 Bugfix: Remove Remove possible null pointer dereferences
- Removed a possible derefrence on data in case of MQTT5 SUBACK with
  MQTT5 disabled.
- Covered a case of NULL data on message with negative size.
- Use correct type on calloc for alpn_protos
- Changed strcasecmp to strncasecmp.
2022-12-15 13:02:46 +01:00
d5a2c0a7c6 Merge branch 'bugfix/subscribe_error_detection' into 'master'
Fix error code verification on SUBSCRIBE error

See merge request espressif/esp-mqtt!155
2022-12-15 18:59:01 +08:00
d1f6ad23b7 Fix error code verification on SUBSCRIBE error
- Return codes other than 0x1, 0x2, 0x3 and 0x80 are reserved and
  forbidden by the specification.
2022-12-05 15:22:48 +01:00
fde00340f1 Merge branch 'bugfix/event_queue_disabled_deafult' into 'master'
Fix the default configuration for event queue

See merge request espressif/esp-mqtt!153
2022-11-23 22:17:25 +08:00
fb42588a03 Fix the default configuration for event queue
- Event queue should be disabled, making it an opt-in feature.
2022-11-23 20:40:31 +08:00
3e0a118e0b Merge branch 'bugfix/missing_header' into 'master'
Adds missing header.

See merge request espressif/esp-mqtt!152
2022-11-04 00:26:54 +08:00
8a6005781d Adds missing header.
- esp_heap_caps is directly needed and wasn't included.
- For target it's indirecly included but for host test it's needed.
2022-11-03 15:26:43 +01:00
e80f3e6a87 Merge branch 'bugfix/stop_in_wait_reconnection' into 'master'
Moves state change when stopping the client

See merge request espressif/esp-mqtt!150
2022-10-26 21:19:00 +08:00
3738fcd196 Moves state change when stopping the client
- In some situations client could be left in a state where it's
  impossible to restart due to a state change while waiting for the
  stop. This guarantee that it's possible to start after calling stop.

Closes https://github.com/espressif/esp-mqtt/issues/239
2022-10-26 14:37:28 +02:00
5f297c0d62 Merge branch 'bugfix/set_error_on_subscribe_failure' into 'master'
Adds error code to MQTT_EVENT_SUBSCRIBED in case of failure

See merge request espressif/esp-mqtt!143
2022-10-21 23:46:02 +08:00
9af5c26045 Adds error code to MQTT_EVENT_SUBSCRIBED in case of failure
- Payload data parsed for error codes. Check only for first filter
  because our subscribe function only handle one topic filter in each
  call.

- Closes https://github.com/espressif/esp-mqtt/issues/233
2022-10-20 13:29:16 +02:00
2b52b50a6b Merge branch 'feature/debug_retry' into 'master'
Adds debug information on sending dup messages

See merge request espressif/esp-mqtt!145
2022-10-04 13:15:50 +08:00
47b3f9b899 Adds debug information on sending dup messages
- To support debug of resending dup messages QoS 1 and 2 a debug
  log was added.
2022-10-03 07:43:01 +00:00
a87fd9c738 Merge branch 'bugfix/ci_qemu' into 'master'
ci: Fix qemu build

See merge request espressif/esp-mqtt!147
2022-09-30 22:44:15 +08:00
68e8c4f829 ci: Fix qemu build 2022-09-30 16:14:36 +02:00
5688a84cbc Merge branch 'bugfix/extend_ci_idf_v5.1' into 'master'
ci: Build and Test QEMU on v5.0

See merge request espressif/esp-mqtt!142
2022-08-19 23:45:43 +08:00
9db9ee7648 ci: Build and Test QEMU on v5.0
* Patch the QEMU build
* Use public containers for build only tests on v5.0 and master
2022-08-18 16:51:16 +02:00
5f3cadb44d Merge branch 'bugfix/user_events' into 'master'
client: Add support for user events

See merge request espressif/esp-mqtt!140
2022-08-16 21:30:58 +08:00
97503cceb3 client: Add support for user events
Also supporting configurable queue size for the internal event loop.

Closes https://github.com/espressif/esp-mqtt/issues/230
2022-07-29 09:08:52 +02:00
9186e5fa00 Merge branch 'feature/unregister_event_api' into 'master'
Adds unregister event API

See merge request espressif/esp-mqtt!139
2022-07-28 21:07:25 +08:00
a9a9fe76bf Adds unregister event API
- Added to enable users to unregister event handler.

 Closes https://github.com/espressif/esp-idf/issues/9194
2022-07-28 10:36:24 +00:00
f14eeb9157 Merge branch 'feature/mqtt_config_struct_review' into 'master'
Restructure the client configuration struct

See merge request espressif/esp-mqtt!130
2022-07-20 18:40:24 +08:00
ae53d799da Restructure the client configuration struct
- Groups configuration fields by context.
- Removes user_context in favor of the event loop.
2022-07-13 08:37:20 -03:00
9a56b2f086 Merge branch 'bugfix/ping_timer_restart' into 'master'
MQTT tick not starting on connect and switch to esp_timer

See merge request espressif/esp-mqtt!138
2022-07-05 20:09:11 +08:00
89e5c6014f fix: MQTT tick not starting on connect and switch to esp_timer
- Tick should be updated on connect
- Dependency of system timer removed to avoid issues when updating via
  SNTP

Closes https://github.com/espressif/esp-mqtt/issues/225
2022-06-23 12:43:58 -03:00
493822dc9d Merge branch 'feature/support_mqtt_5' into 'master'
mqtt: Support MQTT5 protocol

See merge request espressif/esp-mqtt!125
2022-06-14 21:40:57 +08:00
fdf2aeb36f Seperate MQTT5 from MQTT 3.1.1 2022-06-14 09:37:46 +00:00
3d275f42b9 mqtt: Support MQTT5 protocol 2022-06-14 09:37:46 +00:00
0aa0a342a1 Merge branch 'bugfix/mqtt_ssl_build' into 'master'
mqtt_tcp: Fix build issue when `MQTT_ENABLE_SSL` is disabled

See merge request espressif/esp-mqtt!137
2022-06-14 17:31:41 +08:00
7253211a45 mqtt_tcp: Fix build issue when MQTT_SSL is disabled 2022-06-14 13:43:45 +05:30
a21c387d62 Merge branch 'refactor/tcp_transport' into 'master'
mqtt_client: Added checks for cleanly-closed connection and timeout

See merge request espressif/esp-mqtt!118
2022-06-09 15:20:24 +08:00
7a31a555e9 Merge branch 'bugfix/fix_esp_mqtt_client_enqueue' into 'master'
mqtt_client: fix esp_mqtt_client_enqueue for len=0 (GitHub PR)

See merge request espressif/esp-mqtt!135
2022-06-08 19:33:38 +08:00
16952ea66f Merge branch 'bugfix/implicit_malloc_host_test' into 'master'
Fix implicit malloc/free inclusion

See merge request espressif/esp-mqtt!134
2022-06-08 18:52:04 +08:00
e05d873aa2 Added checks for cleanly-closed connection and timeout
- Related MR: https://gitlab.espressif.cn:6688/espressif/esp-idf/-/merge_requests/16394
2022-06-08 16:12:11 +05:30
9299f5400f Fix implicit malloc/free inclusion
This fails when building on host
2022-06-08 05:16:29 +00:00
69b6493423 mqtt_client: fix esp_mqtt_client_enqueue for len=0
Commit 372b323 (mqtt_client: Fix mqtt send long data error, 2021-12-21)
removed the length calculation from esp_mqtt_client_enqueue_priv and
added it to esp_mqtt_client_publish. However, esp_mqtt_client_enqueue
was missed. Currently calls to esp_mqtt_client_enqueue appear to send no
data, fix this by adding the length calculation to esp_mqtt_client_enqueue.
2022-05-30 21:56:33 +01:00
7f765cac2c Merge branch 'feature/optimize_mqtt_transport_list' into 'master'
feat(mqtt): Optimize mqtt transport list and remove unused transport

See merge request espressif/esp-mqtt!131
2022-05-23 22:19:24 +08:00
647e0eff32 feat(mqtt): Optimize mqtt transport list and remove unused transport 2022-05-23 22:19:24 +08:00
684843a309 Merge branch 'bugfix/wrong_wss_port_definition' into 'master'
Fix WSS default port selection through menuconfig.

See merge request espressif/esp-mqtt!132
2022-05-17 15:43:37 +08:00
f6caaff254 Fix WSS default port selection through menuconfig.
Evaluate the correct define to select default port.

 - Closes https://github.com/espressif/esp-mqtt/issues/223
2022-05-17 07:16:07 +00:00
64f88b4412 Merge branch 'bugfix/fix_transport_config_documentation' into 'master'
Fix documentation of config struct

See merge request espressif/esp-mqtt!129
2022-05-03 20:09:10 +08:00
e31834c00f Fix documentation of config struct
- Transport selection enum was incorrectly pointed as having precedence
  over URI.

- Added names to unnamed enums and structs on typedefs.

- Reorganize config struct fields grouping fields with related context.
2022-05-02 13:29:39 -03:00
59b48a4d49 Merge branch 'bugfix/keep_alive_ping_periodic' into 'master'
Changes the moment we update keepalive_tick.

See merge request espressif/esp-mqtt!127
2022-04-19 22:16:19 +08:00
2cdcdcb4fa Merge branch 'bugfix/mqtt_fix_int_sign_mismatch' into 'master'
MQTT: Fix signature matching for some integer values

See merge request espressif/esp-mqtt!128
2022-04-12 19:35:51 +08:00
6b794e4708 MQTT: Fix signature matching for integer values
Closes https://github.com/espressif/esp-idf/issues/8482
2022-04-08 19:56:56 +04:00
2c2e6f38b5 Changes the moment we update keepalive_tick.
In order to keep sending keep alive messages in the scenario were client
publish too often with QoS0 the keepalive is updated when the response
is received.
2022-04-07 09:14:03 -03:00
5878e2e8a6 Merge branch 'module_logging_tag_lower_case' into 'master'
Make the mqtt submodule logging tags lower case

See merge request espressif/esp-mqtt!122
2022-04-04 18:54:43 +08:00
fb3184cc14 Make the mqtt submodule logging tags lower case 2022-04-04 10:33:06 +02:00
4874bab356 Merge branch 'bugfix/unused_var' into 'master'
remove unused variable

See merge request espressif/esp-mqtt!124
2022-03-04 18:59:54 +08:00
f83d2a9111 remove unused variable 2022-03-04 07:42:25 +00:00
d3d816ed24 Merge branch 'bugfix/ci_update_for_passing' into 'master'
ci: update images to pass jobs with current IDF

See merge request espressif/esp-mqtt!126
2022-03-04 15:41:24 +08:00
2e508fa6ef ci: update images to pass jobs with current IDF 2022-03-04 11:36:04 +07:00
08ce9ed83f Merge branch 'test/ci_qemu_master' into 'master'
CI: Fix idf-env for build and test against IDFv5.0

See merge request espressif/esp-mqtt!121
2022-02-07 09:03:12 +00:00
b66b9745f6 reduce sizes and message counts for QEMU publish test 2022-02-03 10:39:27 +01:00
3a5334de6b ci: Test with QEMU against the latest IDF 2022-02-03 10:39:19 +01:00
0eda78e9b7 Merge branch 'feature/include_alternative_for_esp_system' into 'master'
Replaced esp_system.h inclusion with esp_random.h and esp_mac.h

See merge request espressif/esp-mqtt!119
2022-01-28 07:21:01 +00:00
b7b858cd7f ci: Run tests against IDF v5.0 only
* Supported build only test with ci-evn-5.0
* Disable temporarily publish-connect test on QEMU with qemu-v5.0:1-20210826
2022-01-28 08:09:27 +01:00
1a96ea3efa Replaced esp_system.h inclusion with esp_random.h and esp_mac.h
Signed-off-by: Sudeep Mohanty <sudeep.mohanty@espressif.com>
2022-01-17 15:33:11 +01:00
985078affa Merge branch 'bugfix/ci_image_update' into 'master'
Isolate IDF env for v4.4 and v5.0(master)

See merge request espressif/esp-mqtt!111
2022-01-17 14:00:56 +00:00
4c5a65c79e ci: Isolate IDF env for v4.4 and v5.0(master) 2022-01-17 13:55:06 +01:00
b021fc8e30 Merge branch 'bugfix/remove_legacy_freertos_types_usage' into 'master'
Client: Remove usage of legacy FreeRTOS types

See merge request espressif/esp-mqtt!120
2022-01-17 11:32:20 +00:00
c28a56ddb0 ci: Fix build issues with IDF-4.4 against master
IDF env docker image (v4.4-1) became incompatible with IDF master (v5.0)
2022-01-17 10:22:27 +01:00
6ef98d6510 Client: Remove usage of legacy FreeRTOS types 2022-01-13 00:34:53 +08:00
026253d802 Merge branch 'bugfix/fix_mqtt_send_long_data_error' into 'master'
mqtt_client: Fix mqtt send long data error

See merge request espressif/esp-mqtt!117
2021-12-22 02:15:33 +00:00
372b323535 mqtt_client: Fix mqtt send long data error
Closes https://github.com/espressif/esp-mqtt/issues/214
2021-12-21 15:31:56 +08:00
383e7e5f0f Merge branch 'bugfix/fix_enqueue_api' into 'master'
Client: Fix use esp_mqtt_client_enqueue API to send data, data dup flag will be set 1

See merge request espressif/esp-mqtt!116
2021-12-06 12:01:07 +00:00
df8dc92870 Client: Fix use esp_mqtt_client_enqueue API to send data, data dup flag will be set 1 2021-11-26 15:52:04 +08:00
b86d42c130 Merge branch 'feature/mqtt_client_with_null_id' into 'master'
Adds the possibilty of client with empty id

See merge request espressif/esp-mqtt!114
2021-11-03 09:58:39 +00:00
08c4d62bf4 CI: Fix standard gitlab key 2021-11-03 09:30:08 +01:00
09287a1156 Removes redundant field on mqtt state
Client connection_info was unnecessarilly repeated. Removed from
mqtt_state and kept on mqtt_client.
2021-11-01 18:17:29 +01:00
1fd50dd2cb Adds a config flag to allow an empty client id
This commit covers a use case where the user can select to send an
empty user id.
2021-11-01 18:17:29 +01:00
36de30e46d Merge branch 'bugfix/send_diconnect_msg' into 'master'
Client: Disconnect/Reconnect improvements

See merge request espressif/esp-mqtt!113
2021-10-21 08:34:15 +00:00
320b058e28 CI: Adjust jobs for testing IDFs, cleanup
Removes CI jobs for static analysis and reports as they are not primarily used
2021-10-21 08:39:59 +02:00
3f05b1aedc Client: Fix reconnect/disconnect if auto_reconnect=off
Closes https://github.com/espressif/esp-mqtt/issues/206
2021-10-06 17:46:32 +02:00
86e40f8615 Send disconnect message if client asked to disconnect
https://github.com/espressif/esp-mqtt/issues/208
2021-10-06 17:46:32 +02:00
5ec3702881 Merge branch 'feature/add_suback_payload_flags_to_events' into 'master'
Events: Support qos/dup flags and suback payload in mqtt events (GitHub PR)

See merge request espressif/esp-mqtt!112
2021-10-04 10:53:17 +00:00
de47f1c341 add payload to MQTT_EVENT_SUBSCRIBE
+ documentation
+ cleanup logging

Closes https://github.com/espressif/esp-mqtt/issues/200
Merges https://github.com/espressif/esp-mqtt/pull/203
2021-10-04 10:38:02 +02:00
e1d5a9402f add qos and dup to MQTT_EVENT_DATA 2021-09-23 18:09:39 +02:00
89894bd0c6 Merge branch 'feature/configurable_retransmit' into 'master'
Add configurable retransmit (GitHub PR)

See merge request espressif/esp-mqtt!110
2021-09-15 18:10:50 +00:00
1d10608409 Merge branch 'feature/set_config_error_reporting' into 'master'
Reports config conflicts error to the user

See merge request espressif/esp-mqtt!102
2021-09-15 16:46:35 +00:00
d7b00da517 Merge branch 'bugfix/mqtt_check_certbundle' into 'master'
Fix build issue if cert bundle disabled (GitHub PR)

See merge request espressif/esp-mqtt!109
2021-09-15 16:46:13 +00:00
1b009c840b Config: Add configurable retransmit timeout
sometime user want to configure retransmit timeout due to network or other requirement

Merges https://github.com/espressif/esp-mqtt/pull/199
2021-09-15 18:43:23 +02:00
88f4b8ed50 Reports config conflicts error to the user
- Configuration conflicts were verified, logged but not reported to the
  user.
2021-09-15 15:09:23 +08:00
5b3c81ee48 Config: Fix build issue if WS/WSS transport disabled
Closes https://github.com/espressif/esp-idf/issues/7535
2021-09-10 09:15:41 +02:00
1b71980575 Config: Add error message if certbunde is not enabled
Merges https://github.com/espressif/esp-mqtt/pull/198
2021-09-07 15:42:11 +02:00
4a89bff610 Check CONFIG_MBEDTLS_CERTIFICATE_BUNDLE is set
Fixes a compilation error where `esp_transport_ssl_crt_bundle_attach` is undefined in this scenario.
2021-08-10 15:02:35 -06:00
026ea95338 Merge branch 'remove_outbox_cleanup_function' into 'master'
Removes unnecessary outbox_cleanup

See merge request espressif/esp-mqtt!108
2021-07-09 16:13:48 +00:00
c11c314f44 Merge branch 'bugfix/report_enqueue_error' into 'master'
Fix: Return an error when fail to enqueue

See merge request espressif/esp-mqtt!103
2021-07-09 16:12:55 +00:00
ebef896b00 Removes unnecessary outbox_cleanup
The states that were cleaned by this function, CONFIRMED, are no longer reachable.
Itens were marked with this status previously in PUBCOMP and PUBREL
receive handlers.
2021-07-01 14:40:45 +01:00
7471177fe7 Fix: Return an error when fail to enqueue
The functions that enqueue messages didn't had a return for the
handler, with this the error was only logged instead of returned which
may cause the user to have an ID for a message that was not published.
2021-07-01 09:29:58 +01:00
e24852a4dc Merge branch 'bugfix/qemu_image_esp_env' into 'master'
CI: Use qemu image based on esp-env:v4.4-1

See merge request espressif/esp-mqtt!107
2021-06-28 08:16:56 +00:00
231b274962 CI: Use qemu image based on esp-env:v4.4-1 2021-06-28 08:15:10 +02:00
f10321a53b Merge branch 'bugfix/remove_unnecessary_parenteses' into 'master'
Remove unnecessary parentheses.

See merge request espressif/esp-mqtt!101
2021-06-24 17:22:30 +00:00
db13533904 Remove unnecessary parentheses.
- Removed extra parentheses on definition of certificate bundle attach.
2021-06-24 18:35:26 +02:00
831d25cb56 Merge branch 'update/qemu_test_IDFv4.3' into 'master'
CI: Update QEMU image and test against IDF v4.4-dev (plus minor fixes)

See merge request espressif/esp-mqtt!104
2021-06-24 16:34:31 +00:00
a7e5accc7e CI: Temporariy update QEMU image with python 3.7.0
This will be removed once we updated QEMU image, based on the new CI
environment docker image.
2021-06-24 16:34:22 +02:00
90f0bf8dd4 Updated docker images to work with latest IDFv4.4 2021-06-24 07:40:43 +02:00
1a94efe8b9 outbox: Cleanup all items when connection closes 2021-06-24 06:31:29 +02:00
c4b7324bd6 Merge branch 'feature/remove_unnecessary_queue_requests' into 'master'
Removes unnecessary calls to outbox_set_pending

See merge request espressif/esp-mqtt!105
2021-06-23 06:46:06 +00:00
a4d5ee0f12 Merge branch 'feature/make_abort_connection_void' into 'master'
MQTT: Makes abort connection function void.

See merge request espressif/esp-mqtt!106
2021-06-23 06:45:15 +00:00
67553aba45 MQTT: Makes abort connection function void.
The function only returned ESP_OK and the call was always ignored.
2021-06-18 17:18:51 +01:00
36a3990404 Removes unnecessary calls to outbox_set_pending
The call of this function is unnecessary for PUBACK and PUBCOMP,
also the item is deleted on the call of is_valid_mqtt_msg and the
function allways fail.
2021-06-18 14:11:21 +01:00
2e15c9a5fe Fix IDF supported features: cert-bundle from v4.4 2021-06-17 12:33:34 +02:00
626dc3645b CI: Add build test for IDF v4.3 2021-06-17 12:33:34 +02:00
c7ae67b7f0 CI: Update QEMU image and test against IDF master(v4.4-dev)
Also using test-apps instead of weekend tests.
2021-06-17 12:33:18 +02:00
afba070093 Merge branch 'bugfix/remove_unused_defines' into 'master'
Removes unused defines.

See merge request espressif/esp-mqtt!100
2021-06-01 05:32:40 +00:00
eec6f0e17d Removes unused defines.
- mqtt_config.h had some defines that were not used. This removes them.

Closes https://github.com/espressif/esp-mqtt/issues/194
2021-05-31 13:29:25 +01:00
78fcf23947 Merge branch 'bugfix/partial_transport_writes' into 'master'
Address partial writes and retain flags

See merge request espressif/esp-mqtt!99
2021-05-26 15:56:08 +00:00
048f12f55f Merge branch 'feature/add_crt_bundle' into 'master'
Added support for certificate bundle

See merge request espressif/esp-mqtt!98
2021-05-26 15:54:21 +00:00
ff8226a464 Merge branch 'bugfix/missing_path_field_in_config' into 'master'
Fix: Adds missing field at config struct.

See merge request espressif/esp-mqtt!96
2021-05-26 15:51:45 +00:00
7db36f9177 Merge branch 'feature/mqtt_ssl_optimize' into 'master'
esp-mqtt: Add configure to separate code for depend on ssl

See merge request espressif/esp-mqtt!95
2021-05-26 15:51:15 +00:00
8f3cac8c36 Client: Add optimize for depend on ssl 2021-05-24 16:14:02 +02:00
d8c9c7a9e7 Add support for partial transport writes
Partially addresses https://github.com/espressif/esp-idf/issues/6940
2021-05-24 10:58:42 +02:00
a00a3134c6 Add support for Retain flag in messages posted by events
Closes https://github.com/espressif/esp-mqtt/issues/193
2021-05-24 10:57:37 +02:00
06157be118 Add crt_bundle function pointer to be accessible from esp_mqtt_client_config_t 2021-05-24 10:32:10 +02:00
e1a90d0161 Merge branch 'bugfix/outbox_del_single_STAILQ_FOREACH' into 'master'
mqtt_outbox: Use STAILQ_FOREACH for outbox_delete_single_expired

See merge request espressif/esp-mqtt!97
2021-05-22 06:01:35 +00:00
5b27d1896e Fix: Adds missing field at config struct.
If an user chooses to config broker by hostname it wasn't possible to
 add the path.
2021-05-14 15:57:42 +01:00
ff8e64839a mqtt_outbox: Use STAILQ_FOREACH for outbox_delete_single_expired
For the delete one entry and return case, no need to use STAILQ_FOREACH_SAFE.

Signed-off-by: Axel Lin <axel.lin@ingics.com>
2021-04-20 11:27:42 +08:00
1db731f985 Merge branch 'feature/mqtt_unit_test_cleanup' into 'master'
Reduce the includes used in files.

See merge request espressif/esp-mqtt!93
2021-04-07 11:37:00 +00:00
87fcce72c9 Reduce the includes used in all files.
- To reduce the dependencies to the minimal the number of includes was
  reduced.
2021-04-07 10:49:49 +01:00
2b20b5117c Merge branch 'bugfix/mqtt_add_null_check' into 'master'
esp-mqtt: Add null checks for public APIs

See merge request espressif/esp-mqtt!94
2021-03-10 17:59:17 +00:00
2f57985c0b esp-mqtt: Added nullchecks for public APIs
Closes IDFGH-4724
Closes https://github.com/espressif/esp-mqtt/issues/185
2021-03-04 18:30:27 +04:00
9fdf7b6138 Merge branch 'bugfix/disable_file_in_logs' into 'master'
platform: Remove __FILE__ macro from error logs

See merge request espressif/esp-mqtt!92
2021-02-23 17:07:26 +00:00
169b6986eb platform: Remove __FILE__ macro from error logs 2021-02-22 18:11:41 +01:00
fd2d04e687 Merge branch 'bugfix/vs_nullcheck_on_malloc' into 'master'
Config: Add missing nullcheck after cfg password allocation

See merge request espressif/esp-mqtt!91
2021-02-11 23:39:32 +08:00
001dc1a95e Config: Add missing nullcheck after cfg password allocation
Partially addresses https://github.com/espressif/esp-idf/issues/6440
2021-02-11 15:54:45 +01:00
a5a60752c0 Merge branch 'bugfix/handle_missing_mqtt_states' into 'master'
Renames states and add missing handler on esp mqtt task

See merge request espressif/esp-mqtt!90
2021-02-02 22:14:09 +08:00
369f4207f8 Renames states and add missing handler on task
- The state transition on esp_mqtt_task was missing 2 states
- MQTT_STATE_ERROR removed
- Added a default case for state transition.
- Renamed MQTT_STATE_WAIT_TIMEOUT -> MQTT_STATE_WAIT_RECONNECT
2021-01-27 17:33:22 +00:00
1a64f3176c Merge branch 'feature/public_mqtt_supported_features' into 'master'
Moves mqtt_supported_features to public includes.

See merge request espressif/esp-mqtt!89
2021-01-21 18:41:31 +08:00
0213382593 mqtt: Moves mqtt_supported_features to public includes.
- To simplify user code to support multiple IDF versions.

Closes https://github.com/espressif/esp-mqtt/issues/184
2021-01-21 09:49:24 +00:00
a74adfa9eb Merge branch 'client_init_refactor' into 'master'
Clean client init

See merge request espressif/esp-mqtt!87
2021-01-21 15:57:52 +08:00
7a38867ce2 Merge branch 'destroy_config_refactor' into 'master'
Makes esp_mqtt_destroy_config void

See merge request espressif/esp-mqtt!86
2021-01-21 15:24:06 +08:00
2530edbdce Merge branch 'bugfix/allow_zero_length_username' into 'master'
mqtt_msg: Set zero length username if password is set without username

See merge request espressif/esp-mqtt!88
2021-01-21 15:22:05 +08:00
e05ed2ce18 mqtt: Clean client init
- Moves check and copy of parameter to a function to reduce repetition
- Removes cfg variable to be explicit about what is being modified.
2021-01-19 11:54:09 +00:00
3efac7b7fa mqtt_msg: Set zero length username if password is set without username
Some cloud server (e.g. exosite) takes empty username with password.

When password is set without username, the current esp-mqtt implementation will
ignore the username and only set password. This violates MQTT-3.1.2-22 [1].
To address this issue, send zero length username if password is set without username.

[1] MQTT-3.1.2-22: If the User Name Flag is set to 0 then the Password Flag MUST be set to 0.

Signed-off-by: Axel Lin <axel.lin@ingics.com>
2021-01-19 08:36:17 +01:00
b834be80a5 mqtt: Makes esp_mqtt_destroy_config void
- Makes the function a nop in case of NULL config.
2021-01-18 11:42:59 +00:00
9ea804e0ab Merge branch 'feature/queue_if_disconnect' into 'master'
esp-mqtt: More configs to queue when disconnected, events on delete, incremental msg-id

See merge request espressif/esp-mqtt!85
2020-12-21 19:42:15 +08:00
e2de0f3e3e Publish: Allow for qos=0 messages to be stored using esp_mqtt_client_enqueue()
The API presents a boolean parameter to control storing the qos=0
messages into the internal outbox
2020-12-15 19:43:33 +01:00
2e35d4d4d5 Events: Add new event to report deleted messages from outbox 2020-12-09 10:14:54 +01:00
f44dcb1c26 Config: Add a new option to disable publishing when disconnected
Related https://github.com/espressif/esp-mqtt/pull/177
2020-12-09 10:14:54 +01:00
dc7fd5c0b1 Publish: Add new API to enqueue qos>0 messages
Closes https://github.com/espressif/esp-mqtt/issues/155
2020-12-09 10:14:54 +01:00
8bb4a26f46 Config: Add a new option to use incremental message id
This option is off by default, so the client still uses
random message id unless CONFIG_MQTT_MSG_ID_INCREMENTAL is set

Closes https://github.com/espressif/esp-mqtt/issues/176
2020-12-09 10:12:57 +01:00
f65d5d05db Cleanup public include dirs 2020-12-06 11:26:03 +01:00
cef3e16c5d Merge branch 'bugfix/unused_mqtt_header_state_t' into 'master'
Remove unused mqtt_header_state_t

See merge request espressif/esp-mqtt!84
2020-12-03 18:48:17 +08:00
b7158a4aea mqtt: Remove unused mqtt_header_state_t
mqtt_header_state_t was added by commit 0450bd0093 ("MQTT Client:  Added support for receiving empty payload"),
but it's no longer used since commit fd564b1f17 ("client receive: refactor receive to read only one message to fragment only payload for longer messages").
Thus remove the unused mqtt_header_state_t.

Signed-off-by: Axel Lin <axel.lin@ingics.com>
2020-11-23 16:24:33 +08:00
da850b0add Merge branch 'feature/support_no_keepalive' into 'master'
mqtt_config: Add config value to disable keepalive mechanism

See merge request espressif/esp-mqtt!83
2020-11-19 22:07:05 +08:00
8562437c8a mqtt_config: Add config value to disable keepalive mechanism
Added a separate config value to allow disable the keepalive mechanism (and keep the existing API the same)
Internally though, the keepalive value (in connect_info) is in line with 3.1.2.10 Keep Alive from mqtt spec:
* keepalive=0: Keep alive mechanism disabled (server not to disconnect the client on its inactivity)
* period in seconds to send a Control packet if inactive

Closes https://github.com/espressif/esp-mqtt/issues/179
2020-11-18 14:41:44 +01:00
e8be6c3aa7 Merge branch 'feature/add_get_outbox_size' into 'master'
Add esp_mqtt_client_get_outbox_size API

See merge request espressif/esp-mqtt!82
2020-11-18 16:45:27 +08:00
65d8a813ea Merge branch 'bugfix/missing_unlock_and_cleanup' into 'master'
Minor fixes and cleanup

See merge request espressif/esp-mqtt!81
2020-11-18 16:44:41 +08:00
36d721e60b Merge branch 'bugfix/mqtt_err_flags_extention' into 'master'
error reporting: extended error event to use errno captured in transports

See merge request espressif/esp-mqtt!80
2020-11-13 05:10:58 +08:00
0a1d9d0300 mqtt: Add esp_mqtt_client_get_outbox_size API
Allow application to get current outbox_size.
Application may try to send many publish request for a long period and then
system can hit OOM when publish QoS>1 with a busy borker.
Reduce OUTBOX_EXPIRED_TIMEOUT_MS does not help too much because the publish
freauency depends on the data received in different environment.
i.e. In some environment, sometimes it's easy to hit OOM before reaching OUTBOX_EXPIRED_TIMEOUT_MS.

To avoid such issue, add esp_mqtt_client_get_outbox_size API, so the application
can stop publishing to avoid OOM when outbox takes too much memory.

Signed-off-by: Axel Lin <axel.lin@ingics.com>
2020-11-11 17:13:32 +08:00
673086e13a mqtt_outbox: Remove unused retry_count field from outbox_item_t
Signed-off-by: Axel Lin <axel.lin@ingics.com>
2020-11-09 16:08:22 +08:00
259baaec96 config: Fix typo for configuring OUTBOX_EXPIRED_TIMEOUT_MS
In esp-idf, it uses CONFIG_MQTT_OUTBOX_EXPIRED_TIMEOUT_MS rather than
CONFIG_OUTBOX_EXPIRED_TIMEOUT_MS.

Signed-off-by: Axel Lin <axel.lin@ingics.com>
2020-11-09 16:07:10 +08:00
845c2a3a1e mqtt: Fix missing MQTT_API_UNLOCK in esp_mqtt_client_stop error path
Fixes: 5e17dcaeb2 ("MQTT: Fix esp_mqtt_client_stop deadlock")
Signed-off-by: Axel Lin <axel.lin@ingics.com>
2020-11-09 16:06:58 +08:00
23c8e1ecf5 error reporting: extended error event to use errno captured in transports
Also renamed error type MQTT_ERROR_TYPE_ESP_TLS to
MQTT_ERROR_TYPE_TCP_TRANSPORT, as the former was confusing and might
have implied the error occurred in TLS layer.

Applicable IDF version >= v4.3

Closes https://github.com/espressif/esp-idf/issues/5906
2020-11-04 08:01:06 +01:00
d6613e995b Merge branch 'bugfix/size_t_for_all_lengths' into 'master'
Use size_t for all lengths

See merge request espressif/esp-mqtt!79
2020-10-12 18:16:29 +08:00
b9db8d9020 Use size_t for all lengths
Previously, uint32_t and size_t were used interchangeably. These types are
interchangeable on Xtensa gcc (uint32_t == size_t == unsigned int), but not on most
other 32-bit gcc architectures (where uint32_t == unsigned long, size_t ==
unsigned int).
2020-10-09 16:33:12 +11:00
fcd7f0d083 Merge branch 'bugfix/network_timeout' into 'master'
Allow to configure network timeout

See merge request espressif/esp-mqtt!78
2020-09-02 19:38:15 +08:00
a03228ac46 Allow to configure network timeout
Merges https://github.com/espressif/esp-mqtt/pull/166
2020-09-02 08:36:01 +02:00
01594bf118 Merge branch 'feature/mqtt_support_esp_ds' into 'master'
esp-mqtt: Add support for Digital Signature (through ESP-TLS)

See merge request espressif/esp-mqtt!71
2020-08-18 15:22:41 +08:00
7d8e59de00 mqtt: Add support for Digital Signature (through ESP-TLS)
Digital Signature enables hardware accelerated RSA signature
for TLS handshake.The RSA private key(client key) is also stored in
encrypted format and ecryption key is stored in hardware(efuse) which adds
additional level of security for mutual authentication.
* Digital Signature is only supported for ESP32-S2.

Applicable IDF version >= v4.3
2020-08-18 11:55:43 +05:30
ae408d9a69 Merge branch 'feature/outbox_limit' into 'master'
MQTT: Cleanup expired messages when offline

See merge request espressif/esp-mqtt!76
2020-08-18 14:08:57 +08:00
a8ef2a434b Merge branch 'bugfix/read_error_event' into 'master'
MQTT: add dispatch error event for read errors

See merge request espressif/esp-mqtt!75
2020-08-18 14:07:50 +08:00
867773e423 Merge branch 'fix/secure_element_feature' into 'master'
esp-mqtt: i) fix version check for secure_element

See merge request espressif/esp-mqtt!70
2020-08-18 14:04:39 +08:00
ac7209049f Merge branch 'bugfix/stop_from_event' into 'master'
MQTT: Fix esp_mqtt_client_stop deadlock

See merge request espressif/esp-mqtt!74
2020-08-17 22:01:08 +08:00
bdadd77c6e mqtt: deleted expired messages even when offline
As long as the client was disconnect no cleanup were performed,
consuming memory for every message published. Even if they were already
expired and would be discarded when reconnected.

Also moves delete of expired msgs before retransmit is done.
This avoids situtations where a message could be sent even if it was
expired.

Closes https://github.com/espressif/esp-idf/issues/5668
2020-08-10 16:42:32 +08:00
f7325bfa10 mqtt: esp_mqtt_client_publish now returns msd id for QoS>0 when offline 2020-08-10 14:47:05 +08:00
d4aaec08ff MQTT: add dispatch error event for read errors
Closes https://github.com/espressif/esp-idf/issues/5704
2020-08-07 17:54:40 +08:00
5e17dcaeb2 MQTT: Fix esp_mqtt_client_stop deadlock
esp_mqtt_client_stop would lead to a deadlock (with itself) when called
from the event handler.

Updated comments to reflect that some functions should not be called from
the event handler.

Closes https://github.com/espressif/esp-mqtt/issues/163
2020-08-04 19:26:37 +08:00
db4bce01ab mqtt: i)fix version check for secure_element
ii) fix secure_element error return

The feature allows use of secure element for TLS connections, which makes use of hardware security for storage of client private keys(only keys with ECC algorithm)

Applicable IDF versions: >= 4.2
2020-08-03 09:45:27 +05:30
702da6d528 Merge branch 'bugfix/build_test_fix' into 'master'
CI: Fixes build test issues

See merge request espressif/esp-mqtt!72
2020-07-31 19:40:25 +08:00
0bafcc5188 ci: Add IDF v4.2 to build tests
Also fixes build issues when default config carried over IDF releases --
always remove previous `sdkconfig` before a new build
2020-07-30 16:54:00 +02:00
651c2fb4a2 ci: Fix travis build with legacy IDFs 2020-07-24 14:56:12 +02:00
d754293d25 Merge branch 'feature/check_cfg_consistency' into 'master'
Add check for consistency between config settings

See merge request espressif/esp-mqtt!69
2020-07-17 00:05:04 +08:00
8a412c147d Add check for consistency between config settings
Warn user if the MQTT config seems misconfigured, e.g.
user specifies a SSL certificate, but SSL not activated
2020-07-08 12:54:00 +08:00
5b8c04f348 Merge branch 'feature/allow_query_in_uri' into 'master'
Allow the query part of the uri to be a part of the path

See merge request espressif/esp-mqtt!68
2020-06-29 21:16:48 +08:00
40b06deb10 Allow the query part of the uri to be a part of the path
Closes IDFGH-3565
Closes https://github.com/espressif/esp-mqtt/issues/161
2020-06-29 10:33:42 +08:00
109985d3ad Merge branch 'feature/enable_tls_with_secure_element' into 'master'
esp-mqtt: add support for tls with secure element (ATECC608A)

See merge request espressif/esp-mqtt!66
2020-06-25 13:42:41 +08:00
a7ff9afa3f esp-mqtt: add support for tls with secure element (ATECC608A)
Closes https://github.com/espressif/esp-mqtt/issues/156
2020-06-25 10:36:58 +05:30
2f9b337071 Merge branch 'feature/skip_cmn_name_check' into 'master'
SSL: add config option for skipping common name check

See merge request espressif/esp-mqtt!67
2020-06-10 15:13:58 +08:00
5e8950e681 SSL: add config option for skipping common name check
Closes IDFGH-3408
Closes https://github.com/espressif/esp-mqtt/issues/158
2020-06-09 14:23:40 +08:00
6bc94add89 Merge branch 'bugfix/confusing_print' into 'master'
mqtt_print: Change the message printed after MQTT connection failure

See merge request espressif/esp-mqtt!65
2020-04-28 19:04:34 +08:00
20bf9928d4 Merge branch 'bugfix/block_api_docs' into 'master'
docs: Makes clear that publish API could block

See merge request espressif/esp-mqtt!64
2020-04-28 15:22:46 +08:00
fb41520206 mqtt_print: Change the message printed after MQTT connection failure
Since the original message was confusing.
2020-04-24 23:05:47 +05:30
615aeae0c2 docs: Makes clear that publish API could block
Closes https://github.com/espressif/esp-idf/issues/5077
2020-04-24 14:26:37 +02:00
0c3d306589 Merge branch 'bugfix/print_messages' into 'master'
Some changes to debug prints

See merge request espressif/esp-mqtt!63
2020-04-08 01:33:01 +08:00
b02746492a esp_mqtt: Change an error print to use ESP_LOGE instead of ESP_LOGI
And another one changed from LOGI to LOGD
2020-04-06 12:13:18 +05:30
50dc010b97 Merge branch 'bugfix/abort_race_condition' into 'master'
esp_mqtt_abort_connection: Fixed an issue which could result in a race...

See merge request espressif/esp-mqtt!62
2020-04-01 22:39:06 +08:00
dc1a635a97 esp_mqtt_abort_connection: Fixed an issue which could result in a race condition and subsequent crash 2020-03-30 19:59:27 +05:30
0fc904c5d8 Merge branch 'feature/config_mqtt_task_prio' into 'master'
config: option to configure mqtt task priority

See merge request espressif/esp-mqtt!61
2020-03-20 14:50:07 +08:00
d8e2081332 config: option to configure mqtt task priority 2020-03-17 13:34:27 +01:00
9b750651fc Merge branch 'bugfix/add_out_buff_size' into 'master'
config: option to configure output buffer size

See merge request espressif/esp-mqtt!60
2020-03-12 04:31:35 +08:00
61a8f4b63c ci: fix build issue (stale CMake cache) between 4.1 and 4.2 2020-03-10 16:19:51 +01:00
f243225521 config: option to configure output buffer size
Both input and output buffers had the same size, but it is desirable in embedded environment to use asymetric buffers. Added configuration option to defined output buffer size, if not defined output buffer defaults to the same size as the input buffer.

Closes https://github.com/espressif/esp-mqtt/issues/152
2020-03-10 15:26:49 +01:00
8a1e1a5a9f Merge branch 'bugfix/mqtt_cpp_build' into 'master'
Minor fixes: C++ invalid event, Resend for QoS > 0

See merge request espressif/esp-mqtt!59
2020-02-21 16:15:23 +08:00
62d1509961 Resend queued: Set duplicate flag for both qos1 and qos2
Closes https://github.com/espressif/esp-mqtt/issues/151
2020-02-20 16:00:15 +01:00
e2aa29d2ea Client: Fix C++ build failing on incorrect event enum conversion
Closes https://github.com/espressif/esp-idf/issues/4787
2020-02-20 14:44:38 +01:00
d801f03f46 Merge branch 'bugfix/missed_mutex_unlock' into 'master'
Fixed missing mutex unlock if subscribe message fails to be created

See merge request espressif/esp-mqtt!58
2020-02-10 15:43:27 +08:00
a9036b82a4 CI: make the qemu tests use IDF release branch
Building the mqtt against idf release/v4.1 for the qemu tests to avoid potential issues on IDF master with running qemu
2020-02-10 08:01:10 +01:00
3e4f91ae50 Client: unlock if unsubscribe message fails to be created
In a similar way as for the subscribe message
2020-02-10 08:01:10 +01:00
7983357489 Client: unlock if subscribe message fails to be created
Closes https://github.com/espressif/esp-mqtt/issues/150
2020-02-10 08:00:45 +01:00
d5e915296e Merge branch 'bugfix/failed_to_compile_on4.0' into 'master'
fix compilation issue on v-4.0

See merge request espressif/esp-mqtt!57
2020-02-03 23:53:03 +08:00
9e20c7ae3d CI: Add checks to build against different IDF releases 2020-02-03 10:55:42 +01:00
38eab46f14 Fix compilation issue with IDF version 4.0 and lower
Closes https://github.com/espressif/esp-mqtt/issues/149
2020-01-31 21:42:45 +01:00
b963a5cd86 Merge branch 'bugfix/outbox_tick_type' into 'master'
Various fixes in mqtt library

See merge request espressif/esp-mqtt!55
2020-01-31 21:11:27 +08:00
2994c3f273 receive longer (websocket) data with standard tcp_transport reads
closes IDF-1084
2020-01-30 08:32:24 +01:00
420441b677 set separate ssl connection properties before transport connect 2020-01-30 08:31:59 +01:00
bbcf078a2b fix possible double free of client config if init fails 2020-01-29 08:25:05 +01:00
ed90a64551 client: queued oversized messaged even if not connected 2020-01-29 08:25:05 +01:00
f7941e29be mqtt_outbox: fixed outbox_destroy() to correctly delete all queued messages
Closes https://github.com/espressif/esp-idf/issues/4643
Closes IDFGH-2558
Closes https://github.com/espressif/esp-mqtt/issues/148
Closes IDFGH-2599
Closes https://github.com/espressif/esp-mqtt/issues/147
Closes IDFGH-2598
2020-01-29 08:22:52 +01:00
3a47e3abae client locking: used recursive mutex instead to avoid getting the code too complex 2020-01-27 12:26:10 +01:00
9eca3f6db9 mqtt_client: set_config to update ssl-transport configuration
closes https://github.com/espressif/esp-mqtt/issues/146
closes IDFGH-2534
2020-01-25 22:24:00 +01:00
7087193093 mqtt_msg: address const correctness 2020-01-25 21:57:02 +01:00
89a0c1fc95 removed examples from the submodule
Valid and tested examples are always in esp-idf. these examples were for reference and might and have coused some confussion
2020-01-25 21:57:02 +01:00
6e08f6a04f mqtt_outbox: fix to store timestamps in long-long format
closes https://github.com/espressif/esp-mqtt/issues/144
closes IDFGH-2491
2020-01-25 21:57:02 +01:00
8ab095b5bb Merge branch 'feature/protocol_ver_rt_cfg' into 'master'
MQTT: Add runtime selection of mqtt protocol version

See merge request espressif/esp-mqtt!54
2020-01-20 16:41:55 +08:00
616fa257fb Merge branch 'feature/large_buffers' into 'master'
Support larger buffers and messages

See merge request espressif/esp-mqtt!56
2020-01-17 17:15:10 +08:00
7ac0a42831 MQTT: Add runtime selection of mqtt protocol version
Add config option for selecting protocol version at runtime.

This also fixed MQTT protocol version 3.1 which wasnt working with the original implementation

Closes https://github.com/espressif/esp-idf/issues/4448
Closes IDFGH-2311
Closes IDF-1320
2020-01-09 14:49:33 +08:00
ab1e8d7969 Support larger buffers and messages
Use `uint32_t` instead of `uint16_t` for message and buffer lengths.
This is necessary for receiving messages that are larger than 65K.
2020-01-08 15:00:10 -05:00
86fc8b7584 Merge branch 'feature/support_clientkey_password' into 'master'
add support for password protected client-key

See merge request espressif/esp-mqtt!53
2020-01-09 02:57:30 +08:00
2684ed413d add support for password protected client-key 2020-01-08 09:05:18 +01:00
f74fe3d887 Merge branch 'bugfix/jira_workflow' into 'master'
fix sync issues and pull requests to jira

See merge request espressif/esp-mqtt!52
2020-01-06 14:59:05 +08:00
acc91bacf3 fix sync issues and pull requests to jira 2020-01-03 08:11:00 +01:00
057f140228 Merge branch 'bugfix/fix_connect_timeout' into 'master'
waiting for entire connack message with configured network timeout

See merge request espressif/esp-mqtt!50
2019-12-23 15:57:16 +08:00
97f91eda5c wait for the entire connack message with the configured timeout
Configured network timeout was used to receive separate characters
in the message. This change waits for the configured timeout if reading
the mqtt packet was left in progress (mqtt_message_receive() returns 0)

Closes FCS-254
2019-12-23 07:54:59 +01:00
716b8625ba Merge branch 'feature/qemu_tests' into 'master'
ci: added job with publish tests on qemu

See merge request espressif/esp-mqtt!51
2019-12-23 14:52:47 +08:00
b25077a338 ci: add pushlish weekend tests to all pipelines (running on qemu) 2019-12-19 10:58:58 +01:00
99586c2768 Merge branch 'bugfix/event_handler_mem_leak' into 'master'
Fixed bug where the event loop wouldn't get cleaned up during destroy.

See merge request espressif/esp-mqtt!49
2019-12-04 18:50:43 +08:00
17e2f68e43 Fixed bug where the event loop wouldn't get cleaned up during destroy.
The event loop would never get deleted due to the event loop handle being
cleared to 0 before checking if it exists.

Closes https://github.com/espressif/esp-idf/issues/4433
Closes IDFGH-2293
2019-12-04 11:12:17 +08:00
9a5187771a Merge branch 'bugfix/publish_before_connect' into 'master'
Fixed crash due to publishing before successful transport connect.

See merge request espressif/esp-mqtt!48
2019-11-23 03:39:59 +08:00
e8bb0bcf6f ci: fixed ci build with latest idf using up to date compiler 2019-11-22 20:29:13 +01:00
9ca997d2d4 Fix potential memory leak if failing to create mutex
Closes https://github.com/espressif/esp-idf/issues/4384
Closes IDFGH-2235
2019-11-22 20:28:45 +01:00
9655845fdc Fixed crash due to publishing before successful transport connect.
Initialization of the outgoing message buffer is now done during mqtt_init,
which means messages can be queued before the first connection is made.

The client now checks for fail_message after creating a message, and cancels
the current operation if this happens. Updated error handling in client_publish
to be more inline with API documentation.

Closes https://github.com/espressif/esp-idf/issues/4349
Closes https://github.com/espressif/esp-mqtt/issues/140
2019-11-22 20:28:45 +01:00
1cd0885611 Merge branch 'feature/alpn_support' into 'master'
Add support for ALPN

See merge request espressif/esp-mqtt!46
2019-11-20 21:06:48 +08:00
e1ab64f0d8 Add support for ALPN
Closes IDF-1162

Closes https://github.com/espressif/esp-mqtt/issues/137
2019-11-20 17:30:58 +08:00
c1766c0f56 Merge branch 'feature/configurable_recon_time' into 'master'
Add reconnect time as a configurable parameter.

See merge request espressif/esp-mqtt!47
2019-11-20 17:12:45 +08:00
3da472fd37 Add reconnect time as a configurable parameter.
Closes IDF-1126
2019-11-18 14:43:44 +08:00
566b034984 Merge branch 'bugfix/err_event_mqtt_related' into 'master'
ADD: Get the response code from a failing connection.

See merge request espressif/esp-mqtt!41
2019-10-17 19:00:21 +08:00
e3b013e2db Extended error structure to be used in mqtt library and include mqtt
specific errors.
Corrected typos in comments and log messages
2019-10-09 11:22:02 +02:00
67042a1315 ADD: Get the response code from a failing connection.
This commit adds an event information "connect_return_code" that is written
when the client state is MQTT_STATE_INIT, and the connection fails.

This event info can then be written by the user app to find out the reason
of the fail connection.

Merges https://github.com/espressif/esp-mqtt/pull/100
2019-10-09 09:23:53 +02:00
430676cadb Merge branch 'bugfix/early_retransmit' into 'master'
Fix early retransmit

See merge request espressif/esp-mqtt!44
2019-10-03 20:21:56 +08:00
52cdfa9087 Fix early retransmit
The time for retransmitting a message was set before transfer was done. This ment that if the transfer speed is slow or the message is big then it would be possible to trigger a retransmit too early.

Closes https://github.com/espressif/esp-mqtt/issues/131
2019-10-03 14:03:32 +02:00
40302a3d43 Merge branch 'bugfix/pulished_events_not_posted' into 'master'
MQTT: fix MQTT_PUBLISHED_EVENT not always being posted

See merge request espressif/esp-mqtt!43
2019-10-03 19:58:36 +08:00
3e35fc8323 MQTT: fix MQTT_PUBLISHED_EVENT not always being posted
- Some PUBLISHED events would not be posted due to outbox messages being deleted before receiving PUBCOMP.
 - Current pending_message is no longer used to check for acknowledgements, as it doesn't work with multiple or out of order messages.

Closes https://github.com/espressif/esp-mqtt/issues/132
2019-10-03 13:28:51 +02:00
78e2a7050e Merge branch 'bugfix/mqtt_docs_fix' into 'master'
docs: Updated publish message return code to make it clear that message_id is always 0 for QoS 0

See merge request espressif/esp-mqtt!42
2019-10-03 19:25:47 +08:00
d01c77f70b Merge branch 'feature/error_check_for_null_msgs' into 'master'
Error checks for sending null messages

See merge request espressif/esp-mqtt!39
2019-10-03 19:14:36 +08:00
59b228e0ad Merge branch 'bugfix/err_report_on_publish' into 'master'
Fix not dispatching MQTT_EVENT_ERROR

See merge request espressif/esp-mqtt!40
2019-10-03 17:58:15 +08:00
9fbd7d9244 docs: Updated publish message return code to make it clear that message_id is always 0 for QoS 0
Closes https://github.com/espressif/esp-mqtt/issues/127
2019-09-30 08:05:51 +02:00
2e0e93a2d3 Add a check when publishing data to be able to publish a message without data without crashing.
Signed-off-by: Marius Vikhammer <marius.vikhammer@espressif.com>

Merges https://github.com/espressif/esp-mqtt/pull/117
2019-09-24 18:25:55 +08:00
2b04d177c7 Add a check when publishing data to verify that if some data length is set, data pointer cannot be NULL, in which case an error is returned.
Signed-off-by: Marius Vikhammer <marius.vikhammer@espressif.com>
2019-09-24 18:24:52 +08:00
176be08f75 Fix not dispatching MQTT_EVENT_ERROR
If a publish failure ocurred, MQTT_EVENT_ERROR was not delivered to handler set with esp_mqtt_client_register_event
2019-09-14 21:16:31 -03:00
04253b2b07 Merge branch 'featrue/enable_global_ca_store' into 'master'
client: added config option to enable global ca strore

See merge request espressif/esp-mqtt!38
2019-08-30 22:40:14 +08:00
0234f6e538 client: added config option to enable global ca strore
closes https://github.com/espressif/esp-mqtt/issues/125
2019-08-23 14:33:35 +02:00
1134cb234c Merge branch 'feature/support_der_certs' into 'master'
Feature/support der certs

See merge request espressif/esp-mqtt!37
2019-08-23 02:30:58 +08:00
9a56cc7e14 add der-format support for tls-certificates/keys 2019-08-22 15:11:49 +02:00
54c0161481 Merge branch 'feature/mqtt_use_new_event' into 'master'
MQTT uses new event

See merge request espressif/esp-mqtt!34
2019-08-21 17:20:26 +08:00
fb3d2107cd MQTT examples use new event 2019-08-16 16:15:54 +08:00
92aa01deb8 Merge branch 'bugfix/deadlock_when_close' into 'master'
Bugfix/deadlock when close

See merge request espressif/esp-mqtt!36
2019-08-08 18:12:17 +08:00
cbae6343e9 fix deadlock between xEventGroupWaitBits and API lock semaphore
Merges https://github.com/espressif/esp-mqtt/pull/124
Closes https://github.com/espressif/esp-mqtt/issues/122
2019-08-08 11:54:42 +02:00
2fef1a07c5 Merge branch 'feature/psk_auth' into 'master'
psk ssl could be used to authenticate with mqtt broker as an alternative to cerificate verification

See merge request espressif/esp-mqtt!35
2019-07-29 22:38:14 +08:00
117eef2dad psk ssl could be used to authenticate with mqtt broker as an alternative to cerificate verification
Closes https://github.com/espressif/esp-mqtt/issues/95
2019-07-22 14:26:47 +02:00
dc37d3a065 Merge branch 'feature/transport_pass_error_codes' into 'master'
transport pass error codes to user code

See merge request espressif/esp-mqtt!33
2019-07-18 02:33:44 +08:00
0cc4077bd3 modified error type to be a generic handle to capture different types of errors 2019-07-04 09:12:40 +02:00
65bf2255d7 adding error event with error code 2019-07-03 08:49:54 +02:00
e85430def7 Merge branch 'bugfix/mqtt_fix_close_if_never_connected_crash' into 'master'
MQTT Client: Check for connection before sending disconnect message

See merge request idf/esp-mqtt!32
2019-07-03 14:15:47 +08:00
d9faeb47a3 fix resending subscribe messages
subscribe and unsubscribe messages were pushed to queue, but TRANSMIT flag wasn't set, so they were automatically retransmitted
2019-06-27 16:39:42 +02:00
82fa03a508 fixed possible race conditions in public API of mqtt_client
- Modified most of the public API to lock even if checking for connection state
- Updated `esp_mqtt_set_config` locks to be used also from callbacks (in mqtt-task context)
- Moved initialization of event_loop out of esp_mqtt_set_config
2019-06-27 16:36:12 +02:00
7223302deb MQTT Client: Check for connection before sending disconnect message
Closes https://github.com/espressif/esp-idf/issues/3619
Closes https://github.com/espressif/esp-mqtt/issues/120
Merges https://github.com/espressif/esp-mqtt/pull/118

Signed-off-by: David Cermak <cermak@espressif.com>
2019-06-27 16:33:58 +02:00
11f884623b Merge branch 'idf' to 'master'
Integration of ESP-MQTT to IDF

See merge request idf/esp-mqttmake
2019-06-10 14:51:27 +02:00
27780e3c45 Merge branch 'feature/github_issue_sync' into 'master'
github: Add workflow file for syncing to Jira

See merge request idf/esp-mqtt!22
2019-03-29 15:12:35 +08:00
78a55fac68 github: Add workflow file for syncing to Jira 2019-03-27 18:18:33 +11:00
51a5ca026f Merge branch 'feature/announce_move_to_idf' into 'master'
esp-mqtt announce integration to idf

See merge request idf/esp-mqtt!6
2018-10-10 19:36:27 +08:00
5fd5523b9b esp-mqtt announce integration to idf 2018-10-04 13:12:30 +02:00
99004f2a48 Merge pull request #61 from rbino/add-mutual-auth
Add SSL mutual authentication support
2018-09-13 15:58:46 +02:00
4e4b5dd06f Add ssl mutual authentication example 2018-08-06 16:35:00 +02:00
8e8cf28bca Add mutual SSL auth config to mqtt_client 2018-08-06 16:29:58 +02:00
b930438e3d Add mutual SSL authentication to transport_ssl 2018-08-06 16:29:16 +02:00
54 changed files with 6025 additions and 1356 deletions

View File

@ -0,0 +1,37 @@
name: Build app an run on target
on:
workflow_call:
inputs:
idf_version:
required: true
type: string
target:
required: true
type: string
app_name:
type: string
required: true
app_path:
type: string
required: true
jobs:
build-app:
uses: "./.github/workflows/build-app.yml"
with:
idf_version: ${{inputs.idf_version}}
target: ${{inputs.target}}
app_name: ${{inputs.app_name}}
app_path: ${{inputs.app_path}}
# run-on-target:
# needs: build-app
# uses: "./.github/workflows/run-on-target.yml"
# with:
# idf_version: ${{inputs.idf_version}}
# target: ${{inputs.target}}
# app_name: ${{inputs.app_name}}
# app_path: ${{inputs.app_path}}

59
.github/workflows/build-app.yml vendored Normal file
View File

@ -0,0 +1,59 @@
name: Build app
on:
workflow_call:
inputs:
idf_version:
required: true
type: string
target:
required: true
type: string
app_name:
type: string
required: true
app_path:
type: string
required: true
upload_artifacts:
type: boolean
default: true
jobs:
build:
name: Build App
runs-on: ubuntu-20.04
container: espressif/idf:${{inputs.idf_version}}
steps:
- if: ${{ env.ACT }}
name: Add node for local tests
run: |
curl -fsSL https://deb.nodesource.com/setup_14.x | bash -
apt-get install -y nodejs
- name: Checkout esp-mqtt
uses: actions/checkout@v3
- name: ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ${{inputs.idf_version}}-${{inputs.target}}
- name: Build ${{ inputs.app_name }} with IDF-${{ inputs.idf_version }}
shell: bash
run: |
${IDF_PATH}/install.sh --enable-pytest
. ${IDF_PATH}/export.sh
python -m pip install idf-build-apps
rm -rf $IDF_PATH/components/mqtt/esp-mqtt
cp -r . $IDF_PATH/components/mqtt/esp-mqtt
IDF_CCACHE_ENABLE=1 idf-build-apps build --config-file ci/idf_build_apps.toml -p ${{inputs.app_path}} -t ${{inputs.target}}
- name: Upload files to artifacts for run-target job
uses: actions/upload-artifact@v3
if: ${{inputs.upload_artifacts}}
with:
name: mqtt_bin_${{inputs.target}}_${{ inputs.idf_version }}_${{ inputs.app_name }}
path: |
build_${{inputs.target}}_${{inputs.app_name}}/bootloader/bootloader.bin
build_${{inputs.target}}_${{inputs.app_name}}/partition_table/partition-table.bin
build_${{inputs.target}}_${{inputs.app_name}}/*.bin
build_${{inputs.target}}_${{inputs.app_name}}/*.elf
build_${{inputs.target}}_${{inputs.app_name}}/flasher_args.json
if-no-files-found: error

20
.github/workflows/issue_comment.yml vendored Normal file
View File

@ -0,0 +1,20 @@
name: Sync issue comments to JIRA
# This workflow will be triggered when new issue comment is created (including PR comments)
on: issue_comment
jobs:
sync_issue_comments_to_jira:
name: Sync Issue Comments to Jira
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Sync issue comments to JIRA
uses: espressif/github-actions/sync_issues_to_jira@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
JIRA_PASS: ${{ secrets.JIRA_PASS }}
JIRA_PROJECT: IDFGH
JIRA_COMPONENT: esp-mqtt
JIRA_URL: ${{ secrets.JIRA_URL }}
JIRA_USER: ${{ secrets.JIRA_USER }}

80
.github/workflows/mqtt__host-tests.yml vendored Normal file
View File

@ -0,0 +1,80 @@
name: "esp-mqtt: host-tests"
on:
push:
branches:
- master
pull_request:
types: [opened, synchronize, reopened, labeled]
jobs:
host_test_esp_mqtt:
name: Host Tests
runs-on: ubuntu-22.04
permissions:
contents: write
container: espressif/idf:latest
env:
COMP_DIR: components/mqtt/esp-mqtt
steps:
- name: Checkout esp-mqtt
uses: actions/checkout@v3
- name: Build and Test
shell: bash
run: |
apt-get update && apt-get install -y gcc g++ python3-pip rsync
${IDF_PATH}/install.sh
. ${IDF_PATH}/export.sh
echo "IDF_PATH=${IDF_PATH}" >> $GITHUB_ENV
rm -rf $IDF_PATH/${{ env.COMP_DIR }}
cp -r . $IDF_PATH/${{ env.COMP_DIR }}
cd $IDF_PATH/${{ env.COMP_DIR }}/host_test
idf.py build
./build/host_mqtt_client_test.elf -r junit -o junit.xml
- name: Build with Coverage Enabled
shell: bash
run: |
. ${IDF_PATH}/export.sh
cd $IDF_PATH/${{ env.COMP_DIR }}/host_test
cat sdkconfig.ci.coverage >> sdkconfig.defaults
rm -rf build sdkconfig
idf.py build
./build/host_mqtt_client_test.elf
- name: Run gcovr
shell: bash
run: |
python -m pip install gcovr
cd $IDF_PATH/${{ env.COMP_DIR }}
gcov -b host_test/main/mqtt_client.c. -o `find . -name "mqtt_client*gcda" -exec dirname {} \;`
gcovr --gcov-ignore-parse-errors -g -k -r . --html index.html -x esp_mqtt_coverage.xml
mkdir docs_gcovr
mv index.html docs_gcovr
touch docs_gcovr/.nojekyll
cp -r docs_gcovr esp_mqtt_coverage.xml $GITHUB_WORKSPACE
- name: Code Coverage Summary Report
uses: irongut/CodeCoverageSummary@v1.3.0
with:
filename: ${{ env.GITHUB_WORKSPACE }}/**/esp_mqtt_coverage.xml
badge: true
fail_below_min: false
format: markdown
hide_branch_rate: false
hide_complexity: false
indicators: true
output: both
thresholds: '60 80'
- name: Write to Job Summary
run: cat code-coverage-results.md >> $GITHUB_STEP_SUMMARY
- name: Upload artifacts
uses: actions/upload-artifact@v3
if: always()
with:
name: docs_gcovr
path: ${{ env.IDF_PATH }}/${{ env.COMP_DIR }}/docs_gcovr
if-no-files-found: error
- name: Deploy coverage summary
if: github.ref == 'refs/heads/master'
uses: JamesIves/github-pages-deploy-action@v4.4.1
with:
branch: gh-pages
folder: ${{ env.IDF_PATH }}/${{ env.COMP_DIR }}/docs_gcovr

20
.github/workflows/new_issues.yml vendored Normal file
View File

@ -0,0 +1,20 @@
name: Sync issues to Jira
# This workflow will be triggered when a new issue is opened
on: issues
jobs:
sync_issues_to_jira:
name: Sync issues to Jira
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Sync GitHub issues to Jira project
uses: espressif/github-actions/sync_issues_to_jira@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
JIRA_PASS: ${{ secrets.JIRA_PASS }}
JIRA_PROJECT: IDFGH
JIRA_COMPONENT: esp-mqtt
JIRA_URL: ${{ secrets.JIRA_URL }}
JIRA_USER: ${{ secrets.JIRA_USER }}

29
.github/workflows/new_prs.yml vendored Normal file
View File

@ -0,0 +1,29 @@
name: Sync remain PRs to Jira
# This workflow will be triggered every hour, to sync remaining PRs (i.e. PRs with zero comment) to Jira project
# Note that, PRs can also get synced when new PR comment is created
on:
schedule:
- cron: "0 * * * *"
# Limit to single concurrent run for workflows which can create Jira issues.
# Same concurrency group is used in issue_comment.yml
concurrency: jira_issues
jobs:
sync_prs_to_jira:
name: Sync PRs to Jira
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Sync PRs to Jira project
uses: espressif/github-actions/sync_issues_to_jira@master
with:
cron_job: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
JIRA_PASS: ${{ secrets.JIRA_PASS }}
JIRA_PROJECT: IDFGH
JIRA_COMPONENT: esp-mqtt
JIRA_URL: ${{ secrets.JIRA_URL }}
JIRA_USER: ${{ secrets.JIRA_USER }}

64
.github/workflows/run-on-target.yml vendored Normal file
View File

@ -0,0 +1,64 @@
name: Run on target
on:
workflow_call:
inputs:
idf_version:
required: true
type: string
target:
required: true
type: string
app_name:
type: string
required: true
app_path:
type: string
required: true
jobs:
target-test:
if: github.repository == 'espressif/esp-mqtt'
name: Run App on target
env:
IDF_PATH: idf
runs-on: [self-hosted, ESP32-ETHERNET-KIT]
steps:
- name: Select idf ref
id: detect_version
run: |
if echo "${{inputs.idf_version}}" | grep "latest" -> /dev/null ; then
echo ref="master" >> "$GITHUB_OUTPUT"
else
echo ref="`echo ${{matrix.idf_version}} | sed -s "s/-/\//"`" >> "$GITHUB_OUTPUT"
fi
- name: IP discovery
id: detect_ip
run: |
apt-get update && apt-get install -y iproute2
ip route
echo runner_ip ="`ip -4 addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}'`" >> "$GITHUB_OUTPUT"
- name: Checkout IDF ${{inputs.idf_version}}
uses: actions/checkout@v3
with:
repository: espressif/esp-idf
path: ${{env.IDF_PATH}}
ref: ${{steps.detect_version.outputs.ref}}
- name: Install Python packages
env:
PIP_EXTRA_INDEX_URL: "https://dl.espressif.com/pypi/"
run: |
pip install --only-binary cryptography -r ${{env.IDF_PATH}}/tools/requirements/requirements.pytest.txt
- uses: actions/download-artifact@v3
with:
name: mqtt_bin_${{inputs.target}}_${{ inputs.idf_version }}_${{ inputs.app_name }}
path: build
- name: Run ${{inputs.app_name}} application on ${{inputs.target}}
run: |
python -m pytest ${{inputs.app_path}} --log-cli-level DEBUG --app-path . --junit-xml=./results_${{inputs.app_name}}_${{inputs.idf_version}}.xml --target=${{inputs.target}}
- uses: actions/upload-artifact@v3
if: always()
with:
name: results_${{inputs.app_name}}_${{inputs.idf_version}}.xml
path: build/*.xml

66
.github/workflows/test-examples.yml vendored Normal file
View File

@ -0,0 +1,66 @@
name: "Build example apps"
on:
push:
branches:
- master
pull_request:
types: [opened, synchronize, reopened, labeled]
jobs:
cpp-compatibility:
name: Cpp compatibility
strategy:
matrix:
idf_version: ["release-v5.0", "release-v5.1", "latest"]
target: ["esp32"]
example: [{name: cpp_compatibility, path: "build_test"}]
uses: "./.github/workflows/build-app.yml"
with:
idf_version: ${{matrix.idf_version}}
target: ${{matrix.target}}
app_name: ${{matrix.example.name}}
app_path: $IDF_PATH/tools/test_apps/protocols/mqtt/${{matrix.example.path}}
upload_artifacts: false
build-only-example:
name: Build Only Apps
strategy:
matrix:
idf_version: ["release-v5.0", "release-v5.1", "latest"]
target: ["esp32s2", "esp32c3", "esp32s3"]
example: [{name: ssl_psk, path: "mqtt/ssl_psk"}]
uses: "./.github/workflows/build-app.yml"
with:
idf_version: ${{matrix.idf_version}}
target: ${{matrix.target}}
app_name: ${{matrix.example.name}}
app_path: $IDF_PATH/examples/protocols/${{matrix.example.path}}
build-only-ds-example:
name: Build Only Apps
strategy:
matrix:
idf_version: ["release-v5.0", "release-v5.1", "latest"]
target: ["esp32s2", "esp32c3", "esp32s3"]
example: [{name: ssl_ds, path: "mqtt/ssl_ds"}, {name: ssl_psk, path: "mqtt/ssl_psk"}]
uses: "./.github/workflows/build-app.yml"
with:
idf_version: ${{matrix.idf_version}}
target: ${{matrix.target}}
app_name: ${{matrix.example.name}}
app_path: $IDF_PATH/examples/protocols/${{matrix.example.path}}
build-examples:
name: Build and Run on target
strategy:
matrix:
idf_version: ["release-v5.0", "release-v5.1", "latest"]
target: ["esp32"]
example: [{name: tcp, path: "mqtt/tcp"}, {name: ssl, path: "mqtt/ssl"},{name: ssl_mutual_auth, path: "mqtt/ssl_mutual_auth"},{name: ws, path: "mqtt/ws"},{name: wss, path: "mqtt/wss"}]
uses: "./.github/workflows/build-and-target-test.yml"
with:
idf_version: ${{matrix.idf_version}}
target: ${{matrix.target}}
app_name: ${{matrix.example.name}}
app_path: $IDF_PATH/examples/protocols/${{matrix.example.path}}

View File

@ -1,14 +1,11 @@
stages:
- build
- static_analysis
- deploy_report
- test
- deploy
variables:
IDF_REPO: ${GITLAB_SSH_SERVER}/idf/esp-idf.git
OLDER_IDF: release/v3.1
RECENT_IDF: release/v3.3
.add_gh_key_remote: &add_gh_key_remote |
cit_add_ssh_key "${GH_PUSH_KEY}"
@ -19,110 +16,91 @@ before_script:
# Use CI Tools
- curl -sSL ${CIT_LOADER_URL} | sh
- source citools/import_functions
# Add gitlab ssh key
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- echo -n $GITLAB_KEY > ~/.ssh/id_rsa_base64
- base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- echo -e "Host gitlab.espressif.cn\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
- PATH=$CI_PROJECT_DIR/esp-idf/tools:$PATH
- export MQTT_PATH=$CI_PROJECT_DIR
build_with_older_idf:
.build_template:
stage: build
image: ${CI_DOCKER_REGISTRY}/esp32-ci-env
tags:
- build
dependencies: []
- internet
script:
- cit_add_ssh_key "${GITLAB_KEY}"
- git clone "${IDF_REPO}" && cd esp-idf && git checkout ${OLDER_IDF}
- ./tools/ci/mirror-submodule-update.sh
- export IDF_PATH=$(pwd)
- cd $CI_PROJECT_DIR
- ./modify_for_legacy_idf.sh ${RECENT_IDF} || true
- cd $CI_PROJECT_DIR/examples/tcp
- make defconfig
- make
# Replace the IDF's default esp-mqtt with this version
- rm -rf $IDF_PATH/components/mqtt/esp-mqtt && cp -r $MQTT_PATH $IDF_PATH/components/mqtt/
# Build the examples
- $MQTT_PATH/ci/build_examples.sh
build_with_idf:
build_idf_v5.0:
extends: .build_template
image: espressif/idf:release-v5.0
build_idf_v5.1:
extends: .build_template
image: espressif/idf:release-v5.1
build_idf_latest:
extends: .build_template
image: espressif/idf:latest
build_and_host_test:
stage: build
image: ${CI_DOCKER_REGISTRY}/esp32-ci-env
image: espressif/idf:latest
script:
# Replace the IDF's default esp-mqtt with this version
- rm -rf $IDF_PATH/components/mqtt/esp-mqtt && cp -r $MQTT_PATH $IDF_PATH/components/mqtt/
- cd $IDF_PATH/components/mqtt/esp-mqtt/host_test
- idf.py build
- build/host_mqtt_client_test.elf
build_and_test_qemu:
stage: build
image: ${CI_DOCKER_REGISTRY}/qemu-v5.1:1-20220802
tags:
- build
- shiny
dependencies: []
artifacts:
when: always
paths:
- tidybuild/*
expire_in: 1 day
script:
- cit_add_ssh_key "${GITLAB_KEY}"
- export IDF_PATH=$CI_PROJECT_DIR/esp-idf
- git clone "${IDF_REPO}"
- cd esp-idf
- ./tools/ci/mirror-submodule-update.sh
- export IDF_PATH=$(pwd)
- cd $IDF_PATH/components/mqtt/esp-mqtt
- rm -rf .git
- cp -r $CI_PROJECT_DIR/.git .
- git reset --hard $CI_COMMIT_SHA
# capture compile commands/flags for static analysis
- cd $IDF_PATH/examples/protocols/mqtt/tcp
- mkdir -p tidybuild && cd tidybuild
- cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..
- mv $IDF_PATH/examples/protocols/mqtt/tcp/tidybuild $CI_PROJECT_DIR/tidybuild
# enable pedantic flags for compilation
- export PEDANTIC_CFLAGS="-Werror -Werror=deprecated-declarations -Werror=unused-variable -Werror=unused-but-set-variable -Werror=unused-function"
- export EXTRA_CFLAGS=${PEDANTIC_CFLAGS} && export EXTRA_CXXFLAGS=${EXTRA_CFLAGS}
# build other examples
- cd $IDF_PATH/examples/protocols/mqtt/tcp && idf.py build
- cd $IDF_PATH/examples/protocols/mqtt/ssl && idf.py build
- cd $IDF_PATH/examples/protocols/mqtt/ssl_mutual_auth && idf.py build
- cd $IDF_PATH/examples/protocols/mqtt/ws && idf.py build
- cd $IDF_PATH/examples/protocols/mqtt/wss && idf.py build
# switch to IDF and setup the tools
- $MQTT_PATH/ci/set_idf.sh release/v5.1
- $IDF_PATH/tools/idf_tools.py install-python-env
- cd $IDF_PATH && tools/idf_tools.py --non-interactive install && eval "$(tools/idf_tools.py --non-interactive export)"
# Remove `debug_backend` and Add `paho-mqtt` to the required packages
- sed '/debug_backend/d;/pygobject/d' $IDF_PATH/tools/requirements/requirements.ttfw.txt > requirements.txt
- python -m pip install -r requirements.txt
- python -m pip install paho-mqtt
- $MQTT_PATH/ci/set_mqtt.sh $CI_COMMIT_SHA
# build publish-connect stress test, setup test parameters
- cd tools/test_apps/protocols/mqtt/publish_connect_test && cat sdkconfig.qemu | $IDF_PATH/tools/ci/envsubst.py > sdkconfig.defaults && idf.py build
- export TEST_PATH=`pwd` && export MQTT_PUBLISH_TEST=1
- export PYTHONPATH="$IDF_PATH/tools:$IDF_PATH/tools/ci/python_packages"
# run test (with environment->qemu)
- cd $IDF_PATH/tools/ci/python_packages/tiny_test_fw/bin
# use more relaxed criteria with QEMU tests
- export MQTT_PUBLISH_MSG_len_0=0 MQTT_PUBLISH_MSG_repeat_0=5
- export MQTT_PUBLISH_MSG_len_1=2 MQTT_PUBLISH_MSG_repeat_1=50
- export MQTT_PUBLISH_MSG_len_2=128 MQTT_PUBLISH_MSG_repeat_2=2
- export MQTT_PUBLISH_MSG_len_3=20 MQTT_PUBLISH_MSG_repeat_3=20
- python Runner.py $TEST_PATH -c $MQTT_PATH/ci/publish_connect_mqtt_qemu.yml -e $TEST_PATH/env.yml
clang_tidy_check:
stage: static_analysis
image: ${CI_DOCKER_REGISTRY}/clang-static-analysis
tags:
- host_test
dependencies:
- build_with_idf
artifacts:
reports:
junit: esp-idf/examples/protocols/mqtt/tcp/tidybuild/output.xml
when: always
paths:
- esp-idf/examples/protocols/mqtt/tcp/tidybuild/report/*
expire_in: 1 day
check_remotes_sync:
stage: test
except:
- master
- idf
script:
- cit_add_ssh_key "${GITLAB_KEY}"
- git clone "${IDF_REPO}"
- cd esp-idf
- ./tools/ci/mirror-submodule-update.sh
- export IDF_PATH=$(pwd)
- cd $IDF_PATH/components/mqtt/esp-mqtt
- rm -rf .git
- cp -r $CI_PROJECT_DIR/.git .
- git reset --hard $CI_COMMIT_SHA
- mv $CI_PROJECT_DIR/tidybuild $IDF_PATH/examples/protocols/mqtt/tcp/tidybuild
- cd $IDF_PATH/examples/protocols/mqtt/tcp/tidybuild
- git clone $IDF_ANALYSIS_UTILS static_analysis_utils && cd static_analysis_utils
- ./generate_report.sh $CI_PROJECT_DIR/static-analysis-rules.yml $IDF_PATH/examples/protocols/mqtt/tcp/tidybuild/report $IDF_PATH/examples/protocols/mqtt/tcp/tidybuild/output.xml
deploy_report:
stage: deploy_report
image: $CI_DOCKER_REGISTRY/esp32-ci-env
tags:
- deploy
dependencies:
- clang_tidy_check
script:
- cit_add_ssh_key "${DOCS_DEPLOY_KEY}"
- echo -e "Host $DOCS_SERVER\n\tStrictHostKeyChecking no\n\tUser $DOCS_SERVER_USER\n" >> ~/.ssh/config
- export GIT_VER=$(git describe --always)
- cd esp-idf/examples/protocols/mqtt/tcp/tidybuild
- mv report $GIT_VER
- tar czvf $GIT_VER.tar.gz $GIT_VER
- ssh $DOCS_SERVER -x "mkdir -p $DOCS_PATH/clang-tidy"
- scp $GIT_VER.tar.gz $DOCS_SERVER:$DOCS_PATH/clang-tidy
- ssh $DOCS_SERVER -x "cd $DOCS_PATH/clang-tidy && tar xzvf $GIT_VER.tar.gz && rm -f latest && ln -s $GIT_VER latest"
# add link to view the report
- echo "[static analysis][clang tidy] $CI_DOCKER_REGISTRY/static_analysis/esp-idf/clang-tidy/${GIT_VER}/index.html"
- test ! -e ${GIT_VER}/FAILED_RULES || { echo 'Failed static analysis rules!'; cat ${GIT_VER}/FAILED_RULES; exit 1; }
- *add_gh_key_remote
- git fetch --depth=1 origin master
- git fetch --depth=1 github master
- test "$(git rev-parse origin/master)" == "$(git rev-parse github/master)"
push_master_to_github:
stage: deploy

View File

@ -17,7 +17,7 @@ before_install:
- git checkout -b temporary_ref_branch
- CI_COMMIT_SHA=$(git rev-parse HEAD)
# Test building with latest (stable == v3.3 for now) IDF
- LATEST_IDF=release/v3.3
- LTS_IDF=release/v3.3
install:
# Install ESP32 toochain following steps as desribed
@ -44,13 +44,13 @@ script:
- cd $IDF_PATH
- git checkout v3.1 && git submodule update --init --recursive
- cd $PROJECT_PATH
- ./modify_for_legacy_idf.sh ${LATEST_IDF} || true
- ./ci/modify_for_legacy_idf.sh ${LTS_IDF} || true
- cd $PROJECT_PATH/examples/tcp
- make defconfig
- make -j4
# Build with latest IDF
# Build with v3.3 (LTS) IDF
- cd $IDF_PATH
- git checkout ${LATEST_IDF} && git submodule update --init --recursive
- git checkout ${LTS_IDF} && git submodule update --init --recursive
- cd $IDF_PATH/components/mqtt/esp-mqtt
- git remote add local $PROJECT_PATH/.git
- git fetch local

14
CMakeLists.txt Normal file
View File

@ -0,0 +1,14 @@
set(srcs mqtt_client.c lib/mqtt_msg.c lib/mqtt_outbox.c lib/platform_esp32_idf.c)
if(CONFIG_MQTT_PROTOCOL_5)
list(APPEND srcs lib/mqtt5_msg.c mqtt5_client.c)
endif()
list(TRANSFORM srcs PREPEND ${CMAKE_CURRENT_LIST_DIR}/)
idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS ${CMAKE_CURRENT_LIST_DIR}/include
PRIV_INCLUDE_DIRS ${CMAKE_CURRENT_LIST_DIR}/lib/include
REQUIRES esp_event tcp_transport
PRIV_REQUIRES esp_timer http_parser esp_hw_support heap
KCONFIG ${CMAKE_CURRENT_LIST_DIR}/Kconfig
)

180
Kconfig Normal file
View File

@ -0,0 +1,180 @@
menu "ESP-MQTT Configurations"
config MQTT_PROTOCOL_311
bool "Enable MQTT protocol 3.1.1"
default y
help
If not, this library will use MQTT protocol 3.1
config MQTT_PROTOCOL_5
bool "Enable MQTT protocol 5.0"
default n
help
If not, this library will not support MQTT 5.0
config MQTT_TRANSPORT_SSL
bool "Enable MQTT over SSL"
default y
help
Enable MQTT transport over SSL with mbedtls
config MQTT_TRANSPORT_WEBSOCKET
bool "Enable MQTT over Websocket"
default y
depends on WS_TRANSPORT
help
Enable MQTT transport over Websocket.
config MQTT_TRANSPORT_WEBSOCKET_SECURE
bool "Enable MQTT over Websocket Secure"
default y
depends on MQTT_TRANSPORT_WEBSOCKET
depends on MQTT_TRANSPORT_SSL
help
Enable MQTT transport over Websocket Secure.
config MQTT_MSG_ID_INCREMENTAL
bool "Use Incremental Message Id"
default n
help
Set this to true for the message id (2.3.1 Packet Identifier) to be generated
as an incremental number rather then a random value (used by default)
config MQTT_SKIP_PUBLISH_IF_DISCONNECTED
bool "Skip publish if disconnected"
default n
help
Set this to true to avoid publishing (enqueueing messages) if the client is disconnected.
The MQTT client tries to publish all messages by default, even in the disconnected state
(where the qos1 and qos2 packets are stored in the internal outbox to be published later)
The MQTT_SKIP_PUBLISH_IF_DISCONNECTED option allows applications to override this behaviour
and not enqueue publish packets in the disconnected state.
config MQTT_REPORT_DELETED_MESSAGES
bool "Report deleted messages"
default n
help
Set this to true to post events for all messages which were deleted from the outbox
before being correctly sent and confirmed.
config MQTT_USE_CUSTOM_CONFIG
bool "MQTT Using custom configurations"
default n
help
Custom MQTT configurations.
config MQTT_TCP_DEFAULT_PORT
int "Default MQTT over TCP port"
default 1883
depends on MQTT_USE_CUSTOM_CONFIG
help
Default MQTT over TCP port
config MQTT_SSL_DEFAULT_PORT
int "Default MQTT over SSL port"
default 8883
depends on MQTT_USE_CUSTOM_CONFIG
depends on MQTT_TRANSPORT_SSL
help
Default MQTT over SSL port
config MQTT_WS_DEFAULT_PORT
int "Default MQTT over Websocket port"
default 80
depends on MQTT_USE_CUSTOM_CONFIG
depends on MQTT_TRANSPORT_WEBSOCKET
help
Default MQTT over Websocket port
config MQTT_WSS_DEFAULT_PORT
int "Default MQTT over Websocket Secure port"
default 443
depends on MQTT_USE_CUSTOM_CONFIG
depends on MQTT_TRANSPORT_WEBSOCKET
depends on MQTT_TRANSPORT_WEBSOCKET_SECURE
help
Default MQTT over Websocket Secure port
config MQTT_BUFFER_SIZE
int "Default MQTT Buffer Size"
default 1024
depends on MQTT_USE_CUSTOM_CONFIG
help
This buffer size using for both transmit and receive
config MQTT_TASK_STACK_SIZE
int "MQTT task stack size"
default 6144
depends on MQTT_USE_CUSTOM_CONFIG
help
MQTT task stack size
config MQTT_DISABLE_API_LOCKS
bool "Disable API locks"
default n
depends on MQTT_USE_CUSTOM_CONFIG
help
Default config employs API locks to protect internal structures. It is possible to disable
these locks if the user code doesn't access MQTT API from multiple concurrent tasks
config MQTT_TASK_PRIORITY
int "MQTT task priority"
default 5
depends on MQTT_USE_CUSTOM_CONFIG
help
MQTT task priority. Higher number denotes higher priority.
config MQTT_POLL_READ_TIMEOUT_MS
int "MQTT transport poll read timeut"
default 1000
depends on MQTT_USE_CUSTOM_CONFIG
help
Timeout when polling underlying transport for read.
config MQTT_EVENT_QUEUE_SIZE
int "Number of queued events."
default 1
depends on MQTT_USE_CUSTOM_CONFIG
help
A value higher than 1 enables multiple queued events.
config MQTT_TASK_CORE_SELECTION_ENABLED
bool "Enable MQTT task core selection"
help
This will enable core selection
choice MQTT_TASK_CORE_SELECTION
depends on MQTT_TASK_CORE_SELECTION_ENABLED
prompt "Core to use ?"
config MQTT_USE_CORE_0
bool "Core 0"
config MQTT_USE_CORE_1
bool "Core 1"
endchoice
config MQTT_OUTBOX_DATA_ON_EXTERNAL_MEMORY
bool "Use external memory for outbox data"
default n
depends on MQTT_USE_CUSTOM_CONFIG
help
Set to true to use external memory for outbox data.
config MQTT_CUSTOM_OUTBOX
bool "Enable custom outbox implementation"
default n
help
Set to true if a specific implementation of message outbox is needed (e.g. persistent outbox in NVM or
similar).
Note: Implementation of the custom outbox must be added to the mqtt component. These CMake commands
could be used to append the custom implementation to lib-mqtt sources:
idf_component_get_property(mqtt mqtt COMPONENT_LIB)
set_property(TARGET ${mqtt} PROPERTY SOURCES ${PROJECT_DIR}/custom_outbox.c APPEND)
config MQTT_OUTBOX_EXPIRED_TIMEOUT_MS
int "Outbox message expired timeout[ms]"
default 30000
depends on MQTT_USE_CUSTOM_CONFIG
help
Messages which stays in the outbox longer than this value before being published will be discarded.
endmenu

11
ci/build-test-rules.yml Normal file
View File

@ -0,0 +1,11 @@
# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps
examples/protocols:
enable:
- if: IDF_TARGET in ["esp32"]
examples/protocols/mqtt/ssl_ds:
disable:
- if: SOC_DIG_SIGN_SUPPORTED != 1
temporary: false
reason: DS not present

22
ci/build_examples.sh Executable file
View File

@ -0,0 +1,22 @@
#!/usr/bin/env bash
# build mqtt examples with make if $1=="make", with cmake otherwise
set -o errexit # Exit if command failed.
if [ -z $IDF_PATH ] ; then
echo "Mandatory variables undefined"
exit 1;
fi;
examples="tcp ssl ssl_mutual_auth ws wss"
for i in $examples; do
echo "Building MQTT example $i"
cd $IDF_PATH/examples/protocols/mqtt/$i
if [[ "$1" = "make" ]]; then
make defconfig
make -j 4
else
rm -rf build sdkconfig
idf.py build
fi;
done

2
ci/idf_build_apps.toml Normal file
View File

@ -0,0 +1,2 @@
build_dir = "$GITHUB_WORKSPACE/build_@t_@n"
config="sdkconfig.ci"

View File

@ -0,0 +1,7 @@
CaseConfig:
- name: test_app_protocol_mqtt_publish_connect
overwrite:
dut:
class: ESP32QEMUDUT
package: ttfw_idf

19
ci/set_idf.sh Executable file
View File

@ -0,0 +1,19 @@
#!/usr/bin/env bash
# sets up the IDF repo incl submodules with specified version as $1
set -o errexit # Exit if command failed.
if [ -z $IDF_PATH ] || [ -z $MQTT_PATH ] || [ -z $1 ] ; then
echo "Mandatory variables undefined"
exit 1;
fi;
echo "Checking out IDF version $1"
cd $IDF_PATH
# Cleans out the untracked files in the repo, so the next "git checkout" doesn't fail
git clean -f
git checkout $1
# Removes the mqtt submodule, so the next submodule update doesn't fail
rm -rf $IDF_PATH/components/mqtt/esp-mqtt
git submodule update --init --recursive

16
ci/set_mqtt.sh Executable file
View File

@ -0,0 +1,16 @@
#!/usr/bin/env bash
# sets the mqtt in IDF tree as a submodule with the version specified as $1
set -o errexit # Exit if command failed.
if [ -z $IDF_PATH ] || [ -z $MQTT_PATH ] || [ -z $1 ] ; then
echo "Mandatory variables undefined"
exit 1;
fi;
echo "Checking out MQTT version to $1"
# exchange remotes of mqtt submodules with plain copy
cd $IDF_PATH/components/mqtt/esp-mqtt
rm -rf .git # removes the actual IDF referenced version
cp -r $MQTT_PATH/.git . # replaces with the MQTT_PATH (CI checked tree)
git reset --hard $1 # sets the requested version

View File

@ -1,19 +0,0 @@
cmake_minimum_required(VERSION 3.5)
get_filename_component(DEV_ROOT "${CMAKE_CURRENT_SOURCE_DIR}" ABSOLUTE)
set(PROJECT_ROOT "${DEV_ROOT}/")
set(SUBMODULE_ROOT "${DEV_ROOT}/../../../")
set(PROJECT_NAME "mqtt_ssl")
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set(MAIN_SRCS ${PROJECT_ROOT}/main/app_main.c)
set(EXTRA_COMPONENT_DIRS "${EXTRA_COMPONENT_DIRS} ${SUBMODULE_ROOT}")
set(BUILD_COMPONENTS "${BUILD_COMPONENTS} espmqtt")
project(${PROJECT_NAME})

View File

@ -1,13 +0,0 @@
#
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#
#
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#
PROJECT_NAME := emitter_client
EXTRA_COMPONENT_DIRS += $(PROJECT_PATH)/../../../
include $(IDF_PATH)/make/project.mk

View File

@ -1,10 +0,0 @@
# ESPMQTT Emitter client
## Before you run this Example
- Register an account from https://emitter.io/
- Login and create channel key, grant access for the channel `/topic/` as the images bellow
- `make menuconfig` provide Wi-Fi information and CHANNEL_KEY to `MQTT Application example`
- `make flash monitor`
![](generate-key-0.png)
![](generate-key-1.png)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 234 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

View File

@ -1,22 +0,0 @@
menu "MQTT Application example"
config WIFI_SSID
string "WiFi SSID"
default "myssid"
help
SSID (network name) for the example to connect to.
config WIFI_PASSWORD
string "WiFi Password"
default "mypassword"
help
WiFi password (WPA or WPA2) for the example to use.
config EMITTER_CHANNEL_KEY
string "Emitter channel key"
default ""
help
The Emitter channel key using to pub/sub
endmenu

View File

@ -1,143 +0,0 @@
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include "esp_wifi.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_event_loop.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "freertos/event_groups.h"
#include "lwip/sockets.h"
#include "lwip/dns.h"
#include "lwip/netdb.h"
#include "esp_log.h"
#include "mqtt_client.h"
static const char *TAG = "MQTTS_SAMPLE";
static EventGroupHandle_t wifi_event_group;
const static int CONNECTED_BIT = BIT0;
static esp_err_t wifi_event_handler(void *ctx, system_event_t *event)
{
switch (event->event_id) {
case SYSTEM_EVENT_STA_START:
esp_wifi_connect();
break;
case SYSTEM_EVENT_STA_GOT_IP:
xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
esp_wifi_connect();
xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
break;
default:
break;
}
return ESP_OK;
}
static void wifi_init(void)
{
tcpip_adapter_init();
wifi_event_group = xEventGroupCreate();
ESP_ERROR_CHECK(esp_event_loop_init(wifi_event_handler, NULL));
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
wifi_config_t wifi_config = {
.sta = {
.ssid = CONFIG_WIFI_SSID,
.password = CONFIG_WIFI_PASSWORD,
},
};
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
ESP_LOGI(TAG, "start the WIFI SSID:[%s] password:[%s]", CONFIG_WIFI_SSID, "******");
ESP_ERROR_CHECK(esp_wifi_start());
ESP_LOGI(TAG, "Waiting for wifi");
xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY);
}
static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event)
{
esp_mqtt_client_handle_t client = event->client;
int msg_id;
// your_context_t *context = event->context;
switch (event->event_id) {
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
msg_id = esp_mqtt_client_subscribe(client, CONFIG_EMITTER_CHANNEL_KEY"/topic/", 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
break;
case MQTT_EVENT_SUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
msg_id = esp_mqtt_client_publish(client, CONFIG_EMITTER_CHANNEL_KEY"/topic/", "data", 0, 0, 0);
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_UNSUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_PUBLISHED:
ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_DATA:
ESP_LOGI(TAG, "MQTT_EVENT_DATA");
printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
printf("DATA=%.*s\r\n", event->data_len, event->data);
break;
case MQTT_EVENT_ERROR:
ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
break;
}
return ESP_OK;
}
static void mqtt_app_start(void)
{
const esp_mqtt_client_config_t mqtt_cfg = {
.uri = "mqtts://api.emitter.io:443", // for mqtt over ssl
// .uri = "mqtt://api.emitter.io:8080", //for mqtt over tcp
// .uri = "ws://api.emitter.io:8080", //for mqtt over websocket
// .uri = "wss://api.emitter.io:443", //for mqtt over websocket secure
.event_handle = mqtt_event_handler,
};
ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size());
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
esp_mqtt_client_start(client);
}
void app_main()
{
ESP_LOGI(TAG, "[APP] Startup..");
ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size());
ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());
esp_log_level_set("*", ESP_LOG_INFO);
esp_log_level_set("MQTT_CLIENT", ESP_LOG_VERBOSE);
esp_log_level_set("TRANSPORT_TCP", ESP_LOG_VERBOSE);
esp_log_level_set("TRANSPORT_SSL", ESP_LOG_VERBOSE);
esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE);
esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE);
nvs_flash_init();
wifi_init();
mqtt_app_start();
}

16
host_test/CMakeLists.txt Normal file
View File

@ -0,0 +1,16 @@
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set(COMPONENTS mqtt main)
list(APPEND EXTRA_COMPONENT_DIRS
"mocks/heap/"
"$ENV{IDF_PATH}/tools/mocks/esp_hw_support/"
"$ENV{IDF_PATH}/tools/mocks/freertos/"
"$ENV{IDF_PATH}/tools/mocks/esp_timer/"
"$ENV{IDF_PATH}/tools/mocks/esp_event/"
"$ENV{IDF_PATH}/tools/mocks/lwip/"
"$ENV{IDF_PATH}/tools/mocks/esp-tls/"
"$ENV{IDF_PATH}/tools/mocks/http_parser/"
"$ENV{IDF_PATH}/tools/mocks/tcp_transport/")
project(host_mqtt_client_test)

30
host_test/README.md Normal file
View File

@ -0,0 +1,30 @@
| Supported Targets | Linux |
| ----------------- | ----- |
# Description
This directory contains test code for the mqtt client that runs on host.
Tests are written using [Catch2](https://github.com/catchorg/Catch2) test framework
# Build
Tests build regularly like an idf project.
```
idf.py build
```
# Run
The build produces an executable in the build folder.
Just run:
```
./build/host_mqtt_client_test.elf
```
The test executable have some options provided by the test framework.

View File

@ -0,0 +1,20 @@
idf_component_register(SRCS "test_mqtt_client.cpp"
INCLUDE_DIRS "$ENV{IDF_PATH}/tools/catch"
REQUIRES cmock mqtt esp_timer esp_hw_support http_parser log)
target_compile_options(${COMPONENT_LIB} PUBLIC -fsanitize=address -fconcepts)
target_link_options(${COMPONENT_LIB} PUBLIC -fsanitize=address)
idf_component_get_property(mqtt mqtt COMPONENT_LIB)
target_compile_definitions(${mqtt} PRIVATE SOC_WIFI_SUPPORTED=1)
target_compile_options(${mqtt} PUBLIC -fsanitize=address -fconcepts)
target_link_options(${mqtt} PUBLIC -fsanitize=address)
if(CONFIG_GCOV_ENABLED)
target_compile_options(${COMPONENT_LIB} PUBLIC --coverage -fprofile-arcs -ftest-coverage)
target_link_options(${COMPONENT_LIB} PUBLIC --coverage -fprofile-arcs -ftest-coverage)
idf_component_get_property(mqtt mqtt COMPONENT_LIB)
target_compile_options(${mqtt} PUBLIC --coverage -fprofile-arcs -ftest-coverage)
target_link_options(${mqtt} PUBLIC --coverage -fprofile-arcs -ftest-coverage)
endif()

9
host_test/main/Kconfig Normal file
View File

@ -0,0 +1,9 @@
menu "Host-test config"
config GCOV_ENABLED
bool "Coverage analyzer"
default n
help
Enables coverage analyzing for host tests.
endmenu

View File

@ -0,0 +1,169 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <memory>
#include <net/if.h>
#include <random>
#include <string_view>
#include <type_traits>
#include "esp_transport.h"
#define CATCH_CONFIG_MAIN // This tells the catch header to generate a main
#include "catch.hpp"
#include "mqtt_client.h"
extern "C" {
#include "Mockesp_event.h"
#include "Mockesp_mac.h"
#include "Mockesp_transport.h"
#include "Mockesp_transport_ssl.h"
#include "Mockesp_transport_tcp.h"
#include "Mockesp_transport_ws.h"
#include "Mockevent_groups.h"
#include "Mockhttp_parser.h"
#include "Mockqueue.h"
#include "Mocktask.h"
#if __has_include ("Mockidf_additions.h")
/* Some functions were moved from "task.h" to "idf_additions.h" */
#include "Mockidf_additions.h"
#endif
#include "Mockesp_timer.h"
/*
* The following functions are not directly called but the generation of them
* from cmock is broken, so we need to define them here.
*/
esp_err_t esp_tls_get_and_clear_last_error(esp_tls_error_handle_t h, int *esp_tls_code, int *esp_tls_flags)
{
return ESP_OK;
}
}
auto random_string(std::size_t n)
{
static constexpr std::string_view char_set = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456790";
std::string str;
std::sample(char_set.begin(), char_set.end(), std::back_inserter(str), n,
std::mt19937 {std::random_device{}()});
return str;
}
using unique_mqtt_client = std::unique_ptr < std::remove_pointer_t<esp_mqtt_client_handle_t>, decltype([](esp_mqtt_client_handle_t client)
{
esp_mqtt_client_destroy(client);
}) >;
SCENARIO("MQTT Client Operation")
{
// Set expectations for the mocked calls.
int mtx = 0;
int transport_list = 0;
int transport = 0;
int event_group = 0;
uint8_t mac[] = {0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55};
esp_timer_get_time_IgnoreAndReturn(0);
xQueueTakeMutexRecursive_IgnoreAndReturn(true);
xQueueGiveMutexRecursive_IgnoreAndReturn(true);
xQueueCreateMutex_ExpectAnyArgsAndReturn(
reinterpret_cast<QueueHandle_t>(&mtx));
xEventGroupCreate_IgnoreAndReturn(reinterpret_cast<EventGroupHandle_t>(&event_group));
esp_transport_list_init_IgnoreAndReturn(reinterpret_cast<esp_transport_list_handle_t>(&transport_list));
esp_transport_tcp_init_IgnoreAndReturn(reinterpret_cast<esp_transport_handle_t>(&transport));
esp_transport_ssl_init_IgnoreAndReturn(reinterpret_cast<esp_transport_handle_t>(&transport));
esp_transport_ws_init_IgnoreAndReturn(reinterpret_cast<esp_transport_handle_t>(&transport));
esp_transport_ws_set_subprotocol_IgnoreAndReturn(ESP_OK);
esp_transport_list_add_IgnoreAndReturn(ESP_OK);
esp_transport_set_default_port_IgnoreAndReturn(ESP_OK);
http_parser_url_init_Ignore();
esp_event_loop_create_IgnoreAndReturn(ESP_OK);
esp_read_mac_IgnoreAndReturn(ESP_OK);
esp_read_mac_ReturnThruPtr_mac(mac);
esp_transport_list_destroy_IgnoreAndReturn(ESP_OK);
esp_transport_destroy_IgnoreAndReturn(ESP_OK);
vEventGroupDelete_Ignore();
vQueueDelete_Ignore();
GIVEN("An a minimal config") {
esp_mqtt_client_config_t config{};
config.broker.address.uri = "mqtt://1.1.1.1";
struct http_parser_url ret_uri = {
.field_set = 1 | (1 << 1),
.port = 0,
.field_data = { { 0, 4 } /*mqtt*/, { 7, 1 } } // at least *scheme* and *host*
};
http_parser_parse_url_ExpectAnyArgsAndReturn(0);
http_parser_parse_url_ReturnThruPtr_u(&ret_uri);
xTaskCreatePinnedToCore_ExpectAnyArgsAndReturn(pdTRUE);
SECTION("Client with minimal config") {
auto client = unique_mqtt_client{esp_mqtt_client_init(&config)};
REQUIRE(client != nullptr);
SECTION("User will set a new uri") {
struct http_parser_url ret_uri = {
.field_set = 1,
.port = 0,
.field_data = { { 0, 1} }
};
SECTION("User set a correct URI") {
http_parser_parse_url_StopIgnore();
http_parser_parse_url_ExpectAnyArgsAndReturn(0);
http_parser_parse_url_ReturnThruPtr_u(&ret_uri);
auto res = esp_mqtt_client_set_uri(client.get(), " ");
REQUIRE(res == ESP_OK);
}
SECTION("Incorrect URI from user") {
http_parser_parse_url_StopIgnore();
http_parser_parse_url_ExpectAnyArgsAndReturn(1);
http_parser_parse_url_ReturnThruPtr_u(&ret_uri);
auto res = esp_mqtt_client_set_uri(client.get(), " ");
REQUIRE(res == ESP_FAIL);
}
}
SECTION("User set interface to use"){
http_parser_parse_url_ExpectAnyArgsAndReturn(0);
http_parser_parse_url_ReturnThruPtr_u(&ret_uri);
struct ifreq if_name = {.ifr_ifrn = {"custom"}};
config.network.if_name = &if_name;
SECTION("Client is not started"){
REQUIRE(esp_mqtt_set_config(client.get(), &config)== ESP_OK);
}
}
SECTION("After Start Client Is Cleanly destroyed") {
REQUIRE(esp_mqtt_client_start(client.get()) == ESP_OK);
// Only need to start the client, destroy is called automatically at the end of
// scope
}
}
SECTION("Client with all allocating configuration set") {
auto host = random_string(20);
auto path = random_string(10);
auto username = random_string(10);
auto client_id = random_string(10);
auto password = random_string(10);
auto lw_topic = random_string(10);
auto lw_msg = random_string(10);
config.broker = {.address = {
.hostname = host.data(),
.path = path.data()
}
};
config.credentials = {
.username = username.data(),
.client_id = client_id.data(),
.authentication = {
.password = password.data()
}
};
config.session = {
.last_will {
.topic = lw_topic.data(),
.msg = lw_msg.data()
}
};
auto client = unique_mqtt_client{esp_mqtt_client_init(&config)};
REQUIRE(client != nullptr);
}
}
}

View File

@ -0,0 +1,4 @@
idf_component_get_property(original_heap_dir heap COMPONENT_OVERRIDEN_DIR)
idf_component_register(SRCS heap_mock.c
INCLUDE_DIRS "${original_heap_dir}/include")

View File

@ -0,0 +1,11 @@
#include "esp_heap_caps.h"
#include <stdint.h>
#include <stdlib.h>
void *heap_caps_calloc(size_t n, size_t size, uint32_t caps) {
(void)caps;
return calloc(n, size);
}

View File

@ -0,0 +1,71 @@
/*
* SPDX-FileCopyrightText: 1991-1993 The Regents of the University of California
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#pragma once
/* Implementation from BSD headers*/
#define QMD_SAVELINK(name, link) void **name = (void *)&(link)
#define TRASHIT(x) do {(x) = (void *)-1;} while (0)
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
#define STAILQ_FIRST(head) ((head)->stqh_first)
#define STAILQ_HEAD(name, type) \
struct name { \
struct type *stqh_first;/* first element */ \
struct type **stqh_last;/* addr of last next element */ \
}
#define STAILQ_ENTRY(type) \
struct { \
struct type *stqe_next; /* next element */ \
}
#define STAILQ_INSERT_TAIL(head, elm, field) do { \
STAILQ_NEXT((elm), field) = NULL; \
*(head)->stqh_last = (elm); \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
} while (0)
#define STAILQ_INIT(head) do { \
STAILQ_FIRST((head)) = NULL; \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0)
#define STAILQ_FOREACH(var, head, field) \
for((var) = STAILQ_FIRST((head)); \
(var); \
(var) = STAILQ_NEXT((var), field))
#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = STAILQ_FIRST((head)); \
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
(var) = (tvar))
#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
if ((STAILQ_NEXT(elm, field) = \
STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
} while (0)
#define STAILQ_REMOVE_HEAD(head, field) do { \
if ((STAILQ_FIRST((head)) = \
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0)
#define STAILQ_REMOVE(head, elm, type, field) do { \
QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \
if (STAILQ_FIRST((head)) == (elm)) { \
STAILQ_REMOVE_HEAD((head), field); \
} \
else { \
struct type *curelm = STAILQ_FIRST((head)); \
while (STAILQ_NEXT(curelm, field) != (elm)) \
curelm = STAILQ_NEXT(curelm, field); \
STAILQ_REMOVE_AFTER(head, curelm, field); \
} \
TRASHIT(*oldnext); \
} while (0)

View File

@ -0,0 +1 @@
CONFIG_GCOV_ENABLED=y

View File

@ -0,0 +1,6 @@
CONFIG_IDF_TARGET="linux"
CONFIG_COMPILER_CXX_EXCEPTIONS=y
CONFIG_COMPILER_CXX_RTTI=y
CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE=0
CONFIG_COMPILER_STACK_CHECK_NONE=y
CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=n

5
idf_component.yml Normal file
View File

@ -0,0 +1,5 @@
version: "1.0.0"
description: esp-mqtt
dependencies:
idf:
version: ">=5.0"

286
include/mqtt5_client.h Normal file
View File

@ -0,0 +1,286 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _MQTT5_CLIENT_H_
#define _MQTT5_CLIENT_H_
#include "mqtt_client.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct esp_mqtt_client *esp_mqtt5_client_handle_t;
/**
* MQTT5 protocol error reason code, more details refer to MQTT5 protocol document section 2.4
*/
enum mqtt5_error_reason_code {
MQTT5_UNSPECIFIED_ERROR = 0x80,
MQTT5_MALFORMED_PACKET = 0x81,
MQTT5_PROTOCOL_ERROR = 0x82,
MQTT5_IMPLEMENT_SPECIFIC_ERROR = 0x83,
MQTT5_UNSUPPORTED_PROTOCOL_VER = 0x84,
MQTT5_INVAILD_CLIENT_ID __attribute__((deprecated)) = 0x85,
MQTT5_INVALID_CLIENT_ID = 0x85,
MQTT5_BAD_USERNAME_OR_PWD = 0x86,
MQTT5_NOT_AUTHORIZED = 0x87,
MQTT5_SERVER_UNAVAILABLE = 0x88,
MQTT5_SERVER_BUSY = 0x89,
MQTT5_BANNED = 0x8A,
MQTT5_SERVER_SHUTTING_DOWN = 0x8B,
MQTT5_BAD_AUTH_METHOD = 0x8C,
MQTT5_KEEP_ALIVE_TIMEOUT = 0x8D,
MQTT5_SESSION_TAKEN_OVER = 0x8E,
MQTT5_TOPIC_FILTER_INVAILD __attribute__((deprecated)) = 0x8F,
MQTT5_TOPIC_FILTER_INVALID = 0x8F,
MQTT5_TOPIC_NAME_INVAILD __attribute__((deprecated)) = 0x90,
MQTT5_TOPIC_NAME_INVALID = 0x90,
MQTT5_PACKET_IDENTIFIER_IN_USE = 0x91,
MQTT5_PACKET_IDENTIFIER_NOT_FOUND = 0x92,
MQTT5_RECEIVE_MAXIMUM_EXCEEDED = 0x93,
MQTT5_TOPIC_ALIAS_INVAILD __attribute__((deprecated)) = 0x94,
MQTT5_TOPIC_ALIAS_INVALID = 0x94,
MQTT5_PACKET_TOO_LARGE = 0x95,
MQTT5_MESSAGE_RATE_TOO_HIGH = 0x96,
MQTT5_QUOTA_EXCEEDED = 0x97,
MQTT5_ADMINISTRATIVE_ACTION = 0x98,
MQTT5_PAYLOAD_FORMAT_INVAILD __attribute__((deprecated)) = 0x99,
MQTT5_PAYLOAD_FORMAT_INVALID = 0x99,
MQTT5_RETAIN_NOT_SUPPORT = 0x9A,
MQTT5_QOS_NOT_SUPPORT = 0x9B,
MQTT5_USE_ANOTHER_SERVER = 0x9C,
MQTT5_SERVER_MOVED = 0x9D,
MQTT5_SHARED_SUBSCR_NOT_SUPPORTED = 0x9E,
MQTT5_CONNECTION_RATE_EXCEEDED = 0x9F,
MQTT5_MAXIMUM_CONNECT_TIME = 0xA0,
MQTT5_SUBSCRIBE_IDENTIFIER_NOT_SUPPORT = 0xA1,
MQTT5_WILDCARD_SUBSCRIBE_NOT_SUPPORT = 0xA2,
};
/**
* MQTT5 user property handle
*/
typedef struct mqtt5_user_property_list_t *mqtt5_user_property_handle_t;
/**
* MQTT5 protocol connect properties and will properties configuration, more details refer to MQTT5 protocol document section 3.1.2.11 and 3.3.2.3
*/
typedef struct {
uint32_t session_expiry_interval; /*!< The interval time of session expiry */
uint32_t maximum_packet_size; /*!< The maximum packet size that we can receive */
uint16_t receive_maximum; /*!< The maximum pakcket count that we process concurrently */
uint16_t topic_alias_maximum; /*!< The maximum topic alias that we support */
bool request_resp_info; /*!< This value to request Server to return Response information */
bool request_problem_info; /*!< This value to indicate whether the reason string or user properties are sent in case of failures */
mqtt5_user_property_handle_t user_property; /*!< The handle for user property, call function esp_mqtt5_client_set_user_property to set it */
uint32_t will_delay_interval; /*!< The time interval that server delays publishing will message */
uint32_t message_expiry_interval; /*!< The time interval that message expiry */
bool payload_format_indicator; /*!< This value is to indicator will message payload format */
const char *content_type; /*!< This value is to indicator will message content type, use a MIME content type string */
const char *response_topic; /*!< Topic name for a response message */
const char *correlation_data; /*!< Binary data for receiver to match the response message */
uint16_t correlation_data_len; /*!< The length of correlation data */
mqtt5_user_property_handle_t will_user_property; /*!< The handle for will message user property, call function esp_mqtt5_client_set_user_property to set it */
} esp_mqtt5_connection_property_config_t;
/**
* MQTT5 protocol publish properties configuration, more details refer to MQTT5 protocol document section 3.3.2.3
*/
typedef struct {
bool payload_format_indicator; /*!< This value is to indicator publish message payload format */
uint32_t message_expiry_interval; /*!< The time interval that message expiry */
uint16_t topic_alias; /*!< An interger value to identify the topic instead of using topic name string */
const char *response_topic; /*!< Topic name for a response message */
const char *correlation_data; /*!< Binary data for receiver to match the response message */
uint16_t correlation_data_len; /*!< The length of correlation data */
const char *content_type; /*!< This value is to indicator publish message content type, use a MIME content type string */
mqtt5_user_property_handle_t user_property; /*!< The handle for user property, call function esp_mqtt5_client_set_user_property to set it */
} esp_mqtt5_publish_property_config_t;
/**
* MQTT5 protocol subscribe properties configuration, more details refer to MQTT5 protocol document section 3.8.2.1
*/
typedef struct {
uint16_t subscribe_id; /*!< A variable byte represents the identifier of the subscription */
bool no_local_flag; /*!< Subscription Option to allow that server publish message that client sent */
bool retain_as_published_flag; /*!< Subscription Option to keep the retain flag as published option */
uint8_t retain_handle; /*!< Subscription Option to handle retain option */
bool is_share_subscribe; /*!< Whether subscribe is a shared subscription */
const char *share_name; /*!< The name of shared subscription which is a part of $share/{share_name}/{topic} */
mqtt5_user_property_handle_t user_property; /*!< The handle for user property, call function esp_mqtt5_client_set_user_property to set it */
} esp_mqtt5_subscribe_property_config_t;
/**
* MQTT5 protocol unsubscribe properties configuration, more details refer to MQTT5 protocol document section 3.10.2.1
*/
typedef struct {
bool is_share_subscribe; /*!< Whether subscribe is a shared subscription */
const char *share_name; /*!< The name of shared subscription which is a part of $share/{share_name}/{topic} */
mqtt5_user_property_handle_t user_property; /*!< The handle for user property, call function esp_mqtt5_client_set_user_property to set it */
} esp_mqtt5_unsubscribe_property_config_t;
/**
* MQTT5 protocol disconnect properties configuration, more details refer to MQTT5 protocol document section 3.14.2.2
*/
typedef struct {
uint32_t session_expiry_interval; /*!< The interval time of session expiry */
uint8_t disconnect_reason; /*!< The reason that connection disconnet, refer to mqtt5_error_reason_code */
mqtt5_user_property_handle_t user_property; /*!< The handle for user property, call function esp_mqtt5_client_set_user_property to set it */
} esp_mqtt5_disconnect_property_config_t;
/**
* MQTT5 protocol for event properties
*/
typedef struct {
bool payload_format_indicator; /*!< Payload format of the message */
char *response_topic; /*!< Response topic of the message */
int response_topic_len; /*!< Response topic length of the message */
char *correlation_data; /*!< Correlation data of the message */
uint16_t correlation_data_len; /*!< Correlation data length of the message */
char *content_type; /*!< Content type of the message */
int content_type_len; /*!< Content type length of the message */
uint16_t subscribe_id; /*!< Subscription identifier of the message */
mqtt5_user_property_handle_t user_property; /*!< The handle for user property, call function esp_mqtt5_client_delete_user_property to free the memory */
} esp_mqtt5_event_property_t;
/**
* MQTT5 protocol for user property
*/
typedef struct {
const char *key; /*!< Item key name */
const char *value; /*!< Item value string */
} esp_mqtt5_user_property_item_t;
/**
* @brief Set MQTT5 client connect property configuration
*
* @param client mqtt client handle
* @param connect_property connect property
*
* @return ESP_ERR_NO_MEM if failed to allocate
* ESP_ERR_INVALID_ARG on wrong initialization
* ESP_FAIL on fail
* ESP_OK on success
*/
esp_err_t esp_mqtt5_client_set_connect_property(esp_mqtt5_client_handle_t client, const esp_mqtt5_connection_property_config_t *connect_property);
/**
* @brief Set MQTT5 client publish property configuration
*
* This API will not store the publish property, it is one-time configuration.
* Before call `esp_mqtt_client_publish` to publish data, call this API to set publish property if have
*
* @param client mqtt client handle
* @param property publish property
*
* @return ESP_ERR_INVALID_ARG on wrong initialization
* ESP_FAIL on fail
* ESP_OK on success
*/
esp_err_t esp_mqtt5_client_set_publish_property(esp_mqtt5_client_handle_t client, const esp_mqtt5_publish_property_config_t *property);
/**
* @brief Set MQTT5 client subscribe property configuration
*
* This API will not store the subscribe property, it is one-time configuration.
* Before call `esp_mqtt_client_subscribe` to subscribe topic, call this API to set subscribe property if have
*
* @param client mqtt client handle
* @param property subscribe property
*
* @return ESP_ERR_INVALID_ARG on wrong initialization
* ESP_FAIL on fail
* ESP_OK on success
*/
esp_err_t esp_mqtt5_client_set_subscribe_property(esp_mqtt5_client_handle_t client, const esp_mqtt5_subscribe_property_config_t *property);
/**
* @brief Set MQTT5 client unsubscribe property configuration
*
* This API will not store the unsubscribe property, it is one-time configuration.
* Before call `esp_mqtt_client_unsubscribe` to unsubscribe topic, call this API to set unsubscribe property if have
*
* @param client mqtt client handle
* @param property unsubscribe property
*
* @return ESP_ERR_INVALID_ARG on wrong initialization
* ESP_FAIL on fail
* ESP_OK on success
*/
esp_err_t esp_mqtt5_client_set_unsubscribe_property(esp_mqtt5_client_handle_t client, const esp_mqtt5_unsubscribe_property_config_t *property);
/**
* @brief Set MQTT5 client disconnect property configuration
*
* This API will not store the disconnect property, it is one-time configuration.
* Before call `esp_mqtt_client_disconnect` to disconnect connection, call this API to set disconnect property if have
*
* @param client mqtt client handle
* @param property disconnect property
*
* @return ESP_ERR_NO_MEM if failed to allocate
* ESP_ERR_INVALID_ARG on wrong initialization
* ESP_FAIL on fail
* ESP_OK on success
*/
esp_err_t esp_mqtt5_client_set_disconnect_property(esp_mqtt5_client_handle_t client, const esp_mqtt5_disconnect_property_config_t *property);
/**
* @brief Set MQTT5 client user property configuration
*
* This API will allocate memory for user_property, please DO NOT forget `call esp_mqtt5_client_delete_user_property`
* after you use it.
* Before publish data, subscribe topic, unsubscribe, etc, call this API to set user property if have
*
* @param user_property user_property handle
* @param item array of user property data (eg. {{"var","val"},{"other","2"}})
* @param item_num number of items in user property data
*
* @return ESP_ERR_NO_MEM if failed to allocate
* ESP_FAIL on fail
* ESP_OK on success
*/
esp_err_t esp_mqtt5_client_set_user_property(mqtt5_user_property_handle_t *user_property, esp_mqtt5_user_property_item_t item[], uint8_t item_num);
/**
* @brief Get MQTT5 client user property
*
* @param user_property user_property handle
* @param item point that store user property data
* @param item_num number of items in user property data
*
* This API can use with `esp_mqtt5_client_get_user_property_count` to get list count of user property.
* And malloc number of count item array memory to store the user property data.
* Please DO NOT forget the item memory, key and value point in item memory when get user property data successfully.
*
* @return ESP_ERR_NO_MEM if failed to allocate
* ESP_FAIL on fail
* ESP_OK on success
*/
esp_err_t esp_mqtt5_client_get_user_property(mqtt5_user_property_handle_t user_property, esp_mqtt5_user_property_item_t *item, uint8_t *item_num);
/**
* @brief Get MQTT5 client user property list count
*
* @param user_property user_property handle
* @return user property list count
*/
uint8_t esp_mqtt5_client_get_user_property_count(mqtt5_user_property_handle_t user_property);
/**
* @brief Free the user property list
*
* @param user_property user_property handle
*
* This API will free the memory in user property list and free user_property itself
*/
void esp_mqtt5_client_delete_user_property(mqtt5_user_property_handle_t user_property);
#ifdef __cplusplus
}
#endif //__cplusplus
#endif

View File

@ -11,9 +11,11 @@
#include <stdbool.h>
#include <string.h>
#include "esp_err.h"
#include "mqtt_config.h"
#include "esp_event.h"
#include "esp_transport.h"
#ifdef CONFIG_MQTT_PROTOCOL_5
#include "mqtt5_client.h"
#endif
#ifdef __cplusplus
extern "C" {
@ -21,128 +23,382 @@ extern "C" {
#ifndef ESP_EVENT_DECLARE_BASE
// Define event loop types if macros not available
typedef void * esp_event_loop_handle_t;
typedef void * esp_event_handler_t;
typedef void *esp_event_loop_handle_t;
typedef void *esp_event_handler_t;
#endif
typedef struct esp_mqtt_client *esp_mqtt_client_handle_t;
/**
* @brief MQTT event types.
* @brief *MQTT* event types.
*
* User event handler receives context data in `esp_mqtt_event_t` structure with
* - `user_context` - user data from `esp_mqtt_client_config_t`
* - `client` - mqtt client handle
* - client - *MQTT* client handle
* - various other data depending on event type
*
*/
typedef enum {
MQTT_EVENT_ERROR = 0,
MQTT_EVENT_CONNECTED, /*!< connected event, additional context: session_present flag */
MQTT_EVENT_DISCONNECTED, /*!< disconnected event */
MQTT_EVENT_SUBSCRIBED, /*!< subscribed event, additional context: msg_id */
MQTT_EVENT_UNSUBSCRIBED, /*!< unsubscribed event */
MQTT_EVENT_PUBLISHED, /*!< published event, additional context: msg_id */
MQTT_EVENT_DATA, /*!< data event, additional context:
- msg_id message id
- topic pointer to the received topic
- topic_len length of the topic
- data pointer to the received data
- data_len length of the data for this event
- current_data_offset offset of the current data for this event
- total_data_len total length of the data received
Note: Multiple MQTT_EVENT_DATA could be fired for one message, if it is
longer than internal buffer. In that case only first event contains topic
pointer and length, other contain data only with current data length
and current data offset updating.
*/
MQTT_EVENT_BEFORE_CONNECT, /*!< The event occurs before connecting */
typedef enum esp_mqtt_event_id_t {
MQTT_EVENT_ANY = -1,
MQTT_EVENT_ERROR =
0, /*!< on error event, additional context: connection return code, error
handle from esp_tls (if supported) */
MQTT_EVENT_CONNECTED, /*!< connected event, additional context:
session_present flag */
MQTT_EVENT_DISCONNECTED, /*!< disconnected event */
MQTT_EVENT_SUBSCRIBED, /*!< subscribed event, additional context:
- msg_id message id
- error_handle `error_type` in case subscribing failed
- data pointer to broker response, check for errors.
- data_len length of the data for this
event
*/
MQTT_EVENT_UNSUBSCRIBED, /*!< unsubscribed event, additional context: msg_id */
MQTT_EVENT_PUBLISHED, /*!< published event, additional context: msg_id */
MQTT_EVENT_DATA, /*!< data event, additional context:
- msg_id message id
- topic pointer to the received topic
- topic_len length of the topic
- data pointer to the received data
- data_len length of the data for this event
- current_data_offset offset of the current data for
this event
- total_data_len total length of the data received
- retain retain flag of the message
- qos QoS level of the message
- dup dup flag of the message
Note: Multiple MQTT_EVENT_DATA could be fired for one
message, if it is longer than internal buffer. In that
case only first event contains topic pointer and length,
other contain data only with current data length and
current data offset updating.
*/
MQTT_EVENT_BEFORE_CONNECT, /*!< The event occurs before connecting */
MQTT_EVENT_DELETED, /*!< Notification on delete of one message from the
internal outbox, if the message couldn't have been sent
and acknowledged before expiring defined in
OUTBOX_EXPIRED_TIMEOUT_MS. (events are not posted upon
deletion of successfully acknowledged messages)
- This event id is posted only if
MQTT_REPORT_DELETED_MESSAGES==1
- Additional context: msg_id (id of the deleted
message).
*/
MQTT_USER_EVENT, /*!< Custom event used to queue tasks into mqtt event handler
All fields from the esp_mqtt_event_t type could be used to pass
an additional context data to the handler.
*/
} esp_mqtt_event_id_t;
typedef enum {
/**
* *MQTT* connection error codes propagated via ERROR event
*/
typedef enum esp_mqtt_connect_return_code_t {
MQTT_CONNECTION_ACCEPTED = 0, /*!< Connection accepted */
MQTT_CONNECTION_REFUSE_PROTOCOL, /*!< *MQTT* connection refused reason: Wrong
protocol */
MQTT_CONNECTION_REFUSE_ID_REJECTED, /*!< *MQTT* connection refused reason: ID
rejected */
MQTT_CONNECTION_REFUSE_SERVER_UNAVAILABLE, /*!< *MQTT* connection refused
reason: Server unavailable */
MQTT_CONNECTION_REFUSE_BAD_USERNAME, /*!< *MQTT* connection refused reason:
Wrong user */
MQTT_CONNECTION_REFUSE_NOT_AUTHORIZED /*!< *MQTT* connection refused reason:
Wrong username or password */
} esp_mqtt_connect_return_code_t;
/**
* *MQTT* connection error codes propagated via ERROR event
*/
typedef enum esp_mqtt_error_type_t {
MQTT_ERROR_TYPE_NONE = 0,
MQTT_ERROR_TYPE_TCP_TRANSPORT,
MQTT_ERROR_TYPE_CONNECTION_REFUSED,
MQTT_ERROR_TYPE_SUBSCRIBE_FAILED
} esp_mqtt_error_type_t;
/**
* MQTT_ERROR_TYPE_TCP_TRANSPORT error type hold all sorts of transport layer
* errors, including ESP-TLS error, but in the past only the errors from
* MQTT_ERROR_TYPE_ESP_TLS layer were reported, so the ESP-TLS error type is
* re-defined here for backward compatibility
*/
#define MQTT_ERROR_TYPE_ESP_TLS MQTT_ERROR_TYPE_TCP_TRANSPORT
typedef enum esp_mqtt_transport_t {
MQTT_TRANSPORT_UNKNOWN = 0x0,
MQTT_TRANSPORT_OVER_TCP, /*!< MQTT over TCP, using scheme: ``mqtt`` */
MQTT_TRANSPORT_OVER_SSL, /*!< MQTT over SSL, using scheme: ``mqtts`` */
MQTT_TRANSPORT_OVER_WS, /*!< MQTT over Websocket, using scheme:: ``ws`` */
MQTT_TRANSPORT_OVER_WSS /*!< MQTT over Websocket Secure, using scheme: ``wss`` */
MQTT_TRANSPORT_OVER_TCP, /*!< *MQTT* over TCP, using scheme: ``MQTT`` */
MQTT_TRANSPORT_OVER_SSL, /*!< *MQTT* over SSL, using scheme: ``MQTTS`` */
MQTT_TRANSPORT_OVER_WS, /*!< *MQTT* over Websocket, using scheme:: ``ws`` */
MQTT_TRANSPORT_OVER_WSS /*!< *MQTT* over Websocket Secure, using scheme:
``wss`` */
} esp_mqtt_transport_t;
/**
* MQTT event configuration structure
* *MQTT* protocol version used for connection
*/
typedef struct {
esp_mqtt_event_id_t event_id; /*!< MQTT event type */
esp_mqtt_client_handle_t client; /*!< MQTT client handle for this event */
void *user_context; /*!< User context passed from MQTT client config */
char *data; /*!< Data asociated with this event */
int data_len; /*!< Lenght of the data for this event */
int total_data_len; /*!< Total length of the data (longer data are supplied with multiple events) */
int current_data_offset; /*!< Actual offset for the data asociated with this event */
char *topic; /*!< Topic asociated with this event */
int topic_len; /*!< Length of the topic for this event asociated with this event */
int msg_id; /*!< MQTT messaged id of message */
int session_present; /*!< MQTT session_present flag for connection event */
typedef enum esp_mqtt_protocol_ver_t {
MQTT_PROTOCOL_UNDEFINED = 0,
MQTT_PROTOCOL_V_3_1,
MQTT_PROTOCOL_V_3_1_1,
MQTT_PROTOCOL_V_5,
} esp_mqtt_protocol_ver_t;
/**
* @brief *MQTT* error code structure to be passed as a contextual information
* into ERROR event
*
* Important: This structure extends `esp_tls_last_error` error structure and is
* backward compatible with it (so might be down-casted and treated as
* `esp_tls_last_error` error, but recommended to update applications if used
* this way previously)
*
* Use this structure directly checking error_type first and then appropriate
* error code depending on the source of the error:
*
* | error_type | related member variables | note |
* | MQTT_ERROR_TYPE_TCP_TRANSPORT | esp_tls_last_esp_err, esp_tls_stack_err,
* esp_tls_cert_verify_flags, sock_errno | Error reported from
* tcp_transport/esp-tls | | MQTT_ERROR_TYPE_CONNECTION_REFUSED |
* connect_return_code | Internal error reported from *MQTT* broker on
* connection |
*/
typedef struct esp_mqtt_error_codes {
/* compatible portion of the struct corresponding to struct esp_tls_last_error
*/
esp_err_t esp_tls_last_esp_err; /*!< last esp_err code reported from esp-tls
component */
int esp_tls_stack_err; /*!< tls specific error code reported from underlying
tls stack */
int esp_tls_cert_verify_flags; /*!< tls flags reported from underlying tls
stack during certificate verification */
/* esp-mqtt specific structure extension */
esp_mqtt_error_type_t
error_type; /*!< error type referring to the source of the error */
esp_mqtt_connect_return_code_t
connect_return_code; /*!< connection refused error code reported from
*MQTT* broker on connection */
/* tcp_transport extension */
int esp_transport_sock_errno; /*!< errno from the underlying socket */
} esp_mqtt_error_codes_t;
/**
* *MQTT* event configuration structure
*/
typedef struct esp_mqtt_event_t {
esp_mqtt_event_id_t event_id; /*!< *MQTT* event type */
esp_mqtt_client_handle_t client; /*!< *MQTT* client handle for this event */
char *data; /*!< Data associated with this event */
int data_len; /*!< Length of the data for this event */
int total_data_len; /*!< Total length of the data (longer data are supplied
with multiple events) */
int current_data_offset; /*!< Actual offset for the data associated with this
event */
char *topic; /*!< Topic associated with this event */
int topic_len; /*!< Length of the topic for this event associated with this
event */
int msg_id; /*!< *MQTT* messaged id of message */
int session_present; /*!< *MQTT* session_present flag for connection event */
esp_mqtt_error_codes_t
*error_handle; /*!< esp-mqtt error handle including esp-tls errors as well
as internal *MQTT* errors */
bool retain; /*!< Retained flag of the message associated with this event */
int qos; /*!< QoS of the messages associated with this event */
bool dup; /*!< dup flag of the message associated with this event */
esp_mqtt_protocol_ver_t protocol_ver; /*!< MQTT protocol version used for connection, defaults to value from menuconfig*/
#ifdef CONFIG_MQTT_PROTOCOL_5
esp_mqtt5_event_property_t *property; /*!< MQTT 5 property associated with this event */
#endif
} esp_mqtt_event_t;
typedef esp_mqtt_event_t *esp_mqtt_event_handle_t;
typedef esp_err_t (* mqtt_event_callback_t)(esp_mqtt_event_handle_t event);
/**
* MQTT client configuration structure
* *MQTT* client configuration structure
*
* - Default values can be set via menuconfig
* - All certificates and key data could be passed in PEM or DER format. PEM format must have a terminating NULL
* character and the related len field set to 0. DER format requires a related len field set to the correct length.
*/
typedef struct {
mqtt_event_callback_t event_handle; /*!< handle for MQTT events as a callback in legacy mode */
esp_event_loop_handle_t event_loop_handle; /*!< handle for MQTT event loop library */
const char *host; /*!< MQTT server domain (ipv4 as string) */
const char *uri; /*!< Complete MQTT broker URI */
uint32_t port; /*!< MQTT server port */
const char *client_id; /*!< default client id is ``ESP32_%CHIPID%`` where %CHIPID% are last 3 bytes of MAC address in hex format */
const char *username; /*!< MQTT username */
const char *password; /*!< MQTT password */
const char *lwt_topic; /*!< LWT (Last Will and Testament) message topic (NULL by default) */
const char *lwt_msg; /*!< LWT message (NULL by default) */
int lwt_qos; /*!< LWT message qos */
int lwt_retain; /*!< LWT retained message flag */
int lwt_msg_len; /*!< LWT message length */
int disable_clean_session; /*!< mqtt clean session, default clean_session is true */
int keepalive; /*!< mqtt keepalive, default is 120 seconds */
bool disable_auto_reconnect; /*!< this mqtt client will reconnect to server (when errors/disconnect). Set disable_auto_reconnect=true to disable */
void *user_context; /*!< pass user context to this option, then can receive that context in ``event->user_context`` */
int task_prio; /*!< MQTT task priority, default is 5, can be changed in ``make menuconfig`` */
int task_stack; /*!< MQTT task stack size, default is 6144 bytes, can be changed in ``make menuconfig`` */
int buffer_size; /*!< size of MQTT send/receive buffer, default is 1024 */
const char *cert_pem; /*!< Pointer to certificate data in PEM format for server verify (with SSL), default is NULL, not required to verify the server */
const char *client_cert_pem; /*!< Pointer to certificate data in PEM format for SSL mutual authentication, default is NULL, not required if mutual authentication is not needed. If it is not NULL, also `client_key_pem` has to be provided. */
const char *client_key_pem; /*!< Pointer to private key data in PEM format for SSL mutual authentication, default is NULL, not required if mutual authentication is not needed. If it is not NULL, also `client_cert_pem` has to be provided. */
esp_mqtt_transport_t transport; /*!< overrides URI transport */
int refresh_connection_after_ms; /*!< Refresh connection after this value (in milliseconds) */
typedef struct esp_mqtt_client_config_t {
/**
* Broker related configuration
*/
struct broker_t {
/**
* Broker address
*
* - uri have precedence over other fields
* - If uri isn't set at least hostname, transport and port should.
*/
struct address_t {
const char *uri; /*!< Complete *MQTT* broker URI */
const char *hostname; /*!< Hostname, to set ipv4 pass it as string) */
esp_mqtt_transport_t transport; /*!< Selects transport*/
const char *path; /*!< Path in the URI*/
uint32_t port; /*!< *MQTT* server port */
} address; /*!< Broker address configuration */
/**
* Broker identity verification
*
* If fields are not set broker's identity isn't verified. it's recommended
* to set the options in this struct for security reasons.
*/
struct verification_t {
bool use_global_ca_store; /*!< Use a global ca_store, look esp-tls
documentation for details. */
esp_err_t (*crt_bundle_attach)(void *conf); /*!< Pointer to ESP x509 Certificate Bundle attach function for
the usage of certificate bundles. Client only attach the bundle, the clean up must be done by the user. */
const char *certificate; /*!< Certificate data, default is NULL. It's not copied nor freed by the client, user needs to clean up.*/
size_t certificate_len; /*!< Length of the buffer pointed to by certificate. */
const struct psk_key_hint *psk_hint_key; /*!< Pointer to PSK struct defined in esp_tls.h to enable PSK
authentication (as alternative to certificate verification).
PSK is enabled only if there are no other ways to
verify broker. It's not copied nor freed by the client, user needs to clean up.*/
bool skip_cert_common_name_check; /*!< Skip any validation of server certificate CN field, this reduces the
security of TLS and makes the *MQTT* client susceptible to MITM attacks */
const char **alpn_protos; /*!< NULL-terminated list of supported application protocols to be used for ALPN.*/
const char *common_name; /*!< Pointer to the string containing server certificate common name.
If non-NULL, server certificate CN must match this name,
If NULL, server certificate CN must match hostname.
This is ignored if skip_cert_common_name_check=true.
It's not copied nor freed by the client, user needs to clean up.*/
} verification; /*!< Security verification of the broker */
} broker; /*!< Broker address and security verification */
/**
* Client related credentials for authentication.
*/
struct credentials_t {
const char *username; /*!< *MQTT* username */
const char *client_id; /*!< Set *MQTT* client identifier. Ignored if set_null_client_id == true If NULL set
the default client id. Default client id is ``ESP32_%CHIPID%`` where `%CHIPID%` are
last 3 bytes of MAC address in hex format */
bool set_null_client_id; /*!< Selects a NULL client id */
/**
* Client authentication
*
* Fields related to client authentication by broker
*
* For mutual authentication using TLS, user could select certificate and key,
* secure element or digital signature peripheral if available.
*
*/
struct authentication_t {
const char *password; /*!< *MQTT* password */
const char *certificate; /*!< Certificate for ssl mutual authentication, not required if mutual
authentication is not needed. Must be provided with `key`. It's not copied nor freed by the client, user needs to clean up.*/
size_t certificate_len; /*!< Length of the buffer pointed to by certificate.*/
const char *key; /*!< Private key for SSL mutual authentication, not required if mutual authentication
is not needed. If it is not NULL, also `certificate` has to be provided. It's not copied nor freed by the client, user needs to clean up.*/
size_t key_len; /*!< Length of the buffer pointed to by key.*/
const char *key_password; /*!< Client key decryption password, not PEM nor DER, if provided
`key_password_len` must be correctly set.*/
int key_password_len; /*!< Length of the password pointed to by `key_password` */
bool use_secure_element; /*!< Enable secure element, available in ESP32-ROOM-32SE, for SSL connection */
void *ds_data; /*!< Carrier of handle for digital signature parameters, digital signature peripheral is
available in some Espressif devices. It's not copied nor freed by the client, user needs to clean up.*/
} authentication; /*!< Client authentication */
} credentials; /*!< User credentials for broker */
/**
* *MQTT* Session related configuration
*/
struct session_t {
/**
* Last Will and Testament message configuration.
*/
struct last_will_t {
const char *topic; /*!< LWT (Last Will and Testament) message topic */
const char *msg; /*!< LWT message, may be NULL terminated*/
int msg_len; /*!< LWT message length, if msg isn't NULL terminated must have the correct length */
int qos; /*!< LWT message QoS */
int retain; /*!< LWT retained message flag */
} last_will; /*!< Last will configuration */
bool disable_clean_session; /*!< *MQTT* clean session, default clean_session is true */
int keepalive; /*!< *MQTT* keepalive, default is 120 seconds
When configuring this value, keep in mind that the client attempts
to communicate with the broker at half the interval that is actually set.
This conservative approach allows for more attempts before the broker's timeout occurs */
bool disable_keepalive; /*!< Set `disable_keepalive=true` to turn off keep-alive mechanism, keepalive is active
by default. Note: setting the config value `keepalive` to `0` doesn't disable
keepalive feature, but uses a default keepalive period */
esp_mqtt_protocol_ver_t protocol_ver; /*!< *MQTT* protocol version used for connection.*/
int message_retransmit_timeout; /*!< timeout for retransmitting of failed packet */
} session; /*!< *MQTT* session configuration. */
/**
* Network related configuration
*/
struct network_t {
int reconnect_timeout_ms; /*!< Reconnect to the broker after this value in miliseconds if auto reconnect is not
disabled (defaults to 10s) */
int timeout_ms; /*!< Abort network operation if it is not completed after this value, in milliseconds
(defaults to 10s). */
int refresh_connection_after_ms; /*!< Refresh connection after this value (in milliseconds) */
bool disable_auto_reconnect; /*!< Client will reconnect to server (when errors/disconnect). Set
`disable_auto_reconnect=true` to disable */
esp_transport_handle_t transport; /*!< Custom transport handle to use. Warning: The transport should be valid during the client lifetime and is destroyed when esp_mqtt_client_destroy is called. */
struct ifreq * if_name; /*!< The name of interface for data to go through. Use the default interface without setting */
} network; /*!< Network configuration */
/**
* Client task configuration
*/
struct task_t {
int priority; /*!< *MQTT* task priority*/
int stack_size; /*!< *MQTT* task stack size*/
} task; /*!< FreeRTOS task configuration.*/
/**
* Client buffer size configuration
*
* Client have two buffers for input and output respectivelly.
*/
struct buffer_t {
int size; /*!< size of *MQTT* send/receive buffer*/
int out_size; /*!< size of *MQTT* output buffer. If not defined, defaults to the size defined by
``buffer_size`` */
} buffer; /*!< Buffer size configuration.*/
/**
* Client outbox configuration options.
*/
struct outbox_config_t {
uint64_t limit; /*!< Size limit for the outbox in bytes.*/
} outbox; /*!< Outbox configuration. */
} esp_mqtt_client_config_t;
/**
* @brief Creates mqtt client handle based on the configuration
* Topic definition struct
*/
typedef struct topic_t {
const char *filter; /*!< Topic filter to subscribe */
int qos; /*!< Max QoS level of the subscription */
} esp_mqtt_topic_t;
/**
* @brief Creates *MQTT* client handle based on the configuration
*
* @param config mqtt configuration structure
* @param config *MQTT* configuration structure
*
* @return mqtt_client_handle if successfully created, NULL on error
*/
esp_mqtt_client_handle_t esp_mqtt_client_init(const esp_mqtt_client_config_t *config);
esp_mqtt_client_handle_t
esp_mqtt_client_init(const esp_mqtt_client_config_t *config);
/**
* @brief Sets mqtt connection URI. This API is usually used to overrides the URI
* configured in esp_mqtt_client_init
* @brief Sets *MQTT* connection URI. This API is usually used to overrides the
* URI configured in esp_mqtt_client_init
*
* @param client mqtt client hanlde
* @param client *MQTT* client handle
* @param uri
*
* @return ESP_FAIL if URI parse error, ESP_OK on success
*/
esp_err_t esp_mqtt_client_set_uri(esp_mqtt_client_handle_t client, const char *uri);
esp_err_t esp_mqtt_client_set_uri(esp_mqtt_client_handle_t client,
const char *uri);
/**
* @brief Starts mqtt client with already created client handle
* @brief Starts *MQTT* client with already created client handle
*
* @param client mqtt client handle
* @param client *MQTT* client handle
*
* @return ESP_OK on success
* ESP_ERR_INVALID_ARG on wrong initialization
@ -153,110 +409,257 @@ esp_err_t esp_mqtt_client_start(esp_mqtt_client_handle_t client);
/**
* @brief This api is typically used to force reconnection upon a specific event
*
* @param client mqtt client handle
* @param client *MQTT* client handle
*
* @return ESP_OK on success
* ESP_ERR_INVALID_ARG on wrong initialization
* ESP_FAIL if client is in invalid state
*/
esp_err_t esp_mqtt_client_reconnect(esp_mqtt_client_handle_t client);
/**
* @brief Stops mqtt client tasks
* @brief This api is typically used to force disconnection from the broker
*
* @param client mqtt client handle
* @param client *MQTT* client handle
*
* @return ESP_OK on success
* ESP_ERR_INVALID_ARG on wrong initialization
*/
esp_err_t esp_mqtt_client_disconnect(esp_mqtt_client_handle_t client);
/**
* @brief Stops *MQTT* client tasks
*
* * Notes:
* - Cannot be called from the *MQTT* event handler
*
* @param client *MQTT* client handle
*
* @return ESP_OK on success
* ESP_ERR_INVALID_ARG on wrong initialization
* ESP_FAIL if client is in invalid state
*/
esp_err_t esp_mqtt_client_stop(esp_mqtt_client_handle_t client);
#ifdef __cplusplus
#define esp_mqtt_client_subscribe esp_mqtt_client_subscribe_single
#else
/**
* @brief Convenience macro to select subscribe function to use.
*
* Notes:
* - Usage of `esp_mqtt_client_subscribe_single` is the same as previous
* esp_mqtt_client_subscribe, refer to it for details.
*
* @param client_handle *MQTT* client handle
* @param topic_type Needs to be char* for single subscription or `esp_mqtt_topic_t` for multiple topics
* @param qos_or_size It's either a qos when subscribing to a single topic or the size of the subscription array when subscribing to multiple topics.
*
* @return message_id of the subscribe message on success
* -1 on failure
* -2 in case of full outbox.
*/
#define esp_mqtt_client_subscribe(client_handle, topic_type, qos_or_size) _Generic((topic_type), \
char *: esp_mqtt_client_subscribe_single, \
const char *: esp_mqtt_client_subscribe_single, \
esp_mqtt_topic_t*: esp_mqtt_client_subscribe_multiple \
)(client_handle, topic_type, qos_or_size)
#endif /* __cplusplus*/
/**
* @brief Subscribe the client to defined topic with defined qos
*
* Notes:
* - Client must be connected to send subscribe message
* - This API is could be executed from a user task or
* from a mqtt event callback i.e. internal mqtt task
* from a *MQTT* event callback i.e. internal *MQTT* task
* (API is protected by internal mutex, so it might block
* if a longer data receive operation is in progress.
* - `esp_mqtt_client_subscribe` could be used to call this function.
*
* @param client mqtt client handle
* @param topic
* @param qos
* @param client *MQTT* client handle
* @param topic topic filter to subscribe
* @param qos Max qos level of the subscription
*
* @return message_id of the subscribe message on success
* -1 on failure
* -2 in case of full outbox.
*/
int esp_mqtt_client_subscribe(esp_mqtt_client_handle_t client, const char *topic, int qos);
int esp_mqtt_client_subscribe_single(esp_mqtt_client_handle_t client,
const char *topic, int qos);
/**
* @brief Subscribe the client to a list of defined topics with defined qos
*
* Notes:
* - Client must be connected to send subscribe message
* - This API is could be executed from a user task or
* from a *MQTT* event callback i.e. internal *MQTT* task
* (API is protected by internal mutex, so it might block
* if a longer data receive operation is in progress.
* - `esp_mqtt_client_subscribe` could be used to call this function.
*
* @param client *MQTT* client handle
* @param topic_list List of topics to subscribe
* @param size size of topic_list
*
* @return message_id of the subscribe message on success
* -1 on failure
* -2 in case of full outbox.
*/
int esp_mqtt_client_subscribe_multiple(esp_mqtt_client_handle_t client,
const esp_mqtt_topic_t *topic_list, int size);
/**
* @brief Unsubscribe the client from defined topic
*
* Notes:
* - Client must be connected to send unsubscribe message
* - It is thread safe, please refer to `esp_mqtt_client_subscribe` for details
* - It is thread safe, please refer to `esp_mqtt_client_subscribe_single` for details
*
* @param client mqtt client handle
* @param client *MQTT* client handle
* @param topic
*
* @return message_id of the subscribe message on success
* -1 on failure
*/
int esp_mqtt_client_unsubscribe(esp_mqtt_client_handle_t client, const char *topic);
int esp_mqtt_client_unsubscribe(esp_mqtt_client_handle_t client,
const char *topic);
/**
* @brief Client to send a publish message to the broker
*
* Notes:
* - Client doesn't have to be connected to send publish message
* (although it would drop all qos=0 messages, qos>1 messages would be enqueued)
* - This API might block for several seconds, either due to network timeout
* (10s) or if publishing payloads longer than internal buffer (due to message
* fragmentation)
* - Client doesn't have to be connected for this API to work, enqueueing the
* messages with qos>1 (returning -1 for all the qos=0 messages if
* disconnected). If MQTT_SKIP_PUBLISH_IF_DISCONNECTED is enabled, this API will
* not attempt to publish when the client is not connected and will always
* return -1.
* - It is thread safe, please refer to `esp_mqtt_client_subscribe` for details
*
* @param client mqtt client handle
* @param client *MQTT* client handle
* @param topic topic string
* @param data payload string (set to NULL, sending empty payload message)
* @param len data length, if set to 0, length is calculated from payload string
* @param qos qos of publish message
* @param retain ratain flag
* @param len data length, if set to 0, length is calculated from payload
* string
* @param qos QoS of publish message
* @param retain retain flag
*
* @return message_id of the subscribe message on success
* 0 if cannot publish
* @return message_id of the publish message (for QoS 0 message_id will always
* be zero) on success. -1 on failure, -2 in case of full outbox.
*/
int esp_mqtt_client_publish(esp_mqtt_client_handle_t client, const char *topic, const char *data, int len, int qos, int retain);
int esp_mqtt_client_publish(esp_mqtt_client_handle_t client, const char *topic,
const char *data, int len, int qos, int retain);
/**
* @brief Enqueue a message to the outbox, to be sent later. Typically used for
* messages with qos>0, but could be also used for qos=0 messages if store=true.
*
* This API generates and stores the publish message into the internal outbox
* and the actual sending to the network is performed in the mqtt-task context
* (in contrast to the esp_mqtt_client_publish() which sends the publish message
* immediately in the user task's context). Thus, it could be used as a non
* blocking version of esp_mqtt_client_publish().
*
* @param client *MQTT* client handle
* @param topic topic string
* @param data payload string (set to NULL, sending empty payload message)
* @param len data length, if set to 0, length is calculated from payload
* string
* @param qos QoS of publish message
* @param retain retain flag
* @param store if true, all messages are enqueued; otherwise only QoS 1 and
* QoS 2 are enqueued
*
* @return message_id if queued successfully, -1 on failure, -2 in case of full outbox.
*/
int esp_mqtt_client_enqueue(esp_mqtt_client_handle_t client, const char *topic,
const char *data, int len, int qos, int retain,
bool store);
/**
* @brief Destroys the client handle
*
* @param client mqtt client handle
* Notes:
* - Cannot be called from the *MQTT* event handler
*
* @param client *MQTT* client handle
*
* @return ESP_OK
* ESP_ERR_INVALID_ARG on wrong initialization
*/
esp_err_t esp_mqtt_client_destroy(esp_mqtt_client_handle_t client);
/**
* @brief Set configuration structure, typically used when updating the config (i.e. on "before_connect" event
* @brief Set configuration structure, typically used when updating the config
* (i.e. on "before_connect" event
*
* @param client mqtt client handle
* Notes:
* - When calling this function make sure to have all the intendend configurations
* set, otherwise default values are set.
* @param client *MQTT* client handle
*
* @param config mqtt configuration structure
* @param config *MQTT* configuration structure
*
* @return ESP_ERR_NO_MEM if failed to allocate
* ESP_ERR_INVALID_ARG if conflicts on transport configuration.
* ESP_OK on success
*/
esp_err_t esp_mqtt_set_config(esp_mqtt_client_handle_t client, const esp_mqtt_client_config_t *config);
esp_err_t esp_mqtt_set_config(esp_mqtt_client_handle_t client,
const esp_mqtt_client_config_t *config);
/**
* @brief Registers mqtt event
* @brief Registers *MQTT* event
*
* @param client mqtt client handle
* @param client *MQTT* client handle
* @param event event type
* @param event_handler hanlder callback
* @param event_handler handler callback
* @param event_handler_arg handlers context
*
* @return ESP_ERR_NO_MEM if failed to allocate
* ESP_ERR_INVALID_ARG on wrong initialization
* ESP_OK on success
*/
esp_err_t esp_mqtt_client_register_event(esp_mqtt_client_handle_t client, esp_mqtt_event_id_t event, esp_event_handler_t event_handler, void* event_handler_arg);
esp_err_t esp_mqtt_client_register_event(esp_mqtt_client_handle_t client,
esp_mqtt_event_id_t event,
esp_event_handler_t event_handler,
void *event_handler_arg);
/**
* @brief Unregisters mqtt event
*
* @param client mqtt client handle
* @param event event ID
* @param event_handler handler to unregister
*
* @return ESP_ERR_NO_MEM if failed to allocate
* ESP_ERR_INVALID_ARG on invalid event ID
* ESP_OK on success
*/
esp_err_t esp_mqtt_client_unregister_event(esp_mqtt_client_handle_t client, esp_mqtt_event_id_t event, esp_event_handler_t event_handler);
/**
* @brief Get outbox size
*
* @param client *MQTT* client handle
* @return outbox size
* 0 on wrong initialization
*/
int esp_mqtt_client_get_outbox_size(esp_mqtt_client_handle_t client);
/**
* @brief Dispatch user event to the mqtt internal event loop
*
* @param client *MQTT* client handle
* @param event *MQTT* event handle structure
* @return ESP_OK on success
* ESP_ERR_TIMEOUT if the event couldn't be queued (ref also CONFIG_MQTT_EVENT_QUEUE_SIZE)
*/
esp_err_t esp_mqtt_dispatch_custom_event(esp_mqtt_client_handle_t client, esp_mqtt_event_t *event);
#ifdef __cplusplus
}

View File

@ -31,13 +31,44 @@
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(3, 3, 0)
// Features supported from 3.3
#define MQTT_SUPPORTED_FEATURE_EVENT_LOOP
#define MQTT_SUPPORTED_FEATURE_SKIP_CRT_CMN_NAME_CHECK
#endif
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 0, 0)
// Features supported in 4.0
#define MQTT_SUPPORTED_FEATURE_WS_SUBPROTOCOL
#define MQTT_SUPPORTED_FEATURE_TRANSPORT_ERR_REPORTING
#endif
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 1, 0)
// Features supported in 4.1
#define MQTT_SUPPORTED_FEATURE_PSK_AUTHENTICATION
#define MQTT_SUPPORTED_FEATURE_DER_CERTIFICATES
#define MQTT_SUPPORTED_FEATURE_ALPN
#define MQTT_SUPPORTED_FEATURE_CLIENT_KEY_PASSWORD
#endif
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0)
// Features supported in 4.2
#define MQTT_SUPPORTED_FEATURE_SECURE_ELEMENT
#endif
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 3, 0)
// Features supported in 4.3
#define MQTT_SUPPORTED_FEATURE_DIGITAL_SIGNATURE
#define MQTT_SUPPORTED_FEATURE_TRANSPORT_SOCK_ERRNO_REPORTING
#endif
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0)
// Features supported in 4.4
#define MQTT_SUPPORTED_FEATURE_CERTIFICATE_BUNDLE
#endif
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0)
// Features supported in 5.1.0
#define MQTT_SUPPORTED_FEATURE_CRT_CMN_NAME
#endif
#endif // _MQTT_SUPPORTED_FEATURES_H_
#endif /* ESP_IDF_VERSION */
#endif // _MQTT_SUPPORTED_FEATURES_H_

View File

@ -0,0 +1,55 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _MQTT5_CLIENT_PRIV_H_
#define _MQTT5_CLIENT_PRIV_H_
#include "mqtt5_client.h"
#include "mqtt_client_priv.h"
#include "mqtt5_msg.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct mqtt5_topic_alias {
char *topic;
uint16_t topic_len;
uint16_t topic_alias;
STAILQ_ENTRY(mqtt5_topic_alias) next;
} mqtt5_topic_alias_t;
STAILQ_HEAD(mqtt5_topic_alias_list_t, mqtt5_topic_alias);
typedef struct mqtt5_topic_alias_list_t *mqtt5_topic_alias_handle_t;
typedef struct mqtt5_topic_alias *mqtt5_topic_alias_item_t;
typedef struct {
esp_mqtt5_connection_property_storage_t connect_property_info;
esp_mqtt5_connection_will_property_storage_t will_property_info;
esp_mqtt5_connection_server_resp_property_t server_resp_property_info;
esp_mqtt5_disconnect_property_config_t disconnect_property_info;
const esp_mqtt5_publish_property_config_t *publish_property_info;
const esp_mqtt5_subscribe_property_config_t *subscribe_property_info;
const esp_mqtt5_unsubscribe_property_config_t *unsubscribe_property_info;
mqtt5_topic_alias_handle_t peer_topic_alias;
} mqtt5_config_storage_t;
void esp_mqtt5_increment_packet_counter(esp_mqtt5_client_handle_t client);
void esp_mqtt5_decrement_packet_counter(esp_mqtt5_client_handle_t client);
void esp_mqtt5_parse_pubcomp(esp_mqtt5_client_handle_t client);
void esp_mqtt5_parse_puback(esp_mqtt5_client_handle_t client);
void esp_mqtt5_parse_unsuback(esp_mqtt5_client_handle_t client);
void esp_mqtt5_parse_suback(esp_mqtt5_client_handle_t client);
esp_err_t esp_mqtt5_parse_connack(esp_mqtt5_client_handle_t client, int *connect_rsp_code);
void esp_mqtt5_client_destory(esp_mqtt5_client_handle_t client);
esp_err_t esp_mqtt5_client_publish_check(esp_mqtt5_client_handle_t client, int qos, int retain);
esp_err_t esp_mqtt5_client_subscribe_check(esp_mqtt5_client_handle_t client, int qos);
esp_err_t esp_mqtt5_create_default_config(esp_mqtt5_client_handle_t client);
esp_err_t esp_mqtt5_get_publish_data(esp_mqtt5_client_handle_t client, uint8_t *msg_buf, size_t msg_read_len, char **msg_topic, size_t *msg_topic_len, char **msg_data, size_t *msg_data_len);
#ifdef __cplusplus
}
#endif //__cplusplus
#endif

142
lib/include/mqtt5_msg.h Normal file
View File

@ -0,0 +1,142 @@
#ifndef MQTT5_MSG_H
#define MQTT5_MSG_H
#include <stdint.h>
#include <stdbool.h>
#include "sys/queue.h"
#include "mqtt_config.h"
#include "mqtt_msg.h"
#include "mqtt_client.h"
#ifdef __cplusplus
extern "C" {
#endif
enum mqtt_properties_type {
MQTT5_PROPERTY_PAYLOAD_FORMAT_INDICATOR = 0x01,
MQTT5_PROPERTY_MESSAGE_EXPIRY_INTERVAL = 0x02,
MQTT5_PROPERTY_CONTENT_TYPE = 0x03,
MQTT5_PROPERTY_RESPONSE_TOPIC = 0x08,
MQTT5_PROPERTY_CORRELATION_DATA = 0x09,
MQTT5_PROPERTY_SUBSCRIBE_IDENTIFIER = 0x0B,
MQTT5_PROPERTY_SESSION_EXPIRY_INTERVAL = 0x11,
MQTT5_PROPERTY_ASSIGNED_CLIENT_IDENTIFIER = 0x12,
MQTT5_PROPERTY_SERVER_KEEP_ALIVE = 0x13,
MQTT5_PROPERTY_AUTHENTICATION_METHOD = 0x15,
MQTT5_PROPERTY_AUTHENTICATION_DATA = 0x16,
MQTT5_PROPERTY_REQUEST_PROBLEM_INFO = 0x17,
MQTT5_PROPERTY_WILL_DELAY_INTERVAL = 0x18,
MQTT5_PROPERTY_REQUEST_RESP_INFO = 0x19,
MQTT5_PROPERTY_RESP_INFO = 0x1A,
MQTT5_PROPERTY_SERVER_REFERENCE = 0x1C,
MQTT5_PROPERTY_REASON_STRING = 0x1F,
MQTT5_PROPERTY_RECEIVE_MAXIMUM = 0x21,
MQTT5_PROPERTY_TOPIC_ALIAS_MAXIMIM = 0x22,
MQTT5_PROPERTY_TOPIC_ALIAS = 0x23,
MQTT5_PROPERTY_MAXIMUM_QOS = 0x24,
MQTT5_PROPERTY_RETAIN_AVAILABLE = 0x25,
MQTT5_PROPERTY_USER_PROPERTY = 0x26,
MQTT5_PROPERTY_MAXIMUM_PACKET_SIZE = 0x27,
MQTT5_PROPERTY_WILDCARD_SUBSCR_AVAILABLE = 0x28,
MQTT5_PROPERTY_SUBSCR_IDENTIFIER_AVAILABLE = 0x29,
MQTT5_PROPERTY_SHARED_SUBSCR_AVAILABLE = 0x2A,
};
typedef struct mqtt5_user_property {
char *key;
char *value;
STAILQ_ENTRY(mqtt5_user_property) next;
} mqtt5_user_property_t;
STAILQ_HEAD(mqtt5_user_property_list_t, mqtt5_user_property);
typedef struct mqtt5_user_property *mqtt5_user_property_item_t;
typedef struct {
uint32_t maximum_packet_size;
uint16_t receive_maximum;
uint16_t topic_alias_maximum;
uint8_t max_qos;
bool retain_available;
bool wildcard_subscribe_available;
bool subscribe_identifiers_available;
bool shared_subscribe_available;
char *response_info;
} esp_mqtt5_connection_server_resp_property_t;
typedef struct {
bool payload_format_indicator;
uint32_t message_expiry_interval;
uint16_t topic_alias;
char *response_topic;
int response_topic_len;
char *correlation_data;
uint16_t correlation_data_len;
char *content_type;
int content_type_len;
uint16_t subscribe_id;
} esp_mqtt5_publish_resp_property_t;
typedef struct {
uint32_t session_expiry_interval;
uint32_t maximum_packet_size;
uint16_t receive_maximum;
uint16_t topic_alias_maximum;
bool request_resp_info;
bool request_problem_info;
mqtt5_user_property_handle_t user_property;
} esp_mqtt5_connection_property_storage_t;
typedef struct {
uint32_t will_delay_interval;
uint32_t message_expiry_interval;
bool payload_format_indicator;
char *content_type;
char *response_topic;
char *correlation_data;
uint16_t correlation_data_len;
mqtt5_user_property_handle_t user_property;
} esp_mqtt5_connection_will_property_storage_t;
#define mqtt5_get_type mqtt_get_type
#define mqtt5_get_dup mqtt_get_dup
#define mqtt5_set_dup mqtt_set_dup
#define mqtt5_get_qos mqtt_get_qos
#define mqtt5_get_retain mqtt_get_retain
#define mqtt5_msg_init mqtt_msg_init
#define mqtt5_get_total_length mqtt_get_total_length
#define mqtt5_has_valid_msg_hdr mqtt_has_valid_msg_hdr
#define mqtt5_msg_pingreq mqtt_msg_pingreq
#define mqtt5_msg_pingresp mqtt_msg_pingresp
#define mqtt5_get_unsuback_data mqtt5_get_suback_data
#define mqtt5_get_pubcomp_data mqtt5_get_puback_data
uint16_t mqtt5_get_id(uint8_t *buffer, size_t length);
char *mqtt5_get_publish_property_payload(uint8_t *buffer, size_t buffer_length, char **msg_topic, size_t *msg_topic_len, esp_mqtt5_publish_resp_property_t *resp_property, uint16_t *property_len, size_t *payload_len, mqtt5_user_property_handle_t *user_property);
char *mqtt5_get_suback_data(uint8_t *buffer, size_t *length, mqtt5_user_property_handle_t *user_property);
char *mqtt5_get_puback_data(uint8_t *buffer, size_t *length, mqtt5_user_property_handle_t *user_property);
mqtt_message_t *mqtt5_msg_connect(mqtt_connection_t *connection, mqtt_connect_info_t *info, esp_mqtt5_connection_property_storage_t *property, esp_mqtt5_connection_will_property_storage_t *will_property);
mqtt_message_t *mqtt5_msg_publish(mqtt_connection_t *connection, const char *topic, const char *data, int data_length, int qos, int retain, uint16_t *message_id, const esp_mqtt5_publish_property_config_t *property, const char *resp_info);
esp_err_t mqtt5_msg_parse_connack_property(uint8_t *buffer, size_t buffer_len, mqtt_connect_info_t *connection_info, esp_mqtt5_connection_property_storage_t *connection_property, esp_mqtt5_connection_server_resp_property_t *resp_property, int *reason_code, uint8_t *ack_flag, mqtt5_user_property_handle_t *user_property);
int mqtt5_msg_get_reason_code(uint8_t *buffer, size_t length);
mqtt_message_t *mqtt5_msg_subscribe(mqtt_connection_t *connection, const esp_mqtt_topic_t *topic, int size, uint16_t *message_id, const esp_mqtt5_subscribe_property_config_t *property);
mqtt_message_t *mqtt5_msg_unsubscribe(mqtt_connection_t *connection, const char *topic, uint16_t *message_id, const esp_mqtt5_unsubscribe_property_config_t *property);
mqtt_message_t *mqtt5_msg_disconnect(mqtt_connection_t *connection, esp_mqtt5_disconnect_property_config_t *disconnect_property_info);
mqtt_message_t *mqtt5_msg_pubcomp(mqtt_connection_t *connection, uint16_t message_id);
mqtt_message_t *mqtt5_msg_pubrel(mqtt_connection_t *connection, uint16_t message_id);
mqtt_message_t *mqtt5_msg_pubrec(mqtt_connection_t *connection, uint16_t message_id);
mqtt_message_t *mqtt5_msg_puback(mqtt_connection_t *connection, uint16_t message_id);
#ifdef __cplusplus
}
#endif
#endif /* MQTT5_MSG_H */

View File

@ -0,0 +1,146 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _MQTT_CLIENT_PRIV_H_
#define _MQTT_CLIENT_PRIV_H_
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdatomic.h>
#include "esp_err.h"
#include "platform.h"
#include "esp_event.h"
#include "mqtt_client.h"
#include "mqtt_msg.h"
#ifdef MQTT_PROTOCOL_5
#include "mqtt5_client_priv.h"
#endif
#include "esp_transport.h"
#include "esp_transport_tcp.h"
#include "esp_transport_ssl.h"
#include "esp_transport_ws.h"
#include "esp_log.h"
#include "mqtt_outbox.h"
#include "freertos/event_groups.h"
#include <errno.h>
#include <string.h>
#include "mqtt_supported_features.h"
/* using uri parser */
#include "http_parser.h"
#ifdef __cplusplus
extern "C" {
#endif
#if CONFIG_NEWLIB_NANO_FORMAT
#define NEWLIB_NANO_COMPAT_FORMAT PRIu32
#define NEWLIB_NANO_COMPAT_CAST(size_t_var) (uint32_t)size_t_var
#else
#define NEWLIB_NANO_COMPAT_FORMAT "zu"
#define NEWLIB_NANO_COMPAT_CAST(size_t_var) size_t_var
#endif
#ifdef MQTT_DISABLE_API_LOCKS
# define MQTT_API_LOCK(c)
# define MQTT_API_UNLOCK(c)
#else
# define MQTT_API_LOCK(c) xSemaphoreTakeRecursive(c->api_lock, portMAX_DELAY)
# define MQTT_API_UNLOCK(c) xSemaphoreGiveRecursive(c->api_lock)
#endif /* MQTT_USE_API_LOCKS */
typedef struct mqtt_state {
uint8_t *in_buffer;
int in_buffer_length;
size_t message_length;
size_t in_buffer_read_len;
mqtt_connection_t connection;
uint16_t pending_msg_id;
int pending_msg_type;
int pending_publish_qos;
} mqtt_state_t;
typedef struct {
esp_event_loop_handle_t event_loop_handle;
int task_stack;
int task_prio;
char *uri;
char *host;
char *path;
char *scheme;
int port;
bool auto_reconnect;
int network_timeout_ms;
int refresh_connection_after_ms;
int reconnect_timeout_ms;
char **alpn_protos;
int num_alpn_protos;
char *clientkey_password;
int clientkey_password_len;
bool use_global_ca_store;
esp_err_t ((*crt_bundle_attach)(void *conf));
const char *cacert_buf;
size_t cacert_bytes;
const char *clientcert_buf;
size_t clientcert_bytes;
const char *clientkey_buf;
size_t clientkey_bytes;
const struct psk_key_hint *psk_hint_key;
bool skip_cert_common_name_check;
const char *common_name;
bool use_secure_element;
void *ds_data;
int message_retransmit_timeout;
uint64_t outbox_limit;
esp_transport_handle_t transport;
struct ifreq * if_name;
} mqtt_config_storage_t;
typedef enum {
MQTT_STATE_INIT = 0,
MQTT_STATE_DISCONNECTED,
MQTT_STATE_CONNECTED,
MQTT_STATE_WAIT_RECONNECT,
} mqtt_client_state_t;
struct esp_mqtt_client {
esp_transport_list_handle_t transport_list;
esp_transport_handle_t transport;
mqtt_config_storage_t *config;
mqtt_state_t mqtt_state;
_Atomic mqtt_client_state_t state;
uint64_t refresh_connection_tick;
int64_t keepalive_tick;
uint64_t reconnect_tick;
#ifdef MQTT_PROTOCOL_5
mqtt5_config_storage_t *mqtt5_config;
uint16_t send_publish_packet_count; // This is for MQTT v5.0 flow control
#endif
int wait_timeout_ms;
int auto_reconnect;
esp_mqtt_event_t event;
bool run;
bool wait_for_ping_resp;
outbox_handle_t outbox;
EventGroupHandle_t status_bits;
SemaphoreHandle_t api_lock;
TaskHandle_t task_handle;
#if MQTT_EVENT_QUEUE_SIZE > 1
atomic_int queued_events;
#endif
};
bool esp_mqtt_set_if_config(char const *const new_config, char **old_config);
void esp_mqtt_destroy_config(esp_mqtt_client_handle_t client);
#ifdef __cplusplus
}
#endif //__cplusplus
#endif

View File

@ -8,9 +8,27 @@
#include "sdkconfig.h"
#define MQTT_PROTOCOL_311 CONFIG_MQTT_PROTOCOL_311
#define MQTT_RECONNECT_TIMEOUT_MS (10*1000)
#ifdef CONFIG_MQTT_PROTOCOL_311
#define MQTT_PROTOCOL_311
#endif
#ifdef CONFIG_MQTT_PROTOCOL_5
#define MQTT_PROTOCOL_5
#endif
#define MQTT_RECON_DEFAULT_MS (10*1000)
#ifdef CONFIG_MQTT_POLL_READ_TIMEOUT_MS
#define MQTT_POLL_READ_TIMEOUT_MS CONFIG_MQTT_POLL_READ_TIMEOUT_MS
#else
#define MQTT_POLL_READ_TIMEOUT_MS (1000)
#endif
#define MQTT_MSG_ID_INCREMENTAL CONFIG_MQTT_MSG_ID_INCREMENTAL
#define MQTT_SKIP_PUBLISH_IF_DISCONNECTED CONFIG_MQTT_SKIP_PUBLISH_IF_DISCONNECTED
#define MQTT_REPORT_DELETED_MESSAGES CONFIG_MQTT_REPORT_DELETED_MESSAGES
#if CONFIG_MQTT_BUFFER_SIZE
#define MQTT_BUFFER_SIZE_BYTE CONFIG_MQTT_BUFFER_SIZE
@ -18,13 +36,11 @@
#define MQTT_BUFFER_SIZE_BYTE 1024
#endif
#define MQTT_MAX_HOST_LEN 64
#define MQTT_MAX_CLIENT_LEN 32
#define MQTT_MAX_USERNAME_LEN 32
#define MQTT_MAX_PASSWORD_LEN 65
#define MQTT_MAX_LWT_TOPIC 32
#define MQTT_MAX_LWT_MSG 128
#if CONFIG_MQTT_TASK_PRIORITY
#define MQTT_TASK_PRIORITY CONFIG_MQTT_TASK_PRIORITY
#else
#define MQTT_TASK_PRIORITY 5
#endif
#if CONFIG_MQTT_TASK_STACK_SIZE
#define MQTT_TASK_STACK CONFIG_MQTT_TASK_STACK_SIZE
@ -33,7 +49,6 @@
#endif
#define MQTT_KEEPALIVE_TICK (120)
#define MQTT_CMD_QUEUE_SIZE (10)
#define MQTT_NETWORK_TIMEOUT_MS (10000)
#ifdef CONFIG_MQTT_TCP_DEFAULT_PORT
@ -54,7 +69,7 @@
#define MQTT_WS_DEFAULT_PORT 80
#endif
#ifdef MQTT_WSS_DEFAULT_PORT
#ifdef CONFIG_MQTT_WSS_DEFAULT_PORT
#define MQTT_WSS_DEFAULT_PORT CONFIG_MQTT_WSS_DEFAULT_PORT
#else
#define MQTT_WSS_DEFAULT_PORT 443
@ -76,11 +91,28 @@
#endif
#endif
#ifdef CONFIG_MQTT_OUTBOX_EXPIRED_TIMEOUT_MS
#define OUTBOX_EXPIRED_TIMEOUT_MS CONFIG_MQTT_OUTBOX_EXPIRED_TIMEOUT_MS
#else
#define OUTBOX_EXPIRED_TIMEOUT_MS (30*1000)
#endif
#define MQTT_ENABLE_SSL CONFIG_MQTT_TRANSPORT_SSL
#define MQTT_ENABLE_WS CONFIG_MQTT_TRANSPORT_WEBSOCKET
#define MQTT_ENABLE_WSS CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE
#define MQTT_DEFAULT_RETRANSMIT_TIMEOUT_MS 1000
#ifdef CONFIG_MQTT_EVENT_QUEUE_SIZE
#define MQTT_EVENT_QUEUE_SIZE CONFIG_MQTT_EVENT_QUEUE_SIZE
#else
#define MQTT_EVENT_QUEUE_SIZE 1
#endif
#ifdef CONFIG_MQTT_OUTBOX_DATA_ON_EXTERNAL_MEMORY
#define MQTT_OUTBOX_MEMORY MALLOC_CAP_SPIRAM
#else
#define MQTT_OUTBOX_MEMORY MALLOC_CAP_DEFAULT
#endif
#define OUTBOX_EXPIRED_TIMEOUT_MS (30*1000)
#define OUTBOX_MAX_SIZE (4*1024)
#endif

View File

@ -1,6 +1,10 @@
#ifndef MQTT_MSG_H
#define MQTT_MSG_H
#include <stdint.h>
#include <stdbool.h>
#include "mqtt_config.h"
#include "mqtt_client.h"
#ifdef __cplusplus
extern "C" {
#endif
@ -57,59 +61,51 @@ enum mqtt_message_type {
MQTT_MSG_TYPE_DISCONNECT = 14
};
enum mqtt_connect_return_code {
CONNECTION_ACCEPTED = 0,
CONNECTION_REFUSE_PROTOCOL,
CONNECTION_REFUSE_ID_REJECTED,
CONNECTION_REFUSE_SERVER_UNAVAILABLE,
CONNECTION_REFUSE_BAD_USERNAME,
CONNECTION_REFUSE_NOT_AUTHORIZED
};
typedef struct mqtt_message {
uint8_t *data;
uint32_t length;
uint32_t fragmented_msg_total_length; /*!< total len of fragmented messages (zero for all other messages) */
uint32_t fragmented_msg_data_offset; /*!< data offset of fragmented messages (zero for all other messages) */
size_t length;
size_t fragmented_msg_total_length; /*!< total len of fragmented messages (zero for all other messages) */
size_t fragmented_msg_data_offset; /*!< data offset of fragmented messages (zero for all other messages) */
} mqtt_message_t;
typedef struct mqtt_connection {
mqtt_message_t message;
uint16_t message_id;
uint8_t *buffer;
uint16_t buffer_length;
} mqtt_connection_t;
typedef struct mqtt_connect_info {
char *client_id;
char *username;
char *password;
char *will_topic;
char *will_message;
int keepalive;
int64_t keepalive; /*!< keepalive=0 -> keepalive is disabled */
int will_length;
int will_qos;
int will_retain;
int clean_session;
esp_mqtt_protocol_ver_t protocol_ver;
} mqtt_connect_info_t;
typedef struct mqtt_connection {
mqtt_message_t outbound_message;
#if MQTT_MSG_ID_INCREMENTAL
uint16_t last_message_id; /*!< last used id if incremental message id configured */
#endif
uint8_t *buffer;
size_t buffer_length;
mqtt_connect_info_t information;
static inline int mqtt_get_type(uint8_t *buffer)
} mqtt_connection_t;
static inline int mqtt_get_type(const uint8_t *buffer)
{
return (buffer[0] & 0xf0) >> 4;
}
static inline int mqtt_get_connect_session_present(uint8_t *buffer)
static inline int mqtt_get_connect_session_present(const uint8_t *buffer)
{
return buffer[2] & 0x01;
}
static inline int mqtt_get_connect_return_code(uint8_t *buffer)
static inline int mqtt_get_connect_return_code(const uint8_t *buffer)
{
return buffer[3];
}
static inline int mqtt_get_dup(uint8_t *buffer)
static inline int mqtt_get_dup(const uint8_t *buffer)
{
return (buffer[0] & 0x08) >> 3;
}
@ -117,22 +113,25 @@ static inline void mqtt_set_dup(uint8_t *buffer)
{
buffer[0] |= 0x08;
}
static inline int mqtt_get_qos(uint8_t *buffer)
static inline int mqtt_get_qos(const uint8_t *buffer)
{
return (buffer[0] & 0x06) >> 1;
}
static inline int mqtt_get_retain(uint8_t *buffer)
static inline int mqtt_get_retain(const uint8_t *buffer)
{
return (buffer[0] & 0x01);
}
void mqtt_msg_init(mqtt_connection_t *connection, uint8_t *buffer, uint16_t buffer_length);
bool mqtt_header_complete(uint8_t *buffer, uint16_t buffer_length);
uint32_t mqtt_get_total_length(uint8_t *buffer, uint16_t length, int *fixed_size_len);
char *mqtt_get_publish_topic(uint8_t *buffer, uint32_t *length);
char *mqtt_get_publish_data(uint8_t *buffer, uint32_t *length);
uint16_t mqtt_get_id(uint8_t *buffer, uint16_t length);
int mqtt_has_valid_msg_hdr(uint8_t *buffer, uint16_t length);
bool mqtt_header_complete(uint8_t *buffer, size_t buffer_length);
size_t mqtt_get_total_length(const uint8_t *buffer, size_t length, int *fixed_size_len);
char *mqtt_get_publish_topic(uint8_t *buffer, size_t *length);
char *mqtt_get_publish_data(uint8_t *buffer, size_t *length);
char *mqtt_get_suback_data(uint8_t *buffer, size_t *length);
uint16_t mqtt_get_id(uint8_t *buffer, size_t length);
int mqtt_has_valid_msg_hdr(uint8_t *buffer, size_t length);
esp_err_t mqtt_msg_buffer_init(mqtt_connection_t *connection, int buffer_size);
void mqtt_msg_buffer_destroy(mqtt_connection_t *connection);
mqtt_message_t *mqtt_msg_connect(mqtt_connection_t *connection, mqtt_connect_info_t *info);
mqtt_message_t *mqtt_msg_publish(mqtt_connection_t *connection, const char *topic, const char *data, int data_length, int qos, int retain, uint16_t *message_id);
@ -140,13 +139,11 @@ mqtt_message_t *mqtt_msg_puback(mqtt_connection_t *connection, uint16_t message_
mqtt_message_t *mqtt_msg_pubrec(mqtt_connection_t *connection, uint16_t message_id);
mqtt_message_t *mqtt_msg_pubrel(mqtt_connection_t *connection, uint16_t message_id);
mqtt_message_t *mqtt_msg_pubcomp(mqtt_connection_t *connection, uint16_t message_id);
mqtt_message_t *mqtt_msg_subscribe(mqtt_connection_t *connection, const char *topic, int qos, uint16_t *message_id);
mqtt_message_t *mqtt_msg_subscribe(mqtt_connection_t *connection, const esp_mqtt_topic_t topic_list[], int size, uint16_t *message_id) __attribute__((nonnull));
mqtt_message_t *mqtt_msg_unsubscribe(mqtt_connection_t *connection, const char *topic, uint16_t *message_id);
mqtt_message_t *mqtt_msg_pingreq(mqtt_connection_t *connection);
mqtt_message_t *mqtt_msg_pingresp(mqtt_connection_t *connection);
mqtt_message_t *mqtt_msg_disconnect(mqtt_connection_t *connection);
#ifdef __cplusplus
}
#endif

View File

@ -6,6 +6,7 @@
#ifndef _MQTT_OUTOBX_H_
#define _MQTT_OUTOBX_H_
#include "platform.h"
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
@ -13,9 +14,10 @@ extern "C" {
struct outbox_item;
typedef struct outbox_list_t *outbox_handle_t;
typedef struct outbox_t *outbox_handle_t;
typedef struct outbox_item *outbox_item_handle_t;
typedef struct outbox_message *outbox_message_handle_t;
typedef long long outbox_tick_t;
typedef struct outbox_message {
uint8_t *data;
@ -30,23 +32,31 @@ typedef struct outbox_message {
typedef enum pending_state {
QUEUED,
TRANSMITTED,
ACKNOWLEDGED,
CONFIRMED
} pending_state_t;
outbox_handle_t outbox_init(void);
outbox_item_handle_t outbox_enqueue(outbox_handle_t outbox, outbox_message_handle_t message, int tick);
outbox_item_handle_t outbox_dequeue(outbox_handle_t outbox, pending_state_t pending, int *tick);
outbox_item_handle_t outbox_enqueue(outbox_handle_t outbox, outbox_message_handle_t message, outbox_tick_t tick);
outbox_item_handle_t outbox_dequeue(outbox_handle_t outbox, pending_state_t pending, outbox_tick_t *tick);
outbox_item_handle_t outbox_get(outbox_handle_t outbox, int msg_id);
uint8_t *outbox_item_get_data(outbox_item_handle_t item, size_t *len, uint16_t *msg_id, int *msg_type, int *qos);
esp_err_t outbox_delete(outbox_handle_t outbox, int msg_id, int msg_type);
esp_err_t outbox_delete_msgid(outbox_handle_t outbox, int msg_id);
esp_err_t outbox_delete_msgtype(outbox_handle_t outbox, int msg_type);
int outbox_delete_expired(outbox_handle_t outbox, int current_tick, int timeout);
esp_err_t outbox_delete_item(outbox_handle_t outbox, outbox_item_handle_t item);
int outbox_delete_expired(outbox_handle_t outbox, outbox_tick_t current_tick, outbox_tick_t timeout);
/**
* @brief Deletes single expired message returning it's message id
*
* @return msg id of the deleted message, -1 if no expired message in the outbox
*/
int outbox_delete_single_expired(outbox_handle_t outbox, outbox_tick_t current_tick, outbox_tick_t timeout);
esp_err_t outbox_set_pending(outbox_handle_t outbox, int msg_id, pending_state_t pending);
int outbox_get_size(outbox_handle_t outbox);
esp_err_t outbox_cleanup(outbox_handle_t outbox, int max_size);
pending_state_t outbox_item_get_pending(outbox_item_handle_t item);
esp_err_t outbox_set_tick(outbox_handle_t outbox, int msg_id, outbox_tick_t tick);
uint64_t outbox_get_size(outbox_handle_t outbox);
void outbox_destroy(outbox_handle_t outbox);
void outbox_delete_all_items(outbox_handle_t outbox);
#ifdef __cplusplus
}

View File

@ -7,29 +7,23 @@
#define _ESP_PLATFORM_H__
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "freertos/event_groups.h"
#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"
#include "lwip/dns.h"
#include "sys/queue.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp_system.h"
#include <stdint.h>
#include <sys/time.h>
char *platform_create_id_string(void);
int platform_random(int max);
long long platform_tick_get_ms(void);
void ms_to_timeval(int timeout_ms, struct timeval *tv);
uint64_t platform_tick_get_ms(void);
#define ESP_MEM_CHECK(TAG, a, action) if (!(a)) { \
ESP_LOGE(TAG,"%s:%d (%s): %s", __FILE__, __LINE__, __FUNCTION__, "Memory exhausted"); \
ESP_LOGE(TAG,"%s(%d): %s", __FUNCTION__, __LINE__, "Memory exhausted"); \
action; \
}
#define ESP_OK_CHECK(TAG, a, action) if ((a) != ESP_OK) { \
ESP_LOGE(TAG,"%s(%d): %s", __FUNCTION__, __LINE__, "Failed with non ESP_OK err code"); \
action; \
}
#endif

1043
lib/mqtt5_msg.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -28,14 +28,15 @@
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "mqtt_client.h"
#include "mqtt_msg.h"
#include "mqtt_config.h"
#include "platform.h"
#define MQTT_MAX_FIXED_HEADER_SIZE 5
#define MQTT_3_1_VARIABLE_HEADER_SIZE 12
#define MQTT_3_1_1_VARIABLE_HEADER_SIZE 10
enum mqtt_connect_flag {
MQTT_CONNECT_FLAG_USERNAME = 1 << 7,
@ -45,30 +46,16 @@ enum mqtt_connect_flag {
MQTT_CONNECT_FLAG_CLEAN_SESSION = 1 << 1
};
struct __attribute((__packed__)) mqtt_connect_variable_header {
uint8_t lengthMsb;
uint8_t lengthLsb;
#if defined(MQTT_PROTOCOL_311)
uint8_t magic[4];
#else
uint8_t magic[6];
#endif
uint8_t version;
uint8_t flags;
uint8_t keepaliveMsb;
uint8_t keepaliveLsb;
};
static int append_string(mqtt_connection_t *connection, const char *string, int len)
{
if (connection->message.length + len + 2 > connection->buffer_length) {
if (connection->outbound_message.length + len + 2 > connection->buffer_length) {
return -1;
}
connection->buffer[connection->message.length++] = len >> 8;
connection->buffer[connection->message.length++] = len & 0xff;
memcpy(connection->buffer + connection->message.length, string, len);
connection->message.length += len;
connection->buffer[connection->outbound_message.length++] = len >> 8;
connection->buffer[connection->outbound_message.length++] = len & 0xff;
memcpy(connection->buffer + connection->outbound_message.length, string, len);
connection->outbound_message.length += len;
return len + 2;
}
@ -78,41 +65,45 @@ static uint16_t append_message_id(mqtt_connection_t *connection, uint16_t messag
// If message_id is zero then we should assign one, otherwise
// we'll use the one supplied by the caller
while (message_id == 0) {
#if MQTT_MSG_ID_INCREMENTAL
message_id = ++connection->last_message_id;
#else
message_id = platform_random(65535);
#endif
}
if (connection->message.length + 2 > connection->buffer_length) {
if (connection->outbound_message.length + 2 > connection->buffer_length) {
return 0;
}
connection->buffer[connection->message.length++] = message_id >> 8;
connection->buffer[connection->message.length++] = message_id & 0xff;
connection->buffer[connection->outbound_message.length++] = message_id >> 8;
connection->buffer[connection->outbound_message.length++] = message_id & 0xff;
return message_id;
}
static int init_message(mqtt_connection_t *connection)
static int set_message_header_size(mqtt_connection_t *connection)
{
connection->message.length = MQTT_MAX_FIXED_HEADER_SIZE;
connection->outbound_message.length = MQTT_MAX_FIXED_HEADER_SIZE;
return MQTT_MAX_FIXED_HEADER_SIZE;
}
static mqtt_message_t *fail_message(mqtt_connection_t *connection)
{
connection->message.data = connection->buffer;
connection->message.length = 0;
return &connection->message;
connection->outbound_message.data = connection->buffer;
connection->outbound_message.length = 0;
return &connection->outbound_message;
}
static mqtt_message_t *fini_message(mqtt_connection_t *connection, int type, int dup, int qos, int retain)
{
int message_length = connection->message.length - MQTT_MAX_FIXED_HEADER_SIZE;
int message_length = connection->outbound_message.length - MQTT_MAX_FIXED_HEADER_SIZE;
int total_length = message_length;
int encoded_length = 0;
uint8_t encoded_lens[4] = {0};
// Check if we have fragmented message and update total_len
if (connection->message.fragmented_msg_total_length) {
total_length = connection->message.fragmented_msg_total_length - MQTT_MAX_FIXED_HEADER_SIZE;
if (connection->outbound_message.fragmented_msg_total_length) {
total_length = connection->outbound_message.fragmented_msg_total_length - MQTT_MAX_FIXED_HEADER_SIZE;
}
// Encode MQTT message length
@ -133,10 +124,10 @@ static mqtt_message_t *fini_message(mqtt_connection_t *connection, int type, int
}
// Save the header bytes
connection->message.length = message_length + len_bytes + 1; // msg len + encoded_size len + type (1 byte)
connection->outbound_message.length = message_length + len_bytes + 1; // msg len + encoded_size len + type (1 byte)
int offs = MQTT_MAX_FIXED_HEADER_SIZE - 1 - len_bytes;
connection->message.data = connection->buffer + offs;
connection->message.fragmented_msg_data_offset -= offs;
connection->outbound_message.data = connection->buffer + offs;
connection->outbound_message.fragmented_msg_data_offset -= offs;
// type byte
connection->buffer[offs++] = ((type & 0x0f) << 4) | ((dup & 1) << 3) | ((qos & 3) << 1) | (retain & 1);
// length bytes
@ -144,20 +135,13 @@ static mqtt_message_t *fini_message(mqtt_connection_t *connection, int type, int
connection->buffer[offs++] = encoded_lens[j];
}
return &connection->message;
return &connection->outbound_message;
}
void mqtt_msg_init(mqtt_connection_t *connection, uint8_t *buffer, uint16_t buffer_length)
{
memset(connection, 0, sizeof(mqtt_connection_t));
connection->buffer = buffer;
connection->buffer_length = buffer_length;
}
uint32_t mqtt_get_total_length(uint8_t *buffer, uint16_t length, int *fixed_size_len)
size_t mqtt_get_total_length(const uint8_t *buffer, size_t length, int *fixed_size_len)
{
int i;
uint32_t totlen = 0;
size_t totlen = 0;
for (i = 1; i < length; ++i) {
totlen += (buffer[i] & 0x7f) << (7 * (i - 1));
@ -174,7 +158,7 @@ uint32_t mqtt_get_total_length(uint8_t *buffer, uint16_t length, int *fixed_size
return totlen;
}
bool mqtt_header_complete(uint8_t *buffer, uint16_t buffer_length)
bool mqtt_header_complete(uint8_t *buffer, size_t buffer_length)
{
uint16_t i;
uint16_t topiclen;
@ -205,20 +189,17 @@ bool mqtt_header_complete(uint8_t *buffer, uint16_t buffer_length)
return buffer_length >= i;
}
char *mqtt_get_publish_topic(uint8_t *buffer, uint32_t *length)
char *mqtt_get_publish_topic(uint8_t *buffer, size_t *length)
{
int i;
int totlen = 0;
int topiclen;
for (i = 1; i < *length; ++i) {
totlen += (buffer[i] & 0x7f) << (7 * (i - 1));
if ((buffer[i] & 0x80) == 0) {
++i;
break;
}
}
totlen += i;
if (i + 2 >= *length) {
return NULL;
@ -234,7 +215,7 @@ char *mqtt_get_publish_topic(uint8_t *buffer, uint32_t *length)
return (char *)(buffer + i);
}
char *mqtt_get_publish_data(uint8_t *buffer, uint32_t *length)
char *mqtt_get_publish_data(uint8_t *buffer, size_t *length)
{
int i;
int totlen = 0;
@ -282,7 +263,19 @@ char *mqtt_get_publish_data(uint8_t *buffer, uint32_t *length)
return (char *)(buffer + i);
}
uint16_t mqtt_get_id(uint8_t *buffer, uint16_t length)
char *mqtt_get_suback_data(uint8_t *buffer, size_t *length)
{
// SUBACK payload length = total length - (fixed header (2 bytes) + variable header (2 bytes))
// This requires the remaining length to be encoded in 1 byte.
if (*length > 4) {
*length -= 4;
return (char *)(buffer + 4);
}
*length = 0;
return NULL;
}
uint16_t mqtt_get_id(uint8_t *buffer, size_t length)
{
if (length < 1) {
return 0;
@ -346,33 +339,45 @@ uint16_t mqtt_get_id(uint8_t *buffer, uint16_t length)
mqtt_message_t *mqtt_msg_connect(mqtt_connection_t *connection, mqtt_connect_info_t *info)
{
struct mqtt_connect_variable_header *variable_header;
init_message(connection);
set_message_header_size(connection);
if (connection->message.length + sizeof(*variable_header) > connection->buffer_length) {
int header_len;
if (info->protocol_ver == MQTT_PROTOCOL_V_3_1) {
header_len = MQTT_3_1_VARIABLE_HEADER_SIZE;
} else {
header_len = MQTT_3_1_1_VARIABLE_HEADER_SIZE;
}
if (connection->outbound_message.length + header_len > connection->buffer_length) {
return fail_message(connection);
}
variable_header = (void *)(connection->buffer + connection->message.length);
connection->message.length += sizeof(*variable_header);
char *variable_header = (char *)(connection->buffer + connection->outbound_message.length);
connection->outbound_message.length += header_len;
variable_header->lengthMsb = 0;
#if defined(CONFIG_MQTT_PROTOCOL_311)
variable_header->lengthLsb = 4;
memcpy(variable_header->magic, "MQTT", 4);
variable_header->version = 4;
#else
variable_header->lengthLsb = 6;
memcpy(variable_header->magic, "MQIsdp", 6);
variable_header->version = 3;
#endif
int header_idx = 0;
variable_header[header_idx++] = 0; // Variable header length MSB
variable_header->flags = 0;
variable_header->keepaliveMsb = info->keepalive >> 8;
variable_header->keepaliveLsb = info->keepalive & 0xff;
if (info->protocol_ver == MQTT_PROTOCOL_V_3_1) {
variable_header[header_idx++] = 6; // Variable header length LSB
memcpy(&variable_header[header_idx], "MQIsdp", 6); // Protocol name
header_idx = header_idx + 6;
variable_header[header_idx++] = 3; // Protocol version
} else {
/* Defaults to protocol version 3.1.1 values */
variable_header[header_idx++] = 4; // Variable header length LSB
memcpy(&variable_header[header_idx], "MQTT", 4); // Protocol name
header_idx = header_idx + 4;
variable_header[header_idx++] = 4; // Protocol version
}
int flags_offset = header_idx;
variable_header[header_idx++] = 0; // Flags
variable_header[header_idx++] = info->keepalive >> 8; // Keep-alive MSB
variable_header[header_idx] = info->keepalive & 0xff; // Keep-alive LSB
if (info->clean_session) {
variable_header->flags |= MQTT_CONNECT_FLAG_CLEAN_SESSION;
variable_header[flags_offset] |= MQTT_CONNECT_FLAG_CLEAN_SESSION;
}
if (info->client_id != NULL && info->client_id[0] != '\0') {
@ -380,7 +385,9 @@ mqtt_message_t *mqtt_msg_connect(mqtt_connection_t *connection, mqtt_connect_inf
return fail_message(connection);
}
} else {
return fail_message(connection);
if (append_string(connection, "", 0) < 0) {
return fail_message(connection);
}
}
if (info->will_topic != NULL && info->will_topic[0] != '\0') {
@ -392,11 +399,11 @@ mqtt_message_t *mqtt_msg_connect(mqtt_connection_t *connection, mqtt_connect_inf
return fail_message(connection);
}
variable_header->flags |= MQTT_CONNECT_FLAG_WILL;
variable_header[flags_offset] |= MQTT_CONNECT_FLAG_WILL;
if (info->will_retain) {
variable_header->flags |= MQTT_CONNECT_FLAG_WILL_RETAIN;
variable_header[flags_offset] |= MQTT_CONNECT_FLAG_WILL_RETAIN;
}
variable_header->flags |= (info->will_qos & 3) << 3;
variable_header[flags_offset] |= (info->will_qos & 3) << 3;
}
if (info->username != NULL && info->username[0] != '\0') {
@ -404,15 +411,26 @@ mqtt_message_t *mqtt_msg_connect(mqtt_connection_t *connection, mqtt_connect_inf
return fail_message(connection);
}
variable_header->flags |= MQTT_CONNECT_FLAG_USERNAME;
variable_header[flags_offset] |= MQTT_CONNECT_FLAG_USERNAME;
}
if (info->password != NULL && info->password[0] != '\0') {
if (info->username == NULL || info->username[0] == '\0') {
/* In case if password is set without username, we need to set a zero length username.
* (otherwise we violate: MQTT-3.1.2-22: If the User Name Flag is set to 0 then the Password Flag MUST be set to 0.)
*/
if (append_string(connection, "", 0) < 0) {
return fail_message(connection);
}
variable_header[flags_offset] |= MQTT_CONNECT_FLAG_USERNAME;
}
if (append_string(connection, info->password, strlen(info->password)) < 0) {
return fail_message(connection);
}
variable_header->flags |= MQTT_CONNECT_FLAG_PASSWORD;
variable_header[flags_offset] |= MQTT_CONNECT_FLAG_PASSWORD;
}
return fini_message(connection, MQTT_MSG_TYPE_CONNECT, 0, 0, 0);
@ -420,7 +438,7 @@ mqtt_message_t *mqtt_msg_connect(mqtt_connection_t *connection, mqtt_connect_inf
mqtt_message_t *mqtt_msg_publish(mqtt_connection_t *connection, const char *topic, const char *data, int data_length, int qos, int retain, uint16_t *message_id)
{
init_message(connection);
set_message_header_size(connection);
if (topic == NULL || topic[0] == '\0') {
return fail_message(connection);
@ -430,6 +448,10 @@ mqtt_message_t *mqtt_msg_publish(mqtt_connection_t *connection, const char *topi
return fail_message(connection);
}
if (data == NULL && data_length > 0) {
return fail_message(connection);
}
if (qos > 0) {
if ((*message_id = append_message_id(connection, 0)) == 0) {
return fail_message(connection);
@ -438,23 +460,25 @@ mqtt_message_t *mqtt_msg_publish(mqtt_connection_t *connection, const char *topi
*message_id = 0;
}
if (connection->message.length + data_length > connection->buffer_length) {
// Not enough size in buffer -> fragment this message
connection->message.fragmented_msg_data_offset = connection->message.length;
memcpy(connection->buffer + connection->message.length, data, connection->buffer_length - connection->message.length);
connection->message.length = connection->buffer_length;
connection->message.fragmented_msg_total_length = data_length + connection->message.fragmented_msg_data_offset;
} else {
memcpy(connection->buffer + connection->message.length, data, data_length);
connection->message.length += data_length;
connection->message.fragmented_msg_total_length = 0;
if (data != NULL) {
if (connection->outbound_message.length + data_length > connection->buffer_length) {
// Not enough size in buffer -> fragment this message
connection->outbound_message.fragmented_msg_data_offset = connection->outbound_message.length;
memcpy(connection->buffer + connection->outbound_message.length, data, connection->buffer_length - connection->outbound_message.length);
connection->outbound_message.length = connection->buffer_length;
connection->outbound_message.fragmented_msg_total_length = data_length + connection->outbound_message.fragmented_msg_data_offset;
} else {
memcpy(connection->buffer + connection->outbound_message.length, data, data_length);
connection->outbound_message.length += data_length;
connection->outbound_message.fragmented_msg_total_length = 0;
}
}
return fini_message(connection, MQTT_MSG_TYPE_PUBLISH, 0, qos, retain);
}
mqtt_message_t *mqtt_msg_puback(mqtt_connection_t *connection, uint16_t message_id)
{
init_message(connection);
set_message_header_size(connection);
if (append_message_id(connection, message_id) == 0) {
return fail_message(connection);
}
@ -463,7 +487,7 @@ mqtt_message_t *mqtt_msg_puback(mqtt_connection_t *connection, uint16_t message_
mqtt_message_t *mqtt_msg_pubrec(mqtt_connection_t *connection, uint16_t message_id)
{
init_message(connection);
set_message_header_size(connection);
if (append_message_id(connection, message_id) == 0) {
return fail_message(connection);
}
@ -472,7 +496,7 @@ mqtt_message_t *mqtt_msg_pubrec(mqtt_connection_t *connection, uint16_t message_
mqtt_message_t *mqtt_msg_pubrel(mqtt_connection_t *connection, uint16_t message_id)
{
init_message(connection);
set_message_header_size(connection);
if (append_message_id(connection, message_id) == 0) {
return fail_message(connection);
}
@ -481,40 +505,43 @@ mqtt_message_t *mqtt_msg_pubrel(mqtt_connection_t *connection, uint16_t message_
mqtt_message_t *mqtt_msg_pubcomp(mqtt_connection_t *connection, uint16_t message_id)
{
init_message(connection);
set_message_header_size(connection);
if (append_message_id(connection, message_id) == 0) {
return fail_message(connection);
}
return fini_message(connection, MQTT_MSG_TYPE_PUBCOMP, 0, 0, 0);
}
mqtt_message_t *mqtt_msg_subscribe(mqtt_connection_t *connection, const char *topic, int qos, uint16_t *message_id)
mqtt_message_t *mqtt_msg_subscribe(mqtt_connection_t *connection, const esp_mqtt_topic_t topic_list[], int size, uint16_t *message_id)
{
init_message(connection);
if (topic == NULL || topic[0] == '\0') {
return fail_message(connection);
}
set_message_header_size(connection);
if ((*message_id = append_message_id(connection, 0)) == 0) {
return fail_message(connection);
}
if (append_string(connection, topic, strlen(topic)) < 0) {
return fail_message(connection);
}
for (int topic_number = 0; topic_number < size; ++topic_number) {
if (topic_list[topic_number].filter[0] == '\0') {
return fail_message(connection);
}
if (connection->message.length + 1 > connection->buffer_length) {
return fail_message(connection);
if (append_string(connection, topic_list[topic_number].filter, strlen(topic_list[topic_number].filter)) < 0) {
return fail_message(connection);
}
if (connection->outbound_message.length + 1 > connection->buffer_length) {
return fail_message(connection);
}
connection->buffer[connection->outbound_message.length] = topic_list[topic_number].qos;
connection->outbound_message.length ++;
}
connection->buffer[connection->message.length++] = qos;
return fini_message(connection, MQTT_MSG_TYPE_SUBSCRIBE, 0, 1, 0);
}
mqtt_message_t *mqtt_msg_unsubscribe(mqtt_connection_t *connection, const char *topic, uint16_t *message_id)
{
init_message(connection);
set_message_header_size(connection);
if (topic == NULL || topic[0] == '\0') {
return fail_message(connection);
@ -533,19 +560,19 @@ mqtt_message_t *mqtt_msg_unsubscribe(mqtt_connection_t *connection, const char *
mqtt_message_t *mqtt_msg_pingreq(mqtt_connection_t *connection)
{
init_message(connection);
set_message_header_size(connection);
return fini_message(connection, MQTT_MSG_TYPE_PINGREQ, 0, 0, 0);
}
mqtt_message_t *mqtt_msg_pingresp(mqtt_connection_t *connection)
{
init_message(connection);
set_message_header_size(connection);
return fini_message(connection, MQTT_MSG_TYPE_PINGRESP, 0, 0, 0);
}
mqtt_message_t *mqtt_msg_disconnect(mqtt_connection_t *connection)
{
init_message(connection);
set_message_header_size(connection);
return fini_message(connection, MQTT_MSG_TYPE_DISCONNECT, 0, 0, 0);
}
@ -553,7 +580,7 @@ mqtt_message_t *mqtt_msg_disconnect(mqtt_connection_t *connection)
* check flags: [MQTT-2.2.2-1], [MQTT-2.2.2-2]
* returns 0 if flags are invalid, otherwise returns 1
*/
int mqtt_has_valid_msg_hdr(uint8_t *buffer, uint16_t length)
int mqtt_has_valid_msg_hdr(uint8_t *buffer, size_t length)
{
int qos, dup;
@ -587,4 +614,24 @@ int mqtt_has_valid_msg_hdr(uint8_t *buffer, uint16_t length)
default:
return 0;
}
}
}
esp_err_t mqtt_msg_buffer_init(mqtt_connection_t *connection, int buffer_size)
{
memset(&connection->outbound_message, 0, sizeof(mqtt_message_t));
connection->buffer = (uint8_t *)calloc(buffer_size, sizeof(uint8_t));
if (!connection->buffer) {
return ESP_ERR_NO_MEM;
}
connection->buffer_length = buffer_size;
return ESP_OK;
}
void mqtt_msg_buffer_destroy(mqtt_connection_t *connection)
{
if (connection) {
free(connection->buffer);
}
}

View File

@ -1,13 +1,14 @@
#include "mqtt_outbox.h"
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "mqtt_config.h"
#include "sys/queue.h"
#include "esp_heap_caps.h"
#include "esp_log.h"
#ifndef CONFIG_MQTT_CUSTOM_OUTBOX
static const char *TAG = "OUTBOX";
static const char *TAG = "outbox";
typedef struct outbox_item {
char *buffer;
@ -15,24 +16,30 @@ typedef struct outbox_item {
int msg_id;
int msg_type;
int msg_qos;
int tick;
int retry_count;
outbox_tick_t tick;
pending_state_t pending;
STAILQ_ENTRY(outbox_item) next;
} outbox_item_t;
STAILQ_HEAD(outbox_list_t, outbox_item);
struct outbox_t {
_Atomic uint64_t size;
struct outbox_list_t *list;
};
outbox_handle_t outbox_init(void)
{
outbox_handle_t outbox = calloc(1, sizeof(struct outbox_list_t));
outbox_handle_t outbox = calloc(1, sizeof(struct outbox_t));
ESP_MEM_CHECK(TAG, outbox, return NULL);
STAILQ_INIT(outbox);
outbox->list = calloc(1, sizeof(struct outbox_list_t));
ESP_MEM_CHECK(TAG, outbox->list, {free(outbox); return NULL;});
outbox->size = 0;
STAILQ_INIT(outbox->list);
return outbox;
}
outbox_item_handle_t outbox_enqueue(outbox_handle_t outbox, outbox_message_handle_t message, int tick)
outbox_item_handle_t outbox_enqueue(outbox_handle_t outbox, outbox_message_handle_t message, outbox_tick_t tick)
{
outbox_item_handle_t item = calloc(1, sizeof(outbox_item_t));
ESP_MEM_CHECK(TAG, item, return NULL);
@ -42,7 +49,7 @@ outbox_item_handle_t outbox_enqueue(outbox_handle_t outbox, outbox_message_handl
item->tick = tick;
item->len = message->len + message->remaining_len;
item->pending = QUEUED;
item->buffer = malloc(message->len + message->remaining_len);
item->buffer = heap_caps_malloc(message->len + message->remaining_len, MQTT_OUTBOX_MEMORY);
ESP_MEM_CHECK(TAG, item->buffer, {
free(item);
return NULL;
@ -51,15 +58,16 @@ outbox_item_handle_t outbox_enqueue(outbox_handle_t outbox, outbox_message_handl
if (message->remaining_data) {
memcpy(item->buffer + message->len, message->remaining_data, message->remaining_len);
}
STAILQ_INSERT_TAIL(outbox, item, next);
ESP_LOGD(TAG, "ENQUEUE msgid=%d, msg_type=%d, len=%d, size=%d", message->msg_id, message->msg_type, message->len + message->remaining_len, outbox_get_size(outbox));
STAILQ_INSERT_TAIL(outbox->list, item, next);
outbox->size += item->len;
ESP_LOGD(TAG, "ENQUEUE msgid=%d, msg_type=%d, len=%d, size=%"PRIu64, message->msg_id, message->msg_type, message->len + message->remaining_len, outbox_get_size(outbox));
return item;
}
outbox_item_handle_t outbox_get(outbox_handle_t outbox, int msg_id)
{
outbox_item_handle_t item;
STAILQ_FOREACH(item, outbox, next) {
STAILQ_FOREACH(item, outbox->list, next) {
if (item->msg_id == msg_id) {
return item;
}
@ -67,10 +75,10 @@ outbox_item_handle_t outbox_get(outbox_handle_t outbox, int msg_id)
return NULL;
}
outbox_item_handle_t outbox_dequeue(outbox_handle_t outbox, pending_state_t pending, int *tick)
outbox_item_handle_t outbox_dequeue(outbox_handle_t outbox, pending_state_t pending, outbox_tick_t *tick)
{
outbox_item_handle_t item;
STAILQ_FOREACH(item, outbox, next) {
STAILQ_FOREACH(item, outbox->list, next) {
if (item->pending == pending) {
if (tick) {
*tick = item->tick;
@ -81,6 +89,21 @@ outbox_item_handle_t outbox_dequeue(outbox_handle_t outbox, pending_state_t pend
return NULL;
}
esp_err_t outbox_delete_item(outbox_handle_t outbox, outbox_item_handle_t item_to_delete)
{
outbox_item_handle_t item;
STAILQ_FOREACH(item, outbox->list, next) {
if (item == item_to_delete) {
STAILQ_REMOVE(outbox->list, item, outbox_item, next);
outbox->size -= item->len;
free(item->buffer);
free(item);
return ESP_OK;
}
}
return ESP_FAIL;
}
uint8_t *outbox_item_get_data(outbox_item_handle_t item, size_t *len, uint16_t *msg_id, int *msg_type, int *qos)
{
if (item) {
@ -96,31 +119,20 @@ uint8_t *outbox_item_get_data(outbox_item_handle_t item, size_t *len, uint16_t
esp_err_t outbox_delete(outbox_handle_t outbox, int msg_id, int msg_type)
{
outbox_item_handle_t item, tmp;
STAILQ_FOREACH_SAFE(item, outbox, next, tmp) {
STAILQ_FOREACH_SAFE(item, outbox->list, next, tmp) {
if (item->msg_id == msg_id && (0xFF & (item->msg_type)) == msg_type) {
STAILQ_REMOVE(outbox, item, outbox_item, next);
STAILQ_REMOVE(outbox->list, item, outbox_item, next);
outbox->size -= item->len;
free(item->buffer);
free(item);
ESP_LOGD(TAG, "DELETED msgid=%d, msg_type=%d, remain size=%d", msg_id, msg_type, outbox_get_size(outbox));
ESP_LOGD(TAG, "DELETED msgid=%d, msg_type=%d, remain size=%"PRIu64, msg_id, msg_type, outbox_get_size(outbox));
return ESP_OK;
}
}
return ESP_FAIL;
}
esp_err_t outbox_delete_msgid(outbox_handle_t outbox, int msg_id)
{
outbox_item_handle_t item, tmp;
STAILQ_FOREACH_SAFE(item, outbox, next, tmp) {
if (item->msg_id == msg_id) {
STAILQ_REMOVE(outbox, item, outbox_item, next);
free(item->buffer);
free(item);
}
}
return ESP_OK;
}
esp_err_t outbox_set_pending(outbox_handle_t outbox, int msg_id, pending_state_t pending)
{
outbox_item_handle_t item = outbox_get(outbox, msg_id);
@ -131,28 +143,51 @@ esp_err_t outbox_set_pending(outbox_handle_t outbox, int msg_id, pending_state_t
return ESP_FAIL;
}
esp_err_t outbox_delete_msgtype(outbox_handle_t outbox, int msg_type)
pending_state_t outbox_item_get_pending(outbox_item_handle_t item)
{
outbox_item_handle_t item, tmp;
STAILQ_FOREACH_SAFE(item, outbox, next, tmp) {
if (item->msg_type == msg_type) {
STAILQ_REMOVE(outbox, item, outbox_item, next);
if (item) {
return item->pending;
}
return QUEUED;
}
esp_err_t outbox_set_tick(outbox_handle_t outbox, int msg_id, outbox_tick_t tick)
{
outbox_item_handle_t item = outbox_get(outbox, msg_id);
if (item) {
item->tick = tick;
return ESP_OK;
}
return ESP_FAIL;
}
int outbox_delete_single_expired(outbox_handle_t outbox, outbox_tick_t current_tick, outbox_tick_t timeout)
{
int msg_id = -1;
outbox_item_handle_t item;
STAILQ_FOREACH(item, outbox->list, next) {
if (current_tick - item->tick > timeout) {
STAILQ_REMOVE(outbox->list, item, outbox_item, next);
free(item->buffer);
outbox->size -= item->len;
msg_id = item->msg_id;
free(item);
return msg_id;
}
}
return ESP_OK;
return msg_id;
}
int outbox_delete_expired(outbox_handle_t outbox, int current_tick, int timeout)
int outbox_delete_expired(outbox_handle_t outbox, outbox_tick_t current_tick, outbox_tick_t timeout)
{
int deleted_items = 0;
outbox_item_handle_t item, tmp;
STAILQ_FOREACH_SAFE(item, outbox, next, tmp) {
STAILQ_FOREACH_SAFE(item, outbox->list, next, tmp) {
if (current_tick - item->tick > timeout) {
STAILQ_REMOVE(outbox, item, outbox_item, next);
STAILQ_REMOVE(outbox->list, item, outbox_item, next);
free(item->buffer);
outbox->size -= item->len;
free(item);
deleted_items ++;
}
@ -161,35 +196,25 @@ int outbox_delete_expired(outbox_handle_t outbox, int current_tick, int timeout)
return deleted_items;
}
int outbox_get_size(outbox_handle_t outbox)
uint64_t outbox_get_size(outbox_handle_t outbox)
{
int siz = 0;
outbox_item_handle_t item;
STAILQ_FOREACH(item, outbox, next) {
// Suppressing "use after free" warning as this could happen only if queue is in inconsistent state
// which never happens if STAILQ interface used
siz += item->len; // NOLINT(clang-analyzer-unix.Malloc)
}
return siz;
return outbox->size;
}
esp_err_t outbox_cleanup(outbox_handle_t outbox, int max_size)
void outbox_delete_all_items(outbox_handle_t outbox)
{
while (outbox_get_size(outbox) > max_size) {
outbox_item_handle_t item = outbox_dequeue(outbox, CONFIRMED, NULL);
if (item == NULL) {
return ESP_FAIL;
}
STAILQ_REMOVE(outbox, item, outbox_item, next);
outbox_item_handle_t item, tmp;
STAILQ_FOREACH_SAFE(item, outbox->list, next, tmp) {
STAILQ_REMOVE(outbox->list, item, outbox_item, next);
outbox->size -= item->len;
free(item->buffer);
free(item);
}
return ESP_OK;
}
void outbox_destroy(outbox_handle_t outbox)
{
outbox_cleanup(outbox, 0);
outbox_delete_all_items(outbox);
free(outbox->list);
free(outbox);
}

View File

@ -1,21 +1,37 @@
#include "platform.h"
#ifdef ESP_PLATFORM
#include "esp_system.h"
#include "esp_log.h"
#include <sys/time.h>
#include "esp_mac.h"
#include "soc/soc_caps.h"
#include "esp_timer.h"
#include "esp_random.h"
#include <stdlib.h>
#include <stdint.h>
static const char *TAG = "PLATFORM";
static const char *TAG = "platform";
#define MAX_ID_STRING (32)
#if defined SOC_WIFI_SUPPORTED
#define MAC_TYPE ESP_MAC_WIFI_STA
#elif defined SOC_EMAC_SUPPORTED
#define MAC_TYPE ESP_MAC_ETH
#elif defined SOC_IEEE802154_SUPPORTED
#define MAC_TYPE ESP_MAC_IEEE802154
#endif
char *platform_create_id_string(void)
{
uint8_t mac[6];
char *id_string = calloc(1, MAX_ID_STRING);
ESP_MEM_CHECK(TAG, id_string, return NULL);
esp_read_mac(mac, ESP_MAC_WIFI_STA);
#ifndef MAC_TYPE
ESP_LOGW(TAG, "Soc doesn't provide MAC, client could be disconnected in case of device with same name in the broker.");
sprintf(id_string, "esp_mqtt_client_id");
#else
uint8_t mac[6];
esp_read_mac(mac, MAC_TYPE);
sprintf(id_string, "ESP32_%02x%02X%02X", mac[3], mac[4], mac[5]);
#endif
return id_string;
}
@ -24,18 +40,9 @@ int platform_random(int max)
return esp_random() % max;
}
long long platform_tick_get_ms(void)
uint64_t platform_tick_get_ms(void)
{
struct timeval te;
gettimeofday(&te, NULL); // get current time
long long milliseconds = te.tv_sec * 1000LL + te.tv_usec / 1000; // calculate milliseconds
// printf("milliseconds: %lld\n", milliseconds);
return milliseconds;
return esp_timer_get_time()/(int64_t)1000;
}
void ms_to_timeval(int timeout_ms, struct timeval *tv)
{
tv->tv_sec = timeout_ms / 1000;
tv->tv_usec = (timeout_ms - (tv->tv_sec * 1000)) * 1000;
}
#endif

761
mqtt5_client.c Normal file
View File

@ -0,0 +1,761 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "mqtt_client_priv.h"
#include "esp_log.h"
#include <string.h>
static const char *TAG = "mqtt5_client";
static void esp_mqtt5_print_error_code(esp_mqtt5_client_handle_t client, int code);
static esp_err_t esp_mqtt5_client_update_topic_alias(mqtt5_topic_alias_handle_t topic_alias_handle, uint16_t topic_alias, char *topic, size_t topic_len);
static char *esp_mqtt5_client_get_topic_alias(mqtt5_topic_alias_handle_t topic_alias_handle, uint16_t topic_alias, size_t *topic_length);
static void esp_mqtt5_client_delete_topic_alias(mqtt5_topic_alias_handle_t topic_alias_handle);
static esp_err_t esp_mqtt5_user_property_copy(mqtt5_user_property_handle_t user_property_new, const mqtt5_user_property_handle_t user_property_old);
void esp_mqtt5_increment_packet_counter(esp_mqtt5_client_handle_t client)
{
bool msg_dup = mqtt5_get_dup(client->mqtt_state.connection.outbound_message.data);
if (msg_dup == false) {
client->send_publish_packet_count ++;
ESP_LOGD(TAG, "Sent (%d) qos > 0 publish packet without ack", client->send_publish_packet_count);
}
}
void esp_mqtt5_decrement_packet_counter(esp_mqtt5_client_handle_t client)
{
if (client->send_publish_packet_count > 0) {
client->send_publish_packet_count --;
ESP_LOGD(TAG, "Receive (%d) qos > 0 publish packet with ack", client->send_publish_packet_count);
}
}
void esp_mqtt5_parse_pubcomp(esp_mqtt5_client_handle_t client)
{
if (client->mqtt_state.connection.information.protocol_ver == MQTT_PROTOCOL_V_5) {
ESP_LOGI(TAG, "MQTT_MSG_TYPE_PUBCOMP return code is %d", mqtt5_msg_get_reason_code(client->mqtt_state.in_buffer, client->mqtt_state.in_buffer_read_len));
size_t msg_data_len = client->mqtt_state.in_buffer_read_len;
client->event.data = mqtt5_get_pubcomp_data(client->mqtt_state.in_buffer, &msg_data_len, &client->event.property->user_property);
client->event.data_len = msg_data_len;
client->event.total_data_len = msg_data_len;
client->event.current_data_offset = 0;
}
}
void esp_mqtt5_parse_puback(esp_mqtt5_client_handle_t client)
{
if (client->mqtt_state.connection.information.protocol_ver == MQTT_PROTOCOL_V_5) {
ESP_LOGI(TAG, "MQTT_MSG_TYPE_PUBACK return code is %d", mqtt5_msg_get_reason_code(client->mqtt_state.in_buffer, client->mqtt_state.in_buffer_read_len));
size_t msg_data_len = client->mqtt_state.in_buffer_read_len;
client->event.data = mqtt5_get_puback_data(client->mqtt_state.in_buffer, &msg_data_len, &client->event.property->user_property);
client->event.data_len = msg_data_len;
client->event.total_data_len = msg_data_len;
client->event.current_data_offset = 0;
}
}
void esp_mqtt5_parse_unsuback(esp_mqtt5_client_handle_t client)
{
if (client->mqtt_state.connection.information.protocol_ver == MQTT_PROTOCOL_V_5) {
ESP_LOGI(TAG, "MQTT_MSG_TYPE_UNSUBACK return code is %d", mqtt5_msg_get_reason_code(client->mqtt_state.in_buffer, client->mqtt_state.in_buffer_read_len));
size_t msg_data_len = client->mqtt_state.in_buffer_read_len;
client->event.data = mqtt5_get_unsuback_data(client->mqtt_state.in_buffer, &msg_data_len, &client->event.property->user_property);
client->event.data_len = msg_data_len;
client->event.total_data_len = msg_data_len;
client->event.current_data_offset = 0;
}
}
void esp_mqtt5_parse_suback(esp_mqtt5_client_handle_t client)
{
if (client->mqtt_state.connection.information.protocol_ver == MQTT_PROTOCOL_V_5) {
ESP_LOGI(TAG, "MQTT_MSG_TYPE_SUBACK return code is %d", mqtt5_msg_get_reason_code(client->mqtt_state.in_buffer, client->mqtt_state.in_buffer_read_len));
}
}
esp_err_t esp_mqtt5_parse_connack(esp_mqtt5_client_handle_t client, int *connect_rsp_code)
{
size_t len = client->mqtt_state.in_buffer_read_len;
client->mqtt_state.in_buffer_read_len = 0;
uint8_t ack_flag = 0;
if (mqtt5_msg_parse_connack_property(client->mqtt_state.in_buffer, len, &client->mqtt_state.
connection.information, &client->mqtt5_config->connect_property_info, &client->mqtt5_config->server_resp_property_info, connect_rsp_code, &ack_flag, &client->event.property->user_property) != ESP_OK) {
ESP_LOGE(TAG, "Failed to parse CONNACK packet");
return ESP_FAIL;
}
if (*connect_rsp_code == MQTT_CONNECTION_ACCEPTED) {
ESP_LOGD(TAG, "Connected");
client->event.session_present = ack_flag & 0x01;
return ESP_OK;
}
esp_mqtt5_print_error_code(client, *connect_rsp_code);
return ESP_FAIL;
}
esp_err_t esp_mqtt5_get_publish_data(esp_mqtt5_client_handle_t client, uint8_t *msg_buf, size_t msg_read_len, char **msg_topic, size_t *msg_topic_len, char **msg_data, size_t *msg_data_len)
{
// get property
uint16_t property_len = 0;
esp_mqtt5_publish_resp_property_t property = {0};
*msg_data = mqtt5_get_publish_property_payload(msg_buf, msg_read_len, msg_topic, msg_topic_len, &property, &property_len, msg_data_len, &client->event.property->user_property);
if (*msg_data == NULL) {
ESP_LOGE(TAG, "%s: mqtt5_get_publish_property_payload() failed", __func__);
return ESP_FAIL;
}
if (property.topic_alias > client->mqtt5_config->connect_property_info.topic_alias_maximum) {
ESP_LOGE(TAG, "%s: Broker response topic alias %d is over the max topic alias %d", __func__, property.topic_alias, client->mqtt5_config->connect_property_info.topic_alias_maximum);
return ESP_FAIL;
}
if (property.topic_alias) {
if (*msg_topic_len == 0) {
ESP_LOGI(TAG, "Publish topic is empty, use topic alias");
*msg_topic = esp_mqtt5_client_get_topic_alias(client->mqtt5_config->peer_topic_alias, property.topic_alias, msg_topic_len);
if (!*msg_topic) {
ESP_LOGE(TAG, "%s: esp_mqtt5_client_get_topic_alias() failed", __func__);
return ESP_FAIL;
}
} else {
if (esp_mqtt5_client_update_topic_alias(client->mqtt5_config->peer_topic_alias, property.topic_alias, *msg_topic, *msg_topic_len) != ESP_OK) {
ESP_LOGE(TAG, "%s: esp_mqtt5_client_update_topic_alias() failed", __func__);
return ESP_FAIL;
}
}
}
client->event.property->payload_format_indicator = property.payload_format_indicator;
client->event.property->response_topic = property.response_topic;
client->event.property->response_topic_len = property.response_topic_len;
client->event.property->correlation_data = property.correlation_data;
client->event.property->correlation_data_len = property.correlation_data_len;
client->event.property->content_type = property.content_type;
client->event.property->content_type_len = property.content_type_len;
client->event.property->subscribe_id = property.subscribe_id;
return ESP_OK;
}
esp_err_t esp_mqtt5_create_default_config(esp_mqtt5_client_handle_t client)
{
if (client->mqtt_state.connection.information.protocol_ver == MQTT_PROTOCOL_V_5) {
client->event.property = calloc(1, sizeof(esp_mqtt5_event_property_t));
ESP_MEM_CHECK(TAG, client->event.property, return ESP_FAIL)
client->mqtt5_config = calloc(1, sizeof(mqtt5_config_storage_t));
ESP_MEM_CHECK(TAG, client->mqtt5_config, return ESP_FAIL)
client->mqtt5_config->server_resp_property_info.max_qos = 2;
client->mqtt5_config->server_resp_property_info.retain_available = true;
client->mqtt5_config->server_resp_property_info.wildcard_subscribe_available = true;
client->mqtt5_config->server_resp_property_info.subscribe_identifiers_available = true;
client->mqtt5_config->server_resp_property_info.shared_subscribe_available = true;
client->mqtt5_config->server_resp_property_info.receive_maximum = 65535;
}
return ESP_OK;
}
static void esp_mqtt5_print_error_code(esp_mqtt5_client_handle_t client, int code)
{
switch (code) {
case MQTT5_UNSPECIFIED_ERROR:
ESP_LOGW(TAG, "Unspecified error");
break;
case MQTT5_MALFORMED_PACKET:
ESP_LOGW(TAG, "Malformed Packet");
break;
case MQTT5_PROTOCOL_ERROR:
ESP_LOGW(TAG, "Protocol Error");
break;
case MQTT5_IMPLEMENT_SPECIFIC_ERROR:
ESP_LOGW(TAG, "Implementation specific error");
break;
case MQTT5_UNSUPPORTED_PROTOCOL_VER:
ESP_LOGW(TAG, "Unsupported Protocol Version");
break;
case MQTT5_INVALID_CLIENT_ID:
ESP_LOGW(TAG, "Client Identifier not valid");
break;
case MQTT5_BAD_USERNAME_OR_PWD:
ESP_LOGW(TAG, "Bad User Name or Password");
break;
case MQTT5_NOT_AUTHORIZED:
ESP_LOGW(TAG, "Not authorized");
break;
case MQTT5_SERVER_UNAVAILABLE:
ESP_LOGW(TAG, "Server unavailable");
break;
case MQTT5_SERVER_BUSY:
ESP_LOGW(TAG, "Server busy");
break;
case MQTT5_BANNED:
ESP_LOGW(TAG, "Banned");
break;
case MQTT5_SERVER_SHUTTING_DOWN:
ESP_LOGW(TAG, "Server shutting down");
break;
case MQTT5_BAD_AUTH_METHOD:
ESP_LOGW(TAG, "Bad authentication method");
break;
case MQTT5_KEEP_ALIVE_TIMEOUT:
ESP_LOGW(TAG, "Keep Alive timeout");
break;
case MQTT5_SESSION_TAKEN_OVER:
ESP_LOGW(TAG, "Session taken over");
break;
case MQTT5_TOPIC_FILTER_INVALID:
ESP_LOGW(TAG, "Topic Filter invalid");
break;
case MQTT5_TOPIC_NAME_INVALID:
ESP_LOGW(TAG, "Topic Name invalid");
break;
case MQTT5_PACKET_IDENTIFIER_IN_USE:
ESP_LOGW(TAG, "Packet Identifier in use");
break;
case MQTT5_PACKET_IDENTIFIER_NOT_FOUND:
ESP_LOGW(TAG, "Packet Identifier not found");
break;
case MQTT5_RECEIVE_MAXIMUM_EXCEEDED:
ESP_LOGW(TAG, "Receive Maximum exceeded");
break;
case MQTT5_TOPIC_ALIAS_INVALID:
ESP_LOGW(TAG, "Topic Alias invalid");
break;
case MQTT5_PACKET_TOO_LARGE:
ESP_LOGW(TAG, "Packet too large");
break;
case MQTT5_MESSAGE_RATE_TOO_HIGH:
ESP_LOGW(TAG, "Message rate too high");
break;
case MQTT5_QUOTA_EXCEEDED:
ESP_LOGW(TAG, "Quota exceeded");
break;
case MQTT5_ADMINISTRATIVE_ACTION:
ESP_LOGW(TAG, "Administrative action");
break;
case MQTT5_PAYLOAD_FORMAT_INVALID:
ESP_LOGW(TAG, "Payload format invalid");
break;
case MQTT5_RETAIN_NOT_SUPPORT:
ESP_LOGW(TAG, "Retain not supported");
break;
case MQTT5_QOS_NOT_SUPPORT:
ESP_LOGW(TAG, "QoS not supported");
break;
case MQTT5_USE_ANOTHER_SERVER:
ESP_LOGW(TAG, "Use another server");
break;
case MQTT5_SERVER_MOVED:
ESP_LOGW(TAG, "Server moved");
break;
case MQTT5_SHARED_SUBSCR_NOT_SUPPORTED:
ESP_LOGW(TAG, "Shared Subscriptions not supported");
break;
case MQTT5_CONNECTION_RATE_EXCEEDED:
ESP_LOGW(TAG, "Connection rate exceeded");
break;
case MQTT5_MAXIMUM_CONNECT_TIME:
ESP_LOGW(TAG, "Maximum connect time");
break;
case MQTT5_SUBSCRIBE_IDENTIFIER_NOT_SUPPORT:
ESP_LOGW(TAG, "Subscription Identifiers not supported");
break;
case MQTT5_WILDCARD_SUBSCRIBE_NOT_SUPPORT:
ESP_LOGW(TAG, "Wildcard Subscriptions not supported");
break;
default:
ESP_LOGW(TAG, "Connection refused, Unknow reason");
break;
}
}
esp_err_t esp_mqtt5_client_subscribe_check(esp_mqtt5_client_handle_t client, int qos)
{
/* Check Server support QoS level */
if (client->mqtt5_config->server_resp_property_info.max_qos < qos) {
ESP_LOGE(TAG, "Server only support max QoS level %d", client->mqtt5_config->server_resp_property_info.max_qos);
return ESP_FAIL;
}
return ESP_OK;
}
esp_err_t esp_mqtt5_client_publish_check(esp_mqtt5_client_handle_t client, int qos, int retain)
{
/* Check Server support QoS level */
if (client->mqtt5_config->server_resp_property_info.max_qos < qos) {
ESP_LOGE(TAG, "Server only support max QoS level %d", client->mqtt5_config->server_resp_property_info.max_qos);
return ESP_FAIL;
}
/* Check Server support RETAIN */
if (!client->mqtt5_config->server_resp_property_info.retain_available && retain) {
ESP_LOGE(TAG, "Server not support retain");
return ESP_FAIL;
}
/* Flow control to check PUBLISH(No PUBACK or PUBCOMP received) packet sent count(Only record QoS1 and QoS2)*/
if (client->send_publish_packet_count > client->mqtt5_config->server_resp_property_info.receive_maximum) {
ESP_LOGE(TAG, "Client send more than %d QoS1 and QoS2 PUBLISH packet without no ack", client->mqtt5_config->server_resp_property_info.receive_maximum);
return ESP_FAIL;
}
return ESP_OK;
}
void esp_mqtt5_client_destory(esp_mqtt5_client_handle_t client)
{
if (client->mqtt_state.connection.information.protocol_ver == MQTT_PROTOCOL_V_5) {
if (client->mqtt5_config) {
free(client->mqtt5_config->will_property_info.content_type);
free(client->mqtt5_config->will_property_info.response_topic);
free(client->mqtt5_config->will_property_info.correlation_data);
free(client->mqtt5_config->server_resp_property_info.response_info);
esp_mqtt5_client_delete_topic_alias(client->mqtt5_config->peer_topic_alias);
esp_mqtt5_client_delete_user_property(client->mqtt5_config->connect_property_info.user_property);
esp_mqtt5_client_delete_user_property(client->mqtt5_config->will_property_info.user_property);
esp_mqtt5_client_delete_user_property(client->mqtt5_config->disconnect_property_info.user_property);
free(client->mqtt5_config);
}
free(client->event.property);
}
}
static void esp_mqtt5_client_delete_topic_alias(mqtt5_topic_alias_handle_t topic_alias_handle)
{
if (topic_alias_handle) {
mqtt5_topic_alias_item_t item, tmp;
STAILQ_FOREACH_SAFE(item, topic_alias_handle, next, tmp) {
STAILQ_REMOVE(topic_alias_handle, item, mqtt5_topic_alias, next);
free(item->topic);
free(item);
}
free(topic_alias_handle);
}
}
static esp_err_t esp_mqtt5_client_update_topic_alias(mqtt5_topic_alias_handle_t topic_alias_handle, uint16_t topic_alias, char *topic, size_t topic_len)
{
mqtt5_topic_alias_item_t item;
bool found = false;
STAILQ_FOREACH(item, topic_alias_handle, next) {
if (item->topic_alias == topic_alias) {
found = true;
break;
}
}
if (found) {
if ((item->topic_len != topic_len) || strncmp(topic, item->topic, topic_len)) {
free(item->topic);
item->topic = calloc(1, topic_len);
ESP_MEM_CHECK(TAG, item->topic, return ESP_FAIL);
memcpy(item->topic, topic, topic_len);
item->topic_len = topic_len;
}
} else {
item = calloc(1, sizeof(mqtt5_topic_alias_t));
ESP_MEM_CHECK(TAG, item, return ESP_FAIL);
item->topic_alias = topic_alias;
item->topic_len = topic_len;
item->topic = calloc(1, topic_len);
ESP_MEM_CHECK(TAG, item->topic, {
free(item);
return ESP_FAIL;
});
memcpy(item->topic, topic, topic_len);
STAILQ_INSERT_TAIL(topic_alias_handle, item, next);
}
return ESP_OK;
}
static char *esp_mqtt5_client_get_topic_alias(mqtt5_topic_alias_handle_t topic_alias_handle, uint16_t topic_alias, size_t *topic_length)
{
mqtt5_topic_alias_item_t item;
STAILQ_FOREACH(item, topic_alias_handle, next) {
if (item->topic_alias == topic_alias) {
*topic_length = item->topic_len;
return item->topic;
}
}
*topic_length = 0;
return NULL;
}
static esp_err_t esp_mqtt5_user_property_copy(mqtt5_user_property_handle_t user_property_new, const mqtt5_user_property_handle_t user_property_old)
{
if (!user_property_new || !user_property_old) {
ESP_LOGE(TAG, "Input is NULL");
return ESP_FAIL;
}
mqtt5_user_property_item_t old_item, new_item;
STAILQ_FOREACH(old_item, user_property_old, next) {
new_item = calloc(1, sizeof(mqtt5_user_property_t));
ESP_MEM_CHECK(TAG, new_item, return ESP_FAIL);
new_item->key = strdup(old_item->key);
ESP_MEM_CHECK(TAG, new_item->key, {
free(new_item);
return ESP_FAIL;
});
new_item->value = strdup(old_item->value);
ESP_MEM_CHECK(TAG, new_item->value, {
free(new_item->key);
free(new_item);
return ESP_FAIL;
});
STAILQ_INSERT_TAIL(user_property_new, new_item, next);
}
return ESP_OK;
}
esp_err_t esp_mqtt5_client_set_publish_property(esp_mqtt5_client_handle_t client, const esp_mqtt5_publish_property_config_t *property)
{
if (!client) {
ESP_LOGE(TAG, "Client was not initialized");
return ESP_ERR_INVALID_ARG;
}
MQTT_API_LOCK(client);
/* Check protocol version */
if (client->mqtt_state.connection.information.protocol_ver != MQTT_PROTOCOL_V_5) {
ESP_LOGE(TAG, "MQTT protocol version is not v5");
MQTT_API_UNLOCK(client);
return ESP_FAIL;
}
/* Check topic alias less than server maximum topic alias */
if (property->topic_alias > client->mqtt5_config->server_resp_property_info.topic_alias_maximum) {
ESP_LOGE(TAG, "Topic alias %d is bigger than server support %d", property->topic_alias, client->mqtt5_config->server_resp_property_info.topic_alias_maximum);
MQTT_API_UNLOCK(client);
return ESP_FAIL;
}
client->mqtt5_config->publish_property_info = property;
MQTT_API_UNLOCK(client);
return ESP_OK;
}
esp_err_t esp_mqtt5_client_set_subscribe_property(esp_mqtt5_client_handle_t client, const esp_mqtt5_subscribe_property_config_t *property)
{
if (!client) {
ESP_LOGE(TAG, "Client was not initialized");
return ESP_ERR_INVALID_ARG;
}
if (property->retain_handle > 2) {
ESP_LOGE(TAG, "retain_handle only support 0, 1, 2");
return -1;
}
MQTT_API_LOCK(client);
/* Check protocol version */
if (client->mqtt_state.connection.information.protocol_ver != MQTT_PROTOCOL_V_5) {
ESP_LOGE(TAG, "MQTT protocol version is not v5");
MQTT_API_UNLOCK(client);
return ESP_FAIL;
}
if (property->is_share_subscribe) {
if (property->no_local_flag) {
// MQTT-3.8.3-4 not allow that No Local bit to 1 on a Shared Subscription
ESP_LOGE(TAG, "Protocol error that no local flag set on shared subscription");
MQTT_API_UNLOCK(client);
return ESP_FAIL;
}
if (!client->mqtt5_config->server_resp_property_info.shared_subscribe_available) {
ESP_LOGE(TAG, "MQTT broker not support shared subscribe");
MQTT_API_UNLOCK(client);
return ESP_FAIL;
}
if (!property->share_name || !strlen(property->share_name)) {
ESP_LOGE(TAG, "Share name can't be empty for shared subscribe");
MQTT_API_UNLOCK(client);
return ESP_FAIL;
}
}
client->mqtt5_config->subscribe_property_info = property;
MQTT_API_UNLOCK(client);
return ESP_OK;
}
esp_err_t esp_mqtt5_client_set_unsubscribe_property(esp_mqtt5_client_handle_t client, const esp_mqtt5_unsubscribe_property_config_t *property)
{
if (!client) {
ESP_LOGE(TAG, "Client was not initialized");
return ESP_ERR_INVALID_ARG;
}
MQTT_API_LOCK(client);
/* Check protocol version */
if (client->mqtt_state.connection.information.protocol_ver != MQTT_PROTOCOL_V_5) {
ESP_LOGE(TAG, "MQTT protocol version is not v5");
MQTT_API_UNLOCK(client);
return ESP_FAIL;
}
if (property->is_share_subscribe) {
if (!client->mqtt5_config->server_resp_property_info.shared_subscribe_available) {
ESP_LOGE(TAG, "MQTT broker not support shared subscribe");
MQTT_API_UNLOCK(client);
return ESP_FAIL;
}
if (!property->share_name || !strlen(property->share_name)) {
ESP_LOGE(TAG, "Share name can't be empty for shared subscribe");
MQTT_API_UNLOCK(client);
return ESP_FAIL;
}
}
client->mqtt5_config->unsubscribe_property_info = property;
MQTT_API_UNLOCK(client);
return ESP_OK;
}
esp_err_t esp_mqtt5_client_set_disconnect_property(esp_mqtt5_client_handle_t client, const esp_mqtt5_disconnect_property_config_t *property)
{
if (!client) {
ESP_LOGE(TAG, "Client was not initialized");
return ESP_ERR_INVALID_ARG;
}
MQTT_API_LOCK(client);
/* Check protocol version */
if (client->mqtt_state.connection.information.protocol_ver != MQTT_PROTOCOL_V_5) {
ESP_LOGE(TAG, "MQTT protocol version is not v5");
MQTT_API_UNLOCK(client);
return ESP_FAIL;
}
if (property) {
if (property->session_expiry_interval) {
client->mqtt5_config->disconnect_property_info.session_expiry_interval = property->session_expiry_interval;
}
if (property->disconnect_reason) {
client->mqtt5_config->disconnect_property_info.disconnect_reason = property->disconnect_reason;
}
if (property->user_property) {
esp_mqtt5_client_delete_user_property(client->mqtt5_config->disconnect_property_info.user_property);
client->mqtt5_config->disconnect_property_info.user_property = calloc(1, sizeof(struct mqtt5_user_property_list_t));
ESP_MEM_CHECK(TAG, client->mqtt5_config->disconnect_property_info.user_property, {
MQTT_API_UNLOCK(client);
return ESP_ERR_NO_MEM;
});
STAILQ_INIT(client->mqtt5_config->disconnect_property_info.user_property);
if (esp_mqtt5_user_property_copy(client->mqtt5_config->disconnect_property_info.user_property, property->user_property) != ESP_OK) {
ESP_LOGE(TAG, "esp_mqtt5_user_property_copy fail");
free(client->mqtt5_config->disconnect_property_info.user_property);
client->mqtt5_config->disconnect_property_info.user_property = NULL;
MQTT_API_UNLOCK(client);
return ESP_FAIL;
}
}
}
MQTT_API_UNLOCK(client);
return ESP_OK;
}
esp_err_t esp_mqtt5_client_set_connect_property(esp_mqtt5_client_handle_t client, const esp_mqtt5_connection_property_config_t *connect_property)
{
if (!client) {
ESP_LOGE(TAG, "Client was not initialized");
return ESP_ERR_INVALID_ARG;
}
MQTT_API_LOCK(client);
/* Check protocol version */
if (client->mqtt_state.connection.information.protocol_ver != MQTT_PROTOCOL_V_5) {
ESP_LOGE(TAG, "MQTT protocol version is not v5");
MQTT_API_UNLOCK(client);
return ESP_FAIL;
}
if (connect_property) {
if (connect_property->session_expiry_interval) {
client->mqtt5_config->connect_property_info.session_expiry_interval = connect_property->session_expiry_interval;
}
if (connect_property->maximum_packet_size) {
if (connect_property->maximum_packet_size > client->mqtt_state.in_buffer_length) {
ESP_LOGW(TAG, "Connect maximum_packet_size property is over buffer_size(%d), Please first change it", client->mqtt_state.in_buffer_length);
MQTT_API_UNLOCK(client);
return ESP_FAIL;
} else {
client->mqtt5_config->connect_property_info.maximum_packet_size = connect_property->maximum_packet_size;
}
} else {
client->mqtt5_config->connect_property_info.maximum_packet_size = client->mqtt_state.in_buffer_length;
}
if (connect_property->receive_maximum) {
client->mqtt5_config->connect_property_info.receive_maximum = connect_property->receive_maximum;
}
if (connect_property->topic_alias_maximum) {
client->mqtt5_config->connect_property_info.topic_alias_maximum = connect_property->topic_alias_maximum;
if (!client->mqtt5_config->peer_topic_alias) {
client->mqtt5_config->peer_topic_alias = calloc(1, sizeof(struct mqtt5_topic_alias_list_t));
ESP_MEM_CHECK(TAG, client->mqtt5_config->peer_topic_alias, goto _mqtt_set_config_failed);
STAILQ_INIT(client->mqtt5_config->peer_topic_alias);
}
}
if (connect_property->request_resp_info) {
client->mqtt5_config->connect_property_info.request_resp_info = connect_property->request_resp_info;
}
if (connect_property->request_problem_info) {
client->mqtt5_config->connect_property_info.request_problem_info = connect_property->request_problem_info;
}
if (connect_property->user_property) {
esp_mqtt5_client_delete_user_property(client->mqtt5_config->connect_property_info.user_property);
client->mqtt5_config->connect_property_info.user_property = calloc(1, sizeof(struct mqtt5_user_property_list_t));
ESP_MEM_CHECK(TAG, client->mqtt5_config->connect_property_info.user_property, goto _mqtt_set_config_failed);
STAILQ_INIT(client->mqtt5_config->connect_property_info.user_property);
if (esp_mqtt5_user_property_copy(client->mqtt5_config->connect_property_info.user_property, connect_property->user_property) != ESP_OK) {
ESP_LOGE(TAG, "esp_mqtt5_user_property_copy fail");
goto _mqtt_set_config_failed;
}
}
if (connect_property->payload_format_indicator) {
client->mqtt5_config->will_property_info.payload_format_indicator = connect_property->payload_format_indicator;
}
if (connect_property->will_delay_interval) {
client->mqtt5_config->will_property_info.will_delay_interval = connect_property->will_delay_interval;
}
if (connect_property->message_expiry_interval) {
client->mqtt5_config->will_property_info.message_expiry_interval = connect_property->message_expiry_interval;
}
ESP_MEM_CHECK(TAG, esp_mqtt_set_if_config(connect_property->content_type, &client->mqtt5_config->will_property_info.content_type), goto _mqtt_set_config_failed);
ESP_MEM_CHECK(TAG, esp_mqtt_set_if_config(connect_property->response_topic, &client->mqtt5_config->will_property_info.response_topic), goto _mqtt_set_config_failed);
if (connect_property->correlation_data && connect_property->correlation_data_len) {
free(client->mqtt5_config->will_property_info.correlation_data);
client->mqtt5_config->will_property_info.correlation_data = malloc(connect_property->correlation_data_len);
ESP_MEM_CHECK(TAG, client->mqtt5_config->will_property_info.correlation_data, goto _mqtt_set_config_failed);
memcpy(client->mqtt5_config->will_property_info.correlation_data, connect_property->correlation_data, connect_property->correlation_data_len);
client->mqtt5_config->will_property_info.correlation_data_len = connect_property->correlation_data_len;
}
if (connect_property->will_user_property) {
esp_mqtt5_client_delete_user_property(client->mqtt5_config->will_property_info.user_property);
client->mqtt5_config->will_property_info.user_property = calloc(1, sizeof(struct mqtt5_user_property_list_t));
ESP_MEM_CHECK(TAG, client->mqtt5_config->will_property_info.user_property, goto _mqtt_set_config_failed);
STAILQ_INIT(client->mqtt5_config->will_property_info.user_property);
if (esp_mqtt5_user_property_copy(client->mqtt5_config->will_property_info.user_property, connect_property->will_user_property) != ESP_OK) {
ESP_LOGE(TAG, "esp_mqtt5_user_property_copy fail");
goto _mqtt_set_config_failed;
}
}
}
MQTT_API_UNLOCK(client);
return ESP_OK;
_mqtt_set_config_failed:
esp_mqtt_destroy_config(client);
MQTT_API_UNLOCK(client);
return ESP_ERR_NO_MEM;
}
esp_err_t esp_mqtt5_client_set_user_property(mqtt5_user_property_handle_t *user_property, esp_mqtt5_user_property_item_t item[], uint8_t item_num)
{
if (!item_num || !item) {
ESP_LOGE(TAG, "Input value is NULL");
return ESP_FAIL;
}
if (!*user_property) {
*user_property = calloc(1, sizeof(struct mqtt5_user_property_list_t));
ESP_MEM_CHECK(TAG, *user_property, return ESP_ERR_NO_MEM);
STAILQ_INIT(*user_property);
}
for (int i = 0; i < item_num; i ++) {
if (item[i].key && item[i].value) {
mqtt5_user_property_item_t user_property_item = calloc(1, sizeof(mqtt5_user_property_t));
ESP_MEM_CHECK(TAG, user_property_item, goto err);
size_t key_len = strlen(item[i].key);
size_t value_len = strlen(item[i].value);
user_property_item->key = calloc(1, key_len + 1);
ESP_MEM_CHECK(TAG, user_property_item->key, {
free(user_property_item);
goto err;
});
memcpy(user_property_item->key, item[i].key, key_len);
user_property_item->key[key_len] = '\0';
user_property_item->value = calloc(1, value_len + 1);
ESP_MEM_CHECK(TAG, user_property_item->value, {
free(user_property_item->key);
free(user_property_item);
goto err;
});
memcpy(user_property_item->value, item[i].value, value_len);
user_property_item->value[value_len] = '\0';
STAILQ_INSERT_TAIL(*user_property, user_property_item, next);
}
}
return ESP_OK;
err:
esp_mqtt5_client_delete_user_property(*user_property);
*user_property = NULL;
return ESP_ERR_NO_MEM;
}
esp_err_t esp_mqtt5_client_get_user_property(mqtt5_user_property_handle_t user_property, esp_mqtt5_user_property_item_t *item, uint8_t *item_num)
{
int i = 0, j = 0;
if (user_property && item && *item_num) {
mqtt5_user_property_item_t user_property_item;
uint8_t num = *item_num;
STAILQ_FOREACH(user_property_item, user_property, next) {
if (i < num) {
size_t item_key_len = strlen(user_property_item->key);
size_t item_value_len = strlen(user_property_item->value);
char *key = calloc(1, item_key_len + 1);
ESP_MEM_CHECK(TAG, key, goto err);
memcpy(key, user_property_item->key, item_key_len);
key[item_key_len] = '\0';
char *value = calloc(1, item_value_len + 1);
ESP_MEM_CHECK(TAG, value, {
free(key);
goto err;
});
memcpy(value, user_property_item->value, item_value_len);
value[item_value_len] = '\0';
item[i].key = key;
item[i].value = value;
i ++;
} else {
break;
}
}
*item_num = i;
return ESP_OK;
} else {
ESP_LOGE(TAG, "Input value is NULL or item_num is 0");
return ESP_FAIL;
}
err:
for (j = 0; j < i; j ++) {
if (item[j].key) {
free((char *)item[j].key);
}
if (item[j].value) {
free((char *)item[j].value);
}
}
return ESP_ERR_NO_MEM;
}
uint8_t esp_mqtt5_client_get_user_property_count(mqtt5_user_property_handle_t user_property)
{
uint8_t count = 0;
if (user_property) {
mqtt5_user_property_item_t item;
STAILQ_FOREACH(item, user_property, next) {
count ++;
}
}
return count;
}
void esp_mqtt5_client_delete_user_property(mqtt5_user_property_handle_t user_property)
{
if (user_property) {
mqtt5_user_property_item_t item, tmp;
STAILQ_FOREACH_SAFE(item, user_property, next, tmp) {
STAILQ_REMOVE(user_property, item, mqtt5_user_property, next);
free(item->key);
free(item->value);
free(item);
}
}
free(user_property);
}

File diff suppressed because it is too large Load Diff