A portable MQTT C client for embedded systems and PCs alike.

Overview


MQTT-C is an MQTT v3.1.1 client written in C. MQTT is a lightweight publisher-subscriber-based messaging protocol that is commonly used in IoT and networking applications where high-latency and low data-rate links are expected. The purpose of MQTT-C is to provide a portable MQTT client, written in C, for embedded systems and PC's alike. MQTT-C does this by providing a transparent Platform Abstraction Layer (PAL) which makes porting to new platforms easy. MQTT-C is completely thread-safe but can also run perfectly fine on single-threaded systems making MQTT-C well-suited for embedded systems and microcontrollers. Finally, MQTT-C is small; there are only two source files totalling less than 2000 lines.

A note from the author

It's been great to hear about all the places MQTT-C is being used! Please don't hesitate to get in touch with me or submit issues on GitHub!

Getting Started

To use MQTT-C you first instantiate a struct mqtt_client and initialize it by calling @ref mqtt_init.

    struct mqtt_client client; /* instantiate the client */
    mqtt_init(&client, ...);   /* initialize the client */

Once your client is initialized you need to connect to an MQTT broker.

    mqtt_connect(&client, ...); /* send a connection request to the broker. */

At this point the client is ready to use! For example, we can subscribe to a topic like so:

    /* subscribe to "toaster/temperature" with a max QoS level of 0 */
    mqtt_subscribe(&client, "toaster/temperature", 0);

And we can publish to a topic like so:

    /* publish coffee temperature with a QoS level of 1 */
    int temperature = 67;
    mqtt_publish(&client, "coffee/temperature", &temperature, sizeof(int), MQTT_PUBLISH_QOS_1);

Those are the basics! From here the examples and API documentation are good places to get started.

Building

There are only two source files that need to be built, mqtt.c and mqtt_pal.c. These files are ANSI C (C89) compatible, and should compile with any C compiler.

Then, simply #include <mqtt.h>.

Alternatively, you can build MQTT-C with CMake or the provided Makefile. These are provided for convenience.

Documentation

Pre-built documentation can be found here: https://liambindle.ca/MQTT-C. Be sure to check out the examples too.

The @ref api documentation contains all the documentation application programmers should need. The @ref pal documentation contains everything you should need to port MQTT-C to a new platform, and the other modules contain documentation for MQTT-C developers.

Testing and Building the Tests

The MQTT-C unit tests use the cmocka unit testing framework. Therefore, cmocka must be installed on your machine to build and run the unit tests. For convenience, a simple "makefile" is included to build the unit tests and examples on UNIX-like machines. The unit tests and examples can be built as follows:

    $ make all

The unit tests and examples will be built in the "bin/" directory. The unit tests can be run like so:

    $ ./bin/tests [address [port]]

Note that the \c address and \c port arguments are both optional to specify the location of the MQTT broker that is to be used for the tests. If no \c address is given then the Mosquitto MQTT Test Server will be used. If no \c port is given, port 1883 will be used.

Portability

MQTT-C provides a transparent platform abstraction layer (PAL) in mqtt_pal.h and mqtt_pal.c. These files declare and implement the types and calls that MQTT-C requires. Refer to @ref pal for the complete documentation of the PAL.

Contributing

Please feel free to submit issues and pull-requests here. When submitting a pull-request please ensure you have fully documented your changes and added the appropriate unit tests.

License

This project is licensed under the MIT License. See the "LICENSE" file for more details.

Authors

MQTT-C was initially developed as a CMPT 434 (Winter Term, 2018) final project at the University of Saskatchewan by:

  • Liam Bindle
  • Demilade Adeoye
Comments
  • Issue/90 MQTT-C header rename

    Issue/90 MQTT-C header rename

    Rename:

    • mqtt.c -> mqttc.c
    • mqtt.h -> mqttc.h

    Update:

    • CMake and Makefile to use renamed MQTT-C source file
    • examples and tests to use renamed MQTT-C header file
    opened by vpetrigo 18
  • Automatic reconnect

    Automatic reconnect

    Supporting the auto-reconnecting feature that some other MQTT libraries support would be a good enhancement. I'm not yet familiar with this feature, but it was requested by @jedidiahuang.

    I'm not going to have time to add this right away, but I wanted to submit this issue to start a discussion/take note that its something that would be good to add.

    If anyone has any comments/suggestion feel free to include them in this thread.

    enhancement 
    opened by LiamBindle 14
  • There is three pacthes.

    There is three pacthes.

    1. Remove trailing space.
    2. Always setting the last byte of recvbuf to zero. So that string are null terminated.
    3. Fixes MQTT_ERROR_SEND_BUFFER_IS_FULL that cause reconnect. MQTT_ERROR_SEND_BUFFER_IS_FULL should not cause reconnect and not necessary. We can recover from it.

    Fixes __mqtt_next_pid that client may not initialized yet when calling to mqtt_publish and using mqtt_init_reconnect

    opened by lygstate 12
  • Add anonymous client functionality

    Add anonymous client functionality

    3.1.3.1 Client Identifier ... A Server MAY allow a Client to supply a ClientId that has a length of zero bytes, however if it does so the Server MUST treat this as a special case and assign a unique ClientId to that Client. It MUST then process the CONNECT packet as if the Client had provided that unique ClientId [MQTT-3.1.3-6]. ...

    Additionally, this updates the error enum, renaming MQTT_ERROR_CONNECT_NULL_CLIENT_ID to MQTT_ERROR_CONNECT_NULL_CLIENT_ID_OBSOLETE (as to preserve the numerical values of all options). And updates the samples reconnect_subscriber, simple_publisher, simple_subscriber to use the new empty client identifier functionality, along with the MQTT_CONNECT_CLEAN_SESSION flag.

    Thanks to the user dsal from #[email protected] getting me kick-started analyzing the protocol.

    opened by learn-more 11
  • MQTT_ERROR_CONTROL_FORBIDDEN_TYPE error with QOS_1

    MQTT_ERROR_CONTROL_FORBIDDEN_TYPE error with QOS_1

    I am using your library on an embedded device and its mostly working quite well, but I've run into an issue with receiving messages that were sent from Azure IOTHUB while the device is not connected to iothub.

    The device connects only every so often to iothub to check for messages from the server and send messages to the server. It then disconnects the underlying socket and does a mqtt_reinit on the next connection to start again.

    The issue I'm running into specifically is that when I set 1 in mqtt_subscribe in the max_qos argument to guarantee that I will get any messages from the server that were sent while I was offline, it gives me the MQTT_ERROR_CONTROL_FORBIDDEN_TYPE specifically in the following conditions

    1. I send more than 1 message to the device while it is offline, it comes online and then receives the first message. After which it will (I assume) send an ack and whatever it receives next has a header with a control_type of 0x0 causing the MQTT_ERROR_CONTROL_FORBIDDEN_TYPE error.

    After that error has occured I can no longer send anything to the server. When it reconnects again later it will receive the same message it already received and error again on the same thing. It doesn't even get to the second message.

    Repeating this on every reconnect until the server stops sending the message.

    1. The second scenario is when setting the mqtt_publish side to MQTT_PUBLISH_QOS_1 as well as themqtt_subscribeside. Then I only ever get thatMQTT_ERROR_CONTROL_FORBIDDEN_TYPE` error and I cannot even receive one message.

    I wondered if you had any insight as to why this might be happening?

    opened by TonyTheLion 10
  • Work in progress msvc building

    Work in progress msvc building

    • CMake works
    • bio_publisher builds
    • openssl_publisher builds
    • reconnect_subscriber builds + works
    • simple_publisher builds + works
    • simple_subscriber builds + works
    • tests do not build yet
    • Ctrl+d handling does not work yet

    @LiamBindle I made this a draft so that you can easily follow the progress and comment on it while it is in-progress.

    opened by learn-more 9
  • blocking socket support

    blocking socket support

    Hi @LiamBindle, Do you support blocking mode for receiving message? I see a busy loop to call mqtt_sync(). It will be great if you have a blocking function Thank you

    enhancement 
    opened by BloodyF 9
  • Create explicit functions for each PAL protocol

    Create explicit functions for each PAL protocol

    This will allow easy support of socket handles that support several transports at runtime. For example able to establish two connections over TLS and TCP transport without recompiling.

    opened by maht 7
  • Unaligned TX buffer leads to Segmentation/Hard Fault

    Unaligned TX buffer leads to Segmentation/Hard Fault

    Hello,

    As the implementation reflects MQTT TX buffer to the internal memory queue that leads to Segmentation/Memory/Hard Faults on some platform. It definitely leads to Hard Fault on ARMv7-M architectures and most likely for other ARM architectures (ARMv7E-M, ARMv6, ARMv5, etc.) upon a write access operation. On the x86/x86-64 platform it is not so critical as it supports unaligned pointer read/write access, but it definitely would drop performance as unaligned access has its cost.

    So, I see the following options:

    • document that TX buffer should be aligned to word boundary
    • silently check alignment and operate on aligned part of provided buffer

    Would you tell if that makes sense for you?

    todo doc update 
    opened by vpetrigo 7
  • How to get number of writable bytes in send buffer

    How to get number of writable bytes in send buffer

    Hi Liam,

    Is there a way to get the number of writable bytes remaining in a client's send buffer? I see that there is the curr_sz field in the client's message queue, but this doesn't appear to do exactly what I need it to. This field will remain unchanged (as far as I can tell) after a call to mqtt_sync.

    Say my buffer size is 4096. Initially, curr_sz will be approximately 4096 (let's say 4000). After I publish a 150-byte message, curr_sz will decrease by just over 150 bytes. So now, curr_sz is somewhere around 3800. After I call mqtt_sync, curr_sz is still 3800. What I'm looking for is a field (or an expression, perhaps) that will give me 4000 after calling mqtt_sync, indicating that there is more room in the buffer because a message has been sent.

    Basically, I'm trying to avoid the MQTT_ERROR_SEND_BUFFER_IS_FULL error. I am using the automatic recovery feature. But for my use case, it would be better for my application to not attempt to send a message that won't fit in the buffer.

    Thanks for your help. Fantastic library, by the way.

    question 
    opened by Josh798 7
  • Fixed some conversion errors that occur when the -Wc++-compat compiler flag is enabled

    Fixed some conversion errors that occur when the -Wc++-compat compiler flag is enabled

    The compiler flag -Wc++-compat causes some errors in the build process. These are conversion errors that I fixed in this PR. Attached is a build.log.

    We are using the MQTT library in the open-source project open62541. For this reason, it would be great if the PR is merged as soon as possible. Also, it would be great if a new tag could be created after the merge, which we can then use for our git submodules. Thanks

    opened by NoelGraf 6
  • Fix mqtt_init_reconnect initialisation

    Fix mqtt_init_reconnect initialisation

    When using mqtt_init_reconnect() instead of mqtt_init() there are a couple of fields in the data structures that are currently left uninitialised. This PR proposes a fix.

    opened by MartinKlang 0
  • Cross-compilation through Zig compiler toolchain

    Cross-compilation through Zig compiler toolchain

    Adds a build.zig file to be able to use the Zig build system to compile a static library for Windows (x86_64), macOS (Apple Silicon and Intel) and Linux (x86_64 and ARM64).

    You can try it yourself by executing zig build in the repo root and following files should be created in zig-out/lib:

    libmqtt-c-apple-silicon.a
    libmqtt-c-arm64.a
    libmqtt-c-mac-x64.a
    libmqtt-c-x64.a
    mqtt-c.lib
    
    opened by akgvn 0
  • How to check the client has received a Connack from the Broker after connect()

    How to check the client has received a Connack from the Broker after connect()

    after reading the API Docu and reading the code, I still have no clue how to check for an successful connect, so how one can check if the broker sent a Connack, and the Client is in a Connected state prior to executing a publish?

    opened by schnedann 2
  • MQTT-C Security Issue Report (mqtt_unpack_publish_response)

    MQTT-C Security Issue Report (mqtt_unpack_publish_response)

    Overview

    An issue was discovered in MQTT-C through 1.1.5. The MQTT input data processing function mqtt_unpack_publish_response in mqtt.c does not validate the length of incoming topic_name_size, which leads to an out-of-bounds read when subsequent processing of the input data. And this could also lead to an integer overflow when calculating the remaining length of incoming response. Eventually causing Denial-of-Service or an information leak, even remote code execution.

    Description

    In mqtt_unpack_publish_response, topic_name_size is unpack from input data directly (Line 1352). And then buf pointer add topic_name_size without checking if it exceeds the range of buf, which leads to a buffer overflow. ([Line 1355])

    And if attacker provide a topic_name_size is bigger than remaining_length, which could leads to an integer overflow. ([Line 1365] and [Line 1367])

    ssize_t mqtt_unpack_publish_response(struct mqtt_response *mqtt_response, const uint8_t *buf)
    {
    ...
    		/* parse variable header */
        response->topic_name_size = __mqtt_unpack_uint16(buf);
        buf += 2;
        response->topic_name = buf;
        buf += response->topic_name_size;                           // buffer overflow
    		
    if (response->qos_level > 0) {
            response->packet_id = __mqtt_unpack_uint16(buf);
            buf += 2;
        }
    
        /* get payload */
        response->application_message = buf;
        if (response->qos_level == 0) {
            response->application_message_size = fixed_header->remaining_length - response->topic_name_size - 2;  // integer overflow                
        } else {
            response->application_message_size = fixed_header->remaining_length - response->topic_name_size - 4;  // integer overflow
        }
        buf += response->application_message_size;
    ...
    }
    

    https://github.com/LiamBindle/MQTT-C/blob/be12c343ac5b7125d5e15cb9ab2d743de7f4fab4/src/mqtt.c#L1332-L1373

    Impact

    Denial-of-Service or an information leak, even remote code execution.

    opened by GANGE666 0
  • Possible bug in MQTT_CLIENT_TRY_PACK macro

    Possible bug in MQTT_CLIENT_TRY_PACK macro

    #define MQTT_CLIENT_TRY_PACK(tmp, msg, client, pack_call, release)  \
        if (client->error < 0) {                                        \
            if (release) MQTT_PAL_MUTEX_UNLOCK(&client->mutex);         \
            return client->error;                                       \
        }                                                               \
    

    I think it should be:

    if (client->error < 0 && client->error != MQTT_ERROR_SEND_BUFFER_IS_FULL) { \

    otherwise one buffer full state will cause subsequent messages to fail without trying.

    opened by gyavolo 0
Releases(v1.1.6)
  • v1.1.6(May 24, 2022)

    • MinGW support coutesy of @kimim
    • CMake improvments courtesy of @hobbes1069
    • Fixed keep alive ping time compliance courtesy of @ziron4
    • Fixed bug in UNIX PAL that caused MQTT_ERROR_SOCKET_ERROR
    • Added simple CI tests
    • Converted #ifdef to #if defined coutesy of @yamt
    • Custom pal template coutesy of @yamt
    • Fixed build compatibility with -Wc++-compat flag coutesy of @NoelGraf

    Other contributors: @alvin1221, @Willieodwyer, @gc87

    Source code(tar.gz)
    Source code(zip)
  • 1.1.5(Mar 31, 2021)

    • NuttX support courtesy of @xiaoxiang781216
    • WolfSSL support courtesy of @xiongyu0523
    • OpenVMS support courtesy of @Monarda
    • MQTTC_PAL_FILE preprocessor definition can be used to specify a custom PAL file, courtesy of @vpetrigo
    • Minor tweaks/updates courtesy of @learn-more, @mpfj, @przemyslawzygmunt, @yamt, @underhood, @timgates42
    Source code(tar.gz)
    Source code(zip)
  • 1.1.4(Oct 6, 2020)

    • New mqtt_reconnect() function to terminate session and trigger reconnect courtesy of @markrad
    • Headers are now C++ compatible courtesy of @markrad
    • Added mechanism to specify own PAL header courtesy of @vpetrigo
    • OpenSSL example for windows courtesy of @learn-more
    • Minor fixes for CMakeLists for Windows courtesy of @learn-more

    Additional contributions by @vpetrigo, @kokke, @timgates42

    Source code(tar.gz)
    Source code(zip)
  • 1.1.3(Jul 23, 2020)

    • BearSSL support courtesy of @markrad
    • Fixed bug breaking messages larger than 64 KB courtesy of @adamczykpiotr
    • Minor Mbed TLS fixes courtesy of @yamt
    Source code(tar.gz)
    Source code(zip)
  • 1.1.2(Apr 28, 2020)

  • 1.1.1(Feb 5, 2020)

  • 1.1.0(Nov 25, 2019)

  • 1.0.3(Aug 26, 2019)

  • 1.0.2(Aug 19, 2019)

  • 1.0.1(Mar 20, 2019)

Owner
Liam Bindle
scientific applications software engineer @wustl, support team member @geoschem, former electrical design team lead @UofSSpaceTeam
Liam Bindle
Eclipse Paho C Client Library for the MQTT Protocol

Eclipse Paho C Client Library for the MQTT Protocol This repository contains the source code for the Eclipse Paho MQTT C client library. This code bui

null 2 Apr 27, 2022
Eclipse Paho MQTT C++ Client Library

Eclipse Paho MQTT C++ Client Library This repository contains the source code for the Eclipse Paho MQTT C++ client library on memory-managed operating

Eclipse Foundation 657 Sep 27, 2022
FreeModbus is a Modbus ASCII/RTU and Modbus TCP implementation for embedded systems

FreeModbus is a Modbus ASCII/RTU and Modbus TCP implementation for embedded systems. It provides an implementation of the Modbus Application Protocol

Mahmood Hosseini 21 Sep 27, 2022
Open source file system for small embedded systems

STORfs Open Source File System Release Version 1.0.2 Created by: KrauseGLOBAL Solutions, LLC What is STORfs? STORfs is an open source flash file syste

null 17 Jul 26, 2022
Common utilities useful for embedded systems that are often not included in an RTOS or the standard C library.

Welcome to Fitterbap, the Firmware toolkit to enable reliable best architecture practices! Fitterbap provides common utilities useful for embedded systems that are often not included in an RTOS or the standard C library.

Jetperch 21 Apr 2, 2022
Netstick client for Nintendo 3DS -- turn your portable console into a Linux compatible WiFi gamepad!

Netstick turns your 3DS into a wifi enabled gamepad! Control any linux-based device (such as a Raspberry Pi running Retropie) using your 3DS!

null 32 May 6, 2022
Triton Python and C++ client libraries and example, and client examples for go, java and scala.

Triton Client Libraries and Examples To simplify communication with Triton, the Triton project provides several client libraries and examples of how t

Triton Inference Server 179 Sep 30, 2022
An MQTT-based Virtual Wall for ESP8266 Devices and Gerber files to make the IR hat; this code and board can easily be adapted to be ANY infrared controller/remote!

Roomba-Virtual-Wall-ESP8266-MQTT An MQTT-based Virtual Wall for ESP8266 Devices I made this based off of the IRSend, IRremoteESP8266, and EspMQTTClien

null 8 Sep 20, 2021
This is a MQTT-enabled, compact weather station powered by a Wemos D1 minicontroller and built with 3D-printed parts

This is a MQTT-enabled, compact weather station powered by a Wemos D1 minicontroller and built with 3D-printed parts. It supports OTA updates.

65397 1 Feb 10, 2022
RPI Pico WIFI via ESP-01S, LWESP, FreeRTOS, and MQTT example

RPIPicoRTOSMQTT RPI Pico WIFI via ESP-01S, LWESP, FreeRTOS, and MQTT example Demo code for RPI Pico using ESP-01S for wifi connection over uart. With

Dr Jon Durrant 2 Dec 2, 2021
Webdav-client-cpp - C++ WebDAV Client provides easy and convenient to work with WebDAV-servers.

WebDAV Client Package WebDAV Client provides easy and convenient to work with WebDAV-servers: Yandex.Disk Dropbox Google Drive Box 4shared ownCloud ..

Cloud Polis 102 Oct 1, 2022
Control Hörmann doors drives directly via MQTT from Home Assistant

hoermann_door Control Hörmann doors drives directly via MQTT from Home Assistant

null 59 Sep 21, 2022
WiFi/MQTT Code For the ThingPulse ESPGateway

ESP32-Paxcounter with ThingPulse ESPGateway This project lets you run the ESP32-Paxcounter project on the ThingPulse ESPGateway. The ESPGateway has tw

Daniel Eichhorn 6 Aug 13, 2022
Wifi MQTT Data Logging via an esp8266 for the Ikea VINDRIKTNING PM2.5 air quality sensor

MQTT connectivity for the Ikea VINDRIKTNING This repository contains an ESP8266 firmware, which adds MQTT to the Ikea VINDRIKTNING PM2.5 air quality s

Sören Beye 897 Sep 28, 2022
Eclipse Mosquitto - An open source MQTT broker

Mosquitto is an open source implementation of a server for version 5.0, 3.1.1, and 3.1 of the MQTT protocol. It also includes a C and C++ client library, and the mosquitto_pub and mosquitto_sub utilities for publishing and subscribing.

Eclipse Foundation 6.6k Sep 30, 2022
Show pressure & temperature readings from Home Assistant/MQTT on a mini display

home-assistant-barometer-display A mini Home Assistant display to show pressure & temperature readings (and made to look pretty with 'freeform pcb' br

David Barton 4 Jan 4, 2022
AWS FreeRTOS MQTT demo project running on the NXP i.MXRT1050-EVKB.

AWS MQTT demo example project Click to import in Keil Studio Cloud: Board: NXP IMXRT1050-EVKB The tables below list the device configuration for this

Arm - Keil tools 1 Oct 18, 2021
Use an esp32 as gateway for the Eqiva Bluetooth smart lock to integrate it in Home Assistant as MQTT lock

esp32-keyble-homeassistant Use an esp32 as gateway for the Eqiva Bluetooth smart lock to integrate it in Home Assistant as MQTT lock Based on the grea

null 8 Jul 12, 2022
Google IOT MQTT Sample

This is an adaptation of Zephyr's Google Cloud IoT Core MQTT sample samples/net/cloud/google_iot_mqtt for the nRF9160-DK, using modem features to offload certificate storage, TLS and JWT calculation.

Jeffrey Urban 5 Jan 27, 2022