├── .github └── workflows │ └── ci-tests.yml ├── .gitignore ├── CMakeLists.txt ├── Doxyfile ├── LICENSE ├── README.md ├── build.zig ├── cmake └── FindMbedTLS.cmake ├── docs ├── annotated.html ├── arrowdown.png ├── arrowright.png ├── bc_s.png ├── bdwn.png ├── bio_publisher_8c-example.html ├── classes.html ├── closed.png ├── dir_000001_000000.html ├── dir_68267d1309a1af8e8297ef4c3efbcdba.html ├── dir_68267d1309a1af8e8297ef4c3efbcdba_dep.map ├── dir_68267d1309a1af8e8297ef4c3efbcdba_dep.md5 ├── dir_68267d1309a1af8e8297ef4c3efbcdba_dep.png ├── dir_d44c64559bbebec7f509842c48db8b23.html ├── doc.png ├── doxygen.css ├── doxygen.png ├── dynsections.js ├── examples.html ├── files.html ├── folderclosed.png ├── folderopen.png ├── functions.html ├── functions_func.html ├── functions_vars.html ├── globals.html ├── globals_defs.html ├── globals_enum.html ├── globals_func.html ├── graph_legend.html ├── graph_legend.md5 ├── graph_legend.png ├── group__api.html ├── group__details.html ├── group__packers.html ├── group__pal.html ├── group__unpackers.html ├── index.html ├── jquery.js ├── menu.js ├── menudata.js ├── modules.html ├── mqtt-c-logo.png ├── mqtt_8c.html ├── mqtt_8c__incl.map ├── mqtt_8c__incl.md5 ├── mqtt_8c__incl.png ├── mqtt_8h.html ├── mqtt_8h__dep__incl.map ├── mqtt_8h__dep__incl.md5 ├── mqtt_8h__dep__incl.png ├── mqtt_8h__incl.map ├── mqtt_8h__incl.md5 ├── mqtt_8h__incl.png ├── mqtt_8h_source.html ├── mqtt__pal_8c.html ├── mqtt__pal_8c__incl.map ├── mqtt__pal_8c__incl.md5 ├── mqtt__pal_8c__incl.png ├── mqtt__pal_8h.html ├── mqtt__pal_8h__dep__incl.map ├── mqtt__pal_8h__dep__incl.md5 ├── mqtt__pal_8h__dep__incl.png ├── mqtt__pal_8h_source.html ├── nav_f.png ├── nav_g.png ├── nav_h.png ├── open.png ├── openssl_publisher_8c-example.html ├── reconnect_subscriber_8c-example.html ├── simple_publisher_8c-example.html ├── simple_subscriber_8c-example.html ├── splitbar.png ├── structmqtt__client.html ├── structmqtt__fixed__header.html ├── structmqtt__message__queue.html ├── structmqtt__queued__message.html ├── structmqtt__response.html ├── structmqtt__response__connack.html ├── structmqtt__response__pingresp.html ├── structmqtt__response__puback.html ├── structmqtt__response__pubcomp.html ├── structmqtt__response__publish.html ├── structmqtt__response__pubrec.html ├── structmqtt__response__pubrel.html ├── structmqtt__response__suback.html ├── structmqtt__response__unsuback.html ├── sync_off.png ├── sync_on.png ├── tab_a.png ├── tab_b.png ├── tab_h.png ├── tab_s.png └── tabs.css ├── examples ├── bearssl_publisher.c ├── bio_publisher.c ├── bio_publisher_win.c ├── mbedtls_publisher.c ├── mosquitto.org.pem ├── openssl_publisher.c ├── openssl_publisher_win.c ├── reconnect_subscriber.c ├── simple_publisher.c ├── simple_subscriber.c └── templates │ ├── bearssl_sockets.h │ ├── bio_sockets.h │ ├── mbedtls_sockets.h │ ├── openssl_sockets.h │ └── posix_sockets.h ├── include ├── mqtt.h └── mqtt_pal.h ├── makefile ├── src ├── mqtt.c └── mqtt_pal.c └── tests.c /.github/workflows/ci-tests.yml: -------------------------------------------------------------------------------- 1 | # This workflow will install Python dependencies, run tests and lint with a variety of Python versions 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions 3 | 4 | name: CI 5 | 6 | on: 7 | push: 8 | branches: [ master ] 9 | pull_request: 10 | branches: [ master ] 11 | 12 | jobs: 13 | quick-test: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Check out repository code 17 | uses: actions/checkout@v2 18 | - name: Install cmocka 19 | run: | 20 | sudo apt-get update 21 | sudo apt-get install libcmocka-dev 22 | - name: make 23 | run: make 24 | - name: make check 25 | run: make check 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | bin/ 3 | build/ 4 | .idea/ 5 | zig-cache/ 6 | zig-out/ 7 | .DS_Store -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | project(MQTT-C VERSION 1.1.2 LANGUAGES C) 3 | 4 | # MQTT-C build options 5 | option(MQTT_C_OpenSSL_SUPPORT "Build MQTT-C with OpenSSL support?" OFF) 6 | option(MQTT_C_MbedTLS_SUPPORT "Build MQTT-C with mbed TLS support?" OFF) 7 | option(MQTT_C_BearSSL_SUPPORT "Build MQTT-C with Bear SSL support?" OFF) 8 | option(MQTT_C_EXAMPLES "Build MQTT-C examples?" ON) 9 | option(MQTT_C_INSTALL_EXAMPLES "Install MQTT-C examples?" OFF) 10 | option(MQTT_C_TESTS "Build MQTT-C tests?" OFF) 11 | 12 | list (APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) 13 | set(CMAKE_POSITION_INDEPENDENT_CODE ON) 14 | 15 | # MQTT-C library 16 | add_library(mqttc STATIC 17 | src/mqtt_pal.c 18 | src/mqtt.c 19 | ) 20 | target_include_directories(mqttc PUBLIC include) 21 | target_link_libraries(mqttc PUBLIC 22 | $<$:ws2_32> 23 | ) 24 | 25 | if(MQTT_C_BearSSL_SUPPORT) 26 | set(bearssl_root "$ENV{BEARSSL_ROOT}") 27 | 28 | set(bearssl_include "${bearssl_root}/include") 29 | find_file(bearinc NAMES bearssl.h PATHS "${bearssl_include}") 30 | 31 | if ("${bearinc}" STREQUAL "bearinc-NOTFOUND") 32 | MESSAGE(FATAL_ERROR "BEARSSL_ROOT does not contain include/bearssl.h") 33 | endif() 34 | 35 | set(bearssl_lib "${bearssl_root}/lib") 36 | find_library(bearlib NAMES libbearssl.a bearssl.lib PATHS "{bearssl_lib}") 37 | 38 | if("${bearlib}" STREQUAL "bearlib-NOTFOUND") 39 | MESSAGE(FATAL_ERROR "BEARSSL_ROOT does not contain lib with bearssl library") 40 | endif() 41 | 42 | get_filename_component(bearinc "${bearinc}" DIRECTORY) 43 | get_filename_component(bearlib2 "${bearlib}" DIRECTORY) 44 | 45 | target_include_directories(mqttc PUBLIC bearsslinc) 46 | target_link_libraries(mqttc INTERFACE "${bearlib}") 47 | target_compile_definitions(mqttc PUBLIC MQTT_USE_BEARSSL) 48 | endif() 49 | 50 | # Configure with OpenSSL support 51 | if(MQTT_C_OpenSSL_SUPPORT) 52 | find_package(OpenSSL REQUIRED) 53 | target_link_libraries(mqttc INTERFACE OpenSSL::SSL) 54 | target_include_directories(mqttc PUBLIC ${OPENSSL_INCLUDE_DIR}) 55 | target_compile_definitions(mqttc PUBLIC MQTT_USE_BIO) 56 | endif() 57 | 58 | # Configure with mbed TLS support 59 | if(MQTT_C_MbedTLS_SUPPORT) 60 | find_package(MbedTLS REQUIRED) 61 | target_include_directories(mqttc PUBLIC ${MBEDTLS_INCLUDE_DIRS}) 62 | target_link_libraries(mqttc INTERFACE ${MBEDTLS_LIBRARY}) 63 | target_compile_definitions(mqttc PUBLIC MQTT_USE_MBEDTLS) 64 | endif() 65 | 66 | # Build examples 67 | if(MQTT_C_EXAMPLES) 68 | find_package(Threads REQUIRED) 69 | 70 | if(MQTT_C_OpenSSL_SUPPORT) 71 | if(MSVC) 72 | add_executable(bio_publisher examples/bio_publisher_win.c) 73 | add_executable(openssl_publisher examples/openssl_publisher_win.c) 74 | else() 75 | add_executable(bio_publisher examples/bio_publisher.c) 76 | add_executable(openssl_publisher examples/openssl_publisher.c) 77 | endif() 78 | if(MQTT_C_INSTALL_EXAMPLES) 79 | install(TARGETS bio_publisher openssl_publisher) 80 | endif() 81 | target_link_libraries(bio_publisher Threads::Threads mqttc) 82 | target_link_libraries(openssl_publisher Threads::Threads mqttc) 83 | 84 | elseif(MQTT_C_MbedTLS_SUPPORT) 85 | add_executable(mbedtls_publisher examples/mbedtls_publisher.c) 86 | target_link_libraries(mbedtls_publisher Threads::Threads mqttc ${MBEDX509_LIBRARY} ${MBEDCRYPTO_LIBRARY}) 87 | if(MQTT_C_INSTALL_EXAMPLES) 88 | install(TARGETS mbedtls_publisher) 89 | endif() 90 | 91 | elseif(MQTT_C_BearSSL_SUPPORT) 92 | add_executable(bearssl_publisher examples/bearssl_publisher.c) 93 | target_link_libraries(bearssl_publisher mqttc bearssl) 94 | if(MQTT_C_INSTALL_EXAMPLES) 95 | install(TARGETS bearssl_publisher) 96 | endif() 97 | else() 98 | add_executable(simple_publisher examples/simple_publisher.c) 99 | target_link_libraries(simple_publisher Threads::Threads mqttc) 100 | if(MQTT_C_INSTALL_EXAMPLES) 101 | install(TARGETS simple_publisher) 102 | endif() 103 | endif() 104 | 105 | # Always install subscriber targets 106 | add_executable(simple_subscriber examples/simple_subscriber.c) 107 | target_link_libraries(simple_subscriber Threads::Threads mqttc) 108 | add_executable(reconnect_subscriber examples/reconnect_subscriber.c) 109 | target_link_libraries(reconnect_subscriber Threads::Threads mqttc) 110 | if(MQTT_C_INSTALL_EXAMPLES) 111 | install(TARGETS simple_subscriber reconnect_subscriber) 112 | endif() 113 | endif() 114 | 115 | # Build tests 116 | if(MQTT_C_TESTS) 117 | find_path(CMOCKA_INCLUDE_DIR cmocka.h) 118 | find_library(CMOCKA_LIBRARY cmocka) 119 | if((NOT CMOCKA_INCLUDE_DIR) OR (NOT CMOCKA_LIBRARY)) 120 | message(FATAL_ERROR "Failed to find cmocka! Add cmocka's install prefix to CMAKE_PREFIX_PATH to resolve this error.") 121 | endif() 122 | 123 | add_executable(tests tests.c) 124 | target_link_libraries(tests ${CMOCKA_LIBRARY} mqttc) 125 | target_include_directories(tests PRIVATE ${CMOCKA_INCLUDE_DIR}) 126 | endif() 127 | 128 | # Handle multi-lib linux systems correctly and allow custom installation locations. 129 | if(UNIX) 130 | include(GNUInstallDirs) 131 | mark_as_advanced(CLEAR 132 | CMAKE_INSTALL_BINDIR 133 | CMAKE_INSTALL_LIBDIR 134 | CMAKE_INSTALL_INCLUDEDIR) 135 | else() 136 | set(CMAKE_INSTALL_LIBDIR "lib") 137 | set(CMAKE_INSTALL_INCLUDEDIR "include") 138 | endif() 139 | 140 | # Install includes and library 141 | install(TARGETS mqttc 142 | DESTINATION ${CMAKE_INSTALL_LIBDIR} 143 | ) 144 | install(DIRECTORY include/ 145 | DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) 146 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Liam Bindle 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 |

5 | 6 |

7 |
8 | 9 | 10 | 11 | 12 | 13 |

14 | 15 | MQTT-C is an [MQTT v3.1.1](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html) 16 | client written in C. MQTT is a lightweight publisher-subscriber-based messaging protocol that is 17 | commonly used in IoT and networking applications where high-latency and low data-rate links 18 | are expected. The purpose of MQTT-C is to provide a **portable** MQTT client, **written in C**, 19 | for embedded systems and PC's alike. MQTT-C does this by providing a transparent Platform 20 | Abstraction Layer (PAL) which makes porting to new platforms easy. MQTT-C is completely 21 | thread-safe but can also run perfectly fine on single-threaded systems making MQTT-C 22 | well-suited for embedded systems and microcontrollers. Finally, MQTT-C is small; there are only 23 | two source files totalling less than 2000 lines. 24 | 25 | #### A note from the author 26 | It's been great to hear about all the places MQTT-C is being used! Please don't hesitate 27 | to get in touch with me or submit issues on GitHub! 28 | 29 | ## Getting Started 30 | To use MQTT-C you first instantiate a `struct mqtt_client` and initialize it by calling 31 | @ref mqtt_init. 32 | ```c 33 | struct mqtt_client client; /* instantiate the client */ 34 | mqtt_init(&client, ...); /* initialize the client */ 35 | ``` 36 | Once your client is initialized you need to connect to an MQTT broker. 37 | ```c 38 | mqtt_connect(&client, ...); /* send a connection request to the broker. */ 39 | ``` 40 | At this point the client is ready to use! For example, we can subscribe to a topic like so: 41 | ```c 42 | /* subscribe to "toaster/temperature" with a max QoS level of 0 */ 43 | mqtt_subscribe(&client, "toaster/temperature", 0); 44 | ``` 45 | And we can publish to a topic like so: 46 | ```c 47 | /* publish coffee temperature with a QoS level of 1 */ 48 | int temperature = 67; 49 | mqtt_publish(&client, "coffee/temperature", &temperature, sizeof(int), MQTT_PUBLISH_QOS_1); 50 | ``` 51 | Those are the basics! From here the [examples](https://github.com/LiamBindle/MQTT-C/tree/master/examples) and [API documentation](https://liambindle.ca/MQTT-C/group__api.html) are good places to get started. 52 | 53 | ## Building 54 | There are **only two source files** that need to be built, `mqtt.c` and `mqtt_pal.c`. 55 | These files are ANSI C (C89) compatible, and should compile with any C compiler. 56 | 57 | Then, simply \#include . 58 | 59 | Alternatively, you can build MQTT-C with CMake or the provided Makefile. These are provided for convenience. 60 | 61 | ## Documentation 62 | Pre-built documentation can be found here: [https://liambindle.ca/MQTT-C](https://liambindle.ca/MQTT-C). Be sure to check out the [examples](https://github.com/LiamBindle/MQTT-C/tree/master/examples) too. 63 | 64 | The @ref api documentation contains all the documentation application programmers should need. 65 | The @ref pal documentation contains everything you should need to port MQTT-C to a new platform, 66 | and the other modules contain documentation for MQTT-C developers. 67 | 68 | ## Testing and Building the Tests 69 | The MQTT-C unit tests use the [cmocka unit testing framework](https://cmocka.org/). 70 | Therefore, [cmocka](https://cmocka.org/) *must* be installed on your machine to build and run 71 | the unit tests. For convenience, a simple `"makefile"` is included to build the unit tests and 72 | examples on UNIX-like machines. The unit tests and examples can be built as follows: 73 | ```bash 74 | $ make all 75 | ``` 76 | The unit tests and examples will be built in the `"bin/"` directory. The unit tests can be run 77 | like so: 78 | ```bash 79 | $ ./bin/tests [address [port]] 80 | ``` 81 | Note that the \c address and \c port arguments are both optional to specify the location of the 82 | MQTT broker that is to be used for the tests. If no \c address is given then the 83 | [Mosquitto MQTT Test Server](https://test.mosquitto.org/) will be used. If no \c port is given, 84 | port 1883 will be used. 85 | 86 | ## Portability 87 | MQTT-C provides a transparent platform abstraction layer (PAL) in `mqtt_pal.h` and `mqtt_pal.c`. 88 | These files declare and implement the types and calls that MQTT-C requires. Refer to 89 | @ref pal for the complete documentation of the PAL. 90 | 91 | ## Contributing 92 | Please feel free to submit issues and pull-requests [here](https://github.com/LiamBindle/MQTT-C). 93 | When submitting a pull-request please ensure you have *fully documented* your changes and 94 | added the appropriate unit tests. 95 | 96 | 97 | ## License 98 | This project is licensed under the [MIT License](https://opensource.org/licenses/MIT). See the 99 | `"LICENSE"` file for more details. 100 | 101 | ## Authors 102 | MQTT-C was initially developed as a CMPT 434 (Winter Term, 2018) final project at the University of 103 | Saskatchewan by: 104 | - **Liam Bindle** 105 | - **Demilade Adeoye** 106 | 107 | -------------------------------------------------------------------------------- /build.zig: -------------------------------------------------------------------------------- 1 | // Used the following as cross-compilation build.zig example: 2 | // https://git.sr.ht/~jamii/focus/tree/master/build.zig 3 | 4 | const std = @import("std"); 5 | 6 | pub fn build(b: *std.build.Builder) !void { 7 | const windows = b.addStaticLibrary("mqtt-c", null); 8 | try includeCommon(windows); 9 | windows.setTarget(std.zig.CrossTarget{ 10 | .cpu_arch = .x86_64, 11 | .os_tag = .windows, 12 | }); 13 | windows.install(); 14 | 15 | const apple_silicon_mac = b.addStaticLibrary("mqtt-c-apple-silicon", null); 16 | try includeCommon(apple_silicon_mac); 17 | apple_silicon_mac.setTarget(std.zig.CrossTarget{ 18 | .cpu_arch = .aarch64, 19 | .os_tag = .macos, 20 | }); 21 | apple_silicon_mac.install(); 22 | 23 | const x86_64_mac = b.addStaticLibrary("mqtt-c-mac-x64", null); 24 | try includeCommon(x86_64_mac); 25 | x86_64_mac.setTarget(std.zig.CrossTarget{ 26 | .cpu_arch = .x86_64, 27 | .os_tag = .macos, 28 | }); 29 | x86_64_mac.install(); 30 | 31 | const x86_64_linux = b.addStaticLibrary("mqtt-c-x64", null); 32 | try includeCommon(x86_64_linux); 33 | x86_64_linux.setTarget(std.zig.CrossTarget{ 34 | .cpu_arch = .x86_64, 35 | .os_tag = .linux, 36 | }); 37 | x86_64_linux.install(); 38 | 39 | const arm64_linux = b.addStaticLibrary("mqtt-c-arm64", null); 40 | try includeCommon(arm64_linux); 41 | arm64_linux.setTarget(std.zig.CrossTarget{ 42 | .cpu_arch = .aarch64, 43 | .os_tag = .linux, 44 | }); 45 | arm64_linux.install(); 46 | 47 | const windows_step = b.step("windows", "Build for Windows"); 48 | windows_step.dependOn(&windows.step); 49 | 50 | const apple_silicon_mac_step = b.step("apple_silicon_mac", "Build for Apple Silicon Macs"); 51 | apple_silicon_mac_step.dependOn(&apple_silicon_mac.step); 52 | 53 | const x86_64_mac_step = b.step("x86_64_mac", "Build for Intel Macs"); 54 | x86_64_mac_step.dependOn(&x86_64_mac.step); 55 | 56 | const x86_64_linux_step = b.step("x86_64_linux", "Build for Linux"); 57 | x86_64_linux_step.dependOn(&x86_64_linux.step); 58 | 59 | const arm64_linux_step = b.step("arm64_linux", "Build for ARM64 Linux"); 60 | arm64_linux_step.dependOn(&arm64_linux.step); 61 | } 62 | 63 | fn includeCommon(lib: *std.build.LibExeObjStep) !void { 64 | lib.addIncludeDir("include"); 65 | 66 | lib.addCSourceFile("src/mqtt.c", &[_][]const u8 {}); 67 | lib.addCSourceFile("src/mqtt_pal.c", &[_][]const u8 {}); 68 | 69 | lib.setBuildMode(.Debug); // Can be .Debug, .ReleaseSafe, .ReleaseFast, and .ReleaseSmall 70 | lib.linkLibC(); 71 | } 72 | -------------------------------------------------------------------------------- /cmake/FindMbedTLS.cmake: -------------------------------------------------------------------------------- 1 | find_path(MBEDTLS_INCLUDE_DIRS mbedtls/ssl.h) 2 | 3 | find_library(MBEDCRYPTO_LIBRARY mbedcrypto) 4 | find_library(MBEDTLS_LIBRARY mbedtls) 5 | find_library(MBEDX509_LIBRARY mbedx509) 6 | 7 | include(FindPackageHandleStandardArgs) 8 | find_package_handle_standard_args(MbedTLS DEFAULT_MSG 9 | MBEDTLS_INCLUDE_DIRS MBEDCRYPTO_LIBRARY MBEDTLS_LIBRARY MBEDX509_LIBRARY) 10 | -------------------------------------------------------------------------------- /docs/annotated.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | MQTT-C: Data Structures 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 | 18 | 19 | 20 | 24 | 25 | 26 |
21 |
MQTT-C 22 |
23 |
27 |
28 | 29 | 30 | 31 | 32 | 37 | 38 |
39 |
40 |
41 |
Data Structures
42 |
43 |
44 |
Here are the data structures with brief descriptions:
45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 |
 Cmqtt_clientAn MQTT client
 Cmqtt_fixed_headerThe fixed header of an MQTT control packet
 Cmqtt_message_queueA message queue
 Cmqtt_queued_messageA message in a mqtt_message_queue
 Cmqtt_responseA struct used to deserialize/interpret an incoming packet from the broker
 Cmqtt_response_connackA connection response datastructure
 Cmqtt_response_pingrespThe response to a ping request
 Cmqtt_response_pubackA publish acknowledgement for messages that were published with QoS level 1
 Cmqtt_response_pubcompThe response to a PUBREL packet
 Cmqtt_response_publishA publish packet received from the broker.A publish packet is received from the broker when a client publishes to a topic that the {local client} is subscribed to
 Cmqtt_response_pubrecThe response packet to a PUBLISH packet with QoS level 2
 Cmqtt_response_pubrelThe response to a PUBREC packet
 Cmqtt_response_subackThe response to a subscription request
 Cmqtt_response_unsubackThe brokers response to a UNSUBSCRIBE request
61 |
62 |
63 | 64 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /docs/arrowdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiamBindle/MQTT-C/7a986a68ebea63921d4aab20a9d1b26a8b5f8c9d/docs/arrowdown.png -------------------------------------------------------------------------------- /docs/arrowright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiamBindle/MQTT-C/7a986a68ebea63921d4aab20a9d1b26a8b5f8c9d/docs/arrowright.png -------------------------------------------------------------------------------- /docs/bc_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiamBindle/MQTT-C/7a986a68ebea63921d4aab20a9d1b26a8b5f8c9d/docs/bc_s.png -------------------------------------------------------------------------------- /docs/bdwn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiamBindle/MQTT-C/7a986a68ebea63921d4aab20a9d1b26a8b5f8c9d/docs/bdwn.png -------------------------------------------------------------------------------- /docs/classes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | MQTT-C: Data Structure Index 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 | 18 | 19 | 20 | 24 | 25 | 26 |
21 |
MQTT-C 22 |
23 |
27 |
28 | 29 | 30 | 31 | 32 | 37 | 38 |
39 |
40 |
41 |
Data Structure Index
42 |
43 |
44 | 45 | 46 | 48 | 49 | 50 | 51 | 52 |
  m  
47 |
mqtt_message_queue   mqtt_response_pingresp   mqtt_response_pubrec   
mqtt_queued_message   mqtt_response_puback   mqtt_response_pubrel   
mqtt_client   mqtt_response   mqtt_response_pubcomp   mqtt_response_suback   
mqtt_fixed_header   mqtt_response_connack   mqtt_response_publish   mqtt_response_unsuback   
53 | 54 |
55 | 56 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /docs/closed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiamBindle/MQTT-C/7a986a68ebea63921d4aab20a9d1b26a8b5f8c9d/docs/closed.png -------------------------------------------------------------------------------- /docs/dir_000001_000000.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | MQTT-C: src -> include Relation 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 | 18 | 19 | 20 | 24 | 25 | 26 |
21 |
MQTT-C 22 |
23 |
27 |
28 | 29 | 30 | 31 | 32 | 37 | 38 | 42 |
43 |
44 |

src → include Relation

File in srcIncludes file in include
mqtt.cmqtt.h
mqtt_pal.cmqtt.h
45 | 46 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /docs/dir_68267d1309a1af8e8297ef4c3efbcdba.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | MQTT-C: src Directory Reference 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 | 18 | 19 | 20 | 24 | 25 | 26 |
21 |
MQTT-C 22 |
23 |
27 |
28 | 29 | 30 | 31 | 32 | 37 | 38 | 42 |
43 |
44 |
45 |
src Directory Reference
46 |
47 |
48 |
49 | Directory dependency graph for src:
50 |
51 |
src
52 | 53 | 54 | 55 | 56 | 57 |
58 | 59 | 61 | 62 | 63 | 64 | 65 | 66 | 67 |

60 | Files

file  mqtt.c
 Implements the functionality of MQTT-C.
 
file  mqtt_pal.c
 Implements mqtt_pal_sendall and mqtt_pal_recvall and any platform-specific helpers you'd like.
 
68 |
69 | 70 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /docs/dir_68267d1309a1af8e8297ef4c3efbcdba_dep.map: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/dir_68267d1309a1af8e8297ef4c3efbcdba_dep.md5: -------------------------------------------------------------------------------- 1 | 9426e705d6c99c39f2fe3934158670e3 -------------------------------------------------------------------------------- /docs/dir_68267d1309a1af8e8297ef4c3efbcdba_dep.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiamBindle/MQTT-C/7a986a68ebea63921d4aab20a9d1b26a8b5f8c9d/docs/dir_68267d1309a1af8e8297ef4c3efbcdba_dep.png -------------------------------------------------------------------------------- /docs/dir_d44c64559bbebec7f509842c48db8b23.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | MQTT-C: include Directory Reference 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 | 18 | 19 | 20 | 24 | 25 | 26 |
21 |
MQTT-C 22 |
23 |
27 |
28 | 29 | 30 | 31 | 32 | 37 | 38 | 42 |
43 |
44 |
45 |
include Directory Reference
46 |
47 |
48 | 49 | 51 | 52 | 53 | 54 | 55 | 56 | 57 |

50 | Files

file  mqtt.h [code]
 Declares all the MQTT-C functions and datastructures.
 
file  mqtt_pal.h [code]
 Includes/supports the types/calls required by the MQTT-C client.
 
58 |
59 | 60 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /docs/doc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiamBindle/MQTT-C/7a986a68ebea63921d4aab20a9d1b26a8b5f8c9d/docs/doc.png -------------------------------------------------------------------------------- /docs/doxygen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiamBindle/MQTT-C/7a986a68ebea63921d4aab20a9d1b26a8b5f8c9d/docs/doxygen.png -------------------------------------------------------------------------------- /docs/dynsections.js: -------------------------------------------------------------------------------- 1 | /* 2 | @licstart The following is the entire license notice for the 3 | JavaScript code in this file. 4 | 5 | Copyright (C) 1997-2017 by Dimitri van Heesch 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License along 18 | with this program; if not, write to the Free Software Foundation, Inc., 19 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 20 | 21 | @licend The above is the entire license notice 22 | for the JavaScript code in this file 23 | */ 24 | function toggleVisibility(linkObj) 25 | { 26 | var base = $(linkObj).attr('id'); 27 | var summary = $('#'+base+'-summary'); 28 | var content = $('#'+base+'-content'); 29 | var trigger = $('#'+base+'-trigger'); 30 | var src=$(trigger).attr('src'); 31 | if (content.is(':visible')===true) { 32 | content.hide(); 33 | summary.show(); 34 | $(linkObj).addClass('closed').removeClass('opened'); 35 | $(trigger).attr('src',src.substring(0,src.length-8)+'closed.png'); 36 | } else { 37 | content.show(); 38 | summary.hide(); 39 | $(linkObj).removeClass('closed').addClass('opened'); 40 | $(trigger).attr('src',src.substring(0,src.length-10)+'open.png'); 41 | } 42 | return false; 43 | } 44 | 45 | function updateStripes() 46 | { 47 | $('table.directory tr'). 48 | removeClass('even').filter(':visible:even').addClass('even'); 49 | } 50 | 51 | function toggleLevel(level) 52 | { 53 | $('table.directory tr').each(function() { 54 | var l = this.id.split('_').length-1; 55 | var i = $('#img'+this.id.substring(3)); 56 | var a = $('#arr'+this.id.substring(3)); 57 | if (l 2 | 3 | 4 | 5 | 6 | 7 | 8 | MQTT-C: Examples 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 | 18 | 19 | 20 | 24 | 25 | 26 |
21 |
MQTT-C 22 |
23 |
27 |
28 | 29 | 30 | 31 | 32 | 37 | 38 |
39 |
40 |
41 |
Examples
42 |
43 |
44 |
Here is a list of all examples:
56 |
57 | 58 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /docs/files.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | MQTT-C: File List 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 | 18 | 19 | 20 | 24 | 25 | 26 |
21 |
MQTT-C 22 |
23 |
27 |
28 | 29 | 30 | 31 | 32 | 37 | 38 |
39 |
40 |
41 |
File List
42 |
43 |
44 |
Here is a list of all documented files with brief descriptions:
45 |
[detail level 12]
46 | 47 | 48 | 49 | 50 | 51 | 52 |
  include
 mqtt.hDeclares all the MQTT-C functions and datastructures
 mqtt_pal.hIncludes/supports the types/calls required by the MQTT-C client
  src
 mqtt.cImplements the functionality of MQTT-C
 mqtt_pal.cImplements mqtt_pal_sendall and mqtt_pal_recvall and any platform-specific helpers you'd like
53 |
54 |
55 | 56 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /docs/folderclosed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiamBindle/MQTT-C/7a986a68ebea63921d4aab20a9d1b26a8b5f8c9d/docs/folderclosed.png -------------------------------------------------------------------------------- /docs/folderopen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiamBindle/MQTT-C/7a986a68ebea63921d4aab20a9d1b26a8b5f8c9d/docs/folderopen.png -------------------------------------------------------------------------------- /docs/functions_func.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | MQTT-C: Data Fields - Functions 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 | 18 | 19 | 20 | 24 | 25 | 26 |
21 |
MQTT-C 22 |
23 |
27 |
28 | 29 | 30 | 31 | 32 | 37 | 38 |
39 |
40 |   72 |
73 | 74 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /docs/globals_defs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | MQTT-C: Globals 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 | 18 | 19 | 20 | 24 | 25 | 26 |
21 |
MQTT-C 22 |
23 |
27 |
28 | 29 | 30 | 31 | 32 | 37 | 38 |
39 |
40 |  
    41 |
  • __ALL_MQTT_ERRORS 42 | : mqtt.h 43 |
  • 44 |
  • __mqtt_packed_cstrlen 45 | : mqtt.h 46 |
  • 47 |
  • GENERATE_ENUM 48 | : mqtt.h 49 |
  • 50 |
  • GENERATE_STRING 51 | : mqtt.h 52 |
  • 53 |
  • mqtt_mq_currsz 54 | : mqtt.h 55 |
  • 56 |
  • mqtt_mq_get 57 | : mqtt.h 58 |
  • 59 |
  • mqtt_mq_length 60 | : mqtt.h 61 |
  • 62 |
  • MQTT_PROTOCOL_LEVEL 63 | : mqtt.h 64 |
  • 65 |
  • MQTT_SUBSCRIBE_REQUEST_MAX_NUM_TOPICS 66 | : mqtt.h 67 |
  • 68 |
  • MQTT_UNSUBSCRIBE_REQUEST_MAX_NUM_TOPICS 69 | : mqtt.h 70 |
  • 71 |
72 |
73 | 74 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /docs/globals_enum.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | MQTT-C: Globals 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 | 18 | 19 | 20 | 24 | 25 | 26 |
21 |
MQTT-C 22 |
23 |
27 |
28 | 29 | 30 | 31 | 32 | 37 | 38 |
39 |
40 |  
    41 |
  • MQTTConnackReturnCode 42 | : mqtt.h 43 |
  • 44 |
  • MQTTConnectFlags 45 | : mqtt.h 46 |
  • 47 |
  • MQTTControlPacketType 48 | : mqtt.h 49 |
  • 50 |
  • MQTTErrors 51 | : mqtt.h 52 |
  • 53 |
  • MQTTPublishFlags 54 | : mqtt.h 55 |
  • 56 |
  • MQTTQueuedMessageState 57 | : mqtt.h 58 |
  • 59 |
  • MQTTSubackReturnCodes 60 | : mqtt.h 61 |
  • 62 |
63 |
64 | 65 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /docs/globals_func.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | MQTT-C: Globals 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 | 18 | 19 | 20 | 24 | 25 | 26 |
21 |
MQTT-C 22 |
23 |
27 |
28 | 29 | 30 | 31 | 32 | 37 | 38 |
39 |
40 |   41 | 42 |

- _ -

    43 |
  • __mqtt_next_pid() 44 | : mqtt.h 45 |
  • 46 |
  • __mqtt_pack_str() 47 | : mqtt.h 48 |
  • 49 |
  • __mqtt_pack_uint16() 50 | : mqtt.h 51 |
  • 52 |
  • __mqtt_ping() 53 | : mqtt.h 54 |
  • 55 |
  • __mqtt_puback() 56 | : mqtt.h 57 |
  • 58 |
  • __mqtt_pubcomp() 59 | : mqtt.h 60 |
  • 61 |
  • __mqtt_pubrec() 62 | : mqtt.h 63 |
  • 64 |
  • __mqtt_pubrel() 65 | : mqtt.h 66 |
  • 67 |
  • __mqtt_recv() 68 | : mqtt.h 69 |
  • 70 |
  • __mqtt_send() 71 | : mqtt.h 72 |
  • 73 |
  • __mqtt_unpack_uint16() 74 | : mqtt.h 75 |
  • 76 |
77 | 78 | 79 |

- m -

    80 |
  • mqtt_connect() 81 | : mqtt.h 82 |
  • 83 |
  • mqtt_disconnect() 84 | : mqtt.h 85 |
  • 86 |
  • mqtt_error_str() 87 | : mqtt.h 88 |
  • 89 |
  • mqtt_init() 90 | : mqtt.h 91 |
  • 92 |
  • mqtt_init_reconnect() 93 | : mqtt.h 94 |
  • 95 |
  • mqtt_pack_connection_request() 96 | : mqtt.h 97 |
  • 98 |
  • mqtt_pack_disconnect() 99 | : mqtt.h 100 |
  • 101 |
  • mqtt_pack_fixed_header() 102 | : mqtt.h 103 |
  • 104 |
  • mqtt_pack_ping_request() 105 | : mqtt.h 106 |
  • 107 |
  • mqtt_pack_publish_request() 108 | : mqtt.h 109 |
  • 110 |
  • mqtt_pack_pubxxx_request() 111 | : mqtt.h 112 |
  • 113 |
  • mqtt_pack_subscribe_request() 114 | : mqtt.h 115 |
  • 116 |
  • mqtt_pack_unsubscribe_request() 117 | : mqtt.h 118 |
  • 119 |
  • mqtt_pal_recvall() 120 | : mqtt_pal.h 121 |
  • 122 |
  • mqtt_pal_sendall() 123 | : mqtt_pal.h 124 |
  • 125 |
  • mqtt_ping() 126 | : mqtt.h 127 |
  • 128 |
  • mqtt_publish() 129 | : mqtt.h 130 |
  • 131 |
  • mqtt_reinit() 132 | : mqtt.h 133 |
  • 134 |
  • mqtt_subscribe() 135 | : mqtt.h 136 |
  • 137 |
  • mqtt_sync() 138 | : mqtt.h 139 |
  • 140 |
  • mqtt_unpack_fixed_header() 141 | : mqtt.h 142 |
  • 143 |
  • mqtt_unsubscribe() 144 | : mqtt.h 145 |
  • 146 |
147 |
148 | 149 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /docs/graph_legend.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | MQTT-C: Graph Legend 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 | 18 | 19 | 20 | 24 | 25 | 26 |
21 |
MQTT-C 22 |
23 |
27 |
28 | 29 | 30 | 31 | 32 | 37 | 38 |
39 |
40 |
41 |
Graph Legend
42 |
43 |
44 |

This page explains how to interpret the graphs that are generated by doxygen.

45 |

Consider the following example:

/*! Invisible class because of truncation */
class Invisible { };
/*! Truncated class, inheritance relation is hidden */
class Truncated : public Invisible { };
/* Class not documented with doxygen comments */
class Undocumented { };
/*! Class that is inherited using public inheritance */
class PublicBase : public Truncated { };
/*! A template class */
template<class T> class Templ { };
/*! Class that is inherited using protected inheritance */
class ProtectedBase { };
/*! Class that is inherited using private inheritance */
class PrivateBase { };
/*! Class that is used by the Inherited class */
class Used { };
/*! Super class that inherits a number of other classes */
class Inherited : public PublicBase,
protected ProtectedBase,
private PrivateBase,
public Undocumented,
public Templ<int>
{
private:
Used *m_usedClass;
};

This will result in the following graph:

46 |
47 | 48 |
49 |

The boxes in the above graph have the following meaning:

50 |
    51 |
  • 52 | A filled gray box represents the struct or class for which the graph is generated.
  • 53 |
  • 54 | A box with a black border denotes a documented struct or class.
  • 55 |
  • 56 | A box with a gray border denotes an undocumented struct or class.
  • 57 |
  • 58 | A box with a red border denotes a documented struct or class forwhich not all inheritance/containment relations are shown. A graph is truncated if it does not fit within the specified boundaries.
  • 59 |
60 |

The arrows have the following meaning:

61 |
    62 |
  • 63 | A dark blue arrow is used to visualize a public inheritance relation between two classes.
  • 64 |
  • 65 | A dark green arrow is used for protected inheritance.
  • 66 |
  • 67 | A dark red arrow is used for private inheritance.
  • 68 |
  • 69 | A purple dashed arrow is used if a class is contained or used by another class. The arrow is labelled with the variable(s) through which the pointed class or struct is accessible.
  • 70 |
  • 71 | A yellow dashed arrow denotes a relation between a template instance and the template class it was instantiated from. The arrow is labelled with the template parameters of the instance.
  • 72 |
73 |
74 | 75 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /docs/graph_legend.md5: -------------------------------------------------------------------------------- 1 | 387ff8eb65306fa251338d3c9bd7bfff -------------------------------------------------------------------------------- /docs/graph_legend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiamBindle/MQTT-C/7a986a68ebea63921d4aab20a9d1b26a8b5f8c9d/docs/graph_legend.png -------------------------------------------------------------------------------- /docs/menu.js: -------------------------------------------------------------------------------- 1 | function initMenu(relPath,searchEnabled,serverSide,searchPage,search) { 2 | function makeTree(data,relPath) { 3 | var result=''; 4 | if ('children' in data) { 5 | result+=''; 12 | } 13 | return result; 14 | } 15 | 16 | $('#main-nav').append(makeTree(menudata,relPath)); 17 | $('#main-nav').children(':first').addClass('sm sm-dox').attr('id','main-menu'); 18 | if (searchEnabled) { 19 | if (serverSide) { 20 | $('#main-menu').append('
  • '); 21 | } else { 22 | $('#main-menu').append('
  • '); 23 | } 24 | } 25 | $('#main-menu').smartmenus(); 26 | } 27 | -------------------------------------------------------------------------------- /docs/menudata.js: -------------------------------------------------------------------------------- 1 | var menudata={children:[ 2 | {text:"Main Page",url:"index.html"}, 3 | {text:"Modules",url:"modules.html"}, 4 | {text:"Data Structures",url:"annotated.html",children:[ 5 | {text:"Data Structures",url:"annotated.html"}, 6 | {text:"Data Structure Index",url:"classes.html"}, 7 | {text:"Data Fields",url:"functions.html",children:[ 8 | {text:"All",url:"functions.html",children:[ 9 | {text:"a",url:"functions.html#index_a"}, 10 | {text:"c",url:"functions.html#index_c"}, 11 | {text:"d",url:"functions.html#index_d"}, 12 | {text:"e",url:"functions.html#index_e"}, 13 | {text:"f",url:"functions.html#index_f"}, 14 | {text:"i",url:"functions.html#index_i"}, 15 | {text:"k",url:"functions.html#index_k"}, 16 | {text:"m",url:"functions.html#index_m"}, 17 | {text:"n",url:"functions.html#index_n"}, 18 | {text:"p",url:"functions.html#index_p"}, 19 | {text:"q",url:"functions.html#index_q"}, 20 | {text:"r",url:"functions.html#index_r"}, 21 | {text:"s",url:"functions.html#index_s"}, 22 | {text:"t",url:"functions.html#index_t"}]}, 23 | {text:"Functions",url:"functions_func.html"}, 24 | {text:"Variables",url:"functions_vars.html",children:[ 25 | {text:"a",url:"functions_vars.html#index_a"}, 26 | {text:"c",url:"functions_vars.html#index_c"}, 27 | {text:"d",url:"functions_vars.html#index_d"}, 28 | {text:"e",url:"functions_vars.html#index_e"}, 29 | {text:"f",url:"functions_vars.html#index_f"}, 30 | {text:"i",url:"functions_vars.html#index_i"}, 31 | {text:"k",url:"functions_vars.html#index_k"}, 32 | {text:"m",url:"functions_vars.html#index_m"}, 33 | {text:"n",url:"functions_vars.html#index_n"}, 34 | {text:"p",url:"functions_vars.html#index_p"}, 35 | {text:"q",url:"functions_vars.html#index_q"}, 36 | {text:"r",url:"functions_vars.html#index_r"}, 37 | {text:"s",url:"functions_vars.html#index_s"}, 38 | {text:"t",url:"functions_vars.html#index_t"}]}]}]}, 39 | {text:"Files",url:"files.html",children:[ 40 | {text:"File List",url:"files.html"}, 41 | {text:"Globals",url:"globals.html",children:[ 42 | {text:"All",url:"globals.html",children:[ 43 | {text:"_",url:"globals.html#index__"}, 44 | {text:"g",url:"globals.html#index_g"}, 45 | {text:"m",url:"globals.html#index_m"}]}, 46 | {text:"Functions",url:"globals_func.html",children:[ 47 | {text:"_",url:"globals_func.html#index__"}, 48 | {text:"m",url:"globals_func.html#index_m"}]}, 49 | {text:"Enumerations",url:"globals_enum.html"}, 50 | {text:"Macros",url:"globals_defs.html"}]}]}, 51 | {text:"Examples",url:"examples.html"}]} 52 | -------------------------------------------------------------------------------- /docs/modules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | MQTT-C: Modules 9 | 10 | 11 | 12 | 13 | 14 | 15 |
    16 |
    17 | 18 | 19 | 20 | 24 | 25 | 26 |
    21 |
    MQTT-C 22 |
    23 |
    27 |
    28 | 29 | 30 | 31 | 32 | 37 | 38 |
    39 |
    40 |
    41 |
    Modules
    42 |
    43 |
    44 |
    Here is a list of all modules:
    45 | 46 | 47 | 48 | 49 | 50 | 51 |
     APIDocumentation of everything you need to know to use the MQTT-C client
     Control Packet SerializationDeveloper documentation of the functions and datastructures used for serializing MQTT control packets
     Control Packet DeserializationDeveloper documentation of the functions and datastructures used for deserializing MQTT control packets
     UtilitiesDeveloper documentation for the utilities used to implement the MQTT-C client
     Platform abstraction layerDocumentation of the types and calls required to port MQTT-C to a new platform
    52 |
    53 |
    54 | 55 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /docs/mqtt-c-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiamBindle/MQTT-C/7a986a68ebea63921d4aab20a9d1b26a8b5f8c9d/docs/mqtt-c-logo.png -------------------------------------------------------------------------------- /docs/mqtt_8c.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | MQTT-C: src/mqtt.c File Reference 9 | 10 | 11 | 12 | 13 | 14 | 15 |
    16 |
    17 | 18 | 19 | 20 | 24 | 25 | 26 |
    21 |
    MQTT-C 22 |
    23 |
    27 |
    28 | 29 | 30 | 31 | 32 | 37 | 38 | 42 |
    43 |
    44 |
    45 |
    mqtt.c File Reference
    46 |
    47 |
    48 | 49 |

    Implements the functionality of MQTT-C. 50 | More...

    51 |
    #include <mqtt.h>
    52 |
    53 | Include dependency graph for mqtt.c:
    54 |
    55 |
    56 | 57 | 58 | 59 | 60 |
    61 |

    Detailed Description

    62 |

    Implements the functionality of MQTT-C.

    63 |
    Note
    The only files that are included are mqtt.h and mqtt_pal.h.
    64 |
    65 | 66 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /docs/mqtt_8c__incl.map: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /docs/mqtt_8c__incl.md5: -------------------------------------------------------------------------------- 1 | 68dd7e11984224dba8347dc84dabb5e2 -------------------------------------------------------------------------------- /docs/mqtt_8c__incl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiamBindle/MQTT-C/7a986a68ebea63921d4aab20a9d1b26a8b5f8c9d/docs/mqtt_8c__incl.png -------------------------------------------------------------------------------- /docs/mqtt_8h__dep__incl.map: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /docs/mqtt_8h__dep__incl.md5: -------------------------------------------------------------------------------- 1 | 28a95cc45fecbac42acf7f94cf34aff6 -------------------------------------------------------------------------------- /docs/mqtt_8h__dep__incl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiamBindle/MQTT-C/7a986a68ebea63921d4aab20a9d1b26a8b5f8c9d/docs/mqtt_8h__dep__incl.png -------------------------------------------------------------------------------- /docs/mqtt_8h__incl.map: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /docs/mqtt_8h__incl.md5: -------------------------------------------------------------------------------- 1 | 6999781e54df41331bfe60626d788b57 -------------------------------------------------------------------------------- /docs/mqtt_8h__incl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiamBindle/MQTT-C/7a986a68ebea63921d4aab20a9d1b26a8b5f8c9d/docs/mqtt_8h__incl.png -------------------------------------------------------------------------------- /docs/mqtt__pal_8c.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | MQTT-C: src/mqtt_pal.c File Reference 9 | 10 | 11 | 12 | 13 | 14 | 15 |
    16 |
    17 | 18 | 19 | 20 | 24 | 25 | 26 |
    21 |
    MQTT-C 22 |
    23 |
    27 |
    28 | 29 | 30 | 31 | 32 | 37 | 38 | 42 |
    43 |
    44 |
    45 |
    mqtt_pal.c File Reference
    46 |
    47 |
    48 | 49 |

    Implements mqtt_pal_sendall and mqtt_pal_recvall and any platform-specific helpers you'd like. 50 | More...

    51 |
    #include <mqtt.h>
    52 |
    53 | Include dependency graph for mqtt_pal.c:
    54 |
    55 |
    56 | 57 | 58 | 59 | 60 |
    61 |

    Detailed Description

    62 |

    Implements mqtt_pal_sendall and mqtt_pal_recvall and any platform-specific helpers you'd like.

    63 |
    64 | 65 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /docs/mqtt__pal_8c__incl.map: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /docs/mqtt__pal_8c__incl.md5: -------------------------------------------------------------------------------- 1 | d3b4b6c0862483926546f997e01ffeff -------------------------------------------------------------------------------- /docs/mqtt__pal_8c__incl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiamBindle/MQTT-C/7a986a68ebea63921d4aab20a9d1b26a8b5f8c9d/docs/mqtt__pal_8c__incl.png -------------------------------------------------------------------------------- /docs/mqtt__pal_8h.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | MQTT-C: include/mqtt_pal.h File Reference 9 | 10 | 11 | 12 | 13 | 14 | 15 |
    16 |
    17 | 18 | 19 | 20 | 24 | 25 | 26 |
    21 |
    MQTT-C 22 |
    23 |
    27 |
    28 | 29 | 30 | 31 | 32 | 37 | 38 | 42 |
    43 |
    44 |
    45 | Functions
    46 |
    47 |
    mqtt_pal.h File Reference
    48 |
    49 |
    50 | 51 |

    Includes/supports the types/calls required by the MQTT-C client. 52 | More...

    53 |
    54 | This graph shows which files directly or indirectly include this file:
    55 |
    56 |
    57 | 58 | 59 | 60 | 61 | 62 |
    63 |
    64 |

    Go to the source code of this file.

    65 | 66 | 68 | 69 | 70 | 71 | 72 | 73 | 74 |

    67 | Functions

    ssize_t mqtt_pal_sendall (mqtt_pal_socket_handle fd, const void *buf, size_t len, int flags)
     Sends all the bytes in a buffer. More...
     
    ssize_t mqtt_pal_recvall (mqtt_pal_socket_handle fd, void *buf, size_t bufsz, int flags)
     Non-blocking receive all the byte available. More...
     
    75 |

    Detailed Description

    76 |

    Includes/supports the types/calls required by the MQTT-C client.

    77 |
    Note
    This is the only file included in mqtt.h, and mqtt.c. It is therefore responsible for including/supporting all the required types and calls.
    78 |
    79 | 80 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /docs/mqtt__pal_8h__dep__incl.map: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/mqtt__pal_8h__dep__incl.md5: -------------------------------------------------------------------------------- 1 | 8ef04c12d1a76ef09a858a745429d1db -------------------------------------------------------------------------------- /docs/mqtt__pal_8h__dep__incl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiamBindle/MQTT-C/7a986a68ebea63921d4aab20a9d1b26a8b5f8c9d/docs/mqtt__pal_8h__dep__incl.png -------------------------------------------------------------------------------- /docs/nav_f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiamBindle/MQTT-C/7a986a68ebea63921d4aab20a9d1b26a8b5f8c9d/docs/nav_f.png -------------------------------------------------------------------------------- /docs/nav_g.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiamBindle/MQTT-C/7a986a68ebea63921d4aab20a9d1b26a8b5f8c9d/docs/nav_g.png -------------------------------------------------------------------------------- /docs/nav_h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiamBindle/MQTT-C/7a986a68ebea63921d4aab20a9d1b26a8b5f8c9d/docs/nav_h.png -------------------------------------------------------------------------------- /docs/open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiamBindle/MQTT-C/7a986a68ebea63921d4aab20a9d1b26a8b5f8c9d/docs/open.png -------------------------------------------------------------------------------- /docs/splitbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiamBindle/MQTT-C/7a986a68ebea63921d4aab20a9d1b26a8b5f8c9d/docs/splitbar.png -------------------------------------------------------------------------------- /docs/structmqtt__fixed__header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | MQTT-C: mqtt_fixed_header Struct Reference 9 | 10 | 11 | 12 | 13 | 14 | 15 |
    16 |
    17 | 18 | 19 | 20 | 24 | 25 | 26 |
    21 |
    MQTT-C 22 |
    23 |
    27 |
    28 | 29 | 30 | 31 | 32 | 37 | 38 |
    39 |
    40 | 42 |
    43 |
    mqtt_fixed_header Struct Reference
    44 |
    45 |
    46 | 47 |

    The fixed header of an MQTT control packet. 48 | More...

    49 | 50 |

    #include <mqtt.h>

    51 | 52 | 54 | 55 | 56 | 57 | 58 | 59 | 60 |

    53 | Data Fields

    enum MQTTControlPacketType control_type
     
    uint32_t control_flags: 4
     
    uint32_t remaining_length
     
    61 |

    Detailed Description

    62 |

    The fixed header of an MQTT control packet.

    63 |
    See also
    MQTT v3.1.1: Fixed Header
    64 |

    Field Documentation

    65 | 66 |

    ◆ control_flags

    67 | 68 |
    69 |
    70 | 71 | 72 | 73 | 74 |
    uint32_t mqtt_fixed_header::control_flags
    75 |
    76 |

    The packets control flags.

    77 | 78 |
    79 |
    80 | 81 |

    ◆ control_type

    82 | 83 |
    84 |
    85 | 86 | 87 | 88 | 89 |
    enum MQTTControlPacketType mqtt_fixed_header::control_type
    90 |
    91 |

    The type of packet.

    92 | 93 |
    94 |
    95 | 96 |

    ◆ remaining_length

    97 | 98 |
    99 |
    100 | 101 | 102 | 103 | 104 |
    uint32_t mqtt_fixed_header::remaining_length
    105 |
    106 |

    The remaining size of the packet in bytes (i.e. the size of variable header and payload).

    107 | 108 |
    109 |
    110 |
    The documentation for this struct was generated from the following file: 113 |
    114 | 115 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /docs/structmqtt__queued__message.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | MQTT-C: mqtt_queued_message Struct Reference 9 | 10 | 11 | 12 | 13 | 14 | 15 |
    16 |
    17 | 18 | 19 | 20 | 24 | 25 | 26 |
    21 |
    MQTT-C 22 |
    23 |
    27 |
    28 | 29 | 30 | 31 | 32 | 37 | 38 |
    39 |
    40 | 42 |
    43 |
    mqtt_queued_message Struct Reference
    44 |
    45 |
    46 | 47 |

    A message in a mqtt_message_queue. 48 | More...

    49 | 50 |

    #include <mqtt.h>

    51 | 52 | 54 | 56 | 57 | 58 | 60 | 61 | 62 | 64 | 65 | 66 | 67 | 68 | 69 | 71 | 72 | 73 | 74 | 75 | 76 |

    53 | Data Fields

    55 | uint8_t * start
     A pointer to the start of the message.
     
    59 | size_t size
     The number of bytes in the message.
     
    63 | enum MQTTQueuedMessageState state
     The state of the message.
     
    mqtt_pal_time_t time_sent
     The time at which the message was sent.. More...
     
    70 | enum MQTTControlPacketType control_type
     The control type of the message.
     
    uint16_t packet_id
     The packet id of the message. More...
     
    77 |

    Detailed Description

    78 |

    A message in a mqtt_message_queue.

    79 |

    Field Documentation

    80 | 81 |

    ◆ packet_id

    82 | 83 |
    84 |
    85 | 86 | 87 | 88 | 89 |
    uint16_t mqtt_queued_message::packet_id
    90 |
    91 | 92 |

    The packet id of the message.

    93 |
    Note
    This field is only used if the associate control_type has a packet_id field.
    94 | 95 |
    96 |
    97 | 98 |

    ◆ time_sent

    99 | 100 |
    101 |
    102 | 103 | 104 | 105 | 106 |
    mqtt_pal_time_t mqtt_queued_message::time_sent
    107 |
    108 | 109 |

    The time at which the message was sent..

    110 |
    Note
    A timeout will only occur if the message is in the MQTT_QUEUED_AWAITING_ACK state.
    111 | 112 |
    113 |
    114 |
    The documentation for this struct was generated from the following file: 117 |
    118 | 119 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /docs/structmqtt__response__connack.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | MQTT-C: mqtt_response_connack Struct Reference 9 | 10 | 11 | 12 | 13 | 14 | 15 |
    16 |
    17 | 18 | 19 | 20 | 24 | 25 | 26 |
    21 |
    MQTT-C 22 |
    23 |
    27 |
    28 | 29 | 30 | 31 | 32 | 37 | 38 |
    39 |
    40 | 43 |
    44 |
    mqtt_response_connack Struct Reference
    45 |
    46 |
    47 | 48 |

    A connection response datastructure. 49 | More...

    50 | 51 |

    #include <mqtt.h>

    52 | 53 | 55 | 57 | 58 | 59 | 60 | 61 | 62 |

    54 | Data Fields

    56 | uint8_t session_present_flag
     Allows client and broker to check if they have a consistent view about whether there is already a stored session state.
     
    enum MQTTConnackReturnCode return_code
     The return code of the connection request. More...
     
    63 | 65 | 67 | 68 | 69 | 70 |

    64 | Related Functions

    (Note that these are not member functions.)

    66 |
    ssize_t mqtt_unpack_connack_response (struct mqtt_response *mqtt_response, const uint8_t *buf)
     Deserialize a CONNACK response from buf. More...
     
    71 |

    Detailed Description

    72 |

    A connection response datastructure.

    73 |
    See also
    MQTT v3.1.1: CONNACK - Acknowledgement connection response.
    74 |

    Field Documentation

    75 | 76 |

    ◆ return_code

    77 | 78 |
    79 |
    80 | 81 | 82 | 83 | 84 |
    enum MQTTConnackReturnCode mqtt_response_connack::return_code
    85 |
    86 | 87 |

    The return code of the connection request.

    88 |
    See also
    MQTTConnackReturnCode
    89 | 90 |
    91 |
    92 |
    The documentation for this struct was generated from the following file: 95 |
    96 | 97 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /docs/structmqtt__response__pingresp.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | MQTT-C: mqtt_response_pingresp Struct Reference 9 | 10 | 11 | 12 | 13 | 14 | 15 |
    16 |
    17 | 18 | 19 | 20 | 24 | 25 | 26 |
    21 |
    MQTT-C 22 |
    23 |
    27 |
    28 | 29 | 30 | 31 | 32 | 37 | 38 |
    39 |
    40 | 42 |
    43 |
    mqtt_response_pingresp Struct Reference
    44 |
    45 |
    46 | 47 |

    The response to a ping request. 48 | More...

    49 | 50 |

    #include <mqtt.h>

    51 | 52 | 54 | 56 | 57 |

    53 | Data Fields

    55 | int dummy
     
    58 |

    Detailed Description

    59 |

    The response to a ping request.

    60 |
    Note
    This response contains no members.
    61 |
    See also
    MQTT v3.1.1: PINGRESP - Ping Response.
    62 |

    The documentation for this struct was generated from the following file: 65 |
    66 | 67 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /docs/structmqtt__response__puback.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | MQTT-C: mqtt_response_puback Struct Reference 9 | 10 | 11 | 12 | 13 | 14 | 15 |
    16 |
    17 | 18 | 19 | 20 | 24 | 25 | 26 |
    21 |
    MQTT-C 22 |
    23 |
    27 |
    28 | 29 | 30 | 31 | 32 | 37 | 38 |
    39 |
    40 | 43 |
    44 |
    mqtt_response_puback Struct Reference
    45 |
    46 |
    47 | 48 |

    A publish acknowledgement for messages that were published with QoS level 1. 49 | More...

    50 | 51 |

    #include <mqtt.h>

    52 | 53 | 55 | 57 | 58 | 59 |

    54 | Data Fields

    56 | uint16_t packet_id
     The published messages packet ID.
     
    60 | 62 | 64 | 65 | 66 | 67 |

    61 | Related Functions

    (Note that these are not member functions.)

    63 |
    ssize_t mqtt_unpack_pubxxx_response (struct mqtt_response *mqtt_response, const uint8_t *buf)
     Deserialize a PUBACK/PUBREC/PUBREL/PUBCOMP packet from buf. More...
     
    68 |

    Detailed Description

    69 |

    A publish acknowledgement for messages that were published with QoS level 1.

    70 |
    See also
    MQTT v3.1.1: PUBACK - Publish Acknowledgement.
    71 |

    The documentation for this struct was generated from the following file: 74 |
    75 | 76 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /docs/structmqtt__response__pubcomp.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | MQTT-C: mqtt_response_pubcomp Struct Reference 9 | 10 | 11 | 12 | 13 | 14 | 15 |
    16 |
    17 | 18 | 19 | 20 | 24 | 25 | 26 |
    21 |
    MQTT-C 22 |
    23 |
    27 |
    28 | 29 | 30 | 31 | 32 | 37 | 38 |
    39 |
    40 | 42 |
    43 |
    mqtt_response_pubcomp Struct Reference
    44 |
    45 |
    46 | 47 |

    The response to a PUBREL packet. 48 | More...

    49 | 50 |

    #include <mqtt.h>

    51 | 52 | 54 | 55 | 56 | 57 |

    53 | Data Fields

    uint16_t packet_id
     he published messages packet ID. More...
     
    58 |

    Detailed Description

    59 |

    The response to a PUBREL packet.

    60 |
    See also
    MQTT v3.1.1: PUBCOMP - Publish Complete.
    61 |

    Field Documentation

    62 | 63 |

    ◆ packet_id

    64 | 65 |
    66 |
    67 | 68 | 69 | 70 | 71 |
    uint16_t mqtt_response_pubcomp::packet_id
    72 |
    73 | 74 |

    he published messages packet ID.

    75 |

    T

    76 | 77 |
    78 |
    79 |
    The documentation for this struct was generated from the following file: 82 |
    83 | 84 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /docs/structmqtt__response__pubrec.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | MQTT-C: mqtt_response_pubrec Struct Reference 9 | 10 | 11 | 12 | 13 | 14 | 15 |
    16 |
    17 | 18 | 19 | 20 | 24 | 25 | 26 |
    21 |
    MQTT-C 22 |
    23 |
    27 |
    28 | 29 | 30 | 31 | 32 | 37 | 38 |
    39 |
    40 | 42 |
    43 |
    mqtt_response_pubrec Struct Reference
    44 |
    45 |
    46 | 47 |

    The response packet to a PUBLISH packet with QoS level 2. 48 | More...

    49 | 50 |

    #include <mqtt.h>

    51 | 52 | 54 | 56 | 57 | 58 |

    53 | Data Fields

    55 | uint16_t packet_id
     The published messages packet ID.
     
    59 |

    Detailed Description

    60 |

    The response packet to a PUBLISH packet with QoS level 2.

    61 |
    See also
    MQTT v3.1.1: PUBREC - Publish Received.
    62 |

    The documentation for this struct was generated from the following file: 65 |
    66 | 67 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /docs/structmqtt__response__pubrel.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | MQTT-C: mqtt_response_pubrel Struct Reference 9 | 10 | 11 | 12 | 13 | 14 | 15 |
    16 |
    17 | 18 | 19 | 20 | 24 | 25 | 26 |
    21 |
    MQTT-C 22 |
    23 |
    27 |
    28 | 29 | 30 | 31 | 32 | 37 | 38 |
    39 |
    40 | 42 |
    43 |
    mqtt_response_pubrel Struct Reference
    44 |
    45 |
    46 | 47 |

    The response to a PUBREC packet. 48 | More...

    49 | 50 |

    #include <mqtt.h>

    51 | 52 | 54 | 56 | 57 | 58 |

    53 | Data Fields

    55 | uint16_t packet_id
     The published messages packet ID.
     
    59 |

    Detailed Description

    60 |

    The response to a PUBREC packet.

    61 |
    See also
    MQTT v3.1.1: PUBREL - Publish Release.
    62 |

    The documentation for this struct was generated from the following file: 65 |
    66 | 67 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /docs/structmqtt__response__unsuback.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | MQTT-C: mqtt_response_unsuback Struct Reference 9 | 10 | 11 | 12 | 13 | 14 | 15 |
    16 |
    17 | 18 | 19 | 20 | 24 | 25 | 26 |
    21 |
    MQTT-C 22 |
    23 |
    27 |
    28 | 29 | 30 | 31 | 32 | 37 | 38 |
    39 |
    40 | 43 |
    44 |
    mqtt_response_unsuback Struct Reference
    45 |
    46 |
    47 | 48 |

    The brokers response to a UNSUBSCRIBE request. 49 | More...

    50 | 51 |

    #include <mqtt.h>

    52 | 53 | 55 | 57 | 58 | 59 |

    54 | Data Fields

    56 | uint16_t packet_id
     The published messages packet ID.
     
    60 | 62 | 64 | 65 | 66 | 67 |

    61 | Related Functions

    (Note that these are not member functions.)

    63 |
    ssize_t mqtt_unpack_unsuback_response (struct mqtt_response *mqtt_response, const uint8_t *buf)
     Deserialize an UNSUBACK packet from buf. More...
     
    68 |

    Detailed Description

    69 |

    The brokers response to a UNSUBSCRIBE request.

    70 |
    See also
    MQTT v3.1.1: UNSUBACK - Unsubscribe Acknowledgement.
    71 |

    Friends And Related Function Documentation

    72 | 73 |

    ◆ mqtt_unpack_unsuback_response()

    74 | 75 |
    76 |
    77 | 78 | 79 | 100 | 102 | 103 |
    80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 |
    ssize_t mqtt_unpack_unsuback_response (struct mqtt_responsemqtt_response,
    const uint8_t * buf 
    )
    99 |
    101 | related
    104 |
    105 | 106 |

    Deserialize an UNSUBACK packet from buf.

    107 |
    Precondition
    mqtt_unpack_fixed_header must have returned a positive value and the mqtt_response must have a control type of MQTT_CONTROL_UNSUBACK.
    108 |
    Parameters
    109 | 110 | 111 | 112 |
    [out]mqtt_responsethe response that is initialized from the contents of buf.
    [in]bufthe buffer with the incoming data.
    113 |
    114 |
    115 |
    Returns
    The number of bytes that were consumed, or 0 if the buffer does not contain enough bytes to parse the packet, or a negative value if there was a protocol violation.
    116 | 117 |
    118 |
    119 |
    The documentation for this struct was generated from the following file: 122 |
    123 | 124 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /docs/sync_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiamBindle/MQTT-C/7a986a68ebea63921d4aab20a9d1b26a8b5f8c9d/docs/sync_off.png -------------------------------------------------------------------------------- /docs/sync_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiamBindle/MQTT-C/7a986a68ebea63921d4aab20a9d1b26a8b5f8c9d/docs/sync_on.png -------------------------------------------------------------------------------- /docs/tab_a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiamBindle/MQTT-C/7a986a68ebea63921d4aab20a9d1b26a8b5f8c9d/docs/tab_a.png -------------------------------------------------------------------------------- /docs/tab_b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiamBindle/MQTT-C/7a986a68ebea63921d4aab20a9d1b26a8b5f8c9d/docs/tab_b.png -------------------------------------------------------------------------------- /docs/tab_h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiamBindle/MQTT-C/7a986a68ebea63921d4aab20a9d1b26a8b5f8c9d/docs/tab_h.png -------------------------------------------------------------------------------- /docs/tab_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiamBindle/MQTT-C/7a986a68ebea63921d4aab20a9d1b26a8b5f8c9d/docs/tab_s.png -------------------------------------------------------------------------------- /docs/tabs.css: -------------------------------------------------------------------------------- 1 | .sm{position:relative;z-index:9999}.sm,.sm ul,.sm li{display:block;list-style:none;margin:0;padding:0;line-height:normal;direction:ltr;text-align:left;-webkit-tap-highlight-color:transparent}.sm-rtl,.sm-rtl ul,.sm-rtl li{direction:rtl;text-align:right}.sm>li>h1,.sm>li>h2,.sm>li>h3,.sm>li>h4,.sm>li>h5,.sm>li>h6{margin:0;padding:0}.sm ul{display:none}.sm li,.sm a{position:relative}.sm a{display:block}.sm a.disabled{cursor:not-allowed}.sm:after{content:"\00a0";display:block;height:0;font:0px/0 serif;clear:both;visibility:hidden;overflow:hidden}.sm,.sm *,.sm *:before,.sm *:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sm-dox{background-image:url("tab_b.png")}.sm-dox a,.sm-dox a:focus,.sm-dox a:hover,.sm-dox a:active{padding:0px 12px;padding-right:43px;font-family:"Lucida Grande","Geneva","Helvetica",Arial,sans-serif;font-size:13px;font-weight:bold;line-height:36px;text-decoration:none;text-shadow:0px 1px 1px rgba(255,255,255,0.9);color:#283A5D;outline:none}.sm-dox a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:#fff;text-shadow:0px 1px 1px #000}.sm-dox a.current{color:#D23600}.sm-dox a.disabled{color:#bbb}.sm-dox a span.sub-arrow{position:absolute;top:50%;margin-top:-14px;left:auto;right:3px;width:28px;height:28px;overflow:hidden;font:bold 12px/28px monospace !important;text-align:center;text-shadow:none;background:rgba(255,255,255,0.5);border-radius:5px}.sm-dox a.highlighted span.sub-arrow:before{display:block;content:'-'}.sm-dox>li:first-child>a,.sm-dox>li:first-child>:not(ul) a{border-radius:5px 5px 0 0}.sm-dox>li:last-child>a,.sm-dox>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul{border-radius:0 0 5px 5px}.sm-dox>li:last-child>a.highlighted,.sm-dox>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted{border-radius:0}.sm-dox ul{background:rgba(162,162,162,0.1)}.sm-dox ul a,.sm-dox ul a:focus,.sm-dox ul a:hover,.sm-dox ul a:active{font-size:12px;border-left:8px solid transparent;line-height:36px;text-shadow:none;background-color:white;background-image:none}.sm-dox ul a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:#fff;text-shadow:0px 1px 1px #000}.sm-dox ul ul a,.sm-dox ul ul a:hover,.sm-dox ul ul a:focus,.sm-dox ul ul a:active{border-left:16px solid transparent}.sm-dox ul ul ul a,.sm-dox ul ul ul a:hover,.sm-dox ul ul ul a:focus,.sm-dox ul ul ul a:active{border-left:24px solid transparent}.sm-dox ul ul ul ul a,.sm-dox ul ul ul ul a:hover,.sm-dox ul ul ul ul a:focus,.sm-dox ul ul ul ul a:active{border-left:32px solid transparent}.sm-dox ul ul ul ul ul a,.sm-dox ul ul ul ul ul a:hover,.sm-dox ul ul ul ul ul a:focus,.sm-dox ul ul ul ul ul a:active{border-left:40px solid transparent}@media (min-width: 768px){.sm-dox ul{position:absolute;width:12em}.sm-dox li{float:left}.sm-dox.sm-rtl li{float:right}.sm-dox ul li,.sm-dox.sm-rtl ul li,.sm-dox.sm-vertical li{float:none}.sm-dox a{white-space:nowrap}.sm-dox ul a,.sm-dox.sm-vertical a{white-space:normal}.sm-dox .sm-nowrap>li>a,.sm-dox .sm-nowrap>li>:not(ul) a{white-space:nowrap}.sm-dox{padding:0 10px;background-image:url("tab_b.png");line-height:36px}.sm-dox a span.sub-arrow{top:50%;margin-top:-2px;right:12px;width:0;height:0;border-width:4px;border-style:solid dashed dashed dashed;border-color:#283A5D transparent transparent transparent;background:transparent;border-radius:0}.sm-dox a,.sm-dox a:focus,.sm-dox a:active,.sm-dox a:hover,.sm-dox a.highlighted{padding:0px 12px;background-image:url("tab_s.png");background-repeat:no-repeat;background-position:right;border-radius:0 !important}.sm-dox a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:#fff;text-shadow:0px 1px 1px #000}.sm-dox a:hover span.sub-arrow{border-color:#fff transparent transparent transparent}.sm-dox a.has-submenu{padding-right:24px}.sm-dox li{border-top:0}.sm-dox>li>ul:before,.sm-dox>li>ul:after{content:'';position:absolute;top:-18px;left:30px;width:0;height:0;overflow:hidden;border-width:9px;border-style:dashed dashed solid dashed;border-color:transparent transparent #bbb transparent}.sm-dox>li>ul:after{top:-16px;left:31px;border-width:8px;border-color:transparent transparent #fff transparent}.sm-dox ul{border:1px solid #bbb;padding:5px 0;background:#fff;border-radius:5px !important;box-shadow:0 5px 9px rgba(0,0,0,0.2)}.sm-dox ul a span.sub-arrow{right:8px;top:50%;margin-top:-5px;border-width:5px;border-color:transparent transparent transparent #555;border-style:dashed dashed dashed solid}.sm-dox ul a,.sm-dox ul a:hover,.sm-dox ul a:focus,.sm-dox ul a:active,.sm-dox ul a.highlighted{color:#555;background-image:none;border:0 !important;color:#555;background-image:none}.sm-dox ul a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:#fff;text-shadow:0px 1px 1px #000}.sm-dox ul a:hover span.sub-arrow{border-color:transparent transparent transparent #fff}.sm-dox span.scroll-up,.sm-dox span.scroll-down{position:absolute;display:none;visibility:hidden;overflow:hidden;background:#fff;height:36px}.sm-dox span.scroll-up:hover,.sm-dox span.scroll-down:hover{background:#eee}.sm-dox span.scroll-up:hover span.scroll-up-arrow,.sm-dox span.scroll-up:hover span.scroll-down-arrow{border-color:transparent transparent #D23600 transparent}.sm-dox span.scroll-down:hover span.scroll-down-arrow{border-color:#D23600 transparent transparent transparent}.sm-dox span.scroll-up-arrow,.sm-dox span.scroll-down-arrow{position:absolute;top:0;left:50%;margin-left:-6px;width:0;height:0;overflow:hidden;border-width:6px;border-style:dashed dashed solid dashed;border-color:transparent transparent #555 transparent}.sm-dox span.scroll-down-arrow{top:8px;border-style:solid dashed dashed dashed;border-color:#555 transparent transparent transparent}.sm-dox.sm-rtl a.has-submenu{padding-right:12px;padding-left:24px}.sm-dox.sm-rtl a span.sub-arrow{right:auto;left:12px}.sm-dox.sm-rtl.sm-vertical a.has-submenu{padding:10px 20px}.sm-dox.sm-rtl.sm-vertical a span.sub-arrow{right:auto;left:8px;border-style:dashed solid dashed dashed;border-color:transparent #555 transparent transparent}.sm-dox.sm-rtl>li>ul:before{left:auto;right:30px}.sm-dox.sm-rtl>li>ul:after{left:auto;right:31px}.sm-dox.sm-rtl ul a.has-submenu{padding:10px 20px !important}.sm-dox.sm-rtl ul a span.sub-arrow{right:auto;left:8px;border-style:dashed solid dashed dashed;border-color:transparent #555 transparent transparent}.sm-dox.sm-vertical{padding:10px 0;border-radius:5px}.sm-dox.sm-vertical a{padding:10px 20px}.sm-dox.sm-vertical a:hover,.sm-dox.sm-vertical a:focus,.sm-dox.sm-vertical a:active,.sm-dox.sm-vertical a.highlighted{background:#fff}.sm-dox.sm-vertical a.disabled{background-image:url("tab_b.png")}.sm-dox.sm-vertical a span.sub-arrow{right:8px;top:50%;margin-top:-5px;border-width:5px;border-style:dashed dashed dashed solid;border-color:transparent transparent transparent #555}.sm-dox.sm-vertical>li>ul:before,.sm-dox.sm-vertical>li>ul:after{display:none}.sm-dox.sm-vertical ul a{padding:10px 20px}.sm-dox.sm-vertical ul a:hover,.sm-dox.sm-vertical ul a:focus,.sm-dox.sm-vertical ul a:active,.sm-dox.sm-vertical ul a.highlighted{background:#eee}.sm-dox.sm-vertical ul a.disabled{background:#fff}} 2 | -------------------------------------------------------------------------------- /examples/bio_publisher.c: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file 4 | * A simple program to that publishes the current time whenever ENTER is pressed. 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include "templates/bio_sockets.h" 13 | 14 | 15 | /** 16 | * @brief The function that would be called whenever a PUBLISH is received. 17 | * 18 | * @note This function is not used in this example. 19 | */ 20 | void publish_callback(void** unused, struct mqtt_response_publish *published); 21 | 22 | /** 23 | * @brief The client's refresher. This function triggers back-end routines to 24 | * handle ingress/egress traffic to the broker. 25 | * 26 | * @note All this function needs to do is call \ref __mqtt_recv and 27 | * \ref __mqtt_send every so often. I've picked 100 ms meaning that 28 | * client ingress/egress traffic will be handled every 100 ms. 29 | */ 30 | void* client_refresher(void* client); 31 | 32 | /** 33 | * @brief Safelty closes the \p sockfd and cancels the \p client_daemon before \c exit. 34 | */ 35 | void exit_example(int status, BIO* sockfd, pthread_t *client_daemon); 36 | 37 | /** 38 | * A simple program to that publishes the current time whenever ENTER is pressed. 39 | */ 40 | int main(int argc, const char *argv[]) 41 | { 42 | const char* addr; 43 | const char* port; 44 | const char* topic; 45 | 46 | /* Load OpenSSL */ 47 | SSL_load_error_strings(); 48 | ERR_load_BIO_strings(); 49 | OpenSSL_add_all_algorithms(); 50 | 51 | /* get address (argv[1] if present) */ 52 | if (argc > 1) { 53 | addr = argv[1]; 54 | } else { 55 | addr = "test.mosquitto.org"; 56 | } 57 | 58 | /* get port number (argv[2] if present) */ 59 | if (argc > 2) { 60 | port = argv[2]; 61 | } else { 62 | port = "1883"; 63 | } 64 | 65 | /* get the topic name to publish */ 66 | if (argc > 3) { 67 | topic = argv[3]; 68 | } else { 69 | topic = "datetime"; 70 | } 71 | 72 | /* open the non-blocking TCP socket (connecting to the broker) */ 73 | BIO* sockfd = open_nb_socket(addr, port); 74 | 75 | if (sockfd == NULL) { 76 | exit_example(EXIT_FAILURE, sockfd, NULL); 77 | } 78 | 79 | /* setup a client */ 80 | struct mqtt_client client; 81 | uint8_t sendbuf[2048]; /* sendbuf should be large enough to hold multiple whole mqtt messages */ 82 | uint8_t recvbuf[1024]; /* recvbuf should be large enough any whole mqtt message expected to be received */ 83 | mqtt_init(&client, sockfd, sendbuf, sizeof(sendbuf), recvbuf, sizeof(recvbuf), publish_callback); 84 | mqtt_connect(&client, "publishing_client", NULL, NULL, 0, NULL, NULL, 0, 400); 85 | 86 | /* check that we don't have any errors */ 87 | if (client.error != MQTT_OK) { 88 | fprintf(stderr, "error: %s\n", mqtt_error_str(client.error)); 89 | exit_example(EXIT_FAILURE, sockfd, NULL); 90 | } 91 | 92 | /* start a thread to refresh the client (handle egress and ingree client traffic) */ 93 | pthread_t client_daemon; 94 | if(pthread_create(&client_daemon, NULL, client_refresher, &client)) { 95 | fprintf(stderr, "Failed to start client daemon.\n"); 96 | exit_example(EXIT_FAILURE, sockfd, NULL); 97 | 98 | } 99 | 100 | /* start publishing the time */ 101 | printf("%s is ready to begin publishing the time.\n", argv[0]); 102 | printf("Press ENTER to publish the current time.\n"); 103 | printf("Press CTRL-D (or any other key) to exit.\n\n"); 104 | while(fgetc(stdin) == '\n') { 105 | /* get the current time */ 106 | time_t timer; 107 | time(&timer); 108 | struct tm* tm_info = localtime(&timer); 109 | char timebuf[26]; 110 | strftime(timebuf, 26, "%Y-%m-%d %H:%M:%S", tm_info); 111 | 112 | /* print a message */ 113 | char application_message[256]; 114 | snprintf(application_message, sizeof(application_message), "The time is %s", timebuf); 115 | printf("%s published : \"%s\"", argv[0], application_message); 116 | 117 | /* publish the time */ 118 | mqtt_publish(&client, topic, application_message, strlen(application_message) + 1, MQTT_PUBLISH_QOS_2); 119 | 120 | /* check for errors */ 121 | if (client.error != MQTT_OK) { 122 | fprintf(stderr, "error: %s\n", mqtt_error_str(client.error)); 123 | exit_example(EXIT_FAILURE, sockfd, &client_daemon); 124 | } 125 | } 126 | 127 | /* disconnect */ 128 | printf("\n%s disconnecting from %s\n", argv[0], addr); 129 | sleep(1); 130 | 131 | /* exit */ 132 | exit_example(EXIT_SUCCESS, sockfd, &client_daemon); 133 | } 134 | 135 | void exit_example(int status, BIO* sockfd, pthread_t *client_daemon) 136 | { 137 | if (sockfd != NULL) BIO_free_all(sockfd); 138 | if (client_daemon != NULL) pthread_cancel(*client_daemon); 139 | exit(status); 140 | } 141 | 142 | 143 | 144 | void publish_callback(void** unused, struct mqtt_response_publish *published) 145 | { 146 | /* not used in this example */ 147 | } 148 | 149 | void* client_refresher(void* client) 150 | { 151 | while(1) 152 | { 153 | mqtt_sync((struct mqtt_client*) client); 154 | usleep(100000U); 155 | } 156 | return NULL; 157 | } -------------------------------------------------------------------------------- /examples/bio_publisher_win.c: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file 4 | * A simple program to that publishes the current time whenever ENTER is pressed. 5 | */ 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include "templates/bio_sockets.h" 12 | 13 | 14 | /** 15 | * @brief The function that would be called whenever a PUBLISH is received. 16 | * 17 | * @note This function is not used in this example. 18 | */ 19 | void publish_callback(void** unused, struct mqtt_response_publish *published); 20 | 21 | /** 22 | * @brief The client's refresher. This function triggers back-end routines to 23 | * handle ingress/egress traffic to the broker. 24 | * 25 | * @note All this function needs to do is call \ref __mqtt_recv and 26 | * \ref __mqtt_send every so often. I've picked 100 ms meaning that 27 | * client ingress/egress traffic will be handled every 100 ms. 28 | */ 29 | void client_refresher(void* client); 30 | 31 | /** 32 | * @brief Safelty closes the \p sockfd and cancels the \p client_daemon before \c exit. 33 | */ 34 | void exit_example(int status, BIO* sockfd); 35 | 36 | /** 37 | * A simple program to that publishes the current time whenever ENTER is pressed. 38 | */ 39 | int main(int argc, const char *argv[]) 40 | { 41 | const char* addr; 42 | const char* port; 43 | const char* topic; 44 | 45 | /* Load OpenSSL */ 46 | SSL_load_error_strings(); 47 | ERR_load_BIO_strings(); 48 | OpenSSL_add_all_algorithms(); 49 | 50 | /* get address (argv[1] if present) */ 51 | if (argc > 1) { 52 | addr = argv[1]; 53 | } else { 54 | addr = "test.mosquitto.org"; 55 | } 56 | 57 | /* get port number (argv[2] if present) */ 58 | if (argc > 2) { 59 | port = argv[2]; 60 | } else { 61 | port = "1883"; 62 | } 63 | 64 | /* get the topic name to publish */ 65 | if (argc > 3) { 66 | topic = argv[3]; 67 | } else { 68 | topic = "datetime"; 69 | } 70 | 71 | /* open the non-blocking TCP socket (connecting to the broker) */ 72 | BIO* sockfd = open_nb_socket(addr, port); 73 | 74 | if (sockfd == NULL) { 75 | exit_example(EXIT_FAILURE, sockfd); 76 | } 77 | 78 | /* setup a client */ 79 | struct mqtt_client client; 80 | uint8_t sendbuf[2048]; /* sendbuf should be large enough to hold multiple whole mqtt messages */ 81 | uint8_t recvbuf[1024]; /* recvbuf should be large enough any whole mqtt message expected to be received */ 82 | mqtt_init(&client, sockfd, sendbuf, sizeof(sendbuf), recvbuf, sizeof(recvbuf), publish_callback); 83 | mqtt_connect(&client, "publishing_client", NULL, NULL, 0, NULL, NULL, 0, 400); 84 | 85 | /* check that we don't have any errors */ 86 | if (client.error != MQTT_OK) { 87 | fprintf(stderr, "error: %s\n", mqtt_error_str(client.error)); 88 | exit_example(EXIT_FAILURE, sockfd); 89 | } 90 | 91 | /* start a thread to refresh the client (handle egress and ingree client traffic) */ 92 | if(_beginthread(client_refresher, 0, &client) == -1) { 93 | fprintf(stderr, "Failed to start client daemon.\n"); 94 | exit_example(EXIT_FAILURE, sockfd); 95 | 96 | } 97 | 98 | /* start publishing the time */ 99 | printf("%s is ready to begin publishing the time.\n", argv[0]); 100 | printf("Press ENTER to publish the current time.\n"); 101 | printf("Press CTRL-D (or any other key) to exit.\n\n"); 102 | while(fgetc(stdin) == '\n') { 103 | /* get the current time */ 104 | time_t timer; 105 | time(&timer); 106 | struct tm* tm_info = localtime(&timer); 107 | char timebuf[26]; 108 | strftime(timebuf, 26, "%Y-%m-%d %H:%M:%S", tm_info); 109 | 110 | /* print a message */ 111 | char application_message[256]; 112 | snprintf(application_message, sizeof(application_message), "The time is %s", timebuf); 113 | printf("%s published : \"%s\"", argv[0], application_message); 114 | 115 | /* publish the time */ 116 | mqtt_publish(&client, topic, application_message, strlen(application_message) + 1, MQTT_PUBLISH_QOS_2); 117 | 118 | /* check for errors */ 119 | if (client.error != MQTT_OK) { 120 | fprintf(stderr, "\nerror: %s\n", mqtt_error_str(client.error)); 121 | exit_example(EXIT_FAILURE, sockfd); 122 | } 123 | } 124 | 125 | /* disconnect */ 126 | printf("\n%s disconnecting from %s\n", argv[0], addr); 127 | Sleep(1000); 128 | 129 | /* exit */ 130 | exit_example(EXIT_SUCCESS, sockfd); 131 | } 132 | 133 | void exit_example(int status, BIO* sockfd) 134 | { 135 | if (sockfd != NULL) BIO_free_all(sockfd); 136 | exit(status); 137 | } 138 | 139 | 140 | 141 | void publish_callback(void** unused, struct mqtt_response_publish *published) 142 | { 143 | /* not used in this example */ 144 | } 145 | 146 | void client_refresher(void* client) 147 | { 148 | while(1) 149 | { 150 | mqtt_sync((struct mqtt_client*) client); 151 | Sleep(100); 152 | } 153 | } -------------------------------------------------------------------------------- /examples/mbedtls_publisher.c: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file 4 | */ 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include "templates/mbedtls_sockets.h" 11 | 12 | 13 | /** 14 | * @brief The function that would be called whenever a PUBLISH is received. 15 | * 16 | * @note This function is not used in this example. 17 | */ 18 | void publish_callback(void** unused, struct mqtt_response_publish *published); 19 | 20 | /** 21 | * @brief The client's refresher. This function triggers back-end routines to 22 | * handle ingress/egress traffic to the broker. 23 | * 24 | * @note All this function needs to do is call \ref __mqtt_recv and 25 | * \ref __mqtt_send every so often. I've picked 100 ms meaning that 26 | * client ingress/egress traffic will be handled every 100 ms. 27 | */ 28 | void* client_refresher(void* client); 29 | 30 | /** 31 | * @brief Safelty closes the \p sockfd and cancels the \p client_daemon before \c exit. 32 | */ 33 | void exit_example(int status, mqtt_pal_socket_handle sockfd, pthread_t *client_daemon); 34 | 35 | /** 36 | * A simple program to that publishes the current time whenever ENTER is pressed. 37 | */ 38 | int main(int argc, const char *argv[]) 39 | { 40 | const char* addr; 41 | const char* port; 42 | const char* topic; 43 | const char* ca_file; 44 | 45 | struct mbedtls_context ctx; 46 | mqtt_pal_socket_handle sockfd; 47 | 48 | if (argc > 1) { 49 | ca_file = argv[1]; 50 | } else { 51 | printf("error: path to the CA certificate to use\n"); 52 | exit(1); 53 | } 54 | 55 | /* get address (argv[2] if present) */ 56 | if (argc > 2) { 57 | addr = argv[2]; 58 | } else { 59 | addr = "test.mosquitto.org"; 60 | } 61 | 62 | /* get port number (argv[3] if present) */ 63 | if (argc > 3) { 64 | port = argv[3]; 65 | } else { 66 | port = "8883"; 67 | } 68 | 69 | /* get the topic name to publish */ 70 | if (argc > 4) { 71 | topic = argv[4]; 72 | } else { 73 | topic = "datetime"; 74 | } 75 | 76 | /* open the non-blocking TCP socket (connecting to the broker) */ 77 | open_nb_socket(&ctx, addr, port, ca_file); 78 | sockfd = &ctx.ssl_ctx; 79 | 80 | if (sockfd == NULL) { 81 | exit_example(EXIT_FAILURE, sockfd, NULL); 82 | } 83 | 84 | /* setup a client */ 85 | struct mqtt_client client; 86 | uint8_t sendbuf[2048]; /* sendbuf should be large enough to hold multiple whole mqtt messages */ 87 | uint8_t recvbuf[1024]; /* recvbuf should be large enough any whole mqtt message expected to be received */ 88 | mqtt_init(&client, sockfd, sendbuf, sizeof(sendbuf), recvbuf, sizeof(recvbuf), publish_callback); 89 | mqtt_connect(&client, "publishing_client", NULL, NULL, 0, NULL, NULL, 0, 400); 90 | 91 | /* check that we don't have any errors */ 92 | if (client.error != MQTT_OK) { 93 | fprintf(stderr, "error: %s\n", mqtt_error_str(client.error)); 94 | exit_example(EXIT_FAILURE, sockfd, NULL); 95 | } 96 | 97 | /* start a thread to refresh the client (handle egress and ingree client traffic) */ 98 | pthread_t client_daemon; 99 | if(pthread_create(&client_daemon, NULL, client_refresher, &client)) { 100 | fprintf(stderr, "Failed to start client daemon.\n"); 101 | exit_example(EXIT_FAILURE, sockfd, NULL); 102 | 103 | } 104 | 105 | /* start publishing the time */ 106 | printf("%s is ready to begin publishing the time.\n", argv[0]); 107 | printf("Press ENTER to publish the current time.\n"); 108 | printf("Press CTRL-D (or any other key) to exit.\n\n"); 109 | while(fgetc(stdin) == '\n') { 110 | /* get the current time */ 111 | time_t timer; 112 | time(&timer); 113 | struct tm* tm_info = localtime(&timer); 114 | char timebuf[26]; 115 | strftime(timebuf, 26, "%Y-%m-%d %H:%M:%S", tm_info); 116 | 117 | /* print a message */ 118 | char application_message[256]; 119 | snprintf(application_message, sizeof(application_message), "The time is %s", timebuf); 120 | printf("%s published : \"%s\"", argv[0], application_message); 121 | 122 | /* publish the time */ 123 | mqtt_publish(&client, topic, application_message, strlen(application_message) + 1, MQTT_PUBLISH_QOS_2); 124 | 125 | /* check for errors */ 126 | if (client.error != MQTT_OK) { 127 | fprintf(stderr, "error: %s\n", mqtt_error_str(client.error)); 128 | exit_example(EXIT_FAILURE, sockfd, &client_daemon); 129 | } 130 | } 131 | 132 | /* disconnect */ 133 | printf("\n%s disconnecting from %s\n", argv[0], addr); 134 | sleep(1); 135 | 136 | /* exit */ 137 | exit_example(EXIT_SUCCESS, sockfd, &client_daemon); 138 | } 139 | 140 | void exit_example(int status, mqtt_pal_socket_handle sockfd, pthread_t *client_daemon) 141 | { 142 | if (client_daemon != NULL) pthread_cancel(*client_daemon); 143 | mbedtls_ssl_free(sockfd); 144 | /* XXX free the rest of contexts */ 145 | exit(status); 146 | } 147 | 148 | 149 | 150 | void publish_callback(void** unused, struct mqtt_response_publish *published) 151 | { 152 | /* not used in this example */ 153 | } 154 | 155 | void* client_refresher(void* client) 156 | { 157 | while(1) 158 | { 159 | mqtt_sync((struct mqtt_client*) client); 160 | usleep(100000U); 161 | } 162 | return NULL; 163 | } 164 | -------------------------------------------------------------------------------- /examples/mosquitto.org.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEAzCCAuugAwIBAgIUBY1hlCGvdj4NhBXkZ/uLUZNILAwwDQYJKoZIhvcNAQEL 3 | BQAwgZAxCzAJBgNVBAYTAkdCMRcwFQYDVQQIDA5Vbml0ZWQgS2luZ2RvbTEOMAwG 4 | A1UEBwwFRGVyYnkxEjAQBgNVBAoMCU1vc3F1aXR0bzELMAkGA1UECwwCQ0ExFjAU 5 | BgNVBAMMDW1vc3F1aXR0by5vcmcxHzAdBgkqhkiG9w0BCQEWEHJvZ2VyQGF0Y2hv 6 | by5vcmcwHhcNMjAwNjA5MTEwNjM5WhcNMzAwNjA3MTEwNjM5WjCBkDELMAkGA1UE 7 | BhMCR0IxFzAVBgNVBAgMDlVuaXRlZCBLaW5nZG9tMQ4wDAYDVQQHDAVEZXJieTES 8 | MBAGA1UECgwJTW9zcXVpdHRvMQswCQYDVQQLDAJDQTEWMBQGA1UEAwwNbW9zcXVp 9 | dHRvLm9yZzEfMB0GCSqGSIb3DQEJARYQcm9nZXJAYXRjaG9vLm9yZzCCASIwDQYJ 10 | KoZIhvcNAQEBBQADggEPADCCAQoCggEBAME0HKmIzfTOwkKLT3THHe+ObdizamPg 11 | UZmD64Tf3zJdNeYGYn4CEXbyP6fy3tWc8S2boW6dzrH8SdFf9uo320GJA9B7U1FW 12 | Te3xda/Lm3JFfaHjkWw7jBwcauQZjpGINHapHRlpiCZsquAthOgxW9SgDgYlGzEA 13 | s06pkEFiMw+qDfLo/sxFKB6vQlFekMeCymjLCbNwPJyqyhFmPWwio/PDMruBTzPH 14 | 3cioBnrJWKXc3OjXdLGFJOfj7pP0j/dr2LH72eSvv3PQQFl90CZPFhrCUcRHSSxo 15 | E6yjGOdnz7f6PveLIB574kQORwt8ePn0yidrTC1ictikED3nHYhMUOUCAwEAAaNT 16 | MFEwHQYDVR0OBBYEFPVV6xBUFPiGKDyo5V3+Hbh4N9YSMB8GA1UdIwQYMBaAFPVV 17 | 6xBUFPiGKDyo5V3+Hbh4N9YSMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL 18 | BQADggEBAGa9kS21N70ThM6/Hj9D7mbVxKLBjVWe2TPsGfbl3rEDfZ+OKRZ2j6AC 19 | 6r7jb4TZO3dzF2p6dgbrlU71Y/4K0TdzIjRj3cQ3KSm41JvUQ0hZ/c04iGDg/xWf 20 | +pp58nfPAYwuerruPNWmlStWAXf0UTqRtg4hQDWBuUFDJTuWuuBvEXudz74eh/wK 21 | sMwfu1HFvjy5Z0iMDU8PUDepjVolOCue9ashlS4EB5IECdSR2TItnAIiIwimx839 22 | LdUdRudafMu5T5Xma182OC0/u/xRlEm+tvKGGmfFcN0piqVl8OrSPBgIlb+1IKJE 23 | m/XriWr/Cq4h/JfB7NTsezVslgkBaoU= 24 | -----END CERTIFICATE----- 25 | -------------------------------------------------------------------------------- /examples/openssl_publisher.c: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include "templates/openssl_sockets.h" 12 | 13 | 14 | /** 15 | * @brief The function that would be called whenever a PUBLISH is received. 16 | * 17 | * @note This function is not used in this example. 18 | */ 19 | void publish_callback(void** unused, struct mqtt_response_publish *published); 20 | 21 | /** 22 | * @brief The client's refresher. This function triggers back-end routines to 23 | * handle ingress/egress traffic to the broker. 24 | * 25 | * @note All this function needs to do is call \ref __mqtt_recv and 26 | * \ref __mqtt_send every so often. I've picked 100 ms meaning that 27 | * client ingress/egress traffic will be handled every 100 ms. 28 | */ 29 | void* client_refresher(void* client); 30 | 31 | /** 32 | * @brief Safelty closes the \p sockfd and cancels the \p client_daemon before \c exit. 33 | */ 34 | void exit_example(int status, BIO* sockfd, pthread_t *client_daemon); 35 | 36 | /** 37 | * A simple program to that publishes the current time whenever ENTER is pressed. 38 | */ 39 | int main(int argc, const char *argv[]) 40 | { 41 | const char* addr; 42 | const char* port; 43 | const char* topic; 44 | const char* ca_file; 45 | const char* cert_file; 46 | const char* key_file; 47 | 48 | /* Load OpenSSL */ 49 | SSL_load_error_strings(); 50 | ERR_load_BIO_strings(); 51 | OpenSSL_add_all_algorithms(); 52 | SSL_library_init(); 53 | 54 | SSL_CTX* ssl_ctx; 55 | BIO* sockfd; 56 | 57 | if (argc > 1) { 58 | ca_file = argv[1]; 59 | } else { 60 | printf("error: path to the CA certificate to use\n"); 61 | exit(1); 62 | } 63 | 64 | /* get address (argv[2] if present) */ 65 | if (argc > 2) { 66 | addr = argv[2]; 67 | } else { 68 | addr = "test.mosquitto.org"; 69 | } 70 | 71 | /* get port number (argv[3] if present) */ 72 | if (argc > 3) { 73 | port = argv[3]; 74 | } else { 75 | port = "8883"; 76 | } 77 | 78 | /* get the topic name to publish */ 79 | if (argc > 4) { 80 | topic = argv[4]; 81 | } else { 82 | topic = "datetime"; 83 | } 84 | 85 | /* get client cert */ 86 | if (argc > 5) { 87 | cert_file = argv[5]; 88 | } else { 89 | cert_file = NULL; 90 | } 91 | 92 | /* get client key */ 93 | if (argc > 6) { 94 | key_file = argv[6]; 95 | } else { 96 | key_file = NULL; 97 | } 98 | 99 | /* open the non-blocking TCP socket (connecting to the broker) */ 100 | open_nb_socket(&sockfd, &ssl_ctx, addr, port, ca_file, NULL, cert_file, key_file); 101 | 102 | if (sockfd == NULL) { 103 | exit_example(EXIT_FAILURE, sockfd, NULL); 104 | } 105 | 106 | /* setup a client */ 107 | struct mqtt_client client; 108 | uint8_t sendbuf[2048]; /* sendbuf should be large enough to hold multiple whole mqtt messages */ 109 | uint8_t recvbuf[1024]; /* recvbuf should be large enough any whole mqtt message expected to be received */ 110 | mqtt_init(&client, sockfd, sendbuf, sizeof(sendbuf), recvbuf, sizeof(recvbuf), publish_callback); 111 | mqtt_connect(&client, "publishing_client", NULL, NULL, 0, NULL, NULL, 0, 400); 112 | 113 | /* check that we don't have any errors */ 114 | if (client.error != MQTT_OK) { 115 | fprintf(stderr, "error: %s\n", mqtt_error_str(client.error)); 116 | exit_example(EXIT_FAILURE, sockfd, NULL); 117 | } 118 | 119 | /* start a thread to refresh the client (handle egress and ingree client traffic) */ 120 | pthread_t client_daemon; 121 | if(pthread_create(&client_daemon, NULL, client_refresher, &client)) { 122 | fprintf(stderr, "Failed to start client daemon.\n"); 123 | exit_example(EXIT_FAILURE, sockfd, NULL); 124 | 125 | } 126 | 127 | /* start publishing the time */ 128 | printf("%s is ready to begin publishing the time.\n", argv[0]); 129 | printf("Press ENTER to publish the current time.\n"); 130 | printf("Press CTRL-D (or any other key) to exit.\n\n"); 131 | while(fgetc(stdin) == '\n') { 132 | /* get the current time */ 133 | time_t timer; 134 | time(&timer); 135 | struct tm* tm_info = localtime(&timer); 136 | char timebuf[26]; 137 | strftime(timebuf, 26, "%Y-%m-%d %H:%M:%S", tm_info); 138 | 139 | /* print a message */ 140 | char application_message[256]; 141 | snprintf(application_message, sizeof(application_message), "The time is %s", timebuf); 142 | printf("%s published : \"%s\"", argv[0], application_message); 143 | 144 | /* publish the time */ 145 | mqtt_publish(&client, topic, application_message, strlen(application_message) + 1, MQTT_PUBLISH_QOS_2); 146 | 147 | /* check for errors */ 148 | if (client.error != MQTT_OK) { 149 | fprintf(stderr, "error: %s\n", mqtt_error_str(client.error)); 150 | exit_example(EXIT_FAILURE, sockfd, &client_daemon); 151 | } 152 | } 153 | 154 | /* disconnect */ 155 | printf("\n%s disconnecting from %s\n", argv[0], addr); 156 | sleep(1); 157 | 158 | /* exit */ 159 | exit_example(EXIT_SUCCESS, sockfd, &client_daemon); 160 | } 161 | 162 | void exit_example(int status, BIO* sockfd, pthread_t *client_daemon) 163 | { 164 | if (sockfd != NULL) BIO_free_all(sockfd); 165 | if (client_daemon != NULL) pthread_cancel(*client_daemon); 166 | exit(status); 167 | } 168 | 169 | 170 | 171 | void publish_callback(void** unused, struct mqtt_response_publish *published) 172 | { 173 | /* not used in this example */ 174 | } 175 | 176 | void* client_refresher(void* client) 177 | { 178 | while(1) 179 | { 180 | mqtt_sync((struct mqtt_client*) client); 181 | usleep(100000U); 182 | } 183 | return NULL; 184 | } 185 | -------------------------------------------------------------------------------- /examples/openssl_publisher_win.c: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file 4 | */ 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include "templates/openssl_sockets.h" 11 | 12 | 13 | /** 14 | * @brief The function that would be called whenever a PUBLISH is received. 15 | * 16 | * @note This function is not used in this example. 17 | */ 18 | void publish_callback(void** unused, struct mqtt_response_publish *published); 19 | 20 | /** 21 | * @brief The client's refresher. This function triggers back-end routines to 22 | * handle ingress/egress traffic to the broker. 23 | * 24 | * @note All this function needs to do is call \ref __mqtt_recv and 25 | * \ref __mqtt_send every so often. I've picked 100 ms meaning that 26 | * client ingress/egress traffic will be handled every 100 ms. 27 | */ 28 | void client_refresher(void* client); 29 | 30 | /** 31 | * @brief Safelty closes the \p sockfd and cancels the \p client_daemon before \c exit. 32 | */ 33 | void exit_example(int status, BIO* sockfd); 34 | 35 | /** 36 | * A simple program to that publishes the current time whenever ENTER is pressed. 37 | */ 38 | int main(int argc, const char *argv[]) 39 | { 40 | const char* addr; 41 | const char* port; 42 | const char* topic; 43 | const char* ca_file; 44 | 45 | /* Load OpenSSL */ 46 | SSL_load_error_strings(); 47 | ERR_load_BIO_strings(); 48 | OpenSSL_add_all_algorithms(); 49 | SSL_library_init(); 50 | 51 | SSL_CTX* ssl_ctx; 52 | BIO* sockfd; 53 | 54 | if (argc > 1) { 55 | ca_file = argv[1]; 56 | } else { 57 | printf("error: path to the CA certificate to use\n"); 58 | exit(1); 59 | } 60 | 61 | /* get address (argv[2] if present) */ 62 | if (argc > 2) { 63 | addr = argv[2]; 64 | } else { 65 | addr = "test.mosquitto.org"; 66 | } 67 | 68 | /* get port number (argv[3] if present) */ 69 | if (argc > 3) { 70 | port = argv[3]; 71 | } else { 72 | port = "8883"; 73 | } 74 | 75 | /* get the topic name to publish */ 76 | if (argc > 4) { 77 | topic = argv[4]; 78 | } else { 79 | topic = "datetime"; 80 | } 81 | 82 | /* open the non-blocking TCP socket (connecting to the broker) */ 83 | open_nb_socket(&sockfd, &ssl_ctx, addr, port, ca_file, NULL); 84 | 85 | if (sockfd == NULL) { 86 | exit_example(EXIT_FAILURE, sockfd); 87 | } 88 | 89 | /* setup a client */ 90 | struct mqtt_client client; 91 | uint8_t sendbuf[2048]; /* sendbuf should be large enough to hold multiple whole mqtt messages */ 92 | uint8_t recvbuf[1024]; /* recvbuf should be large enough any whole mqtt message expected to be received */ 93 | mqtt_init(&client, sockfd, sendbuf, sizeof(sendbuf), recvbuf, sizeof(recvbuf), publish_callback); 94 | mqtt_connect(&client, "publishing_client", NULL, NULL, 0, NULL, NULL, 0, 400); 95 | 96 | /* check that we don't have any errors */ 97 | if (client.error != MQTT_OK) { 98 | fprintf(stderr, "error: %s\n", mqtt_error_str(client.error)); 99 | exit_example(EXIT_FAILURE, sockfd); 100 | } 101 | 102 | /* start a thread to refresh the client (handle egress and ingree client traffic) */ 103 | if(_beginthread(client_refresher, 0, &client) == -1) { 104 | fprintf(stderr, "Failed to start client daemon.\n"); 105 | exit_example(EXIT_FAILURE, sockfd); 106 | 107 | } 108 | 109 | /* start publishing the time */ 110 | printf("%s is ready to begin publishing the time.\n", argv[0]); 111 | printf("Press ENTER to publish the current time.\n"); 112 | printf("Press CTRL-D (or any other key) to exit.\n\n"); 113 | while(fgetc(stdin) == '\n') { 114 | /* get the current time */ 115 | time_t timer; 116 | time(&timer); 117 | struct tm* tm_info = localtime(&timer); 118 | char timebuf[26]; 119 | strftime(timebuf, 26, "%Y-%m-%d %H:%M:%S", tm_info); 120 | 121 | /* print a message */ 122 | char application_message[256]; 123 | snprintf(application_message, sizeof(application_message), "The time is %s", timebuf); 124 | printf("%s published : \"%s\"", argv[0], application_message); 125 | 126 | /* publish the time */ 127 | mqtt_publish(&client, topic, application_message, strlen(application_message) + 1, MQTT_PUBLISH_QOS_2); 128 | 129 | /* check for errors */ 130 | if (client.error != MQTT_OK) { 131 | fprintf(stderr, "error: %s\n", mqtt_error_str(client.error)); 132 | exit_example(EXIT_FAILURE, sockfd); 133 | } 134 | } 135 | 136 | /* disconnect */ 137 | printf("\n%s disconnecting from %s\n", argv[0], addr); 138 | Sleep(1000); 139 | 140 | /* exit */ 141 | exit_example(EXIT_SUCCESS, sockfd); 142 | } 143 | 144 | void exit_example(int status, BIO* sockfd) 145 | { 146 | if (sockfd != NULL) BIO_free_all(sockfd); 147 | exit(status); 148 | } 149 | 150 | 151 | 152 | void publish_callback(void** unused, struct mqtt_response_publish *published) 153 | { 154 | /* not used in this example */ 155 | } 156 | 157 | void client_refresher(void* client) 158 | { 159 | while(1) 160 | { 161 | mqtt_sync((struct mqtt_client*) client); 162 | Sleep(100); 163 | } 164 | } -------------------------------------------------------------------------------- /examples/reconnect_subscriber.c: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file 4 | * A simple subscriber program that performs automatic reconnections. 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include "templates/posix_sockets.h" 13 | 14 | /** 15 | * @brief A structure that I will use to keep track of some data needed 16 | * to setup the connection to the broker. 17 | * 18 | * An instance of this struct will be created in my \c main(). Then, whenever 19 | * \ref reconnect_client is called, this instance will be passed. 20 | */ 21 | struct reconnect_state_t { 22 | const char* hostname; 23 | const char* port; 24 | const char* topic; 25 | uint8_t* sendbuf; 26 | size_t sendbufsz; 27 | uint8_t* recvbuf; 28 | size_t recvbufsz; 29 | }; 30 | 31 | 32 | /** 33 | * @brief My reconnect callback. It will reestablish the connection whenever 34 | * an error occurs. 35 | */ 36 | void reconnect_client(struct mqtt_client* client, void **reconnect_state_vptr); 37 | 38 | /** 39 | * @brief The function will be called whenever a PUBLISH message is received. 40 | */ 41 | void publish_callback(void** unused, struct mqtt_response_publish *published); 42 | 43 | /** 44 | * @brief The client's refresher. This function triggers back-end routines to 45 | * handle ingress/egress traffic to the broker. 46 | * 47 | * @note All this function needs to do is call \ref __mqtt_recv and 48 | * \ref __mqtt_send every so often. I've picked 100 ms meaning that 49 | * client ingress/egress traffic will be handled every 100 ms. 50 | */ 51 | void* client_refresher(void* client); 52 | 53 | /** 54 | * @brief Safelty closes the \p sockfd and cancels the \p client_daemon before \c exit. 55 | */ 56 | void exit_example(int status, int sockfd, pthread_t *client_daemon); 57 | 58 | 59 | int main(int argc, const char *argv[]) 60 | { 61 | const char* addr; 62 | const char* port; 63 | const char* topic; 64 | 65 | /* get address (argv[1] if present) */ 66 | if (argc > 1) { 67 | addr = argv[1]; 68 | } else { 69 | addr = "test.mosquitto.org"; 70 | } 71 | 72 | /* get port number (argv[2] if present) */ 73 | if (argc > 2) { 74 | port = argv[2]; 75 | } else { 76 | port = "1883"; 77 | } 78 | 79 | /* get the topic name to publish */ 80 | if (argc > 3) { 81 | topic = argv[3]; 82 | } else { 83 | topic = "datetime"; 84 | } 85 | 86 | /* build the reconnect_state structure which will be passed to reconnect */ 87 | struct reconnect_state_t reconnect_state; 88 | reconnect_state.hostname = addr; 89 | reconnect_state.port = port; 90 | reconnect_state.topic = topic; 91 | uint8_t sendbuf[2048]; 92 | uint8_t recvbuf[1024]; 93 | reconnect_state.sendbuf = sendbuf; 94 | reconnect_state.sendbufsz = sizeof(sendbuf); 95 | reconnect_state.recvbuf = recvbuf; 96 | reconnect_state.recvbufsz = sizeof(recvbuf); 97 | 98 | /* setup a client */ 99 | struct mqtt_client client; 100 | 101 | mqtt_init_reconnect(&client, 102 | reconnect_client, &reconnect_state, 103 | publish_callback 104 | ); 105 | 106 | /* start a thread to refresh the client (handle egress and ingree client traffic) */ 107 | pthread_t client_daemon; 108 | if(pthread_create(&client_daemon, NULL, client_refresher, &client)) { 109 | fprintf(stderr, "Failed to start client daemon.\n"); 110 | exit_example(EXIT_FAILURE, -1, NULL); 111 | 112 | } 113 | 114 | /* start publishing the time */ 115 | printf("%s listening for '%s' messages.\n", argv[0], topic); 116 | printf("Press ENTER to inject an error.\n"); 117 | printf("Press CTRL-D to exit.\n\n"); 118 | 119 | /* block */ 120 | while(fgetc(stdin) != EOF) { 121 | printf("Injecting error: \"MQTT_ERROR_SOCKET_ERROR\"\n"); 122 | client.error = MQTT_ERROR_SOCKET_ERROR; 123 | } 124 | 125 | /* disconnect */ 126 | printf("\n%s disconnecting from %s\n", argv[0], addr); 127 | sleep(1); 128 | 129 | /* exit */ 130 | exit_example(EXIT_SUCCESS, client.socketfd, &client_daemon); 131 | } 132 | 133 | void reconnect_client(struct mqtt_client* client, void **reconnect_state_vptr) 134 | { 135 | struct reconnect_state_t *reconnect_state = *((struct reconnect_state_t**) reconnect_state_vptr); 136 | 137 | /* Close the clients socket if this isn't the initial reconnect call */ 138 | if (client->error != MQTT_ERROR_INITIAL_RECONNECT) { 139 | close(client->socketfd); 140 | } 141 | 142 | /* Perform error handling here. */ 143 | if (client->error != MQTT_ERROR_INITIAL_RECONNECT) { 144 | printf("reconnect_client: called while client was in error state \"%s\"\n", 145 | mqtt_error_str(client->error) 146 | ); 147 | } 148 | 149 | /* Open a new socket. */ 150 | int sockfd = open_nb_socket(reconnect_state->hostname, reconnect_state->port); 151 | if (sockfd == -1) { 152 | perror("Failed to open socket: "); 153 | exit_example(EXIT_FAILURE, sockfd, NULL); 154 | } 155 | 156 | /* Reinitialize the client. */ 157 | mqtt_reinit(client, sockfd, 158 | reconnect_state->sendbuf, reconnect_state->sendbufsz, 159 | reconnect_state->recvbuf, reconnect_state->recvbufsz 160 | ); 161 | 162 | /* Create an anonymous session */ 163 | const char* client_id = NULL; 164 | /* Ensure we have a clean session */ 165 | uint8_t connect_flags = MQTT_CONNECT_CLEAN_SESSION; 166 | /* Send connection request to the broker. */ 167 | mqtt_connect(client, client_id, NULL, NULL, 0, NULL, NULL, connect_flags, 400); 168 | 169 | /* Subscribe to the topic. */ 170 | mqtt_subscribe(client, reconnect_state->topic, 0); 171 | } 172 | 173 | void exit_example(int status, int sockfd, pthread_t *client_daemon) 174 | { 175 | if (sockfd != -1) close(sockfd); 176 | if (client_daemon != NULL) pthread_cancel(*client_daemon); 177 | exit(status); 178 | } 179 | 180 | void publish_callback(void** unused, struct mqtt_response_publish *published) 181 | { 182 | /* note that published->topic_name is NOT null-terminated (here we'll change it to a c-string) */ 183 | char* topic_name = (char*) malloc(published->topic_name_size + 1); 184 | memcpy(topic_name, published->topic_name, published->topic_name_size); 185 | topic_name[published->topic_name_size] = '\0'; 186 | 187 | printf("Received publish('%s'): %s\n", topic_name, (const char*) published->application_message); 188 | 189 | free(topic_name); 190 | } 191 | 192 | void* client_refresher(void* client) 193 | { 194 | while(1) 195 | { 196 | mqtt_sync((struct mqtt_client*) client); 197 | usleep(100000U); 198 | } 199 | return NULL; 200 | } 201 | -------------------------------------------------------------------------------- /examples/simple_publisher.c: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file 4 | * A simple program to that publishes the current time whenever ENTER is pressed. 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include "templates/posix_sockets.h" 13 | 14 | 15 | /** 16 | * @brief The function that would be called whenever a PUBLISH is received. 17 | * 18 | * @note This function is not used in this example. 19 | */ 20 | void publish_callback(void** unused, struct mqtt_response_publish *published); 21 | 22 | /** 23 | * @brief The client's refresher. This function triggers back-end routines to 24 | * handle ingress/egress traffic to the broker. 25 | * 26 | * @note All this function needs to do is call \ref __mqtt_recv and 27 | * \ref __mqtt_send every so often. I've picked 100 ms meaning that 28 | * client ingress/egress traffic will be handled every 100 ms. 29 | */ 30 | void* client_refresher(void* client); 31 | 32 | /** 33 | * @brief Safelty closes the \p sockfd and cancels the \p client_daemon before \c exit. 34 | */ 35 | void exit_example(int status, int sockfd, pthread_t *client_daemon); 36 | 37 | /** 38 | * A simple program to that publishes the current time whenever ENTER is pressed. 39 | */ 40 | int main(int argc, const char *argv[]) 41 | { 42 | const char* addr; 43 | const char* port; 44 | const char* topic; 45 | 46 | /* get address (argv[1] if present) */ 47 | if (argc > 1) { 48 | addr = argv[1]; 49 | } else { 50 | addr = "test.mosquitto.org"; 51 | } 52 | 53 | /* get port number (argv[2] if present) */ 54 | if (argc > 2) { 55 | port = argv[2]; 56 | } else { 57 | port = "1883"; 58 | } 59 | 60 | /* get the topic name to publish */ 61 | if (argc > 3) { 62 | topic = argv[3]; 63 | } else { 64 | topic = "datetime"; 65 | } 66 | 67 | /* open the non-blocking TCP socket (connecting to the broker) */ 68 | int sockfd = open_nb_socket(addr, port); 69 | 70 | if (sockfd == -1) { 71 | perror("Failed to open socket: "); 72 | exit_example(EXIT_FAILURE, sockfd, NULL); 73 | } 74 | 75 | /* setup a client */ 76 | struct mqtt_client client; 77 | uint8_t sendbuf[2048]; /* sendbuf should be large enough to hold multiple whole mqtt messages */ 78 | uint8_t recvbuf[1024]; /* recvbuf should be large enough any whole mqtt message expected to be received */ 79 | mqtt_init(&client, sockfd, sendbuf, sizeof(sendbuf), recvbuf, sizeof(recvbuf), publish_callback); 80 | /* Create an anonymous session */ 81 | const char* client_id = NULL; 82 | /* Ensure we have a clean session */ 83 | uint8_t connect_flags = MQTT_CONNECT_CLEAN_SESSION; 84 | /* Send connection request to the broker. */ 85 | mqtt_connect(&client, client_id, NULL, NULL, 0, NULL, NULL, connect_flags, 400); 86 | 87 | /* check that we don't have any errors */ 88 | if (client.error != MQTT_OK) { 89 | fprintf(stderr, "error: %s\n", mqtt_error_str(client.error)); 90 | exit_example(EXIT_FAILURE, sockfd, NULL); 91 | } 92 | 93 | /* start a thread to refresh the client (handle egress and ingree client traffic) */ 94 | pthread_t client_daemon; 95 | if(pthread_create(&client_daemon, NULL, client_refresher, &client)) { 96 | fprintf(stderr, "Failed to start client daemon.\n"); 97 | exit_example(EXIT_FAILURE, sockfd, NULL); 98 | 99 | } 100 | 101 | /* start publishing the time */ 102 | printf("%s is ready to begin publishing the time.\n", argv[0]); 103 | printf("Press ENTER to publish the current time.\n"); 104 | printf("Press CTRL-D (or any other key) to exit.\n\n"); 105 | while(fgetc(stdin) == '\n') { 106 | /* get the current time */ 107 | time_t timer; 108 | time(&timer); 109 | struct tm* tm_info = localtime(&timer); 110 | char timebuf[26]; 111 | strftime(timebuf, 26, "%Y-%m-%d %H:%M:%S", tm_info); 112 | 113 | /* print a message */ 114 | char application_message[256]; 115 | snprintf(application_message, sizeof(application_message), "The time is %s", timebuf); 116 | printf("%s published : \"%s\"", argv[0], application_message); 117 | 118 | /* publish the time */ 119 | mqtt_publish(&client, topic, application_message, strlen(application_message) + 1, MQTT_PUBLISH_QOS_0); 120 | 121 | /* check for errors */ 122 | if (client.error != MQTT_OK) { 123 | fprintf(stderr, "error: %s\n", mqtt_error_str(client.error)); 124 | exit_example(EXIT_FAILURE, sockfd, &client_daemon); 125 | } 126 | } 127 | 128 | /* disconnect */ 129 | printf("\n%s disconnecting from %s\n", argv[0], addr); 130 | sleep(1); 131 | 132 | /* exit */ 133 | exit_example(EXIT_SUCCESS, sockfd, &client_daemon); 134 | } 135 | 136 | void exit_example(int status, int sockfd, pthread_t *client_daemon) 137 | { 138 | if (sockfd != -1) close(sockfd); 139 | if (client_daemon != NULL) pthread_cancel(*client_daemon); 140 | exit(status); 141 | } 142 | 143 | 144 | 145 | void publish_callback(void** unused, struct mqtt_response_publish *published) 146 | { 147 | /* not used in this example */ 148 | } 149 | 150 | void* client_refresher(void* client) 151 | { 152 | while(1) 153 | { 154 | mqtt_sync((struct mqtt_client*) client); 155 | usleep(100000U); 156 | } 157 | return NULL; 158 | } 159 | -------------------------------------------------------------------------------- /examples/simple_subscriber.c: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file 4 | * A simple program that subscribes to a topic. 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include "templates/posix_sockets.h" 13 | 14 | 15 | /** 16 | * @brief The function will be called whenever a PUBLISH message is received. 17 | */ 18 | void publish_callback(void** unused, struct mqtt_response_publish *published); 19 | 20 | /** 21 | * @brief The client's refresher. This function triggers back-end routines to 22 | * handle ingress/egress traffic to the broker. 23 | * 24 | * @note All this function needs to do is call \ref __mqtt_recv and 25 | * \ref __mqtt_send every so often. I've picked 100 ms meaning that 26 | * client ingress/egress traffic will be handled every 100 ms. 27 | */ 28 | void* client_refresher(void* client); 29 | 30 | /** 31 | * @brief Safelty closes the \p sockfd and cancels the \p client_daemon before \c exit. 32 | */ 33 | void exit_example(int status, int sockfd, pthread_t *client_daemon); 34 | 35 | int main(int argc, const char *argv[]) 36 | { 37 | const char* addr; 38 | const char* port; 39 | const char* topic; 40 | 41 | /* get address (argv[1] if present) */ 42 | if (argc > 1) { 43 | addr = argv[1]; 44 | } else { 45 | addr = "test.mosquitto.org"; 46 | } 47 | 48 | /* get port number (argv[2] if present) */ 49 | if (argc > 2) { 50 | port = argv[2]; 51 | } else { 52 | port = "1883"; 53 | } 54 | 55 | /* get the topic name to publish */ 56 | if (argc > 3) { 57 | topic = argv[3]; 58 | } else { 59 | topic = "datetime"; 60 | } 61 | 62 | /* open the non-blocking TCP socket (connecting to the broker) */ 63 | int sockfd = open_nb_socket(addr, port); 64 | 65 | if (sockfd == -1) { 66 | perror("Failed to open socket: "); 67 | exit_example(EXIT_FAILURE, sockfd, NULL); 68 | } 69 | 70 | /* setup a client */ 71 | struct mqtt_client client; 72 | uint8_t sendbuf[2048]; /* sendbuf should be large enough to hold multiple whole mqtt messages */ 73 | uint8_t recvbuf[1024]; /* recvbuf should be large enough any whole mqtt message expected to be received */ 74 | mqtt_init(&client, sockfd, sendbuf, sizeof(sendbuf), recvbuf, sizeof(recvbuf), publish_callback); 75 | /* Create an anonymous session */ 76 | const char* client_id = NULL; 77 | /* Ensure we have a clean session */ 78 | uint8_t connect_flags = MQTT_CONNECT_CLEAN_SESSION; 79 | /* Send connection request to the broker. */ 80 | mqtt_connect(&client, client_id, NULL, NULL, 0, NULL, NULL, connect_flags, 400); 81 | 82 | /* check that we don't have any errors */ 83 | if (client.error != MQTT_OK) { 84 | fprintf(stderr, "error: %s\n", mqtt_error_str(client.error)); 85 | exit_example(EXIT_FAILURE, sockfd, NULL); 86 | } 87 | 88 | /* start a thread to refresh the client (handle egress and ingree client traffic) */ 89 | pthread_t client_daemon; 90 | if(pthread_create(&client_daemon, NULL, client_refresher, &client)) { 91 | fprintf(stderr, "Failed to start client daemon.\n"); 92 | exit_example(EXIT_FAILURE, sockfd, NULL); 93 | 94 | } 95 | 96 | /* subscribe */ 97 | mqtt_subscribe(&client, topic, 0); 98 | 99 | /* start publishing the time */ 100 | printf("%s listening for '%s' messages.\n", argv[0], topic); 101 | printf("Press CTRL-D to exit.\n\n"); 102 | 103 | /* block */ 104 | while(fgetc(stdin) != EOF); 105 | 106 | /* disconnect */ 107 | printf("\n%s disconnecting from %s\n", argv[0], addr); 108 | sleep(1); 109 | 110 | /* exit */ 111 | exit_example(EXIT_SUCCESS, sockfd, &client_daemon); 112 | } 113 | 114 | void exit_example(int status, int sockfd, pthread_t *client_daemon) 115 | { 116 | if (sockfd != -1) close(sockfd); 117 | if (client_daemon != NULL) pthread_cancel(*client_daemon); 118 | exit(status); 119 | } 120 | 121 | 122 | 123 | void publish_callback(void** unused, struct mqtt_response_publish *published) 124 | { 125 | /* note that published->topic_name is NOT null-terminated (here we'll change it to a c-string) */ 126 | char* topic_name = (char*) malloc(published->topic_name_size + 1); 127 | memcpy(topic_name, published->topic_name, published->topic_name_size); 128 | topic_name[published->topic_name_size] = '\0'; 129 | 130 | printf("Received publish('%s'): %s\n", topic_name, (const char*) published->application_message); 131 | 132 | free(topic_name); 133 | } 134 | 135 | void* client_refresher(void* client) 136 | { 137 | while(1) 138 | { 139 | mqtt_sync((struct mqtt_client*) client); 140 | usleep(100000U); 141 | } 142 | return NULL; 143 | } 144 | -------------------------------------------------------------------------------- /examples/templates/bearssl_sockets.h: -------------------------------------------------------------------------------- 1 | #if !defined(__BEARSSL_SOCKET_TEMPLATE_H__) 2 | #define __BEARSSL_SOCKET_TEMPLATE_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | //#include "mqtt_pal.h" 12 | 13 | /* 14 | * Low-level data read callback for the simplified SSL I/O API. 15 | */ 16 | static int sock_read(void *ctx, unsigned char *buf, size_t len) { 17 | ssize_t rlen; 18 | 19 | for (;;) { 20 | rlen = read(*(int *)ctx, buf, len); 21 | 22 | if (rlen < 0) { 23 | if (errno == EINTR) { 24 | continue; 25 | } 26 | else if (errno == EWOULDBLOCK || errno == EAGAIN) { 27 | rlen = 0; 28 | break; 29 | } 30 | else { 31 | break; 32 | } 33 | } 34 | else { 35 | break; 36 | } 37 | } 38 | 39 | return (int)rlen; 40 | } 41 | 42 | /* 43 | * Low-level data write callback for the simplified SSL I/O API. 44 | */ 45 | static int sock_write(void *ctx, const unsigned char *buf, size_t len) { 46 | ssize_t wlen; 47 | 48 | for (;;) { 49 | 50 | wlen = write(*(int *)ctx, buf, len); 51 | if (wlen <= 0 && errno == EINTR) { 52 | continue; 53 | } 54 | return (int)wlen; 55 | } 56 | } 57 | 58 | static int host_connect(const char *host, const char *port) { 59 | struct hostent *he; 60 | struct in_addr **addr_list; 61 | 62 | if (NULL == (he = gethostbyname(host))) 63 | { 64 | fprintf(stderr, "Failed to resolve host name\n"); 65 | return -1; 66 | } 67 | 68 | addr_list = (struct in_addr **) he->h_addr_list; 69 | 70 | int sockfd = -1; 71 | int rv; 72 | int i; 73 | 74 | if (-1 == (sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP))) 75 | return -1; 76 | 77 | struct sockaddr_in server; 78 | 79 | server.sin_family = AF_INET; 80 | server.sin_port = htons(atoi(port)); 81 | 82 | /* open the first possible socket */ 83 | for (i = 0; addr_list[i] != NULL; i++) 84 | { 85 | memcpy(&server.sin_addr.s_addr, he->h_addr_list[0], he->h_length); 86 | 87 | if (0 > (rv = connect(sockfd, (struct sockaddr *)&server , sizeof(server)))) { 88 | continue; 89 | } 90 | else { 91 | int flags = fcntl(sockfd, F_GETFL, 0); 92 | flags |= O_NONBLOCK; 93 | fcntl(sockfd, F_SETFL, flags); 94 | break; 95 | } 96 | } 97 | 98 | if (addr_list[i] == NULL) 99 | sockfd = -1; 100 | 101 | /* return the new socket fd */ 102 | return sockfd; 103 | } 104 | 105 | int open_nb_socket(bearssl_context *ctx, 106 | const char *hostname, 107 | const char *port, 108 | unsigned char *bearssl_iobuf, 109 | size_t bearssl_iobuf_len) { 110 | 111 | /* initialize the BearSSL engine */ 112 | br_ssl_client_init_full(&ctx->sc, &ctx->xc, ctx->anchOut, ctx->ta_count); 113 | br_ssl_engine_set_buffer(&ctx->sc.eng, bearssl_iobuf, bearssl_iobuf_len, 1); 114 | br_ssl_client_reset(&ctx->sc, hostname, 0); 115 | 116 | if (-1 == (ctx->fd = host_connect(hostname, port))) 117 | return -1; 118 | 119 | ctx->low_read = sock_read; 120 | ctx->low_write = sock_write; 121 | 122 | return 0; 123 | } 124 | 125 | int close_socket(bearssl_context *ctx) { 126 | int rc; 127 | 128 | br_ssl_engine_close(&ctx->sc.eng); 129 | 130 | if (ctx->fd != 0) { 131 | shutdown(ctx->fd, SHUT_RDWR); 132 | rc = close(ctx->fd); 133 | ctx->fd = 0; 134 | } 135 | 136 | return rc; 137 | } 138 | 139 | #endif 140 | -------------------------------------------------------------------------------- /examples/templates/bio_sockets.h: -------------------------------------------------------------------------------- 1 | #if !defined(__BIO_SOCKET_TEMPLATE_H__) 2 | #define __BIO_SOCKET_TEMPLATE_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | /* 9 | A template for opening a non-blocking BIO socket. 10 | */ 11 | BIO* open_nb_socket(const char* addr, const char* port) { 12 | BIO* bio = BIO_new_connect(addr); 13 | BIO_set_nbio(bio, 1); 14 | BIO_set_conn_port(bio, port); 15 | 16 | /* timeout after 10 seconds */ 17 | int start_time = time(NULL); 18 | while(BIO_do_connect(bio) == 0 && (int)time(NULL) - start_time < 10); 19 | 20 | if (BIO_do_connect(bio) <= 0) { 21 | fprintf(stderr, "Failed to open socket: BIO_do_connect returned <= 0\n"); 22 | return NULL; 23 | } 24 | 25 | return bio; 26 | } 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /examples/templates/mbedtls_sockets.h: -------------------------------------------------------------------------------- 1 | #if !defined(__MBEDTLS_SOCKET_TEMPLATE_H__) 2 | #define __MBEDTLS_SOCKET_TEMPLATE_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #if !defined(MBEDTLS_NET_POLL_READ) 16 | /* compat for older mbedtls */ 17 | #define MBEDTLS_NET_POLL_READ 1 18 | #define MBEDTLS_NET_POLL_WRITE 1 19 | 20 | int 21 | mbedtls_net_poll(mbedtls_net_context * ctx, uint32_t rw, uint32_t timeout) 22 | { 23 | /* XXX this is not ideal but good enough for an example */ 24 | usleep(300); 25 | return 1; 26 | } 27 | #endif 28 | 29 | struct mbedtls_context { 30 | mbedtls_net_context net_ctx; 31 | mbedtls_ssl_context ssl_ctx; 32 | mbedtls_ssl_config ssl_conf; 33 | mbedtls_x509_crt ca_crt; 34 | mbedtls_entropy_context entropy; 35 | mbedtls_ctr_drbg_context ctr_drbg; 36 | }; 37 | 38 | void failed(const char *fn, int rv); 39 | void cert_verify_failed(uint32_t rv); 40 | void open_nb_socket(struct mbedtls_context *ctx, 41 | const char *hostname, 42 | const char *port, 43 | const char *ca_file); 44 | 45 | 46 | void failed(const char *fn, int rv) { 47 | char buf[100]; 48 | mbedtls_strerror(rv, buf, sizeof(buf)); 49 | printf("%s failed with %x (%s)\n", fn, -rv, buf); 50 | exit(1); 51 | } 52 | 53 | void cert_verify_failed(uint32_t rv) { 54 | char buf[512]; 55 | mbedtls_x509_crt_verify_info(buf, sizeof(buf), "\t", rv); 56 | printf("Certificate verification failed (%0" PRIx32 ")\n%s\n", rv, buf); 57 | exit(1); 58 | } 59 | 60 | /* 61 | A template for opening a non-blocking mbed TLS connection. 62 | */ 63 | void open_nb_socket(struct mbedtls_context *ctx, 64 | const char *hostname, 65 | const char *port, 66 | const char *ca_file) { 67 | const unsigned char *additional = (const unsigned char *)"MQTT-C"; 68 | size_t additional_len = 6; 69 | int rv; 70 | 71 | mbedtls_net_context *net_ctx = &ctx->net_ctx; 72 | mbedtls_ssl_context *ssl_ctx = &ctx->ssl_ctx; 73 | mbedtls_ssl_config *ssl_conf = &ctx->ssl_conf; 74 | mbedtls_x509_crt *ca_crt = &ctx->ca_crt; 75 | mbedtls_entropy_context *entropy = &ctx->entropy; 76 | mbedtls_ctr_drbg_context *ctr_drbg = &ctx->ctr_drbg; 77 | 78 | mbedtls_entropy_init(entropy); 79 | mbedtls_ctr_drbg_init(ctr_drbg); 80 | rv = mbedtls_ctr_drbg_seed(ctr_drbg, mbedtls_entropy_func, entropy, 81 | additional, additional_len); 82 | if (rv != 0) { 83 | failed("mbedtls_ctr_drbg_seed", rv); 84 | } 85 | 86 | mbedtls_x509_crt_init(ca_crt); 87 | rv = mbedtls_x509_crt_parse_file(ca_crt, ca_file); 88 | if (rv != 0) { 89 | failed("mbedtls_x509_crt_parse_file", rv); 90 | } 91 | 92 | mbedtls_ssl_config_init(ssl_conf); 93 | rv = mbedtls_ssl_config_defaults(ssl_conf, MBEDTLS_SSL_IS_CLIENT, 94 | MBEDTLS_SSL_TRANSPORT_STREAM, 95 | MBEDTLS_SSL_PRESET_DEFAULT); 96 | if (rv != 0) { 97 | failed("mbedtls_ssl_config_defaults", rv); 98 | } 99 | mbedtls_ssl_conf_ca_chain(ssl_conf, ca_crt, NULL); 100 | mbedtls_ssl_conf_authmode(ssl_conf, MBEDTLS_SSL_VERIFY_OPTIONAL); 101 | mbedtls_ssl_conf_rng(ssl_conf, mbedtls_ctr_drbg_random, ctr_drbg); 102 | 103 | mbedtls_net_init(net_ctx); 104 | rv = mbedtls_net_connect(net_ctx, hostname, port, MBEDTLS_NET_PROTO_TCP); 105 | if (rv != 0) { 106 | failed("mbedtls_net_connect", rv); 107 | } 108 | rv = mbedtls_net_set_nonblock(net_ctx); 109 | if (rv != 0) { 110 | failed("mbedtls_net_set_nonblock", rv); 111 | } 112 | 113 | mbedtls_ssl_init(ssl_ctx); 114 | rv = mbedtls_ssl_setup(ssl_ctx, ssl_conf); 115 | if (rv != 0) { 116 | failed("mbedtls_ssl_setup", rv); 117 | } 118 | rv = mbedtls_ssl_set_hostname(ssl_ctx, hostname); 119 | if (rv != 0) { 120 | failed("mbedtls_ssl_set_hostname", rv); 121 | } 122 | mbedtls_ssl_set_bio(ssl_ctx, net_ctx, 123 | mbedtls_net_send, mbedtls_net_recv, NULL); 124 | 125 | for (;;) { 126 | rv = mbedtls_ssl_handshake(ssl_ctx); 127 | uint32_t want = 0; 128 | if (rv == MBEDTLS_ERR_SSL_WANT_READ) { 129 | want |= MBEDTLS_NET_POLL_READ; 130 | } else if (rv == MBEDTLS_ERR_SSL_WANT_WRITE) { 131 | want |= MBEDTLS_NET_POLL_WRITE; 132 | } else { 133 | break; 134 | } 135 | rv = mbedtls_net_poll(net_ctx, want, (uint32_t)-1); 136 | if (rv < 0) { 137 | failed("mbedtls_net_poll", rv); 138 | } 139 | } 140 | if (rv != 0) { 141 | failed("mbedtls_ssl_handshake", rv); 142 | } 143 | uint32_t result = mbedtls_ssl_get_verify_result(ssl_ctx); 144 | if (result != 0) { 145 | if (result == (uint32_t)-1) { 146 | failed("mbedtls_ssl_get_verify_result", (int)result); 147 | } else { 148 | cert_verify_failed(result); 149 | } 150 | } 151 | } 152 | 153 | #endif 154 | -------------------------------------------------------------------------------- /examples/templates/openssl_sockets.h: -------------------------------------------------------------------------------- 1 | #if !defined(__OPENSSL_SOCKET_TEMPLATE_H__) 2 | #define __OPENSSL_SOCKET_TEMPLATE_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | /* 11 | A template for opening a non-blocking OpenSSL connection. 12 | */ 13 | void open_nb_socket(BIO** bio, 14 | SSL_CTX** ssl_ctx, 15 | const char* addr, 16 | const char* port, 17 | const char* ca_file, 18 | const char* ca_path, 19 | const char* cert_file, 20 | const char* key_file); 21 | 22 | void open_nb_socket(BIO** bio, 23 | SSL_CTX** ssl_ctx, 24 | const char* addr, 25 | const char* port, 26 | const char* ca_file, 27 | const char* ca_path, 28 | const char* cert_file, 29 | const char* key_file) 30 | { 31 | *ssl_ctx = SSL_CTX_new(SSLv23_client_method()); 32 | SSL* ssl; 33 | 34 | /* load certificate */ 35 | if (!SSL_CTX_load_verify_locations(*ssl_ctx, ca_file, ca_path)) { 36 | printf("error: failed to load ca certificate\n"); 37 | exit(1); 38 | } 39 | 40 | if (cert_file && key_file) 41 | { 42 | if (!SSL_CTX_use_certificate_file(*ssl_ctx, cert_file, SSL_FILETYPE_PEM)) 43 | { 44 | printf("error: failed to load client certificate\n"); 45 | exit(1); 46 | } 47 | 48 | if (!SSL_CTX_use_PrivateKey_file(*ssl_ctx, key_file, SSL_FILETYPE_PEM)) 49 | { 50 | printf("error: failed to load client key\n"); 51 | exit(1); 52 | } 53 | } 54 | 55 | /* open BIO socket */ 56 | char * addr_copy = (char*)malloc(strlen(addr) + 1); 57 | strcpy(addr_copy,addr); 58 | char * port_copy = (char*)malloc(strlen(port) + 1); 59 | strcpy(port_copy,port); 60 | 61 | *bio = BIO_new_ssl_connect(*ssl_ctx); 62 | BIO_get_ssl(*bio, &ssl); 63 | SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); 64 | BIO_set_conn_hostname(*bio, addr_copy); 65 | BIO_set_nbio(*bio, 1); 66 | BIO_set_conn_port(*bio, port_copy); 67 | 68 | free(addr_copy); 69 | free(port_copy); 70 | 71 | /* wait for connect with 10 second timeout */ 72 | int start_time = (int)time(NULL); 73 | int do_connect_rv = (int)BIO_do_connect(*bio); 74 | while(do_connect_rv <= 0 && BIO_should_retry(*bio) && (int)time(NULL) - start_time < 10) { 75 | do_connect_rv = (int)BIO_do_connect(*bio); 76 | } 77 | if (do_connect_rv <= 0) { 78 | printf("error: %s\n", ERR_reason_error_string(ERR_get_error())); 79 | BIO_free_all(*bio); 80 | SSL_CTX_free(*ssl_ctx); 81 | *bio = NULL; 82 | *ssl_ctx=NULL; 83 | return; 84 | } 85 | 86 | /* verify certificate */ 87 | if (SSL_get_verify_result(ssl) != X509_V_OK) { 88 | /* Handle the failed verification */ 89 | printf("error: x509 certificate verification failed\n"); 90 | exit(1); 91 | } 92 | } 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /examples/templates/posix_sockets.h: -------------------------------------------------------------------------------- 1 | #if !defined(__POSIX_SOCKET_TEMPLATE_H__) 2 | #define __POSIX_SOCKET_TEMPLATE_H__ 3 | 4 | #include 5 | #include 6 | #if !defined(WIN32) 7 | #include 8 | #include 9 | #else 10 | #include 11 | #endif 12 | #if defined(__VMS) 13 | #include 14 | #endif 15 | #include 16 | 17 | /* 18 | A template for opening a non-blocking POSIX socket. 19 | */ 20 | int open_nb_socket(const char* addr, const char* port); 21 | 22 | int open_nb_socket(const char* addr, const char* port) { 23 | struct addrinfo hints = {0}; 24 | 25 | hints.ai_family = AF_UNSPEC; /* IPv4 or IPv6 */ 26 | hints.ai_socktype = SOCK_STREAM; /* Must be TCP */ 27 | int sockfd = -1; 28 | int rv; 29 | struct addrinfo *p, *servinfo; 30 | 31 | /* get address information */ 32 | rv = getaddrinfo(addr, port, &hints, &servinfo); 33 | if(rv != 0) { 34 | fprintf(stderr, "Failed to open socket (getaddrinfo): %s\n", gai_strerror(rv)); 35 | return -1; 36 | } 37 | 38 | /* open the first possible socket */ 39 | for(p = servinfo; p != NULL; p = p->ai_next) { 40 | sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol); 41 | if (sockfd == -1) continue; 42 | 43 | /* connect to server */ 44 | rv = connect(sockfd, p->ai_addr, p->ai_addrlen); 45 | if(rv == -1) { 46 | close(sockfd); 47 | sockfd = -1; 48 | continue; 49 | } 50 | break; 51 | } 52 | 53 | /* free servinfo */ 54 | freeaddrinfo(servinfo); 55 | 56 | /* make non-blocking */ 57 | #if !defined(WIN32) 58 | if (sockfd != -1) fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK); 59 | #else 60 | if (sockfd != INVALID_SOCKET) { 61 | int iMode = 1; 62 | ioctlsocket(sockfd, FIONBIO, &iMode); 63 | } 64 | #endif 65 | #if defined(__VMS) 66 | /* 67 | OpenVMS only partially implements fcntl. It works on file descriptors 68 | but silently fails on socket descriptors. So we need to fall back on 69 | to the older ioctl system to set non-blocking IO 70 | */ 71 | int on = 1; 72 | if (sockfd != -1) ioctl(sockfd, FIONBIO, &on); 73 | #endif 74 | 75 | /* return the new socket fd */ 76 | return sockfd; 77 | } 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /include/mqtt_pal.h: -------------------------------------------------------------------------------- 1 | #if !defined(__MQTT_PAL_H__) 2 | #define __MQTT_PAL_H__ 3 | 4 | /* 5 | MIT License 6 | 7 | Copyright(c) 2018 Liam Bindle 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files(the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions : 15 | 16 | The above copyright notice and this permission notice shall be included in all 17 | copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | SOFTWARE. 26 | */ 27 | 28 | #if defined(__cplusplus) 29 | extern "C" { 30 | #endif 31 | 32 | /** 33 | * @file 34 | * @brief Includes/supports the types/calls required by the MQTT-C client. 35 | * 36 | * @note This is the \em only file included in mqtt.h, and mqtt.c. It is therefore 37 | * responsible for including/supporting all the required types and calls. 38 | * 39 | * @defgroup pal Platform abstraction layer 40 | * @brief Documentation of the types and calls required to port MQTT-C to a new platform. 41 | * 42 | * mqtt_pal.h is the \em only header file included in mqtt.c. Therefore, to port MQTT-C to a 43 | * new platform the following types, functions, constants, and macros must be defined in 44 | * mqtt_pal.h: 45 | * - Types: 46 | * - \c size_t, \c ssize_t 47 | * - \c uint8_t, \c uint16_t, \c uint32_t 48 | * - \c va_list 49 | * - \c mqtt_pal_time_t : return type of \c MQTT_PAL_TIME() 50 | * - \c mqtt_pal_mutex_t : type of the argument that is passed to \c MQTT_PAL_MUTEX_LOCK and 51 | * \c MQTT_PAL_MUTEX_RELEASE 52 | * - Functions: 53 | * - \c memcpy, \c strlen 54 | * - \c va_start, \c va_arg, \c va_end 55 | * - Constants: 56 | * - \c INT_MIN 57 | * 58 | * Additionally, three macro's are required: 59 | * - \c MQTT_PAL_HTONS(s) : host-to-network endian conversion for uint16_t. 60 | * - \c MQTT_PAL_NTOHS(s) : network-to-host endian conversion for uint16_t. 61 | * - \c MQTT_PAL_TIME() : returns [type: \c mqtt_pal_time_t] current time in seconds. 62 | * - \c MQTT_PAL_MUTEX_LOCK(mtx_pointer) : macro that locks the mutex pointed to by \c mtx_pointer. 63 | * - \c MQTT_PAL_MUTEX_RELEASE(mtx_pointer) : macro that unlocks the mutex pointed to by 64 | * \c mtx_pointer. 65 | * 66 | * Lastly, \ref mqtt_pal_sendall and \ref mqtt_pal_recvall, must be implemented in mqtt_pal.c 67 | * for sending and receiving data using the platforms socket calls. 68 | */ 69 | 70 | 71 | /* UNIX-like platform support */ 72 | #if defined(__unix__) || defined(__APPLE__) || defined(__NuttX__) 73 | #include 74 | #include 75 | #include 76 | #include 77 | #include 78 | #include 79 | 80 | #define MQTT_PAL_HTONS(s) htons(s) 81 | #define MQTT_PAL_NTOHS(s) ntohs(s) 82 | 83 | #define MQTT_PAL_TIME() time(NULL) 84 | 85 | typedef time_t mqtt_pal_time_t; 86 | typedef pthread_mutex_t mqtt_pal_mutex_t; 87 | 88 | #define MQTT_PAL_MUTEX_INIT(mtx_ptr) pthread_mutex_init(mtx_ptr, NULL) 89 | #define MQTT_PAL_MUTEX_LOCK(mtx_ptr) pthread_mutex_lock(mtx_ptr) 90 | #define MQTT_PAL_MUTEX_UNLOCK(mtx_ptr) pthread_mutex_unlock(mtx_ptr) 91 | 92 | #if !defined(MQTT_USE_CUSTOM_SOCKET_HANDLE) 93 | #if defined(MQTT_USE_MBEDTLS) 94 | struct mbedtls_ssl_context; 95 | typedef struct mbedtls_ssl_context *mqtt_pal_socket_handle; 96 | #elif defined(MQTT_USE_WOLFSSL) 97 | #include 98 | typedef WOLFSSL* mqtt_pal_socket_handle; 99 | #elif defined(MQTT_USE_BIO) 100 | #include 101 | typedef BIO* mqtt_pal_socket_handle; 102 | #elif defined(MQTT_USE_BEARSSL) 103 | #include 104 | 105 | typedef struct _bearssl_context { 106 | br_ssl_client_context sc; 107 | br_x509_minimal_context xc; 108 | br_sslio_context ioc; 109 | size_t ta_count; 110 | br_x509_trust_anchor *anchOut; 111 | int fd; 112 | int (*low_read)(void *read_context, unsigned char *buf, size_t len); 113 | int (*low_write)(void *write_context, const unsigned char *buf, size_t len); 114 | } bearssl_context; 115 | 116 | typedef bearssl_context* mqtt_pal_socket_handle; 117 | #else 118 | typedef int mqtt_pal_socket_handle; 119 | #endif 120 | #endif 121 | #elif defined(_MSC_VER) || defined(WIN32) 122 | #include 123 | #include 124 | #include 125 | #include 126 | #include 127 | 128 | typedef SSIZE_T ssize_t; 129 | #define MQTT_PAL_HTONS(s) htons(s) 130 | #define MQTT_PAL_NTOHS(s) ntohs(s) 131 | 132 | #define MQTT_PAL_TIME() time(NULL) 133 | 134 | typedef time_t mqtt_pal_time_t; 135 | typedef CRITICAL_SECTION mqtt_pal_mutex_t; 136 | 137 | #define MQTT_PAL_MUTEX_INIT(mtx_ptr) InitializeCriticalSection(mtx_ptr) 138 | #define MQTT_PAL_MUTEX_LOCK(mtx_ptr) EnterCriticalSection(mtx_ptr) 139 | #define MQTT_PAL_MUTEX_UNLOCK(mtx_ptr) LeaveCriticalSection(mtx_ptr) 140 | 141 | 142 | #if !defined(MQTT_USE_CUSTOM_SOCKET_HANDLE) 143 | #if defined(MQTT_USE_BIO) 144 | #include 145 | typedef BIO* mqtt_pal_socket_handle; 146 | #else 147 | typedef SOCKET mqtt_pal_socket_handle; 148 | #endif 149 | #endif 150 | 151 | #endif 152 | 153 | /** 154 | * @brief Sends all the bytes in a buffer. 155 | * @ingroup pal 156 | * 157 | * @param[in] fd The file-descriptor (or handle) of the socket. 158 | * @param[in] buf A pointer to the first byte in the buffer to send. 159 | * @param[in] len The number of bytes to send (starting at \p buf). 160 | * @param[in] flags Flags which are passed to the underlying socket. 161 | * 162 | * @returns The number of bytes sent if successful, an \ref MQTTErrors otherwise. 163 | * 164 | * Note about the error handling: 165 | * - On an error, if some bytes have been processed already, 166 | * this function should return the number of bytes successfully 167 | * processed. (partial success) 168 | * - Otherwise, if the error is an equivalent of EAGAIN, return 0. 169 | * - Otherwise, return MQTT_ERROR_SOCKET_ERROR. 170 | */ 171 | ssize_t mqtt_pal_sendall(mqtt_pal_socket_handle fd, const void* buf, size_t len, int flags); 172 | 173 | /** 174 | * @brief Non-blocking receive all the byte available. 175 | * @ingroup pal 176 | * 177 | * @param[in] fd The file-descriptor (or handle) of the socket. 178 | * @param[in] buf A pointer to the receive buffer. 179 | * @param[in] bufsz The max number of bytes that can be put into \p buf. 180 | * @param[in] flags Flags which are passed to the underlying socket. 181 | * 182 | * @returns The number of bytes received if successful, an \ref MQTTErrors otherwise. 183 | * 184 | * Note about the error handling: 185 | * - On an error, if some bytes have been processed already, 186 | * this function should return the number of bytes successfully 187 | * processed. (partial success) 188 | * - Otherwise, if the error is an equivalent of EAGAIN, return 0. 189 | * - Otherwise, return MQTT_ERROR_SOCKET_ERROR. 190 | */ 191 | ssize_t mqtt_pal_recvall(mqtt_pal_socket_handle fd, void* buf, size_t bufsz, int flags); 192 | 193 | #if defined(__cplusplus) 194 | } 195 | #endif 196 | 197 | 198 | #endif 199 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | UNAME = $(shell uname -o) 2 | 3 | CC = gcc 4 | CFLAGS = -Wextra -Wall -std=gnu99 -Iinclude -Wno-unused-parameter -Wno-unused-variable -Wno-duplicate-decl-specifier 5 | 6 | ifeq ($(UNAME), Msys) 7 | MSFLAGS = -lws2_32 8 | endif 9 | 10 | MQTT_C_SOURCES = src/mqtt.c src/mqtt_pal.c 11 | MQTT_C_EXAMPLES = bin/simple_publisher bin/simple_subscriber bin/reconnect_subscriber bin/bio_publisher bin/openssl_publisher 12 | MQTT_C_UNITTESTS = bin/tests 13 | BINDIR = bin 14 | 15 | all: $(BINDIR) $(MQTT_C_UNITTESTS) $(MQTT_C_EXAMPLES) 16 | 17 | bin/simple_%: examples/simple_%.c $(MQTT_C_SOURCES) 18 | $(CC) $(CFLAGS) $^ -lpthread $(MSFLAGS) -o $@ 19 | 20 | bin/reconnect_%: examples/reconnect_%.c $(MQTT_C_SOURCES) 21 | $(CC) $(CFLAGS) $^ -lpthread $(MSFLAGS) -o $@ 22 | 23 | bin/bio_%: examples/bio_%.c $(MQTT_C_SOURCES) 24 | $(CC) $(CFLAGS) `pkg-config --cflags openssl` -D MQTT_USE_BIO $^ -lpthread $(MSFLAGS) `pkg-config --libs openssl` -o $@ 25 | 26 | bin/openssl_%: examples/openssl_%.c $(MQTT_C_SOURCES) 27 | $(CC) $(CFLAGS) `pkg-config --cflags openssl` -D MQTT_USE_BIO $^ -lpthread $(MSFLAGS) `pkg-config --libs openssl` -o $@ 28 | 29 | $(BINDIR): 30 | mkdir -p $(BINDIR) 31 | 32 | $(MQTT_C_UNITTESTS): tests.c $(MQTT_C_SOURCES) 33 | $(CC) $(CFLAGS) $^ -lcmocka $(MSFLAGS) -o $@ 34 | 35 | clean: 36 | rm -rf $(BINDIR) 37 | 38 | check: all 39 | ./$(MQTT_C_UNITTESTS) 40 | --------------------------------------------------------------------------------