新增http、mqtt运行库,实现mqtt功能, 新增spdlog

This commit is contained in:
lixiaoyuan
2025-09-01 20:08:40 +08:00
parent e0b64a20c4
commit 94e467b65e
245 changed files with 54182 additions and 117 deletions

47
thirdparty/paho_mqtt/CODE_OF_CONDUCT.md vendored Normal file
View File

@@ -0,0 +1,47 @@
# Community Code of Conduct
**Version 1.2
August 19, 2020**
## Our Pledge
In the interest of fostering an open and welcoming environment, we as community members, contributors, committers, and project leaders pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
With the support of the Eclipse Foundation staff (the “Staff”), project committers and leaders are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project committers and leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies within all project spaces, and it also applies when an individual is representing the Eclipse Foundation project or its community in public spaces. Examples of representing a project or community include posting via an official social media account, or acting as a project representative at an online or offline event. Representation of a project may be further defined and clarified by project committers, leaders, or the EMO.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the Staff at codeofconduct@eclipse.org. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The Staff is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project committers or leaders who do not follow the Code of Conduct in good faith may face temporary or permanent repercussions as determined by the Staff.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org) , version 1.4, available at [https://www.contributor-covenant.org/version/1/4/code-of-conduct.html](https://www.contributor-covenant.org/version/1/4/code-of-conduct/)

63
thirdparty/paho_mqtt/CONTRIBUTING.md vendored Normal file
View File

@@ -0,0 +1,63 @@
# Contributing to Paho
Thanks for your interest in this project!
You can contribute bugfixes and new features by sending pull requests through GitHub.
## Legal
In order for your contribution to be accepted, it must comply with the Eclipse Foundation IP policy.
Please read the [Eclipse Foundation policy on accepting contributions via Git](http://wiki.eclipse.org/Development_Resources/Contributing_via_Git).
1. Sign the [Eclipse ECA](http://www.eclipse.org/legal/ECA.php)
1. Register for an Eclipse Foundation User ID. You can register [here](https://dev.eclipse.org/site_login/createaccount.php).
2. Log into the [Eclipse projects forge](https://www.eclipse.org/contribute/cla), and click on 'Eclipse Contributor Agreement'.
2. Go to your [account settings](https://dev.eclipse.org/site_login/myaccount.php#open_tab_accountsettings) and add your GitHub username to your account.
3. Make sure that you _sign-off_ your Git commits in the following format:
``` Signed-off-by: Alex Smith <alexsmith@nowhere.com> ``` This is usually at the bottom of the commit message. You can automate this by adding the '-s' flag when you make the commits. e.g. ```git commit -s -m "Adding a cool feature"```
4. Ensure that the email address that you make your commits with is the same one you used to sign up to the Eclipse Foundation website with.
## Contributing a change
1. [Fork the repository on GitHub](https://github.com/eclipse/paho.mqtt.c/fork)
2. Clone the forked repository onto your computer: ``` git clone https://github.com/<your username>/paho.mqtt.c.git ```
3. Create a new branch from the latest ```develop``` branch with ```git checkout -b YOUR_BRANCH_NAME origin/develop```
4. Make your changes
5. If developing a new feature, make sure to include JUnit tests.
6. Ensure that all new and existing tests pass.
7. Commit the changes into the branch: ``` git commit -s ``` Make sure that your commit message is meaningful and describes your changes correctly.
8. If you have a lot of commits for the change, squash them into a single / few commits.
9. Push the changes in your branch to your forked repository.
10. Finally, go to [https://github.com/eclipse/paho.mqtt.c](https://github.com/eclipse/paho.mqtt.c) and create a pull request from your "YOUR_BRANCH_NAME" branch to the ```develop``` one to request review and merge of the commits in your pushed branch.
What happens next depends on the content of the patch.
If it is 100% authored by the contributor with less than 1000 lines of new product code that meets
the needs of the project (refactored, test code and sample code is excluded from the count), then it
can be pulled into the main repository. When there are more than 1000 lines of new product code,
more steps are required. More details are provided in the [handbook](https://www.eclipse.org/projects/handbook/#ip).
## Developer resources:
Information regarding source code management, builds, coding standards, and more.
- [https://projects.eclipse.org/projects/iot.paho/developer](https://projects.eclipse.org/projects/iot.paho/developer)
Contact:
--------
Contact the project developers via the project's development
[mailing list](https://dev.eclipse.org/mailman/listinfo/paho-dev).
Search for bugs:
----------------
This project uses GitHub Issues here: [github.com/eclipse/paho.mqtt.c/issues](https://github.com/eclipse/paho.mqtt.c/issues) to track ongoing development and issues.
Create a new bug:
-----------------
Be sure to search for existing bugs before you create another one. Remember that contributions are always welcome!
- [Create new Paho bug](https://github.com/eclipse/paho.mqtt.c/issues/new)

View File

@@ -0,0 +1,13 @@
Thank you for your interest in this project managed by the Eclipse Foundation.
The guidelines for contributions can be found in the CONTRIBUTING.md file.
At a minimum, you must sign the Eclipse ECA, and sign off each commit.
To complete and submit a ECA, log into the Eclipse projects forge
You will need to create an account with the Eclipse Foundation if you have not already done so.
Be sure to use the same email address when you register for the account that you intend to use when you commit to Git.
Go to https://accounts.eclipse.org/user/eca to sign the Eclipse ECA.

358
thirdparty/paho_mqtt/README.md vendored Normal file
View File

@@ -0,0 +1,358 @@
[![Build Status](https://travis-ci.org/eclipse/paho.mqtt.c.svg?branch=master)](https://travis-ci.org/eclipse/paho.mqtt.c)
[![Total Alerts](https://img.shields.io/lgtm/alerts/g/eclipse/paho.mqtt.c.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/eclipse/paho.mqtt.c/alerts/)
[![Coverity Scan Build Status](https://scan.coverity.com/projects/2339/badge.svg)](https://scan.coverity.com/projects/paho-c)
# Eclipse Paho C Client Library for the MQTT Protocol
This repository contains the source code for the [Eclipse Paho](http://eclipse.org/paho) MQTT C client library.
This code builds libraries which enable applications to connect to an [MQTT](http://mqtt.org) broker to publish messages, and to subscribe to topics and receive published messages.
Synchronous and various asynchronous programming models are supported.
## Information About MQTT
* [MQTT website](http://mqtt.org)
* [The MQTT 3.1.1 standard](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html)
* [The MQTT 5.0 standard](https://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.html)
* [HiveMQ introduction to MQTT](https://www.hivemq.com/mqtt/)
* [OASIS Introduction to MQTT presentation](https://www.oasis-open.org/committees/download.php/49205/MQTT-OASIS-Webinar.pdf)
## Libraries
The Paho C client comprises four variant libraries, shared or static:
* paho-mqtt3a - asynchronous (MQTTAsync)
* paho-mqtt3as - asynchronous with SSL/TLS (MQTTAsync)
* paho-mqtt3c - "classic" / synchronous (MQTTClient)
* paho-mqtt3cs - "classic" / synchronous with SSL/TLS (MQTTClient)
[Which Paho C API to use, with some history, for context](https://modelbasedtesting.co.uk/2013/10/13/which-paho-mqtt-c-api-to-use-and-some-history/)
## Usage and API
Detailed API documentation [is available online](https://eclipse-paho.github.io/paho.mqtt.c/MQTTClient/html/). It is also available by building the Doxygen docs in the ``doc`` directory.
Samples are available in the Doxygen docs and also in `src/samples` for reference. These are:
- *paho_c_pub.c* and *paho_c_sub.c:* command line utilities to publish and subscribe, -h will give help
- *paho_cs_pub.c* and *paho_cs_sub.c:* command line utilities using MQTTClient to publish and subscribe
- *MQTTClient_publish.c, MQTTClient_subscribe.c* and *MQTTClient_publish_async.c:* MQTTClient simple code examples
- *MQTTAsync_publish.c* and *MQTTAsync_subscribe.c:* MQTTAsync simple code examples
Some potentially useful blog posts:
- [Paho client MQTT 5.0 support and command line utilities](https://modelbasedtesting.co.uk/2018/08/08/paho-c-client-mqtt-5-0-and-command-line-utilities/)
- [MQTT, QoS and persistence](https://modelbasedtesting.co.uk/2013/11/24/mqtt-qos-and-persistence/)
- [A story of MQTT 5.0](https://modelbasedtesting.co.uk/2018/04/09/a-story-of-mqtt-5-0/)
[Various MQTT and MQTT-SN talks I've given.](https://modelbasedtesting.co.uk/talks-ive-given/)
### Supported Network Protocols
The library supports connecting to an MQTT server using TCP, SSL/TLS, Unix-domain sockets, and websockets (secure and insecure). This is chosen by the client using the URI supplied in the connect options. It can be specified as:
"mqtt://<host>:<port>" - TCP, unsecure
"tcp://<host>:<port>" (same)
"mqtts://<host>:<port>" - SSL/TLS
"ssl://<host>:<port>" (same)
"unix:///path/to/socket - UNIX-domain socket (*nix systems only)
"ws://<host>:<port>[/path]" - Websockets, unsecure
"wss://<host>:<port>[/path]" - Websockets, secure
The "mqtt://" and "tcp://" schemas are identical. They indicate an insecure connection over TCP. The "mqtt://" variation is new for the library, but becoming more common across different MQTT libraries.
Similarly, the "mqtts://" and "ssl://" schemas are identical. They specify a secure connection over SSL/TLS sockets. The use any of the secure connect options requires that you compile the library with the `PAHO_WITH_SSL=TRUE` CMake option to include OpenSSL. In addition, you _must_ specify `ssl_options` when you connect to the broker - i.e. you must add an instance of `ssl_options` to the `connect_options` when calling `connect()`.
The use of Unix-domain sockets requires the build option of `PAHO_WITH_UNIX_SOCKETS=TRUE` is required. This is only available on *nix-style systems like Linux and macOS. It is not vailable on Windows.
## Runtime tracing
A number of environment variables control runtime tracing of the C library.
Tracing is switched on using `MQTT_C_CLIENT_TRACE` (a value of ON traces to stdout, any other value should specify a file to trace to).
The verbosity of the output is controlled using the `MQTT_C_CLIENT_TRACE_LEVEL` environment variable - valid values are ERROR, PROTOCOL, MINIMUM, MEDIUM and MAXIMUM (from least to most verbose).
The variable `MQTT_C_CLIENT_TRACE_MAX_LINES` limits the number of lines of trace that are output.
```
export MQTT_C_CLIENT_TRACE=ON
export MQTT_C_CLIENT_TRACE_LEVEL=PROTOCOL
```
## Reporting bugs
Please open issues in the Github project: https://github.com/eclipse-paho/paho.mqtt.c/issues.
## More information
Discussion of the Paho clients takes place on the [Eclipse paho-dev mailing list](https://dev.eclipse.org/mailman/listinfo/paho-dev).
## Follow Eclipse Paho on Twitter: [@eclipsepaho](https://twitter.com/eclipsepaho)
General questions about the MQTT protocol are discussed in the [MQTT Google Group](https://groups.google.com/forum/?hl=en-US&fromgroups#!forum/mqtt).
There is more information available via the [MQTT community site](http://mqtt.org).
## Building with CMake
The build process currently supports a number of Linux "flavors" including ARM and s390, OS X, AIX and Solaris as well as the Windows operating system. The build process requires the following tools:
* [CMake](http://cmake.org)
* [GNU Make](https://www.gnu.org/software/make/) or [Ninja](https://martine.github.io/ninja/)
* A conforming C compiler, such as [gcc](https://gcc.gnu.org/), [Clang](https://clang.llvm.org/), etc
On Debian based systems this would mean that the following packages have to be installed:
```
$ apt-get install build-essential gcc make cmake cmake-gui cmake-curses-gui
```
Also, in order to build a debian package from the source code, the following packages have to be installed
```
$ apt-get install fakeroot devscripts dh-make lsb-release
```
Ninja can be downloaded from its github project page in the "releases" section. Optionally it is possible to build binaries with SSL/TLS support. This requires the OpenSSL libraries and includes to be available. E. g. on Debian:
```
$ apt-get install libssl-dev
```
The documentation requires doxygen and optionally graphviz:
```
$ apt-get install doxygen graphviz
```
### Building your application with CMake
If the Paho C library was built with CMake and is already installed on the system, it is relatively easy to set up a CMake build for your application. (If it's not already built and installed read the next section).
The library can be built with several options which create variations of the library for asynchronous or synchronous use; encryption (SSL/TLS) support or not; and whether the library is shared or static. CMake exports all of the libraries that were built as targets, and the user can chose which is best suited for an application.
The package is named: **eclipse-paho-mqtt-c**
The namespace for all the targets is also: **eclipse-paho-mqtt-c**
The target names are the same as the library names. The static libraries append *-static* to the target name even for platforms that use the same base name for shared and static libraries. So:
Target|Description
------|-----------
paho-mqtt3a | asynchronous, no encryption
paho-mqtt3as | asynchronous with SSL/TLS support
paho-mqtt3c | synchronous, no encryption
paho-mqtt3cs | synchronous with SSL/TLS support
paho-mqtt3a-static | asynchronous, no encryption, static linkage
paho-mqtt3as-static | asynchronous with SSL/TLS support, static linkage
paho-mqtt3c-static | synchronous, no encryption, static linkage
paho-mqtt3cs-static | synchronous with SSL/TLS support, static linkage
Remember, though, that not all of these targets may be available. It depends on how the library was built.
A sample *CMakeLists.txt* for an application that uses the asynchronous library with encryption support *(paho-mqtt3as)* might look like this:
```
cmake_minimum_required(VERSION 3.5)
project(MyMQTTApp VERSION 1.0.0 LANGUAGES C)
find_package(eclipse-paho-mqtt-c REQUIRED)
add_executable(MyMQTTApp MyMQTTApp.c)
target_link_libraries(MQTTVersion eclipse-paho-mqtt-c::paho-mqtt3as)
```
If the library was installed to a non-traditional location, you may need to tell CMake where to find it using `CMAKE_PREFIX_PATH`. For example, if you installed it in */opt/mqtt/paho.mqtt.c*
```
$ cmake -DCMAKE_PREFIX_PATH=/opt/mqtt/paho.mqtt.c ..
```
### Building the Paho C library with CMake
Before compiling, determine the value of some variables in order to configure features, library locations, and other options:
Variable | Default Value | Description
------------ | ------------- | -------------
PAHO_BUILD_SHARED | TRUE | Build a shared version of the libraries
PAHO_BUILD_STATIC | FALSE | Build a static version of the libraries
PAHO_HIGH_PERFORMANCE | FALSE | When set to true, the debugging aids internal tracing and heap tracking are not included.
PAHO_WITH_SSL | FALSE | Flag that defines whether to build ssl-enabled binaries too.
OPENSSL_ROOT_DIR | "" (system default) | Directory containing your OpenSSL installation (i.e. `/usr/local` when headers are in `/usr/local/include` and libraries are in `/usr/local/lib`)
PAHO_WITH_LIBRESSL | FALSE | Flag that defines whether to build ssl-enabled binaries with LibreSSL instead of OpenSSL.
LIBRESSL_ROOT_DIR | "" (system default) | Directory containing your LibreSSL installation (i.e. `/usr/local` when headers are in `/usr/local/include` and libraries are in `/usr/local/lib`)
PAHO_WITH_UNIX_SOCKETS | FALSE | (*nix systems only) Flag to enable support for UNIX-domain sockets
PAHO_BUILD_DOCUMENTATION | FALSE | Create and install the HTML based API documentation (requires Doxygen)
PAHO_BUILD_SAMPLES | FALSE | Build sample programs
PAHO_ENABLE_TESTING | TRUE | Build test and run
MQTT_TEST_BROKER | tcp://localhost:1883 | MQTT connection URL for a broker to use during test execution
MQTT_TEST_PROXY | tcp://localhost:1883 | Hostname of the test proxy to use
MQTT_SSL_HOSTNAME | localhost | Hostname of a test SSL MQTT broker to use
PAHO_BUILD_DEB_PACKAGE | FALSE | Build debian package
Using these variables CMake can be used to generate your Ninja or Make files. Using CMake, building out-of-source is the default. Therefore it is recommended to invoke all build commands inside your chosen build directory but outside of the source tree.
An example build session targeting the build platform could look like this:
```
$ mkdir /tmp/build.paho ; cd /tmp/build.paho
$ cmake -DPAHO_WITH_SSL=TRUE -DPAHO_BUILD_DOCUMENTATION=TRUE \
-DPAHO_BUILD_SAMPLES=TRUE ~/paho.mqtt.c
```
Invoking cmake and specifying build options can also be performed using cmake-gui or ccmake (see https://cmake.org/runningcmake/). For example:
```
$ ccmake ~/paho.mqtt.c
```
To compile/link the binaries, to install, or to generate packages, use these commands:
```
$ cmake --build .
$ cmake --build . --target install
$ cmake --build . --target package
```
To build, install, or generate packages, you can also use the generated builder like _ninja_ or _make_ directly after invoking the initial CMake configuration step, such as `ninja package` or `make -j <number-of-jpbs> package`.
### Debug builds
Debug builds can be performed by defining the value of the `CMAKE_BUILD_TYPE` option to `Debug`. For example:
```
$ cmake -DCMAKE_BUILD_TYPE=Debug ~/paho.mqtt.c
```
### Running the tests
Test code is available in the `test` directory. The tests can be built and executed with the CMake build system. The test execution requires a MQTT broker running. By default, the build system uses `localhost`, however it is possible to configure the build to use an external broker. These parameters are documented in the Build Requirements section above.
After ensuring a MQTT broker is available, it is possible to execute the tests by starting the proxy and running `ctest` as described below:
```
$ python ../test/mqttsas.py &
$ ctest -VV
```
### Cross compilation
Cross compilation using CMake is performed by using so called "toolchain files" (see: https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html).
The path to the toolchain file can be specified by using CMake's `-DCMAKE_TOOLCHAIN_FILE` option. In case no toolchain file is specified, the build is performed for the native build platform.
For your convenience toolchain files for the following platforms can be found in the `cmake` directory of Eclipse Paho:
* Linux x86
* Linux ARM11 (a.k.a. the Raspberry Pi)
* Windows x86_64
* Windows x86
The provided toolchain files assume that required compilers/linkers are to be found in the environment, i. e. the PATH-Variable of your user or system. If you prefer, you can also specify the absolute location of your compilers in the toolchain files.
Example invocation for the Raspberry Pi:
```
$ cmake -GNinja -DPAHO_WITH_SSL=TRUE -DPAHO_BUILD_SAMPLES=TRUE \
-DPAHO_BUILD_DOCUMENTATION=TRUE \
-DOPENSSL_LIB_SEARCH_PATH=/tmp/libssl-dev/usr/lib/arm-linux-gnueabihf \
-DOPENSSL_INC_SEARCH_PATH="/tmp/libssl-dev/usr/include/openssl;/tmp/libssl-dev/usr/include/arm-linux-gnueabihf" \
-DCMAKE_TOOLCHAIN_FILE=~/paho.mqtt.c/cmake/toolchain.linux-arm11.cmake \
~/paho.mqtt.c
```
Compilers for the Raspberry Pi and other ARM targets can be obtained from ARM (https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/downloads)
This example assumes that OpenSSL-libraries and includes have been installed in the `/tmp/libssl-dev` directory.
Example invocation for Windows 64 bit:
```
$ cmake -DPAHO_BUILD_SAMPLES=TRUE \
-DCMAKE_TOOLCHAIN_FILE=~/paho.mqtt.c/cmake/toolchain.win64.cmake \
~/paho.mqtt.c
```
In this case the libraries and executable are not linked against OpenSSL Libraries. Cross compilers for the Windows platform can be installed on Debian like systems like this:
```
$ apt-get install gcc-mingw-w64-x86-64 gcc-mingw-w64-i686
```
## Build instructions for GNU Make
Ensure the OpenSSL development package is installed. Then from the client library base directory run:
```
$ make
$ sudo make install
```
This will build and install the libraries. To uninstall:
```
$ sudo make uninstall
```
To build the documentation requires doxygen and optionally graphviz.
```
$ make html
```
The provided GNU Makefile is intended to perform all build steps in the ```build``` directory within the source-tree of Eclipse Paho. Generated binares, libraries, and the documentation can be found in the ```build/output``` directory after completion.
Options that are passed to the compiler/linker can be specified by typical Unix build variables:
Variable | Description
------------ | -------------
CC | Path to the C compiler
CFLAGS | Flags passed to compiler calls
LDFLAGS | Flags passed to linker calls
## Building paho-mqtt - Using vcpkg
You can download and install paho-mqtt using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install paho-mqtt
The paho-mqtt port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
## Fully static builds with musl libc
(By Frank Pagliughi)
[musl libc](https://musl.libc.org/) is is an implementation of the C standard library built on top of the Linux system call API, including interfaces defined in the base language standard, POSIX, and widely agreed-upon extensions.
Users of the Rust library, which wraps this one, had been complaining that they could not compile using the musl build tools. Musl is a small std C lib that can be statically linked. With the latest Paho C library (and a very minor tweak to the build), we're now able to build Rust apps using musl and Paho C that are fully static; no runtime dependencies on the platform; not even on the standard C lib.
$ ./async_publish
Publishing a message on the 'test' topic
$ ldd async_publish
not a dynamic executable
So, for example, if maintaining a suite of apps for some newer and older embedded Linux boards, the same executables could be deployed without worry about the C ABI on the particular boards.
Certainly C apps using the Paho library could do this also.
## Microsoft Windows
### Calling convention
As is normal for C programs on Windows, the calling convention is __cdecl. See the Microsoft documentation here:
https://docs.microsoft.com/en-us/cpp/cpp/cdecl?view=vs-2019
If you call this library from another language, you may need to take this into account.

16
thirdparty/paho_mqtt/SECURITY.md vendored Normal file
View File

@@ -0,0 +1,16 @@
# Security Policy
This project follows the [Eclipse Vulnerability Reporting Policy](https://www.eclipse.org/security/policy.php).
Vulnerabilities are tracked by the Eclipse security team, in cooperation with the project lead.
Fixing vulnerabilities is taken care of by the project committers, with assistance and guidance of the security
team.
## Supported Versions
Eclipse Paho provides security updates for the most recent version only.
## Reporting a Vulnerability
We recommend that in case of suspected vulnerabilities you do not create a GitHub issue, but instead contact the
Eclipse Security Team directly sending an email to security@eclipse.org.

28
thirdparty/paho_mqtt/about.html vendored Normal file
View File

@@ -0,0 +1,28 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>About</title>
</head>
<body lang="EN-US">
<h2>About This Content</h2>
<p><em>April 6, 2020</em></p>
<h3>License</h3>
<p>The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise
indicated below, the Content is provided to you under the terms and conditions of the
Eclipse Public License Version 2.0 ("EPL") and Eclipse Distribution License Version 1.0 ("EDL").
A copy of the EPL is available at
<a href="https://www.eclipse.org/legal/epl-2.0/">https://www.eclipse.org/legal/epl-2.0/</a>
and a copy of the EDL is available at
<a href="http://www.eclipse.org/org/documents/edl-v10.php">http://www.eclipse.org/org/documents/edl-v10.php</a>.
For purposes of the EPL, "Program" will mean the Content.</p>
<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
being redistributed by another party ("Redistributor") and different terms and conditions may
apply to your use of any object code in the Content. Check the Redistributor's license that was
provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
indicated below, the terms and conditions of the EPL still apply to any source code in the Content
and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
</body></html>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
thirdparty/paho_mqtt/bin/MQTTVersion.exe vendored Normal file

Binary file not shown.

BIN
thirdparty/paho_mqtt/bin/paho_c_pub.exe vendored Normal file

Binary file not shown.

BIN
thirdparty/paho_mqtt/bin/paho_c_sub.exe vendored Normal file

Binary file not shown.

BIN
thirdparty/paho_mqtt/bin/paho_cs_pub.exe vendored Normal file

Binary file not shown.

BIN
thirdparty/paho_mqtt/bin/paho_cs_sub.exe vendored Normal file

Binary file not shown.

15
thirdparty/paho_mqtt/edl-v10 vendored Normal file
View File

@@ -0,0 +1,15 @@
Eclipse Distribution License - v 1.0
Copyright (c) 2007, Eclipse Foundation, Inc. and its licensors.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of the Eclipse Foundation, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

2404
thirdparty/paho_mqtt/include/MQTTAsync.h vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,188 @@
/*******************************************************************************
* Copyright (c) 2009, 2024 IBM Corp. and others
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* https://www.eclipse.org/legal/epl-2.0/
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial implementation and documentation
*******************************************************************************/
#if !defined(MQTTASYNCUTILS_H_)
#define MQTTASYNCUTILS_H_
#include "MQTTPacket.h"
#include "Thread.h"
#define URI_TCP "tcp://"
#define URI_MQTT "mqtt://"
#define URI_WS "ws://"
#define URI_WSS "wss://"
#define URI_UNIX "unix://"
enum MQTTAsync_threadStates
{
STOPPED, STARTING, RUNNING, STOPPING
};
typedef struct
{
MQTTAsync_message* msg;
char* topicName;
int topicLen;
unsigned int seqno; /* only used on restore */
} qEntry;
typedef struct
{
int type;
MQTTAsync_onSuccess* onSuccess;
MQTTAsync_onFailure* onFailure;
MQTTAsync_onSuccess5* onSuccess5;
MQTTAsync_onFailure5* onFailure5;
MQTTAsync_token token;
void* context;
START_TIME_TYPE start_time;
MQTTProperties properties;
union
{
struct
{
int count;
char** topics;
int* qoss;
MQTTSubscribe_options opts;
MQTTSubscribe_options* optlist;
} sub;
struct
{
int count;
char** topics;
} unsub;
struct
{
char* destinationName;
int payloadlen;
void* payload;
int qos;
int retained;
} pub;
struct
{
int internal;
int timeout;
enum MQTTReasonCodes reasonCode;
} dis;
struct
{
int currentURI;
int MQTTVersion; /**< current MQTT version being used to connect */
} conn;
} details;
} MQTTAsync_command;
typedef struct MQTTAsync_struct
{
char* serverURI;
int unixsock;
int ssl;
int websocket;
Clients* c;
/* "Global", to the client, callback definitions */
MQTTAsync_connectionLost* cl;
MQTTAsync_messageArrived* ma;
MQTTAsync_deliveryComplete* dc;
void* clContext; /* the context to be associated with the conn lost callback*/
void* maContext; /* the context to be associated with the msg arrived callback*/
void* dcContext; /* the context to be associated with the deliv complete callback*/
MQTTAsync_connected* connected;
void* connected_context; /* the context to be associated with the connected callback*/
MQTTAsync_disconnected* disconnected;
void* disconnected_context; /* the context to be associated with the disconnected callback*/
MQTTAsync_updateConnectOptions* updateConnectOptions;
void* updateConnectOptions_context;
/* Each time connect is called, we store the options that were used. These are reused in
any call to reconnect, or an automatic reconnect attempt */
MQTTAsync_command connect; /* Connect operation properties */
MQTTAsync_command disconnect; /* Disconnect operation properties */
MQTTAsync_command* pending_write; /* Is there a socket write pending? */
List* responses;
unsigned int command_seqno;
MQTTPacket* pack;
/* added for offline buffering */
MQTTAsync_createOptions* createOptions;
int shouldBeConnected;
int noBufferedMessages; /* the current number of buffered (publish) messages for this client */
/* added for automatic reconnect */
int automaticReconnect;
int minRetryInterval;
int maxRetryInterval;
int serverURIcount;
char** serverURIs;
int connectTimeout;
int currentInterval;
int currentIntervalBase;
START_TIME_TYPE lastConnectionFailedTime;
int retrying;
int reconnectNow;
/* MQTT V5 properties */
MQTTProperties* connectProps;
MQTTProperties* willProps;
} MQTTAsyncs;
typedef struct
{
MQTTAsync_command command;
MQTTAsyncs* client;
unsigned int seqno; /* only used on restore */
int not_restored;
char* key; /* if not_restored, this holds the key */
} MQTTAsync_queuedCommand;
void MQTTAsync_lock_mutex(mutex_type amutex);
void MQTTAsync_unlock_mutex(mutex_type amutex);
void MQTTAsync_terminate(void);
#if !defined(NO_PERSISTENCE)
int MQTTAsync_restoreCommands(MQTTAsyncs* client);
#endif
int MQTTAsync_addCommand(MQTTAsync_queuedCommand* command, int command_size);
void MQTTAsync_emptyMessageQueue(Clients* client);
void MQTTAsync_freeResponses(MQTTAsyncs* m);
void MQTTAsync_freeCommands(MQTTAsyncs* m);
int MQTTAsync_unpersistCommandsAndMessages(Clients* c);
void MQTTAsync_closeSession(Clients* client, enum MQTTReasonCodes reasonCode, MQTTProperties* props);
int MQTTAsync_disconnect1(MQTTAsync handle, const MQTTAsync_disconnectOptions* options, int internal);
int MQTTAsync_assignMsgId(MQTTAsyncs* m);
int MQTTAsync_getNoBufferedMessages(MQTTAsyncs* m);
void MQTTAsync_writeContinue(SOCKET socket);
void MQTTAsync_writeComplete(SOCKET socket, int rc);
void setRetryLoopInterval(int keepalive);
void MQTTAsync_NULLPublishResponses(MQTTAsyncs* m);
#if defined(_WIN32)
#else
#define WINAPI
#endif
thread_return_type WINAPI MQTTAsync_sendThread(void* n);
thread_return_type WINAPI MQTTAsync_receiveThread(void* n);
#endif /* MQTTASYNCUTILS_H_ */

2004
thirdparty/paho_mqtt/include/MQTTClient.h vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,277 @@
/*******************************************************************************
* Copyright (c) 2009, 2020 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* https://www.eclipse.org/legal/epl-2.0/
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
*******************************************************************************/
/**
* @file
* \brief This structure represents a persistent data store, used to store
* outbound and inbound messages, in order to achieve reliable messaging.
*
* The MQTT Client persists QoS1 and QoS2 messages in order to meet the
* assurances of delivery associated with these @ref qos levels. The messages
* are saved in persistent storage
* The type and context of the persistence implementation are specified when
* the MQTT client is created (see MQTTClient_create()). The default
* persistence type (::MQTTCLIENT_PERSISTENCE_DEFAULT) uses a file system-based
* persistence mechanism. The <i>persistence_context</i> argument passed to
* MQTTClient_create() when using the default peristence is a string
* representing the location of the persistence directory. If the context
* argument is NULL, the working directory will be used.
*
* To use memory-based persistence, an application passes
* ::MQTTCLIENT_PERSISTENCE_NONE as the <i>persistence_type</i> to
* MQTTClient_create(). This can lead to message loss in certain situations,
* but can be appropriate in some cases (see @ref qos).
*
* Client applications can provide their own persistence mechanism by passing
* ::MQTTCLIENT_PERSISTENCE_USER as the <i>persistence_type</i>. To implement a
* custom persistence mechanism, the application must pass an initialized
* ::MQTTClient_persistence structure as the <i>persistence_context</i>
* argument to MQTTClient_create().
*
* If the functions defined return an ::MQTTCLIENT_PERSISTENCE_ERROR then the
* state of the persisted data should remain as it was prior to the function
* being called. For example, if Persistence_put() returns
* ::MQTTCLIENT_PERSISTENCE_ERROR, then it is assumed tha tthe persistent store
* does not contain the data that was passed to the function. Similarly, if
* Persistence_remove() returns ::MQTTCLIENT_PERSISTENCE_ERROR then it is
* assumed that the data to be removed is still held in the persistent store.
*
* It is up to the persistence implementation to log any error information that
* may be required to diagnose a persistence mechanism failure.
*/
/*
/// @cond EXCLUDE
*/
#if !defined(MQTTCLIENTPERSISTENCE_H)
#define MQTTCLIENTPERSISTENCE_H
/*
/// @endcond
*/
/**
* This <i>persistence_type</i> value specifies the default file system-based
* persistence mechanism (see MQTTClient_create()).
*/
#define MQTTCLIENT_PERSISTENCE_DEFAULT 0
/**
* This <i>persistence_type</i> value specifies a memory-based
* persistence mechanism (see MQTTClient_create()).
*/
#define MQTTCLIENT_PERSISTENCE_NONE 1
/**
* This <i>persistence_type</i> value specifies an application-specific
* persistence mechanism (see MQTTClient_create()).
*/
#define MQTTCLIENT_PERSISTENCE_USER 2
/**
* Application-specific persistence functions must return this error code if
* there is a problem executing the function.
*/
#define MQTTCLIENT_PERSISTENCE_ERROR -2
/**
* @brief Initialize the persistent store.
*
* Either open the existing persistent store for this client ID or create a new
* one if one doesn't exist. If the persistent store is already open, return
* without taking any action.
*
* An application can use the same client identifier to connect to many
* different servers. The <i>clientid</i> in conjunction with the
* <i>serverURI</i> uniquely identifies the persistence store required.
*
* @param handle The address of a pointer to a handle for this persistence
* implementation. This function must set handle to a valid reference to the
* persistence following a successful return.
* The handle pointer is passed as an argument to all the other
* persistence functions. It may include the context parameter and/or any other
* data for use by the persistence functions.
* @param clientID The client identifier for which the persistent store should
* be opened.
* @param serverURI The connection string specified when the MQTT client was
* created (see MQTTClient_create()).
* @param context A pointer to any data required to initialize the persistent
* store (see ::MQTTClient_persistence).
* @return Return 0 if the function completes successfully, otherwise return
* ::MQTTCLIENT_PERSISTENCE_ERROR.
*/
typedef int (*Persistence_open)(void** handle, const char* clientID, const char* serverURI, void* context);
/**
* @brief Close the persistent store referred to by the handle.
*
* @param handle The handle pointer from a successful call to
* Persistence_open().
* @return Return 0 if the function completes successfully, otherwise return
* ::MQTTCLIENT_PERSISTENCE_ERROR.
*/
typedef int (*Persistence_close)(void* handle);
/**
* @brief Put the specified data into the persistent store.
*
* @param handle The handle pointer from a successful call to
* Persistence_open().
* @param key A string used as the key for the data to be put in the store. The
* key is later used to retrieve data from the store with Persistence_get().
* @param bufcount The number of buffers to write to the persistence store.
* @param buffers An array of pointers to the data buffers associated with
* this <i>key</i>.
* @param buflens An array of lengths of the data buffers. <i>buflen[n]</i>
* gives the length of <i>buffer[n]</i>.
* @return Return 0 if the function completes successfully, otherwise return
* ::MQTTCLIENT_PERSISTENCE_ERROR.
*/
typedef int (*Persistence_put)(void* handle, char* key, int bufcount, char* buffers[], int buflens[]);
/**
* @brief Retrieve the specified data from the persistent store.
*
* @param handle The handle pointer from a successful call to
* Persistence_open().
* @param key A string that is the key for the data to be retrieved. This is
* the same key used to save the data to the store with Persistence_put().
* @param buffer The address of a pointer to a buffer. This function sets the
* pointer to point at the retrieved data, if successful.
* @param buflen The address of an int that is set to the length of
* <i>buffer</i> by this function if successful.
* @return Return 0 if the function completes successfully, otherwise return
* ::MQTTCLIENT_PERSISTENCE_ERROR.
*/
typedef int (*Persistence_get)(void* handle, char* key, char** buffer, int* buflen);
/**
* @brief Remove the data for the specified key from the store.
*
* @param handle The handle pointer from a successful call to
* Persistence_open().
* @param key A string that is the key for the data to be removed from the
* store. This is the same key used to save the data to the store with
* Persistence_put().
* @return Return 0 if the function completes successfully, otherwise return
* ::MQTTCLIENT_PERSISTENCE_ERROR.
*/
typedef int (*Persistence_remove)(void* handle, char* key);
/**
* @brief Returns the keys in this persistent data store.
*
* @param handle The handle pointer from a successful call to
* Persistence_open().
* @param keys The address of a pointer to pointers to strings. Assuming
* successful execution, this function allocates memory to hold the returned
* keys (strings used to store the data with Persistence_put()). It also
* allocates memory to hold an array of pointers to these strings. <i>keys</i>
* is set to point to the array of pointers to strings.
* @param nkeys A pointer to the number of keys in this persistent data store.
* This function sets the number of keys, if successful.
* @return Return 0 if the function completes successfully, otherwise return
* ::MQTTCLIENT_PERSISTENCE_ERROR.
*/
typedef int (*Persistence_keys)(void* handle, char*** keys, int* nkeys);
/**
* @brief Clears the persistence store, so that it no longer contains any
* persisted data.
*
* @param handle The handle pointer from a successful call to
* Persistence_open().
* @return Return 0 if the function completes successfully, otherwise return
* ::MQTTCLIENT_PERSISTENCE_ERROR.
*/
typedef int (*Persistence_clear)(void* handle);
/**
* @brief Returns whether any data has been persisted using the specified key.
*
* @param handle The handle pointer from a successful call to
* Persistence_open().
* @param key The string to be tested for existence in the store.
* @return Return 0 if the key was found in the store, otherwise return
* ::MQTTCLIENT_PERSISTENCE_ERROR.
*/
typedef int (*Persistence_containskey)(void* handle, char* key);
/**
* @brief A structure containing the function pointers to a persistence
* implementation and the context or state that will be shared across all
* the persistence functions.
*/
typedef struct {
/**
* A pointer to any data required to initialize the persistent store.
*/
void* context;
/**
* A function pointer to an implementation of Persistence_open().
*/
Persistence_open popen;
/**
* A function pointer to an implementation of Persistence_close().
*/
Persistence_close pclose;
/**
* A function pointer to an implementation of Persistence_put().
*/
Persistence_put pput;
/**
* A function pointer to an implementation of Persistence_get().
*/
Persistence_get pget;
/**
* A function pointer to an implementation of Persistence_remove().
*/
Persistence_remove premove;
/**
* A function pointer to an implementation of Persistence_keys().
*/
Persistence_keys pkeys;
/**
* A function pointer to an implementation of Persistence_clear().
*/
Persistence_clear pclear;
/**
* A function pointer to an implementation of Persistence_containskey().
*/
Persistence_containskey pcontainskey;
} MQTTClient_persistence;
/**
* A callback which is invoked just before a write to persistence. This can be
* used to transform the data, for instance to encrypt it.
* @param context The context as set in ::MQTTAsync_setBeforePersistenceWrite
* @param bufcount The number of buffers to write to the persistence store.
* @param buffers An array of pointers to the data buffers.
* @param buflens An array of lengths of the data buffers.
* @return Return 0 if the function completes successfully, otherwise non 0.
*/
typedef int MQTTPersistence_beforeWrite(void* context, int bufcount, char* buffers[], int buflens[]);
/**
* A callback which is invoked just after a read from persistence. This can be
* used to transform the data, for instance to decrypt it.
* @param context The context as set in ::MQTTAsync_setAfterPersistenceRead
* @param buffer The address of a pointer to a buffer.
* @param buflen The address of an int that is the length of the buffer.
* @return Return 0 if the function completes successfully, otherwise non 0.
*/
typedef int MQTTPersistence_afterRead(void* context, char** buffer, int* buflen);
#endif

View File

@@ -0,0 +1,36 @@
/*******************************************************************************
* Copyright (c) 2020, 2020 Andreas Walter
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* https://www.eclipse.org/legal/epl-2.0/
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Andreas Walter - initially moved export declarations into separate fle
*******************************************************************************/
#if !defined(EXPORTDECLARATIONS_H)
#define EXPORTDECLARATIONS_H
#if defined(_WIN32)
# if defined(PAHO_MQTT_EXPORTS)
# define LIBMQTT_API __declspec(dllexport)
# elif defined(PAHO_MQTT_IMPORTS)
# define LIBMQTT_API __declspec(dllimport)
# else
# define LIBMQTT_API
# endif
#else
# if defined(PAHO_MQTT_EXPORTS)
# define LIBMQTT_API __attribute__ ((visibility ("default")))
# else
# define LIBMQTT_API extern
# endif
#endif
#endif

View File

@@ -0,0 +1,272 @@
/*******************************************************************************
* Copyright (c) 2009, 2024 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* https://www.eclipse.org/legal/epl-2.0/
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
* Ian Craggs, Allan Stockdill-Mander - SSL updates
* Ian Craggs - MQTT 3.1.1 support
* Ian Craggs - big endian Linux reversed definition
* Ian Craggs - MQTT 5.0 support
*******************************************************************************/
#if !defined(MQTTPACKET_H)
#define MQTTPACKET_H
#include "Socket.h"
#if defined(OPENSSL)
#include "SSLSocket.h"
#endif
#include "LinkedList.h"
#include "Clients.h"
typedef unsigned int bit;
typedef void* (*pf)(int, unsigned char, char*, size_t);
#include "MQTTProperties.h"
#include "MQTTReasonCodes.h"
enum errors
{
MQTTPACKET_BAD = -4,
MQTTPACKET_BUFFER_TOO_SHORT = -2,
MQTTPACKET_READ_ERROR = -1,
MQTTPACKET_READ_COMPLETE
};
enum msgTypes
{
CONNECT = 1, CONNACK, PUBLISH, PUBACK, PUBREC, PUBREL,
PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK,
PINGREQ, PINGRESP, DISCONNECT, AUTH
};
#if defined(__linux__)
#include <endian.h>
#if __BYTE_ORDER == __BIG_ENDIAN
#define REVERSED 1
#endif
#endif
/**
* Bitfields for the MQTT header byte.
*/
typedef union
{
/*unsigned*/ char byte; /**< the whole byte */
#if defined(REVERSED)
struct
{
unsigned int type : 4; /**< message type nibble */
bit dup : 1; /**< DUP flag bit */
unsigned int qos : 2; /**< QoS value, 0, 1 or 2 */
bit retain : 1; /**< retained flag bit */
} bits;
#else
struct
{
bit retain : 1; /**< retained flag bit */
unsigned int qos : 2; /**< QoS value, 0, 1 or 2 */
bit dup : 1; /**< DUP flag bit */
unsigned int type : 4; /**< message type nibble */
} bits;
#endif
} Header;
/**
* Data for a connect packet.
*/
typedef struct
{
Header header; /**< MQTT header byte */
union
{
unsigned char all; /**< all connect flags */
#if defined(REVERSED)
struct
{
bit username : 1; /**< 3.1 user name */
bit password : 1; /**< 3.1 password */
bit willRetain : 1; /**< will retain setting */
unsigned int willQoS : 2; /**< will QoS value */
bit will : 1; /**< will flag */
bit cleanstart : 1; /**< cleansession flag */
int : 1; /**< unused */
} bits;
#else
struct
{
int : 1; /**< unused */
bit cleanstart : 1; /**< cleansession flag */
bit will : 1; /**< will flag */
unsigned int willQoS : 2; /**< will QoS value */
bit willRetain : 1; /**< will retain setting */
bit password : 1; /**< 3.1 password */
bit username : 1; /**< 3.1 user name */
} bits;
#endif
} flags; /**< connect flags byte */
char *Protocol, /**< MQTT protocol name */
*clientID, /**< string client id */
*willTopic, /**< will topic */
*willMsg; /**< will payload */
int keepAliveTimer; /**< keepalive timeout value in seconds */
unsigned char version; /**< MQTT version number */
} Connect;
/**
* Data for a connack packet.
*/
typedef struct
{
Header header; /**< MQTT header byte */
union
{
unsigned char all; /**< all connack flags */
#if defined(REVERSED)
struct
{
unsigned int reserved : 7; /**< message type nibble */
bit sessionPresent : 1; /**< was a session found on the server? */
} bits;
#else
struct
{
bit sessionPresent : 1; /**< was a session found on the server? */
unsigned int reserved : 7; /**< message type nibble */
} bits;
#endif
} flags; /**< connack flags byte */
unsigned char rc; /**< connack reason code */
unsigned int MQTTVersion; /**< the version of MQTT */
MQTTProperties properties; /**< MQTT 5.0 properties. Not used for MQTT < 5.0 */
} Connack;
/**
* Data for a packet with header only.
*/
typedef struct
{
Header header; /**< MQTT header byte */
} MQTTPacket;
/**
* Data for a suback packet.
*/
typedef struct
{
Header header; /**< MQTT header byte */
int msgId; /**< MQTT message id */
int MQTTVersion; /**< the version of MQTT */
MQTTProperties properties; /**< MQTT 5.0 properties. Not used for MQTT < 5.0 */
List* qoss; /**< list of granted QoSs (MQTT 3/4) / reason codes (MQTT 5) */
} Suback;
/**
* Data for an MQTT V5 unsuback packet.
*/
typedef struct
{
Header header; /**< MQTT header byte */
int msgId; /**< MQTT message id */
int MQTTVersion; /**< the version of MQTT */
MQTTProperties properties; /**< MQTT 5.0 properties. Not used for MQTT < 5.0 */
List* reasonCodes; /**< list of reason codes */
} Unsuback;
/**
* Data for a publish packet.
*/
typedef struct
{
Header header; /**< MQTT header byte */
char* topic; /**< topic string */
int topiclen;
int msgId; /**< MQTT message id */
char* payload; /**< binary payload, length delimited */
int payloadlen; /**< payload length */
int MQTTVersion; /**< the version of MQTT */
MQTTProperties properties; /**< MQTT 5.0 properties. Not used for MQTT < 5.0 */
uint8_t mask[4]; /**< the websockets mask the payload is masked with, if any */
} Publish;
/**
* Data for one of the ack packets.
*/
typedef struct
{
Header header; /**< MQTT header byte */
int msgId; /**< MQTT message id */
unsigned char rc; /**< MQTT 5 reason code */
int MQTTVersion; /**< the version of MQTT */
MQTTProperties properties; /**< MQTT 5.0 properties. Not used for MQTT < 5.0 */
} Ack;
typedef Ack Puback;
typedef Ack Pubrec;
typedef Ack Pubrel;
typedef Ack Pubcomp;
int MQTTPacket_encode(char* buf, size_t length);
int MQTTPacket_decode(networkHandles* net, size_t* value);
int readInt(char** pptr);
char* readUTF(char** pptr, char* enddata);
unsigned char readChar(char** pptr);
void writeChar(char** pptr, char c);
void writeInt(char** pptr, int anInt);
void writeUTF(char** pptr, const char* string);
void writeData(char** pptr, const void* data, int datalen);
const char* MQTTPacket_name(int ptype);
void* MQTTPacket_Factory(int MQTTVersion, networkHandles* net, int* error);
int MQTTPacket_send(networkHandles* net, Header header, char* buffer, size_t buflen, int free, int MQTTVersion);
int MQTTPacket_sends(networkHandles* net, Header header, PacketBuffers* buffers, int MQTTVersion);
void* MQTTPacket_header_only(int MQTTVersion, unsigned char aHeader, char* data, size_t datalen);
int MQTTPacket_send_disconnect(Clients* client, enum MQTTReasonCodes reason, MQTTProperties* props);
void* MQTTPacket_publish(int MQTTVersion, unsigned char aHeader, char* data, size_t datalen);
void MQTTPacket_freePublish(Publish* pack);
int MQTTPacket_formatPayload(int buflen, char* buf, int payloadlen, char* payload);
int MQTTPacket_send_publish(Publish* pack, int dup, int qos, int retained, networkHandles* net, const char* clientID);
int MQTTPacket_send_puback(int MQTTVersion, int msgid, networkHandles* net, const char* clientID);
void* MQTTPacket_ack(int MQTTVersion, unsigned char aHeader, char* data, size_t datalen);
void MQTTPacket_freeAck(Ack* pack);
void MQTTPacket_freeSuback(Suback* pack);
void MQTTPacket_freeUnsuback(Unsuback* pack);
int MQTTPacket_send_pubrec(int MQTTVersion, int msgid, networkHandles* net, const char* clientID);
int MQTTPacket_send_pubrel(int MQTTVersion, int msgid, int dup, networkHandles* net, const char* clientID);
int MQTTPacket_send_pubcomp(int MQTTVersion, int msgid, networkHandles* net, const char* clientID);
void MQTTPacket_free_packet(MQTTPacket* pack);
void writeInt4(char** pptr, unsigned int anInt);
unsigned int readInt4(char** pptr);
void writeMQTTLenString(char** pptr, MQTTLenString lenstring);
int MQTTLenStringRead(MQTTLenString* lenstring, char** pptr, char* enddata);
int MQTTPacket_VBIlen(int rem_len);
int MQTTPacket_decodeBuf(char* buf, unsigned int* value);
#include "MQTTPacketOut.h"
#endif /* MQTTPACKET_H */

View File

@@ -0,0 +1,39 @@
/*******************************************************************************
* Copyright (c) 2009, 2018 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* https://www.eclipse.org/legal/epl-2.0/
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
* Ian Craggs, Allan Stockdill-Mander - SSL updates
* Ian Craggs - MQTT 3.1.1 support
* Ian Craggs - MQTT 5.0 support
*******************************************************************************/
#if !defined(MQTTPACKETOUT_H)
#define MQTTPACKETOUT_H
#include "MQTTPacket.h"
int MQTTPacket_send_connect(Clients* client, int MQTTVersion,
MQTTProperties* connectProperties, MQTTProperties* willProperties);
void* MQTTPacket_connack(int MQTTVersion, unsigned char aHeader, char* data, size_t datalen);
void MQTTPacket_freeConnack(Connack* pack);
int MQTTPacket_send_pingreq(networkHandles* net, const char* clientID);
int MQTTPacket_send_subscribe(List* topics, List* qoss, MQTTSubscribe_options* opts, MQTTProperties* props,
int msgid, int dup, Clients* client);
void* MQTTPacket_suback(int MQTTVersion, unsigned char aHeader, char* data, size_t datalen);
int MQTTPacket_send_unsubscribe(List* topics, MQTTProperties* props, int msgid, int dup, Clients* client);
void* MQTTPacket_unsuback(int MQTTVersion, unsigned char aHeader, char* data, size_t datalen);
#endif

View File

@@ -0,0 +1,99 @@
/*******************************************************************************
* Copyright (c) 2009, 2022 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* https://www.eclipse.org/legal/epl-2.0/
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
* Ian Craggs - async client updates
* Ian Craggs - fix for bug 432903 - queue persistence
* Ian Craggs - MQTT V5 updates
*******************************************************************************/
#if !defined(MQTTPERSISTENCE_H)
#define MQTTPERSISTENCE_H
#if defined(__cplusplus)
extern "C" {
#endif
#include "Clients.h"
#include "MQTTProperties.h"
/** Stem of the key for a sent PUBLISH QoS1 or QoS2 */
#define PERSISTENCE_PUBLISH_SENT "s-"
/** Stem of the key for a sent PUBREL */
#define PERSISTENCE_PUBREL "sc-"
/** Stem of the key for a received PUBLISH QoS2 */
#define PERSISTENCE_PUBLISH_RECEIVED "r-"
/** Stem of the key for a sent MQTT V5 PUBLISH QoS1 or QoS2 */
#define PERSISTENCE_V5_PUBLISH_SENT "s5-"
/** Stem of the key for a sent MQTT V5 PUBREL */
#define PERSISTENCE_V5_PUBREL "sc5-"
/** Stem of the key for a received MQTT V5 PUBLISH QoS2 */
#define PERSISTENCE_V5_PUBLISH_RECEIVED "r5-"
/** Stem of the key for an async client command */
#define PERSISTENCE_COMMAND_KEY "c-"
/** Stem of the key for an MQTT V5 async client command */
#define PERSISTENCE_V5_COMMAND_KEY "c5-"
/** Stem of the key for an client incoming message queue */
#define PERSISTENCE_QUEUE_KEY "q-"
/** Stem of the key for an MQTT V5 incoming message queue */
#define PERSISTENCE_V5_QUEUE_KEY "q5-"
/** Maximum length of a stem for a persistence key */
#define PERSISTENCE_MAX_STEM_LENGTH 4
/** Maximum allowed length of a persistence key */
#define PERSISTENCE_MAX_KEY_LENGTH 10
/** Maximum size of an integer sequence number appended to a persistence key */
#define PERSISTENCE_SEQNO_LIMIT 1000000 /*10^(PERSISTENCE_MAX_KEY_LENGTH - PERSISTENCE_MAX_STEM_LENGTH)*/
int MQTTPersistence_create(MQTTClient_persistence** per, int type, void* pcontext);
int MQTTPersistence_initialize(Clients* c, const char* serverURI);
int MQTTPersistence_close(Clients* c);
int MQTTPersistence_clear(Clients* c);
int MQTTPersistence_restorePackets(Clients* c);
void* MQTTPersistence_restorePacket(int MQTTVersion, char* buffer, size_t buflen);
void MQTTPersistence_insertInOrder(List* list, void* content, size_t size);
int MQTTPersistence_putPacket(SOCKET socket, char* buf0, size_t buf0len, int count,
char** buffers, size_t* buflens, int htype, int msgId, int scr, int MQTTVersion);
int MQTTPersistence_remove(Clients* c, char* type, int qos, int msgId);
void MQTTPersistence_wrapMsgID(Clients *c);
typedef struct
{
char struct_id[4];
int struct_version;
int payloadlen;
void* payload;
int qos;
int retained;
int dup;
int msgid;
MQTTProperties properties;
} MQTTPersistence_message;
typedef struct
{
MQTTPersistence_message* msg;
char* topicName;
int topicLen;
unsigned int seqno; /* only used on restore */
} MQTTPersistence_qEntry;
int MQTTPersistence_unpersistQueueEntry(Clients* client, MQTTPersistence_qEntry* qe);
int MQTTPersistence_persistQueueEntry(Clients* aclient, MQTTPersistence_qEntry* qe);
int MQTTPersistence_restoreMessageQueue(Clients* c);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,36 @@
/*******************************************************************************
* Copyright (c) 2009, 2018 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* https://www.eclipse.org/legal/epl-2.0/
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
*******************************************************************************/
#if !defined(MQTTPERSISTENCEDEFAULT_H)
#define MQTTPERSISTENCEDEFAULT_H
/** Extension of the filename */
#define MESSAGE_FILENAME_EXTENSION ".msg"
/* prototypes of the functions for the default file system persistence */
int pstopen(void** handle, const char* clientID, const char* serverURI, void* context);
int pstclose(void* handle);
int pstput(void* handle, char* key, int bufcount, char* buffers[], int buflens[]);
int pstget(void* handle, char* key, char** buffer, int* buflen);
int pstremove(void* handle, char* key);
int pstkeys(void* handle, char*** keys, int* nkeys);
int pstclear(void* handle);
int pstcontainskey(void* handle, char* key);
int pstmkdir(char *pPathname);
#endif

View File

@@ -0,0 +1,225 @@
/*******************************************************************************
* Copyright (c) 2017, 2024 IBM Corp. and others
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* https://www.eclipse.org/legal/epl-2.0/
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
*******************************************************************************/
#if !defined(MQTTPROPERTIES_H)
#define MQTTPROPERTIES_H
#include "MQTTExportDeclarations.h"
#include <stdint.h>
#define MQTT_INVALID_PROPERTY_ID -2
/** The one byte MQTT V5 property indicator */
enum MQTTPropertyCodes {
MQTTPROPERTY_CODE_PAYLOAD_FORMAT_INDICATOR = 1, /**< The value is 1 */
MQTTPROPERTY_CODE_MESSAGE_EXPIRY_INTERVAL = 2, /**< The value is 2 */
MQTTPROPERTY_CODE_CONTENT_TYPE = 3, /**< The value is 3 */
MQTTPROPERTY_CODE_RESPONSE_TOPIC = 8, /**< The value is 8 */
MQTTPROPERTY_CODE_CORRELATION_DATA = 9, /**< The value is 9 */
MQTTPROPERTY_CODE_SUBSCRIPTION_IDENTIFIER = 11, /**< The value is 11 */
MQTTPROPERTY_CODE_SESSION_EXPIRY_INTERVAL = 17, /**< The value is 17 */
MQTTPROPERTY_CODE_ASSIGNED_CLIENT_IDENTIFIER = 18,/**< The value is 18 */
MQTTPROPERTY_CODE_ASSIGNED_CLIENT_IDENTIFER = 18,/**< The value is 18 (obsolete, misspelled) */
MQTTPROPERTY_CODE_SERVER_KEEP_ALIVE = 19, /**< The value is 19 */
MQTTPROPERTY_CODE_AUTHENTICATION_METHOD = 21, /**< The value is 21 */
MQTTPROPERTY_CODE_AUTHENTICATION_DATA = 22, /**< The value is 22 */
MQTTPROPERTY_CODE_REQUEST_PROBLEM_INFORMATION = 23,/**< The value is 23 */
MQTTPROPERTY_CODE_WILL_DELAY_INTERVAL = 24, /**< The value is 24 */
MQTTPROPERTY_CODE_REQUEST_RESPONSE_INFORMATION = 25,/**< The value is 25 */
MQTTPROPERTY_CODE_RESPONSE_INFORMATION = 26, /**< The value is 26 */
MQTTPROPERTY_CODE_SERVER_REFERENCE = 28, /**< The value is 28 */
MQTTPROPERTY_CODE_REASON_STRING = 31, /**< The value is 31 */
MQTTPROPERTY_CODE_RECEIVE_MAXIMUM = 33, /**< The value is 33*/
MQTTPROPERTY_CODE_TOPIC_ALIAS_MAXIMUM = 34, /**< The value is 34 */
MQTTPROPERTY_CODE_TOPIC_ALIAS = 35, /**< The value is 35 */
MQTTPROPERTY_CODE_MAXIMUM_QOS = 36, /**< The value is 36 */
MQTTPROPERTY_CODE_RETAIN_AVAILABLE = 37, /**< The value is 37 */
MQTTPROPERTY_CODE_USER_PROPERTY = 38, /**< The value is 38 */
MQTTPROPERTY_CODE_MAXIMUM_PACKET_SIZE = 39, /**< The value is 39 */
MQTTPROPERTY_CODE_WILDCARD_SUBSCRIPTION_AVAILABLE = 40,/**< The value is 40 */
MQTTPROPERTY_CODE_SUBSCRIPTION_IDENTIFIERS_AVAILABLE = 41,/**< The value is 41 */
MQTTPROPERTY_CODE_SHARED_SUBSCRIPTION_AVAILABLE = 42/**< The value is 241 */
};
/**
* Returns a printable string description of an MQTT V5 property code.
* @param value an MQTT V5 property code.
* @return the printable string description of the input property code.
* NULL if the code was not found.
*/
LIBMQTT_API const char* MQTTPropertyName(enum MQTTPropertyCodes value);
/** The one byte MQTT V5 property type */
enum MQTTPropertyTypes {
MQTTPROPERTY_TYPE_BYTE,
MQTTPROPERTY_TYPE_TWO_BYTE_INTEGER,
MQTTPROPERTY_TYPE_FOUR_BYTE_INTEGER,
MQTTPROPERTY_TYPE_VARIABLE_BYTE_INTEGER,
MQTTPROPERTY_TYPE_BINARY_DATA,
MQTTPROPERTY_TYPE_UTF_8_ENCODED_STRING,
MQTTPROPERTY_TYPE_UTF_8_STRING_PAIR
};
/**
* Returns the MQTT V5 type code of an MQTT V5 property.
* @param value an MQTT V5 property code.
* @return the MQTT V5 type code of the input property. -1 if the code was not found.
*/
LIBMQTT_API int MQTTProperty_getType(enum MQTTPropertyCodes value);
/**
* The data for a length delimited string
*/
typedef struct
{
int len; /**< the length of the string */
char* data; /**< pointer to the string data */
} MQTTLenString;
/**
* Structure to hold an MQTT version 5 property of any type
*/
typedef struct
{
enum MQTTPropertyCodes identifier; /**< The MQTT V5 property id. A multi-byte integer. */
/** The value of the property, as a union of the different possible types. */
union {
unsigned char byte; /**< holds the value of a byte property type */
unsigned short integer2; /**< holds the value of a 2 byte integer property type */
unsigned int integer4; /**< holds the value of a 4 byte integer property type */
struct {
MQTTLenString data; /**< The value of a string property, or the name of a user property. */
MQTTLenString value; /**< The value of a user property. */
};
} value;
} MQTTProperty;
/**
* MQTT version 5 property list
*/
typedef struct MQTTProperties
{
int count; /**< number of property entries in the array */
int max_count; /**< max number of properties that the currently allocated array can store */
int length; /**< mbi: byte length of all properties */
MQTTProperty *array; /**< array of properties */
} MQTTProperties;
#define MQTTProperties_initializer {0, 0, 0, NULL}
/**
* Returns the length of the properties structure when serialized ready for network transmission.
* @param props an MQTT V5 property structure.
* @return the length in bytes of the properties when serialized.
*/
int MQTTProperties_len(const MQTTProperties* props);
/**
* Add a property pointer to the property array. Memory is allocated in this function,
* so MQTTClient_create or MQTTAsync_create must be called first to initialize the
* internal heap tracking. Alternatively MQTTAsync_global_init() can be called first
* or build with the HIGH_PERFORMANCE option which disables the heap tracking.
* @param props The property list to add the property to.
* @param prop The property to add to the list.
* @return 0 on success, -1 on failure.
*/
LIBMQTT_API int MQTTProperties_add(MQTTProperties* props, const MQTTProperty* prop);
/**
* Serialize the given property list to a character buffer, e.g. for writing to the network.
* @param pptr pointer to the buffer - move the pointer as we add data
* @param properties pointer to the property list, can be NULL
* @return whether the write succeeded or not: number of bytes written, or < 0 on failure.
*/
int MQTTProperties_write(char** pptr, const MQTTProperties* properties);
/**
* Reads a property list from a character buffer into an array.
* @param properties pointer to the property list to be filled. Should be initalized but empty.
* @param pptr pointer to the character buffer.
* @param enddata pointer to the end of the character buffer so we don't read beyond.
* @return 1 if the properties were read successfully.
*/
int MQTTProperties_read(MQTTProperties* properties, char** pptr, char* enddata);
/**
* Free all memory allocated to the property list, including any to individual properties.
* @param properties pointer to the property list.
*/
LIBMQTT_API void MQTTProperties_free(MQTTProperties* properties);
/**
* Copy the contents of a property list, allocating additional memory if needed.
* @param props pointer to the property list.
* @return the duplicated property list.
*/
LIBMQTT_API MQTTProperties MQTTProperties_copy(const MQTTProperties* props);
/**
* Checks if property list contains a specific property.
* @param props pointer to the property list.
* @param propid the property id to check for.
* @return 1 if found, 0 if not.
*/
LIBMQTT_API int MQTTProperties_hasProperty(const MQTTProperties *props, enum MQTTPropertyCodes propid);
/**
* Returns the number of instances of a property id. Most properties can exist only once.
* User properties and subscription ids can exist more than once.
* @param props pointer to the property list.
* @param propid the property id to check for.
* @return the number of times found. Can be 0.
*/
LIBMQTT_API int MQTTProperties_propertyCount(const MQTTProperties *props, enum MQTTPropertyCodes propid);
/**
* Returns the integer value of a specific property. The property given must be a numeric type.
* @param props pointer to the property list.
* @param propid the property id to check for.
* @return the integer value of the property. -9999999 on failure.
*/
LIBMQTT_API int64_t MQTTProperties_getNumericValue(const MQTTProperties *props, enum MQTTPropertyCodes propid);
/**
* Returns the integer value of a specific property when it's not the only instance.
* The property given must be a numeric type.
* @param props pointer to the property list.
* @param propid the property id to check for.
* @param index the instance number, starting at 0.
* @return the integer value of the property. -9999999 on failure.
*/
LIBMQTT_API int64_t MQTTProperties_getNumericValueAt(const MQTTProperties *props, enum MQTTPropertyCodes propid, int index);
/**
* Returns a pointer to the property structure for a specific property.
* @param props pointer to the property list.
* @param propid the property id to check for.
* @return the pointer to the property structure if found. NULL if not found.
*/
LIBMQTT_API MQTTProperty* MQTTProperties_getProperty(const MQTTProperties *props, enum MQTTPropertyCodes propid);
/**
* Returns a pointer to the property structure for a specific property when it's not the only instance.
* @param props pointer to the property list.
* @param propid the property id to check for.
* @param index the instance number, starting at 0.
* @return the pointer to the property structure if found. NULL if not found.
*/
LIBMQTT_API MQTTProperty* MQTTProperties_getPropertyAt(const MQTTProperties *props, enum MQTTPropertyCodes propid, int index);
#endif /* MQTTPROPERTIES_H */

View File

@@ -0,0 +1,46 @@
/*******************************************************************************
* Copyright (c) 2009, 2022 IBM Corp., Ian Craggs
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* https://www.eclipse.org/legal/epl-2.0/
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
* Ian Craggs - MQTT 3.1.1 updates
*******************************************************************************/
#if !defined(MQTTPROTOCOL_H)
#define MQTTPROTOCOL_H
#include "LinkedList.h"
#include "MQTTPacket.h"
#include "Clients.h"
#define MAX_MSG_ID 65535
#define MAX_CLIENTID_LEN 65535
typedef struct
{
SOCKET socket;
Publications* p;
} pending_write;
typedef struct
{
List publications;
unsigned int msgs_received;
unsigned int msgs_sent;
List pending_writes; /* for qos 0 writes not complete */
} MQTTProtocol;
#include "MQTTProtocolOut.h"
#endif

View File

@@ -0,0 +1,62 @@
/*******************************************************************************
* Copyright (c) 2009, 2022 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* https://www.eclipse.org/legal/epl-2.0/
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
* Ian Craggs, Allan Stockdill-Mander - SSL updates
* Ian Craggs - MQTT 3.1.1 updates
* Rong Xiang, Ian Craggs - C++ compatibility
* Ian Craggs - add debug definition of MQTTStrdup for when needed
*******************************************************************************/
#if !defined(MQTTPROTOCOLCLIENT_H)
#define MQTTPROTOCOLCLIENT_H
#include "LinkedList.h"
#include "MQTTPacket.h"
#include "Log.h"
#include "MQTTProtocol.h"
#include "Messages.h"
#include "MQTTProperties.h"
#define MAX_MSG_ID 65535
#define MAX_CLIENTID_LEN 65535
int MQTTProtocol_startPublish(Clients* pubclient, Publish* publish, int qos, int retained, Messages** m);
Messages* MQTTProtocol_createMessage(Publish* publish, Messages** mm, int qos, int retained, int allocatePayload);
Publications* MQTTProtocol_storePublication(Publish* publish, int* len);
int messageIDCompare(void* a, void* b);
int MQTTProtocol_assignMsgId(Clients* client);
void MQTTProtocol_removePublication(Publications* p);
void Protocol_processPublication(Publish* publish, Clients* client, int allocatePayload);
int MQTTProtocol_handlePublishes(void* pack, SOCKET sock);
int MQTTProtocol_handlePubacks(void* pack, SOCKET sock, Publications** pubToRemove);
int MQTTProtocol_handlePubrecs(void* pack, SOCKET sock, Publications** pubToRemove);
int MQTTProtocol_handlePubrels(void* pack, SOCKET sock);
int MQTTProtocol_handlePubcomps(void* pack, SOCKET sock, Publications** pubToRemove);
void MQTTProtocol_closeSession(Clients* c, int sendwill);
void MQTTProtocol_keepalive(START_TIME_TYPE);
void MQTTProtocol_retry(START_TIME_TYPE, int, int);
void MQTTProtocol_freeClient(Clients* client);
void MQTTProtocol_emptyMessageList(List* msgList);
void MQTTProtocol_freeMessageList(List* msgList);
char* MQTTStrncpy(char *dest, const char* src, size_t num);
char* MQTTStrdup(const char* src);
void MQTTProtocol_writeAvailable(SOCKET socket);
//#define MQTTStrdup(src) MQTTStrncpy(malloc(strlen(src)+1), src, strlen(src)+1)
#endif

View File

@@ -0,0 +1,66 @@
/*******************************************************************************
* Copyright (c) 2009, 2022 IBM Corp., Ian Craggs, and others
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* https://www.eclipse.org/legal/epl-2.0/
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
* Ian Craggs, Allan Stockdill-Mander - SSL updates
* Ian Craggs - MQTT 3.1.1 support
* Ian Craggs - SNI support
* Ian Craggs - MQTT 5.0 support
* Sven Gambel - add generic proxy support
*******************************************************************************/
#if !defined(MQTTPROTOCOLOUT_H)
#define MQTTPROTOCOLOUT_H
#include "LinkedList.h"
#include "MQTTPacket.h"
#include "Clients.h"
#include "Log.h"
#include "Messages.h"
#include "MQTTProtocol.h"
#include "MQTTProtocolClient.h"
#define MQTT_DEFAULT_PORT 1883
#define SECURE_MQTT_DEFAULT_PORT 8883
#define WS_DEFAULT_PORT 80
#define WSS_DEFAULT_PORT 443
#define PROXY_DEFAULT_PORT 8080
size_t MQTTProtocol_addressPort(const char* uri, int* port, const char **topic, int default_port);
void MQTTProtocol_reconnect(const char* ip_address, Clients* client);
#if defined(OPENSSL)
#if defined(__GNUC__) && defined(__linux__)
int MQTTProtocol_connect(const char* ip_address, Clients* acClients, int unixsock, int ssl, int websocket, int MQTTVersion,
MQTTProperties* connectProperties, MQTTProperties* willProperties, long timeout);
#else
int MQTTProtocol_connect(const char* ip_address, Clients* acClients, int unixsock, int ssl, int websocket, int MQTTVersion,
MQTTProperties* connectProperties, MQTTProperties* willProperties);
#endif
#else
#if defined(__GNUC__) && defined(__linux__)
int MQTTProtocol_connect(const char* ip_address, Clients* acClients, int unixsock, int websocket, int MQTTVersion,
MQTTProperties* connectProperties, MQTTProperties* willProperties, long timeout);
#else
int MQTTProtocol_connect(const char* ip_address, Clients* acClients, int unixsock, int websocket, int MQTTVersion,
MQTTProperties* connectProperties, MQTTProperties* willProperties);
#endif
#endif
int MQTTProtocol_handlePingresps(void* pack, SOCKET sock);
int MQTTProtocol_subscribe(Clients* client, List* topics, List* qoss, int msgID,
MQTTSubscribe_options* opts, MQTTProperties* props);
int MQTTProtocol_handleSubacks(void* pack, SOCKET sock);
int MQTTProtocol_unsubscribe(Clients* client, List* topics, int msgID, MQTTProperties* props);
int MQTTProtocol_handleUnsubacks(void* pack, SOCKET sock);
int MQTTProtocol_handleDisconnects(void* pack, SOCKET sock);
#endif

View File

@@ -0,0 +1,79 @@
/*******************************************************************************
* Copyright (c) 2017, 2020 IBM Corp. and others
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* https://www.eclipse.org/legal/epl-2.0/
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
*******************************************************************************/
#if !defined(MQTTREASONCODES_H)
#define MQTTREASONCODES_H
#include "MQTTExportDeclarations.h"
/** The MQTT V5 one byte reason code */
enum MQTTReasonCodes {
MQTTREASONCODE_SUCCESS = 0,
MQTTREASONCODE_NORMAL_DISCONNECTION = 0,
MQTTREASONCODE_GRANTED_QOS_0 = 0,
MQTTREASONCODE_GRANTED_QOS_1 = 1,
MQTTREASONCODE_GRANTED_QOS_2 = 2,
MQTTREASONCODE_DISCONNECT_WITH_WILL_MESSAGE = 4,
MQTTREASONCODE_NO_MATCHING_SUBSCRIBERS = 16,
MQTTREASONCODE_NO_SUBSCRIPTION_FOUND = 17,
MQTTREASONCODE_CONTINUE_AUTHENTICATION = 24,
MQTTREASONCODE_RE_AUTHENTICATE = 25,
MQTTREASONCODE_UNSPECIFIED_ERROR = 128,
MQTTREASONCODE_MALFORMED_PACKET = 129,
MQTTREASONCODE_PROTOCOL_ERROR = 130,
MQTTREASONCODE_IMPLEMENTATION_SPECIFIC_ERROR = 131,
MQTTREASONCODE_UNSUPPORTED_PROTOCOL_VERSION = 132,
MQTTREASONCODE_CLIENT_IDENTIFIER_NOT_VALID = 133,
MQTTREASONCODE_BAD_USER_NAME_OR_PASSWORD = 134,
MQTTREASONCODE_NOT_AUTHORIZED = 135,
MQTTREASONCODE_SERVER_UNAVAILABLE = 136,
MQTTREASONCODE_SERVER_BUSY = 137,
MQTTREASONCODE_BANNED = 138,
MQTTREASONCODE_SERVER_SHUTTING_DOWN = 139,
MQTTREASONCODE_BAD_AUTHENTICATION_METHOD = 140,
MQTTREASONCODE_KEEP_ALIVE_TIMEOUT = 141,
MQTTREASONCODE_SESSION_TAKEN_OVER = 142,
MQTTREASONCODE_TOPIC_FILTER_INVALID = 143,
MQTTREASONCODE_TOPIC_NAME_INVALID = 144,
MQTTREASONCODE_PACKET_IDENTIFIER_IN_USE = 145,
MQTTREASONCODE_PACKET_IDENTIFIER_NOT_FOUND = 146,
MQTTREASONCODE_RECEIVE_MAXIMUM_EXCEEDED = 147,
MQTTREASONCODE_TOPIC_ALIAS_INVALID = 148,
MQTTREASONCODE_PACKET_TOO_LARGE = 149,
MQTTREASONCODE_MESSAGE_RATE_TOO_HIGH = 150,
MQTTREASONCODE_QUOTA_EXCEEDED = 151,
MQTTREASONCODE_ADMINISTRATIVE_ACTION = 152,
MQTTREASONCODE_PAYLOAD_FORMAT_INVALID = 153,
MQTTREASONCODE_RETAIN_NOT_SUPPORTED = 154,
MQTTREASONCODE_QOS_NOT_SUPPORTED = 155,
MQTTREASONCODE_USE_ANOTHER_SERVER = 156,
MQTTREASONCODE_SERVER_MOVED = 157,
MQTTREASONCODE_SHARED_SUBSCRIPTIONS_NOT_SUPPORTED = 158,
MQTTREASONCODE_CONNECTION_RATE_EXCEEDED = 159,
MQTTREASONCODE_MAXIMUM_CONNECT_TIME = 160,
MQTTREASONCODE_SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED = 161,
MQTTREASONCODE_WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED = 162
};
/**
* Returns a printable string description of an MQTT V5 reason code.
* @param value an MQTT V5 reason code.
* @return the printable string description of the input reason code.
* NULL if the code was not found.
*/
LIBMQTT_API const char* MQTTReasonCode_toString(enum MQTTReasonCodes value);
#endif

View File

@@ -0,0 +1,46 @@
/*******************************************************************************
* Copyright (c) 2018 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* https://www.eclipse.org/legal/epl-2.0/
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
*******************************************************************************/
#if !defined(SUBOPTS_H)
#define SUBOPTS_H
/** The MQTT V5 subscribe options, apart from QoS which existed before V5. */
typedef struct MQTTSubscribe_options
{
/** The eyecatcher for this structure. Must be MQSO. */
char struct_id[4];
/** The version number of this structure. Must be 0.
*/
int struct_version;
/** To not receive our own publications, set to 1.
* 0 is the original MQTT behaviour - all messages matching the subscription are received.
*/
unsigned char noLocal;
/** To keep the retain flag as on the original publish message, set to 1.
* If 0, defaults to the original MQTT behaviour where the retain flag is only set on
* publications sent by a broker if in response to a subscribe request.
*/
unsigned char retainAsPublished;
/** 0 - send retained messages at the time of the subscribe (original MQTT behaviour)
* 1 - send retained messages on subscribe only if the subscription is new
* 2 - do not send retained messages at all
*/
unsigned char retainHandling;
} MQTTSubscribe_options;
#define MQTTSubscribe_options_initializer { {'M', 'Q', 'S', 'O'}, 0, 0, 0, 0 }
#endif

49
thirdparty/paho_mqtt/include/MQTTTime.h vendored Normal file
View File

@@ -0,0 +1,49 @@
/*******************************************************************************
* Copyright (c) 2020 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* https://www.eclipse.org/legal/epl-2.0/
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial implementation
*******************************************************************************/
#if !defined(MQTTTIME_H)
#define MQTTTIME_H
#include <stdint.h>
#if defined(_WIN32)
#include <windows.h>
#if WINVER >= _WIN32_WINNT_VISTA
#define START_TIME_TYPE ULONGLONG
#define START_TIME_ZERO 0
#else
#define START_TIME_TYPE DWORD
#define START_TIME_ZERO 0
#endif
#elif defined(AIX)
#define START_TIME_TYPE struct timespec
#define START_TIME_ZERO {0, 0}
#else
#include <sys/time.h>
#define START_TIME_TYPE struct timeval
#define START_TIME_ZERO {0, 0}
#endif
#define ELAPSED_TIME_TYPE uint64_t
#define DIFF_TIME_TYPE int64_t
void MQTTTime_sleep(ELAPSED_TIME_TYPE milliseconds);
START_TIME_TYPE MQTTTime_start_clock(void);
START_TIME_TYPE MQTTTime_now(void);
ELAPSED_TIME_TYPE MQTTTime_elapsed(START_TIME_TYPE milliseconds);
DIFF_TIME_TYPE MQTTTime_difftime(START_TIME_TYPE t_new, START_TIME_TYPE t_old);
#endif

BIN
thirdparty/paho_mqtt/lib/paho-mqtt3a.dll vendored Normal file

Binary file not shown.

BIN
thirdparty/paho_mqtt/lib/paho-mqtt3a.lib vendored Normal file

Binary file not shown.

BIN
thirdparty/paho_mqtt/lib/paho-mqtt3c.dll vendored Normal file

Binary file not shown.

BIN
thirdparty/paho_mqtt/lib/paho-mqtt3c.lib vendored Normal file

Binary file not shown.

108
thirdparty/paho_mqtt/notice.html vendored Normal file
View File

@@ -0,0 +1,108 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Eclipse Foundation Software User Agreement</title>
</head>
<body lang="EN-US">
<h2>Eclipse Foundation Software User Agreement</h2>
<p>April 6, 2020</p>
<h3>Usage Of Content</h3>
<p>THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS
(COLLECTIVELY &quot;CONTENT&quot;). USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND
CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE
OF THE CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR
NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND
CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT USE THE CONTENT.</p>
<h3>Applicable Licenses</h3>
<p>Unless otherwise indicated, all Content made available by the Eclipse Foundation is provided to you under the terms and conditions of the Eclipse Public License Version 2.0
(&quot;EPL&quot;). A copy of the EPL is provided with this Content and is also available at <a href="https://www.eclipse.org/legal/epl-2.0/">https://www.eclipse.org/legal/epl-2.0/</a>.
For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
<p>Content includes, but is not limited to, source code, object code, documentation and other files maintained in the Eclipse Foundation source code
repository (&quot;Repository&quot;) in software modules (&quot;Modules&quot;) and made available as downloadable archives (&quot;Downloads&quot;).</p>
<ul>
<li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content. Typical modules may include plug-ins (&quot;Plug-ins&quot;), plug-in fragments (&quot;Fragments&quot;), and features (&quot;Features&quot;).</li>
<li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java&trade; ARchive) in a directory named &quot;plugins&quot;.</li>
<li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material. Each Feature may be packaged as a sub-directory in a directory named &quot;features&quot;. Within a Feature, files named &quot;feature.xml&quot; may contain a list of the names and version numbers of the Plug-ins
and/or Fragments associated with that Feature.</li>
<li>Features may also include other Features (&quot;Included Features&quot;). Within a Feature, files named &quot;feature.xml&quot; may contain a list of the names and version numbers of Included Features.</li>
</ul>
<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named &quot;about.html&quot; (&quot;Abouts&quot;). The terms and conditions governing Features and
Included Features should be contained in files named &quot;license.html&quot; (&quot;Feature Licenses&quot;). Abouts and Feature Licenses may be located in any directory of a Download or Module
including, but not limited to the following locations:</p>
<ul>
<li>The top-level (root) directory</li>
<li>Plug-in and Fragment directories</li>
<li>Inside Plug-ins and Fragments packaged as JARs</li>
<li>Sub-directories of the directory named &quot;src&quot; of certain Plug-ins</li>
<li>Feature directories</li>
</ul>
<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license (&quot;Feature Update License&quot;) during the
installation process. If the Feature contains Included Features, the Feature Update License should either provide you with the terms and conditions governing the Included Features or
inform you where you can locate them. Feature Update Licenses may be found in the &quot;license&quot; property of files named &quot;feature.properties&quot; found within a Feature.
Such Abouts, Feature Licenses, and Feature Update Licenses contain the terms and conditions (or references to such terms and conditions) that govern your use of the associated Content in
that directory.</p>
<p>THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS. SOME OF THESE
OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):</p>
<ul>
<li>Eclipse Distribution License Version 1.0 (available at <a href="http://www.eclipse.org/licenses/edl-v10.html">http://www.eclipse.org/licenses/edl-v1.0.html</a>)</li>
<li>Common Public License Version 1.0 (available at <a href="http://www.eclipse.org/legal/cpl-v10.html">http://www.eclipse.org/legal/cpl-v10.html</a>)</li>
<li>Apache Software License 1.1 (available at <a href="http://www.apache.org/licenses/LICENSE">http://www.apache.org/licenses/LICENSE</a>)</li>
<li>Apache Software License 2.0 (available at <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)</li>
<li>Metro Link Public License 1.00 (available at <a href="http://www.opengroup.org/openmotif/supporters/metrolink/license.html">http://www.opengroup.org/openmotif/supporters/metrolink/license.html</a>)</li>
<li>Mozilla Public License Version 1.1 (available at <a href="http://www.mozilla.org/MPL/MPL-1.1.html">http://www.mozilla.org/MPL/MPL-1.1.html</a>)</li>
</ul>
<p>IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR TO USE OF THE CONTENT. If no About, Feature License, or Feature Update License is provided, please
contact the Eclipse Foundation to determine what terms and conditions govern that particular Content.</p>
<h3>Use of Provisioning Technology</h3>
<p>The Eclipse Foundation makes available provisioning software, examples of which include, but are not limited to, p2 and the Eclipse
Update Manager (&quot;Provisioning Technology&quot;) for the purpose of allowing users to install software, documentation, information and/or
other materials (collectively &quot;Installable Software&quot;). This capability is provided with the intent of allowing such users to
install, extend and update Eclipse-based products. Information about packaging Installable Software is available at <a
href="http://eclipse.org/equinox/p2/repository_packaging.html">http://eclipse.org/equinox/p2/repository_packaging.html</a>
(&quot;Specification&quot;).</p>
<p>You may use Provisioning Technology to allow other parties to install Installable Software. You shall be responsible for enabling the
applicable license agreements relating to the Installable Software to be presented to, and accepted by, the users of the Provisioning Technology
in accordance with the Specification. By using Provisioning Technology in such a manner and making it available in accordance with the
Specification, you further acknowledge your agreement to, and the acquisition of all necessary rights to permit the following:</p>
<ol>
<li>A series of actions may occur (&quot;Provisioning Process&quot;) in which a user may execute the Provisioning Technology
on a machine (&quot;Target Machine&quot;) with the intent of installing, extending or updating the functionality of an Eclipse-based
product.</li>
<li>During the Provisioning Process, the Provisioning Technology may cause third party Installable Software or a portion thereof to be
accessed and copied to the Target Machine.</li>
<li>Pursuant to the Specification, you will provide to the user the terms and conditions that govern the use of the Installable
Software (&quot;Installable Software Agreement&quot;) and such Installable Software Agreement shall be accessed from the Target
Machine in accordance with the Specification. Such Installable Software Agreement must inform the user of the terms and conditions that govern
the Installable Software and must solicit acceptance by the end user in the manner prescribed in such Installable Software Agreement. Upon such
indication of agreement by the user, the provisioning Technology will complete installation of the Installable Software.</li>
</ol>
<h3>Cryptography</h3>
<p>Content may contain encryption software. The country in which you are currently may have restrictions on the import, possession, and use, and/or re-export to
another country, of encryption software. BEFORE using any encryption software, please check the country's laws, regulations and policies concerning the import,
possession, or use, and re-export of encryption software, to see if this is permitted.</p>
<p><small>Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.</small></p>
</body>
</html>

View File

@@ -0,0 +1,188 @@
/*******************************************************************************
* Copyright (c) 2012, 2025 IBM Corp., Ian Craggs
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* https://www.eclipse.org/legal/epl-2.0/
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial contribution
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MQTTAsync.h"
#if !defined(_WIN32)
#include <unistd.h>
#else
#include <windows.h>
#endif
#if defined(_WRS_KERNEL)
#include <OsWrapper.h>
#endif
#define ADDRESS "tcp://test.mosquitto.org:1883"
#define CLIENTID "ExampleClientPub"
#define TOPIC "MQTT Examples"
#define PAYLOAD "Hello World!"
#define QOS 1
#define TIMEOUT 10000L
int finished = 0;
void connlost(void *context, char *cause)
{
MQTTAsync client = (MQTTAsync)context;
MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
int rc;
printf("\nConnection lost\n");
if (cause)
printf(" cause: %s\n", cause);
printf("Reconnecting\n");
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
{
printf("Failed to start connect, return code %d\n", rc);
finished = 1;
}
}
void onDisconnectFailure(void* context, MQTTAsync_failureData* response)
{
printf("Disconnect failed\n");
finished = 1;
}
void onDisconnect(void* context, MQTTAsync_successData* response)
{
printf("Successful disconnection\n");
finished = 1;
}
void onSendFailure(void* context, MQTTAsync_failureData* response)
{
MQTTAsync client = (MQTTAsync)context;
MQTTAsync_disconnectOptions opts = MQTTAsync_disconnectOptions_initializer;
int rc;
printf("Message send failed token %d error code %d\n", response->token, response->code);
opts.onSuccess = onDisconnect;
opts.onFailure = onDisconnectFailure;
opts.context = client;
if ((rc = MQTTAsync_disconnect(client, &opts)) != MQTTASYNC_SUCCESS)
{
printf("Failed to start disconnect, return code %d\n", rc);
exit(EXIT_FAILURE);
}
}
void onSend(void* context, MQTTAsync_successData* response)
{
MQTTAsync client = (MQTTAsync)context;
MQTTAsync_disconnectOptions opts = MQTTAsync_disconnectOptions_initializer;
int rc;
printf("Message with token value %d delivery confirmed\n", response->token);
opts.onSuccess = onDisconnect;
opts.onFailure = onDisconnectFailure;
opts.context = client;
if ((rc = MQTTAsync_disconnect(client, &opts)) != MQTTASYNC_SUCCESS)
{
printf("Failed to start disconnect, return code %d\n", rc);
exit(EXIT_FAILURE);
}
}
void onConnectFailure(void* context, MQTTAsync_failureData* response)
{
printf("Connect failed, rc %d\n", response ? response->code : 0);
finished = 1;
}
void onConnect(void* context, MQTTAsync_successData* response)
{
MQTTAsync client = (MQTTAsync)context;
MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
MQTTAsync_message pubmsg = MQTTAsync_message_initializer;
int rc;
printf("Successful connection\n");
opts.onSuccess = onSend;
opts.onFailure = onSendFailure;
opts.context = client;
pubmsg.payload = PAYLOAD;
pubmsg.payloadlen = (int)strlen(PAYLOAD);
pubmsg.qos = QOS;
pubmsg.retained = 0;
if ((rc = MQTTAsync_sendMessage(client, TOPIC, &pubmsg, &opts)) != MQTTASYNC_SUCCESS)
{
printf("Failed to start sendMessage, return code %d\n", rc);
exit(EXIT_FAILURE);
}
}
int messageArrived(void* context, char* topicName, int topicLen, MQTTAsync_message* m)
{
/* not expecting any messages */
return 1;
}
int main(int argc, char* argv[])
{
MQTTAsync client;
MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
int rc;
const char* uri = (argc > 1) ? argv[1] : ADDRESS;
printf("Using server at %s\n", uri);
if ((rc = MQTTAsync_create(&client, uri, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL)) != MQTTASYNC_SUCCESS)
{
printf("Failed to create client object, return code %d\n", rc);
exit(EXIT_FAILURE);
}
if ((rc = MQTTAsync_setCallbacks(client, client, connlost, messageArrived, NULL)) != MQTTASYNC_SUCCESS)
{
printf("Failed to set callback, return code %d\n", rc);
exit(EXIT_FAILURE);
}
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
conn_opts.onSuccess = onConnect;
conn_opts.onFailure = onConnectFailure;
conn_opts.context = client;
if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
{
printf("Failed to start connect, return code %d\n", rc);
exit(EXIT_FAILURE);
}
printf("Waiting for publication of %s\n"
"on topic %s for client with ClientID: %s\n",
PAYLOAD, TOPIC, CLIENTID);
while (!finished)
#if defined(_WIN32)
Sleep(100);
#else
usleep(10000L);
#endif
MQTTAsync_destroy(&client);
return rc;
}

View File

@@ -0,0 +1,218 @@
/*******************************************************************************
* Copyright (c) 2012, 2023 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* https://www.eclipse.org/legal/epl-2.0/
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial contribution
* Frank Pagliughi - loop to repeatedly read and sent time values.
*******************************************************************************/
// This is a somewhat contrived example to show an application that publishes
// continuously, like a data acquisition app might do. In this case, though,
// we don't have a sensor to read, so we use the system time as the number
// of milliseconds since the epoch to simulate a data input.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <time.h>
#include "MQTTAsync.h"
#if !defined(_WIN32)
#include <unistd.h>
#else
#include <windows.h>
#include <Minwinbase.h>
#endif
#if defined(_WRS_KERNEL)
#include <OsWrapper.h>
#endif
#if defined(_WIN32)
#define snprintf _snprintf
#endif
// Better not to flood a public broker. Test against localhost.
#define ADDRESS "mqtt://localhost:1883"
#define CLIENTID "ExampleClientTimePub"
#define TOPIC "data/time"
#define QOS 1
#define TIMEOUT 10000L
#define SAMPLE_PERIOD 10L // in ms
volatile int finished = 0;
volatile int connected = 0;
void connlost(void *context, char *cause)
{
MQTTAsync client = (MQTTAsync)context;
MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
int rc;
printf("\nConnection lost\n");
if (cause)
printf(" cause: %s\n", cause);
printf("Reconnecting\n");
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
{
printf("Failed to start connect, return code %d\n", rc);
finished = 1;
}
}
void onDisconnectFailure(void* context, MQTTAsync_failureData* response)
{
printf("Disconnect failed\n");
finished = 1;
}
void onDisconnect(void* context, MQTTAsync_successData* response)
{
printf("Successful disconnection\n");
finished = 1;
}
void onSendFailure(void* context, MQTTAsync_failureData* response)
{
MQTTAsync client = (MQTTAsync)context;
MQTTAsync_disconnectOptions opts = MQTTAsync_disconnectOptions_initializer;
int rc;
printf("Message send failed token %d error code %d\n", response->token, response->code);
opts.onSuccess = onDisconnect;
opts.onFailure = onDisconnectFailure;
opts.context = client;
if ((rc = MQTTAsync_disconnect(client, &opts)) != MQTTASYNC_SUCCESS)
{
printf("Failed to start disconnect, return code %d\n", rc);
exit(EXIT_FAILURE);
}
}
void onSend(void* context, MQTTAsync_successData* response)
{
// This gets called when a message is acknowledged successfully.
}
void onConnectFailure(void* context, MQTTAsync_failureData* response)
{
printf("Connect failed, rc %d\n", response ? response->code : 0);
finished = 1;
}
void onConnect(void* context, MQTTAsync_successData* response)
{
printf("Successful connection\n");
connected = 1;
}
int messageArrived(void* context, char* topicName, int topicLen, MQTTAsync_message* m)
{
/* not expecting any messages */
return 1;
}
int64_t getTime(void)
{
#if defined(_WIN32)
FILETIME ft;
GetSystemTimeAsFileTime(&ft);
return ((((int64_t) ft.dwHighDateTime) << 8) + ft.dwLowDateTime) / 10000;
#else
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
return ((int64_t) ts.tv_sec * 1000) + ((int64_t) ts.tv_nsec / 1000000);
#endif
}
int main(int argc, char* argv[])
{
MQTTAsync client;
MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
MQTTAsync_message pubmsg = MQTTAsync_message_initializer;
MQTTAsync_responseOptions pub_opts = MQTTAsync_responseOptions_initializer;
int rc;
if ((rc = MQTTAsync_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL)) != MQTTASYNC_SUCCESS)
{
printf("Failed to create client object, return code %d\n", rc);
exit(EXIT_FAILURE);
}
if ((rc = MQTTAsync_setCallbacks(client, client, connlost, messageArrived, NULL)) != MQTTASYNC_SUCCESS)
{
printf("Failed to set callback, return code %d\n", rc);
exit(EXIT_FAILURE);
}
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
conn_opts.onSuccess = onConnect;
conn_opts.onFailure = onConnectFailure;
conn_opts.context = client;
if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
{
printf("Failed to start connect, return code %d\n", rc);
exit(EXIT_FAILURE);
}
while (!connected) {
#if defined(_WIN32)
Sleep(100);
#else
usleep(100000L);
#endif
}
while (!finished) {
int64_t t = getTime();
char buf[256];
int n = snprintf(buf, sizeof(buf), "%lld", (long long) t);
printf("%s\n", buf);
pub_opts.onSuccess = onSend;
pub_opts.onFailure = onSendFailure;
pub_opts.context = client;
pubmsg.payload = buf;
pubmsg.payloadlen = n;
pubmsg.qos = QOS;
pubmsg.retained = 0;
if ((rc = MQTTAsync_sendMessage(client, TOPIC, &pubmsg, &pub_opts)) != MQTTASYNC_SUCCESS)
{
printf("Failed to start sendMessage, return code %d\n", rc);
exit(EXIT_FAILURE);
}
#if defined(_WIN32)
Sleep(SAMPLE_PERIOD);
#else
usleep(SAMPLE_PERIOD * 1000);
#endif
}
MQTTAsync_destroy(&client);
return rc;
}

View File

@@ -0,0 +1,206 @@
/*******************************************************************************
* Copyright (c) 2012, 2025 IBM Corp., Ian Craggs
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* https://www.eclipse.org/legal/epl-2.0/
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial contribution
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MQTTAsync.h"
#if !defined(_WIN32)
#include <unistd.h>
#else
#include <windows.h>
#endif
#if defined(_WRS_KERNEL)
#include <OsWrapper.h>
#endif
#define ADDRESS "tcp://test.mosquitto.org:1883"
#define CLIENTID "ExampleClientSub"
#define TOPIC "MQTT Examples"
#define PAYLOAD "Hello World!"
#define QOS 1
#define TIMEOUT 10000L
int disc_finished = 0;
int subscribed = 0;
int finished = 0;
void onConnect(void* context, MQTTAsync_successData* response);
void onConnectFailure(void* context, MQTTAsync_failureData* response);
void connlost(void *context, char *cause)
{
MQTTAsync client = (MQTTAsync)context;
MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
int rc;
printf("\nConnection lost\n");
if (cause)
printf(" cause: %s\n", cause);
printf("Reconnecting\n");
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
conn_opts.onSuccess = onConnect;
conn_opts.onFailure = onConnectFailure;
if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
{
printf("Failed to start connect, return code %d\n", rc);
finished = 1;
}
}
int msgarrvd(void *context, char *topicName, int topicLen, MQTTAsync_message *message)
{
printf("Message arrived\n");
printf(" topic: %s\n", topicName);
printf(" message: %.*s\n", message->payloadlen, (char*)message->payload);
MQTTAsync_freeMessage(&message);
MQTTAsync_free(topicName);
return 1;
}
void onDisconnectFailure(void* context, MQTTAsync_failureData* response)
{
printf("Disconnect failed, rc %d\n", response->code);
disc_finished = 1;
}
void onDisconnect(void* context, MQTTAsync_successData* response)
{
printf("Successful disconnection\n");
disc_finished = 1;
}
void onSubscribe(void* context, MQTTAsync_successData* response)
{
printf("Subscribe succeeded\n");
subscribed = 1;
}
void onSubscribeFailure(void* context, MQTTAsync_failureData* response)
{
printf("Subscribe failed, rc %d\n", response->code);
finished = 1;
}
void onConnectFailure(void* context, MQTTAsync_failureData* response)
{
printf("Connect failed, rc %d\n", response->code);
finished = 1;
}
void onConnect(void* context, MQTTAsync_successData* response)
{
MQTTAsync client = (MQTTAsync)context;
MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
int rc;
printf("Successful connection\n");
printf("Subscribing to topic %s\nfor client %s using QoS%d\n\n"
"Press Q<Enter> to quit\n\n", TOPIC, CLIENTID, QOS);
opts.onSuccess = onSubscribe;
opts.onFailure = onSubscribeFailure;
opts.context = client;
if ((rc = MQTTAsync_subscribe(client, TOPIC, QOS, &opts)) != MQTTASYNC_SUCCESS)
{
printf("Failed to start subscribe, return code %d\n", rc);
finished = 1;
}
}
int main(int argc, char* argv[])
{
MQTTAsync client;
MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
MQTTAsync_disconnectOptions disc_opts = MQTTAsync_disconnectOptions_initializer;
int rc;
int ch;
const char* uri = (argc > 1) ? argv[1] : ADDRESS;
printf("Using server at %s\n", uri);
if ((rc = MQTTAsync_create(&client, uri, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL))
!= MQTTASYNC_SUCCESS)
{
printf("Failed to create client, return code %d\n", rc);
rc = EXIT_FAILURE;
goto exit;
}
if ((rc = MQTTAsync_setCallbacks(client, client, connlost, msgarrvd, NULL)) != MQTTASYNC_SUCCESS)
{
printf("Failed to set callbacks, return code %d\n", rc);
rc = EXIT_FAILURE;
goto destroy_exit;
}
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
conn_opts.onSuccess = onConnect;
conn_opts.onFailure = onConnectFailure;
conn_opts.context = client;
if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
{
printf("Failed to start connect, return code %d\n", rc);
rc = EXIT_FAILURE;
goto destroy_exit;
}
while (!subscribed && !finished)
#if defined(_WIN32)
Sleep(100);
#else
usleep(10000L);
#endif
if (finished)
goto exit;
do
{
ch = getchar();
} while (ch!='Q' && ch != 'q');
disc_opts.onSuccess = onDisconnect;
disc_opts.onFailure = onDisconnectFailure;
if ((rc = MQTTAsync_disconnect(client, &disc_opts)) != MQTTASYNC_SUCCESS)
{
printf("Failed to start disconnect, return code %d\n", rc);
rc = EXIT_FAILURE;
goto destroy_exit;
}
while (!disc_finished)
{
#if defined(_WIN32)
Sleep(100);
#else
usleep(10000L);
#endif
}
destroy_exit:
MQTTAsync_destroy(&client);
exit:
return rc;
}

View File

@@ -0,0 +1,75 @@
/*******************************************************************************
* Copyright (c) 2012, 2025 IBM Corp., Ian Craggs
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* https://www.eclipse.org/legal/epl-2.0/
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial contribution
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MQTTClient.h"
#define ADDRESS "tcp://test.mosquitto.org:1883"
#define CLIENTID "ExampleClientPub"
#define TOPIC "MQTT Examples"
#define PAYLOAD "Hello World!"
#define QOS 1
#define TIMEOUT 10000L
int main(int argc, char* argv[])
{
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
MQTTClient_message pubmsg = MQTTClient_message_initializer;
MQTTClient_deliveryToken token;
int rc;
const char* uri = (argc > 1) ? argv[1] : ADDRESS;
printf("Using server at %s\n", uri);
if ((rc = MQTTClient_create(&client, uri, CLIENTID,
MQTTCLIENT_PERSISTENCE_NONE, NULL)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to create client, return code %d\n", rc);
exit(EXIT_FAILURE);
}
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to connect, return code %d\n", rc);
exit(EXIT_FAILURE);
}
pubmsg.payload = PAYLOAD;
pubmsg.payloadlen = (int)strlen(PAYLOAD);
pubmsg.qos = QOS;
pubmsg.retained = 0;
if ((rc = MQTTClient_publishMessage(client, TOPIC, &pubmsg, &token)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to publish message, return code %d\n", rc);
exit(EXIT_FAILURE);
}
printf("Waiting for up to %d seconds for publication of %s\n"
"on topic %s for client with ClientID: %s\n",
(int)(TIMEOUT/1000), PAYLOAD, TOPIC, CLIENTID);
rc = MQTTClient_waitForCompletion(client, token, TIMEOUT);
printf("Message with delivery token %d delivered\n", token);
if ((rc = MQTTClient_disconnect(client, 10000)) != MQTTCLIENT_SUCCESS)
printf("Failed to disconnect, return code %d\n", rc);
MQTTClient_destroy(&client);
return rc;
}

View File

@@ -0,0 +1,131 @@
/*******************************************************************************
* Copyright (c) 2012, 2025 IBM Corp., Ian Craggs
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* https://www.eclipse.org/legal/epl-2.0/
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial contribution
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MQTTClient.h"
#if !defined(_WIN32)
#include <unistd.h>
#else
#include <windows.h>
#endif
#define ADDRESS "tcp://test.mosquitto.org:1883"
#define CLIENTID "ExampleClientPub"
#define TOPIC "MQTT Examples"
#define PAYLOAD "Hello World!"
#define QOS 1
#define TIMEOUT 10000L
MQTTClient_deliveryToken deliveredtoken;
void delivered(void *context, MQTTClient_deliveryToken dt)
{
printf("Message with token value %d delivery confirmed\n", dt);
deliveredtoken = dt;
}
int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
printf("Message arrived\n");
printf(" topic: %s\n", topicName);
printf(" message: %.*s\n", message->payloadlen, (char*)message->payload);
MQTTClient_freeMessage(&message);
MQTTClient_free(topicName);
return 1;
}
void connlost(void *context, char *cause)
{
printf("\nConnection lost\n");
if (cause)
printf(" cause: %s\n", cause);
}
int main(int argc, char* argv[])
{
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
MQTTClient_message pubmsg = MQTTClient_message_initializer;
MQTTClient_deliveryToken token;
int rc;
const char* uri = (argc > 1) ? argv[1] : ADDRESS;
printf("Using server at %s\n", uri);
if ((rc = MQTTClient_create(&client, uri, CLIENTID,
MQTTCLIENT_PERSISTENCE_NONE, NULL)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to create client, return code %d\n", rc);
rc = EXIT_FAILURE;
goto exit;
}
if ((rc = MQTTClient_setCallbacks(client, NULL, connlost, msgarrvd, delivered)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to set callbacks, return code %d\n", rc);
rc = EXIT_FAILURE;
goto destroy_exit;
}
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to connect, return code %d\n", rc);
rc = EXIT_FAILURE;
goto destroy_exit;
}
pubmsg.payload = PAYLOAD;
pubmsg.payloadlen = (int)strlen(PAYLOAD);
pubmsg.qos = QOS;
pubmsg.retained = 0;
deliveredtoken = 0;
if ((rc = MQTTClient_publishMessage(client, TOPIC, &pubmsg, &token)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to publish message, return code %d\n", rc);
rc = EXIT_FAILURE;
}
else
{
printf("Waiting for publication of %s\n"
"on topic %s for client with ClientID: %s\n",
PAYLOAD, TOPIC, CLIENTID);
while (deliveredtoken != token)
{
#if defined(_WIN32)
Sleep(100);
#else
usleep(10000L);
#endif
}
}
if ((rc = MQTTClient_disconnect(client, 10000)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to disconnect, return code %d\n", rc);
rc = EXIT_FAILURE;
}
destroy_exit:
MQTTClient_destroy(&client);
exit:
return rc;
}

View File

@@ -0,0 +1,118 @@
/*******************************************************************************
* Copyright (c) 2012, 2025 IBM Corp., Ian Craggs
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* https://www.eclipse.org/legal/epl-2.0/
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial contribution
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MQTTClient.h"
#define ADDRESS "tcp://test.mosquitto.org:1883"
#define CLIENTID "ExampleClientSub"
#define TOPIC "MQTT Examples"
#define PAYLOAD "Hello World!"
#define QOS 1
#define TIMEOUT 10000L
volatile MQTTClient_deliveryToken deliveredtoken;
void delivered(void *context, MQTTClient_deliveryToken dt)
{
printf("Message with token value %d delivery confirmed\n", dt);
deliveredtoken = dt;
}
int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
printf("Message arrived\n");
printf(" topic: %s\n", topicName);
printf(" message: %.*s\n", message->payloadlen, (char*)message->payload);
MQTTClient_freeMessage(&message);
MQTTClient_free(topicName);
return 1;
}
void connlost(void *context, char *cause)
{
printf("\nConnection lost\n");
if (cause)
printf(" cause: %s\n", cause);
}
int main(int argc, char* argv[])
{
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
int rc;
const char* uri = (argc > 1) ? argv[1] : ADDRESS;
printf("Using server at %s\n", uri);
if ((rc = MQTTClient_create(&client, uri, CLIENTID,
MQTTCLIENT_PERSISTENCE_NONE, NULL)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to create client, return code %d\n", rc);
rc = EXIT_FAILURE;
goto exit;
}
if ((rc = MQTTClient_setCallbacks(client, NULL, connlost, msgarrvd, delivered)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to set callbacks, return code %d\n", rc);
rc = EXIT_FAILURE;
goto destroy_exit;
}
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to connect, return code %d\n", rc);
rc = EXIT_FAILURE;
goto destroy_exit;
}
printf("Subscribing to topic %s\nfor client %s using QoS%d\n\n"
"Press Q<Enter> to quit\n\n", TOPIC, CLIENTID, QOS);
if ((rc = MQTTClient_subscribe(client, TOPIC, QOS)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to subscribe, return code %d\n", rc);
rc = EXIT_FAILURE;
}
else
{
int ch;
do
{
ch = getchar();
} while (ch!='Q' && ch != 'q');
if ((rc = MQTTClient_unsubscribe(client, TOPIC)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to unsubscribe, return code %d\n", rc);
rc = EXIT_FAILURE;
}
}
if ((rc = MQTTClient_disconnect(client, 10000)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to disconnect, return code %d\n", rc);
rc = EXIT_FAILURE;
}
destroy_exit:
MQTTClient_destroy(&client);
exit:
return rc;
}

View File

@@ -0,0 +1,519 @@
/*******************************************************************************
* Copyright (c) 2012, 2025 IBM Corp., Ian Craggs and others
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* https://www.eclipse.org/legal/epl-2.0/
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial contribution
* Guilherme Maciel Ferreira - add keep alive option
* Ian Craggs - add full capability
*******************************************************************************/
#include "MQTTAsync.h"
#include "pubsub_opts.h"
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#if defined(_WIN32)
#include <windows.h>
#define sleep Sleep
#else
#include <unistd.h>
#include <sys/time.h>
#include <unistd.h>
#endif
#if defined(_WRS_KERNEL)
#include <OsWrapper.h>
#endif
volatile int toStop = 0;
struct pubsub_opts opts =
{
1, 0, 0, 0, "\n", 100, /* debug/app options */
NULL, NULL, 1, 0, 0, /* message options */
MQTTVERSION_DEFAULT, NULL, "paho-c-pub", 0, 0, NULL, NULL, "localhost", "1883", NULL, 10, /* MQTT options */
NULL, NULL, 0, 0, /* will options */
0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* TLS options */
0, {NULL, NULL}, /* MQTT V5 options */
NULL, NULL, /* HTTP and HTTPS proxies */
};
MQTTAsync_responseOptions pub_opts = MQTTAsync_responseOptions_initializer;
MQTTProperty property;
MQTTProperties props = MQTTProperties_initializer;
void mysleep(int ms)
{
#if defined(_WIN32)
Sleep(ms);
#else
usleep(ms * 1000);
#endif
}
void cfinish(int sig)
{
signal(SIGINT, NULL);
toStop = 1;
}
int messageArrived(void* context, char* topicName, int topicLen, MQTTAsync_message* m)
{
/* not expecting any messages */
return 1;
}
static int disconnected = 0;
void onDisconnect5(void* context, MQTTAsync_successData5* response)
{
disconnected = 1;
}
void onDisconnect(void* context, MQTTAsync_successData* response)
{
disconnected = 1;
}
static int connected = 0;
void myconnect(MQTTAsync client);
int mypublish(MQTTAsync client, int datalen, char* data);
void onConnectFailure5(void* context, MQTTAsync_failureData5* response)
{
fprintf(stderr, "Connect failed, rc %s reason code %s\n",
MQTTAsync_strerror(response->code),
MQTTReasonCode_toString(response->reasonCode));
connected = -1;
MQTTAsync client = (MQTTAsync)context;
}
void onConnectFailure(void* context, MQTTAsync_failureData* response)
{
fprintf(stderr, "Connect failed, rc %s\n", response ? MQTTAsync_strerror(response->code) : "none");
connected = -1;
MQTTAsync client = (MQTTAsync)context;
}
void onConnect5(void* context, MQTTAsync_successData5* response)
{
MQTTAsync client = (MQTTAsync)context;
int rc = 0;
if (opts.verbose)
printf("Connected\n");
if (opts.null_message == 1)
rc = mypublish(client, 0, "");
else if (opts.message)
rc = mypublish(client, (int)strlen(opts.message), opts.message);
else if (opts.filename)
{
int data_len = 0;
char* buffer = readfile(&data_len, &opts);
if (buffer == NULL)
toStop = 1;
else
{
rc = mypublish(client, data_len, buffer);
free(buffer);
}
}
connected = 1;
}
void onConnect(void* context, MQTTAsync_successData* response)
{
MQTTAsync client = (MQTTAsync)context;
int rc = 0;
if (opts.verbose)
printf("Connected\n");
if (opts.null_message == 1)
rc = mypublish(client, 0, "");
else if (opts.message)
rc = mypublish(client, (int)strlen(opts.message), opts.message);
else if (opts.filename)
{
int data_len = 0;
char* buffer = readfile(&data_len, &opts);
if (buffer == NULL)
toStop = 1;
else
{
rc = mypublish(client, data_len, buffer);
free(buffer);
}
}
connected = 1;
}
static int published = 0;
void onPublishFailure5(void* context, MQTTAsync_failureData5* response)
{
if (opts.verbose)
fprintf(stderr, "Publish failed, rc %s reason code %s\n",
MQTTAsync_strerror(response->code),
MQTTReasonCode_toString(response->reasonCode));
published = -1;
}
void onPublishFailure(void* context, MQTTAsync_failureData* response)
{
if (opts.verbose)
fprintf(stderr, "Publish failed, rc %s\n", MQTTAsync_strerror(response->code));
published = -1;
}
void onPublish5(void* context, MQTTAsync_successData5* response)
{
if (opts.verbose)
printf("Publish succeeded, reason code %s\n",
MQTTReasonCode_toString(response->reasonCode));
if (opts.null_message || opts.message || opts.filename)
toStop = 1;
published = 1;
}
void onPublish(void* context, MQTTAsync_successData* response)
{
if (opts.verbose)
printf("Publish succeeded\n");
if (opts.null_message || opts.message || opts.filename)
toStop = 1;
published = 1;
}
static int onSSLError(const char *str, size_t len, void *context)
{
MQTTAsync client = (MQTTAsync)context;
return fprintf(stderr, "SSL error: %s\n", str);
}
static unsigned int onPSKAuth(const char* hint,
char* identity,
unsigned int max_identity_len,
unsigned char* psk,
unsigned int max_psk_len,
void* context)
{
int psk_len;
int k, n;
int rc = 0;
struct pubsub_opts* opts = context;
/* printf("Trying TLS-PSK auth with hint: %s\n", hint);*/
if (opts->psk == NULL || opts->psk_identity == NULL)
{
/* printf("No PSK entered\n"); */
goto exit;
}
/* psk should be array of bytes. This is a quick and dirty way to
* convert hex to bytes without input validation */
psk_len = (int)strlen(opts->psk) / 2;
if (psk_len > max_psk_len)
{
fprintf(stderr, "PSK too long\n");
goto exit;
}
for (k=0, n=0; k < psk_len; k++, n += 2)
{
sscanf(&opts->psk[n], "%2hhx", &psk[k]);
}
/* identity should be NULL terminated string */
strncpy(identity, opts->psk_identity, max_identity_len);
if (identity[max_identity_len - 1] != '\0')
{
fprintf(stderr, "Identity too long\n");
goto exit;
}
/* Function should return length of psk on success. */
rc = psk_len;
exit:
return rc;
}
void myconnect(MQTTAsync client)
{
MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
MQTTAsync_SSLOptions ssl_opts = MQTTAsync_SSLOptions_initializer;
MQTTAsync_willOptions will_opts = MQTTAsync_willOptions_initializer;
int rc = 0;
if (opts.verbose)
printf("Connecting\n");
if (opts.MQTTVersion == MQTTVERSION_5)
{
MQTTAsync_connectOptions conn_opts5 = MQTTAsync_connectOptions_initializer5;
conn_opts = conn_opts5;
conn_opts.onSuccess5 = onConnect5;
conn_opts.onFailure5 = onConnectFailure5;
conn_opts.cleanstart = 1;
}
else
{
conn_opts.onSuccess = onConnect;
conn_opts.onFailure = onConnectFailure;
conn_opts.cleansession = 1;
}
conn_opts.keepAliveInterval = opts.keepalive;
conn_opts.username = opts.username;
conn_opts.password = opts.password;
conn_opts.MQTTVersion = opts.MQTTVersion;
conn_opts.context = client;
conn_opts.automaticReconnect = 1;
conn_opts.httpProxy = opts.http_proxy;
conn_opts.httpsProxy = opts.https_proxy;
if (opts.will_topic) /* will options */
{
will_opts.message = opts.will_payload;
will_opts.topicName = opts.will_topic;
will_opts.qos = opts.will_qos;
will_opts.retained = opts.will_retain;
conn_opts.will = &will_opts;
}
if (opts.connection && (strncmp(opts.connection, "ssl://", 6) == 0 ||
strncmp(opts.connection, "tls://", 6) == 0 ||
strncmp(opts.connection, "mqtts://", 7) == 0 ||
strncmp(opts.connection, "wss://", 6) == 0))
{
if (opts.insecure)
ssl_opts.verify = 0;
else
ssl_opts.verify = 1;
ssl_opts.CApath = opts.capath;
ssl_opts.keyStore = opts.cert;
ssl_opts.trustStore = opts.cafile;
ssl_opts.privateKey = opts.key;
ssl_opts.privateKeyPassword = opts.keypass;
ssl_opts.enabledCipherSuites = opts.ciphers;
ssl_opts.ssl_error_cb = onSSLError;
ssl_opts.ssl_error_context = client;
ssl_opts.ssl_psk_cb = onPSKAuth;
ssl_opts.ssl_psk_context = &opts;
conn_opts.ssl = &ssl_opts;
}
connected = 0;
if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
{
fprintf(stderr, "Failed to start connect, return code %s\n", MQTTAsync_strerror(rc));
exit(EXIT_FAILURE);
}
}
int mypublish(MQTTAsync client, int datalen, char* data)
{
int rc;
if (opts.verbose)
printf("Publishing data of length %d\n", datalen);
rc = MQTTAsync_send(client, opts.topic, datalen, data, opts.qos, opts.retained, &pub_opts);
if (opts.verbose && rc != MQTTASYNC_SUCCESS && !opts.quiet)
fprintf(stderr, "Error from MQTTAsync_send: %s\n", MQTTAsync_strerror(rc));
return rc;
}
void trace_callback(enum MQTTASYNC_TRACE_LEVELS level, char* message)
{
fprintf(stderr, "Trace : %d, %s\n", level, message);
}
int main(int argc, char** argv)
{
MQTTAsync_disconnectOptions disc_opts = MQTTAsync_disconnectOptions_initializer;
MQTTAsync_createOptions create_opts = MQTTAsync_createOptions_initializer;
MQTTAsync client;
char* buffer = NULL;
char* url = NULL;
int url_allocated = 0;
int rc = 0;
const char* version = NULL;
const char* program_name = "paho_c_pub";
MQTTAsync_nameValue* infos = MQTTAsync_getVersionInfo();
#if !defined(_WIN32)
struct sigaction sa;
#endif
if (argc < 2)
usage(&opts, (pubsub_opts_nameValue*)infos, program_name);
if (getopts(argc, argv, &opts) != 0)
usage(&opts, (pubsub_opts_nameValue*)infos, program_name);
if (opts.connection)
url = opts.connection;
else
{
url = malloc(100);
url_allocated = 1;
sprintf(url, "%s:%s", opts.host, opts.port);
}
if (opts.verbose)
printf("URL is %s\n", url);
if (opts.tracelevel > 0)
{
MQTTAsync_setTraceCallback(trace_callback);
MQTTAsync_setTraceLevel(opts.tracelevel);
}
create_opts.sendWhileDisconnected = 1;
if (opts.MQTTVersion >= MQTTVERSION_5)
create_opts.MQTTVersion = MQTTVERSION_5;
rc = MQTTAsync_createWithOptions(&client, url, opts.clientid, MQTTCLIENT_PERSISTENCE_NONE, NULL, &create_opts);
if (rc != MQTTASYNC_SUCCESS)
{
if (!opts.quiet)
fprintf(stderr, "Failed to create client, return code: %s\n", MQTTAsync_strerror(rc));
exit(EXIT_FAILURE);
}
#if defined(_WIN32)
signal(SIGINT, cfinish);
signal(SIGTERM, cfinish);
#else
memset(&sa, 0, sizeof(struct sigaction));
sa.sa_handler = cfinish;
sa.sa_flags = 0;
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
#endif
rc = MQTTAsync_setCallbacks(client, client, NULL, messageArrived, NULL);
if (rc != MQTTASYNC_SUCCESS)
{
if (!opts.quiet)
fprintf(stderr, "Failed to set callbacks, return code: %s\n", MQTTAsync_strerror(rc));
exit(EXIT_FAILURE);
}
if (opts.MQTTVersion >= MQTTVERSION_5)
{
pub_opts.onSuccess5 = onPublish5;
pub_opts.onFailure5 = onPublishFailure5;
if (opts.message_expiry > 0)
{
property.identifier = MQTTPROPERTY_CODE_MESSAGE_EXPIRY_INTERVAL;
property.value.integer4 = opts.message_expiry;
MQTTProperties_add(&props, &property);
}
if (opts.user_property.name)
{
property.identifier = MQTTPROPERTY_CODE_USER_PROPERTY;
property.value.data.data = opts.user_property.name;
property.value.data.len = (int)strlen(opts.user_property.name);
property.value.value.data = opts.user_property.value;
property.value.value.len = (int)strlen(opts.user_property.value);
MQTTProperties_add(&props, &property);
}
pub_opts.properties = props;
}
else
{
pub_opts.onSuccess = onPublish;
pub_opts.onFailure = onPublishFailure;
}
myconnect(client);
while (!toStop)
{
int data_len = 0;
int delim_len = 0;
if (opts.stdin_lines)
{
buffer = malloc(opts.maxdatalen);
delim_len = (int)strlen(opts.delimiter);
do
{
buffer[data_len++] = getchar();
if (data_len > delim_len)
{
if (strncmp(opts.delimiter, &buffer[data_len - delim_len], delim_len) == 0)
break;
}
} while (data_len < opts.maxdatalen);
rc = mypublish(client, data_len, buffer);
}
else
mysleep(100);
}
if (opts.message == 0 && opts.null_message == 0 && opts.filename == 0)
free(buffer);
if (opts.MQTTVersion >= MQTTVERSION_5)
disc_opts.onSuccess5 = onDisconnect5;
else
disc_opts.onSuccess = onDisconnect;
if ((rc = MQTTAsync_disconnect(client, &disc_opts)) != MQTTASYNC_SUCCESS)
{
if (!opts.quiet)
fprintf(stderr, "Failed to start disconnect, return code: %s\n", MQTTAsync_strerror(rc));
exit(EXIT_FAILURE);
}
while (!disconnected)
mysleep(100);
MQTTAsync_destroy(&client);
if (url_allocated)
free(url);
return EXIT_SUCCESS;
}

View File

@@ -0,0 +1,351 @@
/*******************************************************************************
* Copyright (c) 2012, 2025 IBM Corp., Ian Craggs and others
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* https://www.eclipse.org/legal/epl-2.0/
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial contribution
* Ian Craggs - fix for bug 413429 - connectionLost not called
* Guilherme Maciel Ferreira - add keep alive option
* Ian Craggs - add full capability
*******************************************************************************/
#include "MQTTAsync.h"
#include "MQTTClientPersistence.h"
#include "pubsub_opts.h"
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#if defined(_WIN32)
#include <windows.h>
#define sleep Sleep
#else
#include <sys/time.h>
#include <unistd.h>
#endif
#if defined(_WRS_KERNEL)
#include <OsWrapper.h>
#endif
volatile int finished = 0;
int subscribed = 0;
int disconnected = 0;
void mysleep(int ms)
{
#if defined(_WIN32)
Sleep(ms);
#else
usleep(ms * 1000);
#endif
}
void cfinish(int sig)
{
signal(SIGINT, NULL);
finished = 1;
}
struct pubsub_opts opts =
{
0, 0, 0, 0, "\n", 100, /* debug/app options */
NULL, NULL, 1, 0, 0, /* message options */
MQTTVERSION_DEFAULT, NULL, "paho-c-sub", 0, 0, NULL, NULL, "localhost", "1883", NULL, 10, /* MQTT options */
NULL, NULL, 0, 0, /* will options */
0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* TLS options */
0, {NULL, NULL}, /* MQTT V5 options */
NULL, NULL, /* HTTP and HTTPS proxies */
};
int messageArrived(void *context, char *topicName, int topicLen, MQTTAsync_message *message)
{
size_t delimlen = 0;
if (opts.verbose)
printf("%d %s\t", message->payloadlen, topicName);
if (opts.delimiter)
delimlen = strlen(opts.delimiter);
if (opts.delimiter == NULL || (message->payloadlen > delimlen &&
strncmp(opts.delimiter, &((char*)message->payload)[message->payloadlen - delimlen], delimlen) == 0))
printf("%.*s", message->payloadlen, (char*)message->payload);
else
printf("%.*s%s", message->payloadlen, (char*)message->payload, opts.delimiter);
if (message->struct_version == 1 && opts.verbose)
logProperties(&message->properties);
fflush(stdout);
MQTTAsync_freeMessage(&message);
MQTTAsync_free(topicName);
return 1;
}
void onDisconnect(void* context, MQTTAsync_successData* response)
{
disconnected = 1;
}
void onSubscribe5(void* context, MQTTAsync_successData5* response)
{
subscribed = 1;
}
void onSubscribe(void* context, MQTTAsync_successData* response)
{
subscribed = 1;
}
void onSubscribeFailure5(void* context, MQTTAsync_failureData5* response)
{
if (!opts.quiet)
fprintf(stderr, "Subscribe failed, rc %s reason code %s\n",
MQTTAsync_strerror(response->code),
MQTTReasonCode_toString(response->reasonCode));
finished = 1;
}
void onSubscribeFailure(void* context, MQTTAsync_failureData* response)
{
if (!opts.quiet)
fprintf(stderr, "Subscribe failed, rc %s\n",
MQTTAsync_strerror(response->code));
finished = 1;
}
void onConnectFailure5(void* context, MQTTAsync_failureData5* response)
{
if (!opts.quiet)
fprintf(stderr, "Connect failed, rc %s reason code %s\n",
MQTTAsync_strerror(response->code),
MQTTReasonCode_toString(response->reasonCode));
finished = 1;
}
void onConnectFailure(void* context, MQTTAsync_failureData* response)
{
if (!opts.quiet)
fprintf(stderr, "Connect failed, rc %s\n", response ? MQTTAsync_strerror(response->code) : "none");
finished = 1;
}
void onConnect5(void* context, MQTTAsync_successData5* response)
{
MQTTAsync client = (MQTTAsync)context;
MQTTAsync_callOptions copts = MQTTAsync_callOptions_initializer;
int rc;
if (opts.verbose)
printf("Subscribing to topic %s with client %s at QoS %d\n", opts.topic, opts.clientid, opts.qos);
copts.onSuccess5 = onSubscribe5;
copts.onFailure5 = onSubscribeFailure5;
copts.context = client;
if ((rc = MQTTAsync_subscribe(client, opts.topic, opts.qos, &copts)) != MQTTASYNC_SUCCESS)
{
if (!opts.quiet)
fprintf(stderr, "Failed to start subscribe, return code %s\n", MQTTAsync_strerror(rc));
finished = 1;
}
}
void onConnect(void* context, MQTTAsync_successData* response)
{
MQTTAsync client = (MQTTAsync)context;
MQTTAsync_responseOptions ropts = MQTTAsync_responseOptions_initializer;
int rc;
if (opts.verbose)
printf("Subscribing to topic %s with client %s at QoS %d\n", opts.topic, opts.clientid, opts.qos);
ropts.onSuccess = onSubscribe;
ropts.onFailure = onSubscribeFailure;
ropts.context = client;
if ((rc = MQTTAsync_subscribe(client, opts.topic, opts.qos, &ropts)) != MQTTASYNC_SUCCESS)
{
if (!opts.quiet)
fprintf(stderr, "Failed to start subscribe, return code %s\n", MQTTAsync_strerror(rc));
finished = 1;
}
}
MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
void trace_callback(enum MQTTASYNC_TRACE_LEVELS level, char* message)
{
fprintf(stderr, "Trace : %d, %s\n", level, message);
}
int main(int argc, char** argv)
{
MQTTAsync client;
MQTTAsync_disconnectOptions disc_opts = MQTTAsync_disconnectOptions_initializer;
MQTTAsync_createOptions create_opts = MQTTAsync_createOptions_initializer;
MQTTAsync_willOptions will_opts = MQTTAsync_willOptions_initializer;
MQTTAsync_SSLOptions ssl_opts = MQTTAsync_SSLOptions_initializer;
int rc = 0;
char* url = NULL;
const char* version = NULL;
const char* program_name = "paho_c_sub";
MQTTAsync_nameValue* infos = MQTTAsync_getVersionInfo();
#if !defined(_WIN32)
struct sigaction sa;
#endif
if (argc < 2)
usage(&opts, (pubsub_opts_nameValue*)infos, program_name);
if (getopts(argc, argv, &opts) != 0)
usage(&opts, (pubsub_opts_nameValue*)infos, program_name);
if (strchr(opts.topic, '#') || strchr(opts.topic, '+'))
opts.verbose = 1;
if (opts.connection)
url = opts.connection;
else
{
url = malloc(100);
sprintf(url, "%s:%s", opts.host, opts.port);
}
if (opts.verbose)
printf("URL is %s\n", url);
if (opts.tracelevel > 0)
{
MQTTAsync_setTraceCallback(trace_callback);
MQTTAsync_setTraceLevel(opts.tracelevel);
}
if (opts.MQTTVersion >= MQTTVERSION_5)
create_opts.MQTTVersion = MQTTVERSION_5;
rc = MQTTAsync_createWithOptions(&client, url, opts.clientid, MQTTCLIENT_PERSISTENCE_NONE,
NULL, &create_opts);
if (rc != MQTTASYNC_SUCCESS)
{
if (!opts.quiet)
fprintf(stderr, "Failed to create client, return code: %s\n", MQTTAsync_strerror(rc));
exit(EXIT_FAILURE);
}
rc = MQTTAsync_setCallbacks(client, client, NULL, messageArrived, NULL);
if (rc != MQTTASYNC_SUCCESS)
{
if (!opts.quiet)
fprintf(stderr, "Failed to set callbacks, return code: %s\n", MQTTAsync_strerror(rc));
exit(EXIT_FAILURE);
}
#if defined(_WIN32)
signal(SIGINT, cfinish);
signal(SIGTERM, cfinish);
#else
memset(&sa, 0, sizeof(struct sigaction));
sa.sa_handler = cfinish;
sa.sa_flags = 0;
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
#endif
if (opts.MQTTVersion == MQTTVERSION_5)
{
MQTTAsync_connectOptions conn_opts5 = MQTTAsync_connectOptions_initializer5;
conn_opts = conn_opts5;
conn_opts.onSuccess5 = onConnect5;
conn_opts.onFailure5 = onConnectFailure5;
conn_opts.cleanstart = 1;
}
else
{
conn_opts.onSuccess = onConnect;
conn_opts.onFailure = onConnectFailure;
conn_opts.cleansession = 1;
}
conn_opts.keepAliveInterval = opts.keepalive;
conn_opts.username = opts.username;
conn_opts.password = opts.password;
conn_opts.MQTTVersion = opts.MQTTVersion;
conn_opts.context = client;
conn_opts.automaticReconnect = 1;
conn_opts.httpProxy = opts.http_proxy;
conn_opts.httpsProxy = opts.https_proxy;
if (opts.will_topic) /* will options */
{
will_opts.message = opts.will_payload;
will_opts.topicName = opts.will_topic;
will_opts.qos = opts.will_qos;
will_opts.retained = opts.will_retain;
conn_opts.will = &will_opts;
}
if (opts.connection && (strncmp(opts.connection, "ssl://", 6) == 0 ||
strncmp(opts.connection, "tls://", 6) == 0||
strncmp(opts.connection, "mqtts://", 7) == 0 ||
strncmp(opts.connection, "wss://", 6) == 0))
{
ssl_opts.verify = (opts.insecure) ? 0 : 1;
ssl_opts.CApath = opts.capath;
ssl_opts.keyStore = opts.cert;
ssl_opts.trustStore = opts.cafile;
ssl_opts.privateKey = opts.key;
ssl_opts.privateKeyPassword = opts.keypass;
ssl_opts.enabledCipherSuites = opts.ciphers;
conn_opts.ssl = &ssl_opts;
}
if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
{
if (!opts.quiet)
fprintf(stderr, "Failed to start connect, return code %s\n", MQTTAsync_strerror(rc));
exit(EXIT_FAILURE);
}
while (!subscribed)
mysleep(100);
if (finished)
goto exit;
while (!finished)
mysleep(100);
disc_opts.onSuccess = onDisconnect;
if ((rc = MQTTAsync_disconnect(client, &disc_opts)) != MQTTASYNC_SUCCESS)
{
if (!opts.quiet)
fprintf(stderr, "Failed to start disconnect, return code: %s\n", MQTTAsync_strerror(rc));
exit(EXIT_FAILURE);
}
while (!disconnected)
mysleep(100);
exit:
MQTTAsync_destroy(&client);
return EXIT_SUCCESS;
}

View File

@@ -0,0 +1,327 @@
/*******************************************************************************
* Copyright (c) 2012, 2025 IBM Corp., Ian Craggs
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* https://www.eclipse.org/legal/epl-2.0/
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial contribution
* Ian Craggs - add full capability
*******************************************************************************/
#include "MQTTClient.h"
#include "MQTTClientPersistence.h"
#include "pubsub_opts.h"
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#if defined(_WIN32)
#define sleep Sleep
#else
#include <sys/time.h>
#endif
volatile int toStop = 0;
void cfinish(int sig)
{
signal(SIGINT, NULL);
toStop = 1;
}
struct pubsub_opts opts =
{
1, 0, 0, 0, "\n", 100, /* debug/app options */
NULL, NULL, 1, 0, 0, /* message options */
MQTTVERSION_DEFAULT, NULL, "paho-cs-pub", 0, 0, NULL, NULL, "localhost", "1883", NULL, 10, /* MQTT options */
NULL, NULL, 0, 0, /* will options */
0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* TLS options */
0, {NULL, NULL}, /* MQTT V5 options */
NULL, NULL, /* HTTP and HTTPS proxies */
};
int myconnect(MQTTClient client)
{
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
MQTTClient_SSLOptions ssl_opts = MQTTClient_SSLOptions_initializer;
MQTTClient_willOptions will_opts = MQTTClient_willOptions_initializer;
int rc = 0;
if (opts.verbose)
printf("Connecting\n");
if (opts.MQTTVersion == MQTTVERSION_5)
{
MQTTClient_connectOptions conn_opts5 = MQTTClient_connectOptions_initializer5;
conn_opts = conn_opts5;
}
conn_opts.keepAliveInterval = opts.keepalive;
conn_opts.username = opts.username;
conn_opts.password = opts.password;
conn_opts.MQTTVersion = opts.MQTTVersion;
conn_opts.httpProxy = opts.http_proxy;
conn_opts.httpsProxy = opts.https_proxy;
if (opts.will_topic) /* will options */
{
will_opts.message = opts.will_payload;
will_opts.topicName = opts.will_topic;
will_opts.qos = opts.will_qos;
will_opts.retained = opts.will_retain;
conn_opts.will = &will_opts;
}
if (opts.connection && (strncmp(opts.connection, "ssl://", 6) == 0 ||
strncmp(opts.connection, "tls://", 6) == 0 ||
strncmp(opts.connection, "mqtts://", 7) == 0 ||
strncmp(opts.connection, "wss://", 6) == 0))
{
if (opts.insecure)
ssl_opts.verify = 0;
else
ssl_opts.verify = 1;
ssl_opts.CApath = opts.capath;
ssl_opts.keyStore = opts.cert;
ssl_opts.trustStore = opts.cafile;
ssl_opts.privateKey = opts.key;
ssl_opts.privateKeyPassword = opts.keypass;
ssl_opts.enabledCipherSuites = opts.ciphers;
conn_opts.ssl = &ssl_opts;
}
if (opts.MQTTVersion == MQTTVERSION_5)
{
MQTTProperties props = MQTTProperties_initializer;
MQTTProperties willProps = MQTTProperties_initializer;
MQTTResponse response = MQTTResponse_initializer;
conn_opts.cleanstart = 1;
response = MQTTClient_connect5(client, &conn_opts, &props, &willProps);
rc = response.reasonCode;
MQTTResponse_free(response);
}
else
{
conn_opts.cleansession = 1;
rc = MQTTClient_connect(client, &conn_opts);
}
if (opts.verbose && rc == MQTTCLIENT_SUCCESS)
printf("Connected\n");
else if (rc != MQTTCLIENT_SUCCESS && !opts.quiet)
fprintf(stderr, "Connect failed return code: %s\n", MQTTClient_strerror(rc));
return rc;
}
int messageArrived(void* context, char* topicName, int topicLen, MQTTClient_message* m)
{
/* not expecting any messages */
return 1;
}
void connectionLost(void* context, char* reason)
{
MQTTClient client = (MQTTClient)context;
if (opts.verbose)
printf("ConnectionLost, reconnecting\n");
myconnect(client);
}
void trace_callback(enum MQTTCLIENT_TRACE_LEVELS level, char* message)
{
fprintf(stderr, "Trace : %d, %s\n", level, message);
}
int main(int argc, char** argv)
{
MQTTClient client;
MQTTProperties pub_props = MQTTProperties_initializer;
MQTTClient_createOptions createOpts = MQTTClient_createOptions_initializer;
MQTTClient_deliveryToken last_token;
char* buffer = NULL;
int rc = 0;
char* url;
const char* version = NULL;
#if !defined(_WIN32)
struct sigaction sa;
#endif
const char* program_name = "paho_cs_pub";
MQTTClient_nameValue* infos = MQTTClient_getVersionInfo();
if (argc < 2)
usage(&opts, (pubsub_opts_nameValue*)infos, program_name);
if (getopts(argc, argv, &opts) != 0)
usage(&opts, (pubsub_opts_nameValue*)infos, program_name);
if (opts.connection)
url = opts.connection;
else
{
url = malloc(100);
sprintf(url, "%s:%s", opts.host, opts.port);
}
if (opts.verbose)
printf("URL is %s\n", url);
if (opts.tracelevel > 0)
{
MQTTClient_setTraceCallback(trace_callback);
MQTTClient_setTraceLevel(opts.tracelevel);
}
if (opts.MQTTVersion >= MQTTVERSION_5)
createOpts.MQTTVersion = MQTTVERSION_5;
rc = MQTTClient_createWithOptions(&client, url, opts.clientid, MQTTCLIENT_PERSISTENCE_NONE,
NULL, &createOpts);
if (rc != MQTTCLIENT_SUCCESS)
{
if (!opts.quiet)
fprintf(stderr, "Failed to create client, return code: %s\n", MQTTClient_strerror(rc));
exit(EXIT_FAILURE);
}
#if defined(_WIN32)
signal(SIGINT, cfinish);
signal(SIGTERM, cfinish);
#else
memset(&sa, 0, sizeof(struct sigaction));
sa.sa_handler = cfinish;
sa.sa_flags = 0;
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
#endif
rc = MQTTClient_setCallbacks(client, client, connectionLost, messageArrived, NULL);
if (rc != MQTTCLIENT_SUCCESS)
{
if (!opts.quiet)
fprintf(stderr, "Failed to set callbacks, return code: %s\n", MQTTClient_strerror(rc));
exit(EXIT_FAILURE);
}
if (myconnect(client) != MQTTCLIENT_SUCCESS)
goto exit;
if (opts.MQTTVersion >= MQTTVERSION_5)
{
MQTTProperty property;
if (opts.message_expiry > 0)
{
property.identifier = MQTTPROPERTY_CODE_MESSAGE_EXPIRY_INTERVAL;
property.value.integer4 = opts.message_expiry;
MQTTProperties_add(&pub_props, &property);
}
if (opts.user_property.name)
{
property.identifier = MQTTPROPERTY_CODE_USER_PROPERTY;
property.value.data.data = opts.user_property.name;
property.value.data.len = (int)strlen(opts.user_property.name);
property.value.value.data = opts.user_property.value;
property.value.value.len = (int)strlen(opts.user_property.value);
MQTTProperties_add(&pub_props, &property);
}
}
while (!toStop)
{
int data_len = 0;
int delim_len = 0;
if (opts.stdin_lines)
{
buffer = malloc(opts.maxdatalen);
delim_len = (int)strlen(opts.delimiter);
do
{
int c = getchar();
if (c < 0)
goto exit;
buffer[data_len++] = c;
if (data_len > delim_len)
{
if (strncmp(opts.delimiter, &buffer[data_len - delim_len], delim_len) == 0)
break;
}
} while (data_len < opts.maxdatalen);
}
else if (opts.message)
{
buffer = opts.message;
data_len = (int)strlen(opts.message);
}
else if (opts.filename)
{
buffer = readfile(&data_len, &opts);
if (buffer == NULL)
goto exit;
}
if (opts.verbose)
fprintf(stderr, "Publishing data of length %d\n", data_len);
if (opts.MQTTVersion == MQTTVERSION_5)
{
MQTTResponse response = MQTTResponse_initializer;
response = MQTTClient_publish5(client, opts.topic, data_len, buffer, opts.qos, opts.retained, &pub_props, &last_token);
rc = response.reasonCode;
}
else
rc = MQTTClient_publish(client, opts.topic, data_len, buffer, opts.qos, opts.retained, &last_token);
if (opts.stdin_lines == 0)
break;
if (rc != 0)
{
myconnect(client);
if (opts.MQTTVersion == MQTTVERSION_5)
{
MQTTResponse response = MQTTResponse_initializer;
response = MQTTClient_publish5(client, opts.topic, data_len, buffer, opts.qos, opts.retained, &pub_props, &last_token);
rc = response.reasonCode;
}
else
rc = MQTTClient_publish(client, opts.topic, data_len, buffer, opts.qos, opts.retained, &last_token);
}
if (opts.qos > 0)
MQTTClient_yield();
}
rc = MQTTClient_waitForCompletion(client, last_token, 5000);
exit:
if (opts.filename || opts.stdin_lines)
free(buffer);
if (opts.MQTTVersion == MQTTVERSION_5)
rc = MQTTClient_disconnect5(client, 0, MQTTREASONCODE_SUCCESS, NULL);
else
rc = MQTTClient_disconnect(client, 0);
MQTTClient_destroy(&client);
return EXIT_SUCCESS;
}

View File

@@ -0,0 +1,257 @@
/*******************************************************************************
* Copyright (c) 2012, 2025 IBM Corp., Ian Craggs and others
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* https://www.eclipse.org/legal/epl-2.0/
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial contribution
* Ian Craggs - change delimiter option from char to string
* Guilherme Maciel Ferreira - add keep alive option
* Ian Craggs - add full capability
*******************************************************************************/
#include "MQTTClient.h"
#include "MQTTClientPersistence.h"
#include "pubsub_opts.h"
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#if defined(_WIN32)
#define sleep Sleep
#else
#include <sys/time.h>
#endif
volatile int toStop = 0;
struct pubsub_opts opts =
{
0, 0, 0, 0, "\n", 100, /* debug/app options */
NULL, NULL, 1, 0, 0, /* message options */
MQTTVERSION_DEFAULT, NULL, "paho-cs-sub", 0, 0, NULL, NULL, "localhost", "1883", NULL, 10, /* MQTT options */
NULL, NULL, 0, 0, /* will options */
0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* TLS options */
0, {NULL, NULL}, /* MQTT V5 options */
NULL, NULL, /* HTTP and HTTPS proxies */
};
int myconnect(MQTTClient client)
{
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
MQTTClient_SSLOptions ssl_opts = MQTTClient_SSLOptions_initializer;
MQTTClient_willOptions will_opts = MQTTClient_willOptions_initializer;
int rc = 0;
if (opts.verbose)
printf("Connecting\n");
if (opts.MQTTVersion == MQTTVERSION_5)
{
MQTTClient_connectOptions conn_opts5 = MQTTClient_connectOptions_initializer5;
conn_opts = conn_opts5;
}
conn_opts.keepAliveInterval = opts.keepalive;
conn_opts.username = opts.username;
conn_opts.password = opts.password;
conn_opts.MQTTVersion = opts.MQTTVersion;
conn_opts.httpProxy = opts.http_proxy;
conn_opts.httpsProxy = opts.https_proxy;
if (opts.will_topic) /* will options */
{
will_opts.message = opts.will_payload;
will_opts.topicName = opts.will_topic;
will_opts.qos = opts.will_qos;
will_opts.retained = opts.will_retain;
conn_opts.will = &will_opts;
}
if (opts.connection && (strncmp(opts.connection, "ssl://", 6) == 0 ||
strncmp(opts.connection, "tls://", 6) == 0 ||
strncmp(opts.connection, "mqtts://", 7) == 0 ||
strncmp(opts.connection, "wss://", 6) == 0))
{
if (opts.insecure)
ssl_opts.verify = 0;
else
ssl_opts.verify = 1;
ssl_opts.CApath = opts.capath;
ssl_opts.keyStore = opts.cert;
ssl_opts.trustStore = opts.cafile;
ssl_opts.privateKey = opts.key;
ssl_opts.privateKeyPassword = opts.keypass;
ssl_opts.enabledCipherSuites = opts.ciphers;
conn_opts.ssl = &ssl_opts;
}
if (opts.MQTTVersion == MQTTVERSION_5)
{
MQTTProperties props = MQTTProperties_initializer;
MQTTProperties willProps = MQTTProperties_initializer;
MQTTResponse response = MQTTResponse_initializer;
conn_opts.cleanstart = 1;
response = MQTTClient_connect5(client, &conn_opts, &props, &willProps);
rc = response.reasonCode;
MQTTResponse_free(response);
}
else
{
conn_opts.cleansession = 1;
rc = MQTTClient_connect(client, &conn_opts);
}
if (opts.verbose && rc == MQTTCLIENT_SUCCESS)
fprintf(stderr, "Connected\n");
else if (rc != MQTTCLIENT_SUCCESS && !opts.quiet)
fprintf(stderr, "Connect failed return code: %s\n", MQTTClient_strerror(rc));
return rc;
}
void cfinish(int sig)
{
signal(SIGINT, NULL);
toStop = 1;
}
void trace_callback(enum MQTTCLIENT_TRACE_LEVELS level, char* message)
{
fprintf(stderr, "Trace : %d, %s\n", level, message);
}
int main(int argc, char** argv)
{
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
MQTTClient_createOptions createOpts = MQTTClient_createOptions_initializer;
int rc = 0;
char* url;
const char* version = NULL;
#if !defined(_WIN32)
struct sigaction sa;
#endif
const char* program_name = "paho_cs_sub";
MQTTClient_nameValue* infos = MQTTClient_getVersionInfo();
if (argc < 2)
usage(&opts, (pubsub_opts_nameValue*)infos, program_name);
if (getopts(argc, argv, &opts) != 0)
usage(&opts, (pubsub_opts_nameValue*)infos, program_name);
if (strchr(opts.topic, '#') || strchr(opts.topic, '+'))
opts.verbose = 1;
if (opts.connection)
url = opts.connection;
else
{
url = malloc(100);
sprintf(url, "%s:%s", opts.host, opts.port);
}
if (opts.verbose)
printf("URL is %s\n", url);
if (opts.tracelevel > 0)
{
MQTTClient_setTraceCallback(trace_callback);
MQTTClient_setTraceLevel(opts.tracelevel);
}
if (opts.MQTTVersion >= MQTTVERSION_5)
createOpts.MQTTVersion = MQTTVERSION_5;
rc = MQTTClient_createWithOptions(&client, url, opts.clientid, MQTTCLIENT_PERSISTENCE_NONE,
NULL, &createOpts);
if (rc != MQTTCLIENT_SUCCESS)
{
if (!opts.quiet)
fprintf(stderr, "Failed to create client, return code: %s\n", MQTTClient_strerror(rc));
exit(EXIT_FAILURE);
}
#if defined(_WIN32)
signal(SIGINT, cfinish);
signal(SIGTERM, cfinish);
#else
memset(&sa, 0, sizeof(struct sigaction));
sa.sa_handler = cfinish;
sa.sa_flags = 0;
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
#endif
if (myconnect(client) != MQTTCLIENT_SUCCESS)
goto exit;
if (opts.MQTTVersion >= MQTTVERSION_5)
{
MQTTResponse response = MQTTClient_subscribe5(client, opts.topic, opts.qos, NULL, NULL);
rc = response.reasonCode;
MQTTResponse_free(response);
}
else
rc = MQTTClient_subscribe(client, opts.topic, opts.qos);
if (rc != MQTTCLIENT_SUCCESS && rc != opts.qos)
{
if (!opts.quiet)
fprintf(stderr, "Error %d subscribing to topic %s\n", rc, opts.topic);
goto exit;
}
while (!toStop)
{
char* topicName = NULL;
int topicLen;
MQTTClient_message* message = NULL;
rc = MQTTClient_receive(client, &topicName, &topicLen, &message, 1000);
if (rc == MQTTCLIENT_DISCONNECTED)
myconnect(client);
else if (message)
{
size_t delimlen = 0;
if (opts.verbose)
printf("%s\t", topicName);
if (opts.delimiter)
delimlen = strlen(opts.delimiter);
if (opts.delimiter == NULL || (message->payloadlen > delimlen &&
strncmp(opts.delimiter, &((char*)message->payload)[message->payloadlen - delimlen], delimlen) == 0))
printf("%.*s", message->payloadlen, (char*)message->payload);
else
printf("%.*s%s", message->payloadlen, (char*)message->payload, opts.delimiter);
if (message->struct_version == 1 && opts.verbose)
logProperties(&message->properties);
fflush(stdout);
MQTTClient_freeMessage(&message);
MQTTClient_free(topicName);
}
}
exit:
MQTTClient_disconnect(client, 0);
MQTTClient_destroy(&client);
return EXIT_SUCCESS;
}

View File

@@ -0,0 +1,521 @@
/*******************************************************************************
* Copyright (c) 2012, 2018 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* https://www.eclipse.org/legal/epl-2.0/
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Ian Craggs - initial contribution
*******************************************************************************/
#include "pubsub_opts.h"
#include <string.h>
#include <stdlib.h>
int printVersionInfo(pubsub_opts_nameValue* info)
{
int rc = 0;
printf("\nLibrary information:\n");
while (info->name)
{
printf("%s: %s\n", info->name, info->value);
info++;
rc = 1; /* at least one value printed */
}
if (rc == 1)
printf("\n");
return rc;
}
void usage(struct pubsub_opts* opts, pubsub_opts_nameValue* name_values, const char* program_name)
{
printf("Eclipse Paho MQTT C %s\n", opts->publisher ? "publisher" : "subscriber");
printVersionInfo(name_values);
printf("Usage: %s [topicname] [-t topic] [-c connection] [-h host] [-p port]\n"
" [-q qos] [-i clientid] [-u username] [-P password] [-k keepalive_timeout]\n"
, program_name);
printf(" [-V MQTT-version] [--quiet] [--trace trace-level]\n");
if (opts->publisher)
{
printf(" [-r] [-n] [-m message] [-f filename]\n");
printf(" [--maxdatalen len] [--message-expiry seconds] [--user-property name value]\n");
}
else
printf(" [-R] [--no-delimiter]\n");
printf(" [--will-topic topic] [--will-payload message] [--will-qos qos] [--will-retain]\n");
printf(" [--cafile filename] [--capath dirname] [--cert filename] [--key filename]\n"
" [--keypass string] [--ciphers string] [--insecure]");
printf(
"\n\n -t (--topic) : MQTT topic to %s to\n"
" -c (--connection) : connection string, overrides host/port e.g wss://hostname:port/ws. Use this option\n"
" rather than host/port to connect with TLS and/or web sockets. No default.\n"
" -h (--host) : host to connect to. Default is %s.\n"
" -p (--port) : network port to connect to. Default is %s.\n"
" -q (--qos) : MQTT QoS to %s with (0, 1 or 2). Default is %d.\n"
" -V (--MQTTversion) : MQTT version (31, 311, or 5). Default is 311.\n"
" --quiet : do not print error messages.\n"
" --trace : print internal trace (\"error\", \"min\", \"max\" or \"protocol\").\n",
opts->publisher ? "publish" : "subscribe", opts->host, opts->port,
opts->publisher ? "publish" : "subscribe", opts->qos);
if (opts->publisher)
{
printf(" -r (--retained) : use MQTT retain option. Default is off.\n");
printf(" -n (--null-message) : send 0-length message.\n");
printf(" -m (--message) : the payload to send.\n");
printf(" -f (--filename) : use the contents of the named file as the payload.\n");
}
printf(
" -i (--clientid) : MQTT client id. Default is %s.\n"
" -u (--username) : MQTT username. No default.\n"
" -P (--password) : MQTT password. No default.\n"
" -k (--keepalive) : MQTT keepalive timeout value. Default is %d seconds.\n"
" --delimiter : delimiter string. Default is \\n.\n",
opts->clientid, opts->keepalive);
if (opts->publisher)
{
printf(" --maxdatalen : maximum length of data to read when publishing strings (default is %d)\n",
opts->maxdatalen);
printf(" --message-expiry : MQTT 5 only. Sets the message expiry property in seconds.\n");
printf(" --user-property : MQTT 5 only. Sets a user property.\n");
}
else
{
printf(" --no-delimiter : do not use a delimiter string between messages.\n");
printf(" -R (--no-retained) : do not print retained messages.\n");
}
printf(
" --will-topic : will topic on connect. No default.\n"
" --will-payload : will message. If the will topic is set, but not payload, a null message will be set.\n"
" --will-retain : set the retained flag on the will message. The default is off.\n"
" --will-qos : the will message QoS. The default is 0.\n"
);
printf(
" --cafile : a filename for the TLS truststore.\n"
" --capath : a directory name containing TLS trusted server certificates.\n"
" --cert : a filename for the TLS keystore containing client certificates.\n"
" --key : client private key file.\n"
" --keypass : password for the client private key file.\n"
" --ciphers : the list of cipher suites that the client will present to the server during\n"
" the TLS handshake.\n"
" --insecure : don't check that the server certificate common name matches the hostname.\n"
" --psk : pre-shared-key in hexadecimal (no leading 0x) \n"
" --psk-identity : client identity string for TLS-PSK mode.\n"
);
printf(
" --http-proxy : HTTP proxy string.\n"
" --https-proxy : HTTPS proxy string.\n"
);
printf("\nSee http://eclipse.org/paho for more information about the Eclipse Paho project.\n");
exit(EXIT_FAILURE);
}
int getopts(int argc, char** argv, struct pubsub_opts* opts)
{
int count = 1;
if (argv[1][0] != '-')
{
opts->topic = argv[1];
count = 2;
}
while (count < argc)
{
if (strcmp(argv[count], "--verbose") == 0 || strcmp(argv[count], "-v") == 0)
opts->verbose = 1;
else if (strcmp(argv[count], "--quiet") == 0)
opts->quiet = 1;
else if (strcmp(argv[count], "--qos") == 0 || strcmp(argv[count], "-q") == 0)
{
if (++count < argc)
{
if (strcmp(argv[count], "0") == 0)
opts->qos = 0;
else if (strcmp(argv[count], "1") == 0)
opts->qos = 1;
else if (strcmp(argv[count], "2") == 0)
opts->qos = 2;
else
return 1;
}
else
return 1;
}
else if (strcmp(argv[count], "--connection") == 0 || strcmp(argv[count], "-c") == 0)
{
if (++count < argc)
opts->connection = argv[count];
else
return 1;
}
else if (strcmp(argv[count], "--host") == 0 || strcmp(argv[count], "-h") == 0)
{
if (++count < argc)
opts->host = argv[count];
else
return 1;
}
else if (strcmp(argv[count], "--port") == 0 || strcmp(argv[count], "-p") == 0)
{
if (++count < argc)
opts->port = argv[count];
else
return 1;
}
else if (strcmp(argv[count], "--http-proxy") == 0)
{
if (++count < argc)
opts->http_proxy = argv[count];
else
return 1;
}
else if (strcmp(argv[count], "--https-proxy") == 0)
{
if (++count < argc)
opts->https_proxy = argv[count];
else
return 1;
}
else if (strcmp(argv[count], "--clientid") == 0 || strcmp(argv[count], "-i") == 0)
{
if (++count < argc)
opts->clientid = argv[count];
else
return 1;
}
else if (strcmp(argv[count], "--username") == 0 || strcmp(argv[count], "-u") == 0)
{
if (++count < argc)
opts->username = argv[count];
else
return 1;
}
else if (strcmp(argv[count], "--password") == 0 || strcmp(argv[count], "-P") == 0)
{
if (++count < argc)
opts->password = argv[count];
else
return 1;
}
else if (strcmp(argv[count], "--maxdatalen") == 0)
{
if (++count < argc)
opts->maxdatalen = atoi(argv[count]);
else
return 1;
}
else if (strcmp(argv[count], "--delimiter") == 0)
{
if (++count < argc)
opts->delimiter = argv[count];
else
return 1;
}
else if (strcmp(argv[count], "--no-delimiter") == 0)
opts->delimiter = NULL;
else if (strcmp(argv[count], "--keepalive") == 0 || strcmp(argv[count], "-k") == 0)
{
if (++count < argc)
opts->keepalive = atoi(argv[count]);
else
return 1;
}
else if (strcmp(argv[count], "--topic") == 0 || strcmp(argv[count], "-t") == 0)
{
if (++count < argc)
opts->topic = argv[count];
else
return 1;
}
else if (strcmp(argv[count], "--will-topic") == 0)
{
if (++count < argc)
opts->will_topic = argv[count];
else
return 1;
}
else if (strcmp(argv[count], "--will-payload") == 0)
{
if (++count < argc)
opts->will_payload = argv[count];
else
return 1;
}
else if (strcmp(argv[count], "--will-qos") == 0)
{
if (++count < argc)
opts->will_qos = atoi(argv[count]);
else
return 1;
}
else if (strcmp(argv[count], "--will-retain") == 0)
{
if (++count < argc)
opts->will_retain = 1;
else
return 1;
}
else if (strcmp(argv[count], "--insecure") == 0)
opts->insecure = 1;
else if (strcmp(argv[count], "--capath") == 0)
{
if (++count < argc)
opts->capath = argv[count];
else
return 1;
}
else if (strcmp(argv[count], "--cafile") == 0)
{
if (++count < argc)
opts->cafile = argv[count];
else
return 1;
}
else if (strcmp(argv[count], "--cert") == 0)
{
if (++count < argc)
opts->cert = argv[count];
else
return 1;
}
else if (strcmp(argv[count], "--key") == 0)
{
if (++count < argc)
opts->key = argv[count];
else
return 1;
}
else if (strcmp(argv[count], "--keypass") == 0)
{
if (++count < argc)
opts->keypass = argv[count];
else
return 1;
}
else if (strcmp(argv[count], "--ciphers") == 0)
{
if (++count < argc)
opts->ciphers = argv[count];
else
return 1;
}
else if (strcmp(argv[count], "--psk") == 0)
{
if (++count < argc)
opts->psk = argv[count];
else
return 1;
}
else if (strcmp(argv[count], "--psk-identity") == 0)
{
if (++count < argc)
opts->psk_identity = argv[count];
else
return 1;
}
else if (strcmp(argv[count], "-V") == 0)
{
if (++count < argc)
{
if (strcmp(argv[count], "mqttv31") == 0 || strcmp(argv[count], "31") == 0)
opts->MQTTVersion = MQTTVERSION_3_1;
else if (strcmp(argv[count], "mqttv311") == 0 || strcmp(argv[count], "311") == 0)
opts->MQTTVersion = MQTTVERSION_3_1_1;
else if (strcmp(argv[count], "mqttv5") == 0 || strcmp(argv[count], "5") == 0)
opts->MQTTVersion = MQTTVERSION_5;
else
return 1;
}
else
return 1;
}
else if (strcmp(argv[count], "--trace") == 0)
{
if (++count < argc)
{
if (strcmp(argv[count], "error") == 0)
opts->tracelevel = MQTTASYNC_TRACE_ERROR;
else if (strcmp(argv[count], "protocol") == 0)
opts->tracelevel = MQTTASYNC_TRACE_PROTOCOL;
else if (strcmp(argv[count], "min") == 0 || strcmp(argv[count], "on") == 0)
opts->tracelevel = MQTTASYNC_TRACE_MINIMUM;
else if (strcmp(argv[count], "max") == 0)
opts->tracelevel = MQTTASYNC_TRACE_MAXIMUM;
else
return 1;
}
else
return 1;
}
else if (opts->publisher == 0)
{
if (strcmp(argv[count], "--no-retained") == 0 || strcmp(argv[count], "-R") == 0)
opts->retained = 1;
else
{
fprintf(stderr, "Unknown option %s\n", argv[count]);
return 1;
}
}
else if (opts->publisher == 1)
{
if (strcmp(argv[count], "--retained") == 0 || strcmp(argv[count], "-r") == 0)
opts->retained = 1;
else if (strcmp(argv[count], "--user-property") == 0)
{
if (count + 2 < argc)
{
opts->user_property.name = argv[++count];
opts->user_property.value = argv[++count];
}
else
return 1;
}
else if (strcmp(argv[count], "--message-expiry") == 0)
{
if (++count < argc)
opts->message_expiry = atoi(argv[count]);
else
return 1;
}
else if (strcmp(argv[count], "-m") == 0 || strcmp(argv[count], "--message") == 0)
{
if (++count < argc)
{
opts->stdin_lines = 0;
opts->message = argv[count];
}
else
return 1;
}
else if (strcmp(argv[count], "-f") == 0 || strcmp(argv[count], "--filename") == 0)
{
if (++count < argc)
{
opts->stdin_lines = 0;
opts->filename = argv[count];
}
else
return 1;
}
else if (strcmp(argv[count], "-n") == 0 || strcmp(argv[count], "--null-message") == 0)
{
opts->stdin_lines = 0;
opts->null_message = 1;
}
else
{
fprintf(stderr, "Unknown option %s\n", argv[count]);
return 1;
}
}
else
{
fprintf(stderr, "Unknown option %s\n", argv[count]);
return 1;
}
count++;
}
if (opts->topic == NULL)
return 1;
return 0;
}
char* readfile(int* data_len, struct pubsub_opts* opts)
{
char* buffer = NULL;
long filesize = 0L;
FILE* infile = fopen(opts->filename, "rb");
if (infile == NULL)
{
fprintf(stderr, "Can't open file %s\n", opts->filename);
return NULL;
}
fseek(infile, 0, SEEK_END);
filesize = ftell(infile);
rewind(infile);
buffer = malloc(sizeof(char)*filesize);
if (buffer == NULL)
{
fprintf(stderr, "Can't allocate buffer to read file %s\n", opts->filename);
fclose(infile);
return NULL;
}
*data_len = (int)fread(buffer, 1, filesize, infile);
if (*data_len != filesize)
{
fprintf(stderr, "%d bytes read of %ld expected for file %s\n", *data_len, filesize, opts->filename);
fclose(infile);
free(buffer);
return NULL;
}
fclose(infile);
return buffer;
}
void logProperties(MQTTProperties *props)
{
int i = 0;
for (i = 0; i < props->count; ++i)
{
int id = props->array[i].identifier;
const char* name = MQTTPropertyName(id);
char* intformat = "Property name %s value %d\n";
switch (MQTTProperty_getType(id))
{
case MQTTPROPERTY_TYPE_BYTE:
printf(intformat, name, props->array[i].value.byte);
break;
case MQTTPROPERTY_TYPE_TWO_BYTE_INTEGER:
printf(intformat, name, props->array[i].value.integer2);
break;
case MQTTPROPERTY_TYPE_FOUR_BYTE_INTEGER:
printf(intformat, name, props->array[i].value.integer4);
break;
case MQTTPROPERTY_TYPE_VARIABLE_BYTE_INTEGER:
printf(intformat, name, props->array[i].value.integer4);
break;
case MQTTPROPERTY_TYPE_BINARY_DATA:
case MQTTPROPERTY_TYPE_UTF_8_ENCODED_STRING:
printf("Property name %s value len %.*s\n", name,
props->array[i].value.data.len, props->array[i].value.data.data);
break;
case MQTTPROPERTY_TYPE_UTF_8_STRING_PAIR:
printf("Property name %s key %.*s value %.*s\n", name,
props->array[i].value.data.len, props->array[i].value.data.data,
props->array[i].value.value.len, props->array[i].value.value.data);
break;
}
}
}