Commit 00652c23 authored by 957dd's avatar 957dd

第三方库

parent 4385c061
paho.mqtt.cpp @ 55833eb9
Subproject commit 55833eb9fb1bf602158d26fffb982a5f0345f77e
---
Language: Cpp
# BasedOnStyle: Google
AccessModifierOffset: -4
#AlignAfterOpenBracket: Align
AlignAfterOpenBracket: BlockIndent
AlignArrayOfStructures: None
AlignConsecutiveAssignments:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: true
AlignConsecutiveBitFields:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
AlignConsecutiveDeclarations:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
AlignConsecutiveMacros:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
# Clang-17
#AlignConsecutiveShortCaseStatements:
# Enabled: false
# AcrossEmptyLines: false
# AcrossComments: false
# AlignCaseColons: false
AlignEscapedNewlines: Left
AlignOperands: Align
AlignTrailingComments:
Kind: Always
OverEmptyLines: 0
AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
AttributeMacros:
- __capability
BinPackArguments: true
BinPackParameters: true
BitFieldColonSpacing: Both
BraceWrapping:
AfterCaseLabel: false
AfterClass: true
AfterControlStatement: Never
AfterEnum: false
AfterExternBlock: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: true
AfterUnion: false
BeforeCatch: true
BeforeElse: true
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakAfterAttributes: Never
BreakAfterJavaFieldAnnotations: false
BreakArrays: true
BreakBeforeBinaryOperators: None
BreakBeforeConceptDeclarations: Always
BreakBeforeBraces: Custom
BreakBeforeInlineASMColon: OnlyMultiline
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon
BreakStringLiterals: true
ColumnLimit: 94
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IfMacros:
- KJ_IF_MAYBE
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^<ext/.*\.h>'
Priority: 2
SortPriority: 0
CaseSensitive: false
- Regex: '^<.*\.h>'
Priority: 1
SortPriority: 0
CaseSensitive: false
- Regex: '^<.*'
Priority: 2
SortPriority: 0
CaseSensitive: false
- Regex: '.*'
Priority: 3
SortPriority: 0
CaseSensitive: false
IncludeIsMainRegex: '([-_](test|unittest))?$'
IncludeIsMainSourceRegex: ''
IndentAccessModifiers: false
IndentCaseBlocks: false
IndentCaseLabels: true
IndentExternBlock: AfterExternBlock
IndentGotoLabels: true
IndentPPDirectives: BeforeHash
IndentRequiresClause: true
IndentWidth: 4
IndentWrappedFunctionNames: false
InsertBraces: false
InsertNewlineAtEOF: true
InsertTrailingCommas: None
IntegerLiteralSeparator:
Binary: 0
BinaryMinDigits: 0
Decimal: 0
DecimalMinDigits: 0
Hex: 0
HexMinDigits: 0
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
KeepEmptyLinesAtEOF: false
LambdaBodyIndentation: Signature
LineEnding: DeriveLF
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Never
ObjCBlockIndentWidth: 2
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PackConstructorInitializers: NextLine
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakOpenParenthesis: 0
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyIndentedWhitespace: 0
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Left
PPIndentWidth: -1
QualifierAlignment: Leave
RawStringFormats:
- Language: Cpp
Delimiters:
- cc
- CC
- cpp
- Cpp
- CPP
- 'c++'
- 'C++'
CanonicalDelimiter: ''
BasedOnStyle: google
- Language: TextProto
Delimiters:
- pb
- PB
- proto
- PROTO
EnclosingFunctions:
- EqualsProto
- EquivToProto
- PARSE_PARTIAL_TEXT_PROTO
- PARSE_TEST_PROTO
- PARSE_TEXT_PROTO
- ParseTextOrDie
- ParseTextProtoOrDie
- ParseTestProto
- ParsePartialTestProto
CanonicalDelimiter: pb
BasedOnStyle: google
ReferenceAlignment: Pointer
ReflowComments: true
RemoveBracesLLVM: false
RemoveParentheses: Leave
RemoveSemicolon: false
RequiresClausePosition: OwnLine
RequiresExpressionIndentation: OuterScope
SeparateDefinitionBlocks: Leave
ShortNamespaceLines: 1
SortIncludes: CaseSensitive
SortJavaStaticImport: Before
SortUsingDeclarations: LexicographicNumeric
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceAroundPointerQualifiers: Default
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeJsonColon: false
SpaceBeforeParens: ControlStatements
SpaceBeforeParensOptions:
AfterControlStatements: true
AfterForeachMacros: true
AfterFunctionDefinitionName: false
AfterFunctionDeclarationName: false
AfterIfMacros: true
AfterOverloadedOperator: false
AfterRequiresInClause: false
AfterRequiresInExpression: false
BeforeNonEmptyParentheses: false
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: false
SpaceInEmptyBlock: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: Never
SpacesInContainerLiterals: true
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: -1
# Clang Format >v17
#SpacesInParens: Never
#SpacesInParensOptions:
# InCStyleCasts: false
# InConditionalStatements: false
# InEmptyParentheses: false
# Other: false
SpacesInSquareBrackets: false
Standard: Auto
StatementAttributeLikeMacros:
- Q_EMIT
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 4
UseTab: Never
VerilogBreakBetweenInstancePorts: true
WhitespaceSensitiveMacros:
- BOOST_PP_STRINGIZE
- CF_SWIFT_NAME
- NS_SWIFT_NAME
- PP_STRINGIZE
- STRINGIZE
...
# This file is for unifying the coding style for different editors and IDEs
# http://EditorConfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 4
end_of_line = lf
insert_final_newline = true
[*.{cpp,c,h}]
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
# This starter workflow is for a CMake project running on multiple platforms. There is a different starter workflow if you just want a single platform.
# See: https://github.com/actions/starter-workflows/blob/main/ci/cmake-single-platform.yml
name: CMake on multiple platforms
on:
push:
branches: [ "master", "develop" ]
pull_request:
branches: [ "master", "develop" ]
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
# Set fail-fast to false to ensure that feedback is delivered for all matrix combinations. Consider changing this to true when your workflow is stable.
fail-fast: false
# Set up a matrix to run the following 3 configurations:
# 1. <Windows, Release, latest MSVC compiler toolchain on the default
# runner image, default generator>
# 2. <Linux, Release, latest GCC compiler toolchain on the default
# runner image, default generator>
# 3. <Linux, Release, latest Clang compiler toolchain on the default
# runner image, default generator>
#
# To add more build types (Release, Debug, RelWithDebInfo, etc.) customize the build_type list.
matrix:
os: [ubuntu-latest, windows-latest]
build_type: [Release, Debug]
c_compiler: [gcc, clang, cl]
include:
- os: windows-latest
c_compiler: cl
cpp_compiler: cl
- os: ubuntu-latest
c_compiler: gcc
cpp_compiler: g++
- os: ubuntu-latest
c_compiler: clang
cpp_compiler: clang++
exclude:
- os: windows-latest
c_compiler: gcc
- os: windows-latest
c_compiler: clang
- os: ubuntu-latest
c_compiler: cl
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Mosquitto (ubuntu)
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa
sudo apt-get update
sudo apt-get -y install mosquitto
# TODO: Figure out how to install and run mosquitto on Windows for unit tests.
# - name: Install Mosquitto from Source (windows)
# if: matrix.os == 'windows-latest'
# run: |
# git clone https://github.com/eclipse/mosquitto.git
# cd mosquitto
# git checkout "v2.0.18"
# mkdir build && cd build
# cmake .. -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }}
# cmake --build . --target install
# "C:\Program Files\mosquitto\mosquitto install"
- name: Install Catch2 v2 from Source (ubuntu)
if: matrix.os == 'ubuntu-latest'
run: |
git clone https://github.com/catchorg/Catch2.git
cd Catch2
git checkout "v2.13.8"
mkdir build && cd build
cmake .. -DBUILD_TESTING=OFF -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }}
sudo cmake --build . --target install
- name: Install Catch2 v2 from Source (windows)
# For Windows, it's important to build Catch2 with the same 'build_type'
# as the Paho C++ library, so that they link without errors.
if: matrix.os == 'windows-latest'
run: |
git clone https://github.com/catchorg/Catch2.git
cd Catch2
git checkout "v2.13.8"
mkdir build && cd build
cmake .. -DBUILD_TESTING=OFF -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }}
cmake --build . --config ${{ matrix.build_type }} --target install
- name: Set reusable strings
# Turn repeated input strings (such as the build output directory) into step outputs.
# These step outputs can be used throughout the workflow file.
id: strings
shell: bash
run: |
echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT"
- name: Configure CMake
# We configure to build the examples, unit tests, and Paho C library.
#
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required
# if you are using a single-configuration generator such as make.
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
run: >
cmake -B ${{ steps.strings.outputs.build-output-dir }}
-DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }}
-DCMAKE_C_COMPILER=${{ matrix.c_compiler }}
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
-DPAHO_BUILD_EXAMPLES=ON
-DPAHO_BUILD_TESTS=ON
-DPAHO_WITH_MQTT_C=ON
-S ${{ github.workspace }}
- name: Build
# Build your program with the given configuration. Note that --config is
# needed for Windows because the default Windows generator is a multi-config
# generator (Visual Studio generator).
run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }}
- name: Test
if: matrix.os == 'ubuntu-latest'
working-directory: ${{ steps.strings.outputs.build-output-dir }}
# Execute tests defined by the CMake configuration.
# Note that --build-config is needed because the default Windows generator
# is a multi-config generator (Visual Studio generator).
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
run: ctest --build-config ${{ matrix.build_type }}
lib/
obj/
\.hg/
\.hgignore
\.hgtags
\test/unit/mqttpp-unittest
.deps/
.libs/
*.vp*
*.vtg
*~
aclocal.m4
# AC_CONFIG_AUX_DIR created by /bootstrap
autotools_build/
autom4te.cache/
config.*
configure
libtool
Makefile.in
*.la
*.lo
*.o
*.stamp
/build/
[submodule "src/externals/paho-mqtt-c"]
path = externals/paho-mqtt-c
url = https://github.com/eclipse/paho.mqtt.c.git
This diff is collapsed.
# CMakeLists.txt
#
# Top-level CMake file for the Paho C++ library.
#
#*******************************************************************************
# This is part of the Paho MQTT C++ client library.
#
# Copyright (c) 2017-2025, Frank Pagliughi
# Copyright (c) 2016-2017, Guilherme Maciel Ferreira
#
# 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
# http://www.eclipse.org/legal/epl-v20.html
# and the Eclipse Distribution License is available at
# http://www.eclipse.org/org/documents/edl-v10.php.
#
# Contributors:
# Guilherme Maciel Ferreira - initial version
# Frank Pagliughi
#*******************************************************************************/
cmake_minimum_required(VERSION 3.13)
project(PahoMqttCpp VERSION "1.5.4")
## --- Build options ---
if(WIN32)
option(PAHO_BUILD_STATIC "Build static library" TRUE)
option(PAHO_BUILD_SHARED "Build shared library (DLL)" FALSE)
option(PAHO_WITH_SSL "Build SSL-enabled library" FALSE)
else()
option(PAHO_BUILD_STATIC "Build static library" FALSE)
option(PAHO_BUILD_SHARED "Build shared library" TRUE)
option(PAHO_WITH_SSL "Build SSL-enabled library" TRUE)
option(PAHO_BUILD_DEB_PACKAGE "Build debian package" FALSE)
endif()
option(PAHO_BUILD_SAMPLES "Build sample/example programs" FALSE)
option(PAHO_BUILD_EXAMPLES "Build sample/example programs" FALSE)
option(PAHO_BUILD_TESTS "Build tests (requires Catch2)" FALSE)
option(PAHO_BUILD_DOCUMENTATION "Create and install the API documentation (requires Doxygen)" FALSE)
option(PAHO_WITH_MQTT_C "Build Paho C from the internal GIT submodule." FALSE)
if(NOT PAHO_BUILD_SHARED AND NOT PAHO_BUILD_STATIC)
message(FATAL_ERROR "You must set either PAHO_BUILD_SHARED, PAHO_BUILD_STATIC, or both")
endif()
# --- Setting naming variables ---
set(PAHO_MQTTPP_GENERATED_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated)
## --- Find Paho C or build it, if reqested ---
if(PAHO_WITH_SSL)
find_package(OpenSSL REQUIRED)
set(PAHO_MQTT_C_LIB eclipse-paho-mqtt-c::paho-mqtt3as)
else()
set(PAHO_MQTT_C_LIB eclipse-paho-mqtt-c::paho-mqtt3a)
endif()
if(PAHO_WITH_MQTT_C)
message(STATUS "Paho C: Bundled")
## Build the Paho C library from the submodule
set(PAHO_ENABLE_TESTING FALSE CACHE BOOL "No Paho C tests")
set(PAHO_HIGH_PERFORMANCE TRUE CACHE BOOL "Paho C high performance")
if(NOT WIN32)
set(PAHO_WITH_UNIX_SOCKETS TRUE CACHE BOOL "Support for Unix-domain sockets")
endif()
set(CMAKE_C_STANDARD 99 CACHE STRING "Paho C language standard")
add_subdirectory(${PROJECT_SOURCE_DIR}/externals/paho-mqtt-c)
## Alias namespace so that the full names can be used with the subdir.
if(PAHO_BUILD_SHARED)
add_library(eclipse-paho-mqtt-c::paho-mqtt3a ALIAS paho-mqtt3a)
list(APPEND PAHO_MQTT_C_LIBS paho-mqtt3a)
if(PAHO_WITH_SSL)
add_library(eclipse-paho-mqtt-c::paho-mqtt3as ALIAS paho-mqtt3as)
list(APPEND PAHO_MQTT_C_LIBS paho-mqtt3as)
endif()
endif()
if(PAHO_BUILD_STATIC)
add_library(eclipse-paho-mqtt-c::paho-mqtt3a-static ALIAS paho-mqtt3a-static)
list(APPEND PAHO_MQTT_C_LIBS paho-mqtt3a-static)
if(PAHO_WITH_SSL)
add_library(eclipse-paho-mqtt-c::paho-mqtt3as-static ALIAS paho-mqtt3as-static)
list(APPEND PAHO_MQTT_C_LIBS paho-mqtt3as-static)
endif()
endif()
## install paho.mqtt.c library (appending to PahoMqttCpp export)
install(TARGETS ${PAHO_MQTT_C_LIBS}
EXPORT PahoMqttCpp
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
else()
find_package(eclipse-paho-mqtt-c REQUIRED)
endif()
# --- System Details ---
include(GNUInstallDirs)
if(WIN32)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
set(LIBS_SYSTEM ws2_32)
endif()
# --- The headers ---
add_subdirectory(include/mqtt)
# For the paho_mqtt_c module
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
add_subdirectory(src)
# --- Documentation ---
if(PAHO_BUILD_DOCUMENTATION)
add_subdirectory(doc)
endif()
# --- Example Apps ---
if(PAHO_BUILD_SAMPLES OR PAHO_BUILD_EXAMPLES)
add_subdirectory(examples)
endif()
# --- Unit Tests ---
if(PAHO_BUILD_TESTS)
enable_testing()
add_subdirectory(test/unit)
endif()
## --- Install generated header(s) ---
install(
DIRECTORY
${PAHO_MQTTPP_GENERATED_DIR}/include/
DESTINATION
${CMAKE_INSTALL_INCLUDEDIR}
)
## --- Packaging settings ---
if(WIN32)
set(CPACK_GENERATOR "ZIP")
elseif(UNIX)
if(PAHO_BUILD_DEB_PACKAGE)
set(CPACK_GENERATOR "DEB")
include(cmake/CPackDebConfig.cmake)
else()
set(CPACK_GENERATOR "TGZ")
endif()
endif()
include(CPack)
# --- Export CMake TARGETS ---
add_subdirectory(cmake)
# 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/)
# Eclipse Paho MQTT C++ Client Library
# Coding Styles
This document describes the coding style and language conventions used by the Eclipse Paho C++ Client Library.
## Language Standard
The Paho C++ library uses Modern C++, adhering to the C++11 standard.
Nothing in the library should prevent it from being built with a compiler adhering to a newer standard such as C++14 or C++17, but at this point the library itself doesn't use any newer language feature than C++11. Unfortunately, compilers vary wildly from version to version and platform to platform. So this is a constant struggle to keep true.
Adherence to the base C++11 standard may change at some point in the future. Newer versions of the library will likely start using newer language features some time in the future as they are more widely adapted by compilers and projects. The next logical jump would probably be to C++17.
## Naming Convention
The Paho C++ library attempts to follow the naming conventions of the C++ standard library as much as possible, as this seems the most definitive standard for the language.
- Class names are lower snake case: *classes_like_this*
- Function names are lower snake case: *functions_like_this*
- Variable names are lower camel case: *varsLikeThis*
- Class members are lower camel case with a trailing underscore: *memVarsLikeThis_*
- Constants are all caps: *CONSTANTS_LIKE_THIS*
## Format Conventions
The top-level project directory contains a _.editorconfig_ file with some basic hints as to formatting conventions for source files.
A few minutes looking through the existing sources will reveal the basic styles used. Pull Requests should generally try to fit in to the existing style and not try to impose new ones.
At some point in the future, a formatter may be added to the project (probably Clang format), but until then, any sources that can be fixed up with an automated code generator or beautifier would generally be accepted into the project. But at some point soon after would then be reformat to fit into the overall conventions.
\ No newline at end of file
# 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.cpp/fork)
2. Clone the forked repository onto your computer: ``` git clone https://github.com/<your username>/paho.mqtt.cpp.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 unit 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.cpp](https://github.com/eclipse/paho.mqtt.cpp) 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 and is less than 1000 lines (and meets the needs of the
project), then it can be pulled into the main repository. If not, more steps
are required. These are detailed in the
[legal process poster](http://www.eclipse.org/legal/EclipseLegalProcessPoster.pdf).
## 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.cpp/issues](https://github.com/eclipse/paho.mqtt.cpp/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.cpp/issues/new)
This diff is collapsed.
Eclipse Public License - v 2.0
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-20/
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
For an explanation of what dual-licensing means to you, see:
https://www.eclipse.org/legal/eplfaq.php#DUALLIC
# Notices for Eclipse Paho
This content is produced and maintained by the Eclipse Paho project.
* Project home: https://projects.eclipse.org/projects/iot.paho
## Trademarks
Paho™ is a trademark of the Eclipse Foundation.
## Copyright
All content is the property of the respective authors or their employers. For
more information regarding authorship of content, please consult the listed
source code repository logs.
## Declared Project Licenses
This program and the accompanying materials are made available under the terms
of the Eclipse Public License v2.0 which is available at
https://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
v1.0 which is available at https://www.eclipse.org/org/documents/edl-v10.php.
SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
## Source Code
The project maintains the following source code repositories:
* https://github.com/eclipse/paho-website
* https://github.com/eclipse/paho.golang
* https://github.com/eclipse/paho.mqtt-sn.embedded-c
* https://github.com/eclipse/paho.mqtt-spy
* https://github.com/eclipse/paho.mqtt.android
* https://github.com/eclipse/paho.mqtt.c
* https://github.com/eclipse/paho.mqtt.cpp
* https://github.com/eclipse/paho.mqtt.d
* https://github.com/eclipse/paho.mqtt.embedded-c
* https://github.com/eclipse/paho.mqtt.golang
* https://github.com/eclipse/paho.mqtt.java
* https://github.com/eclipse/paho.mqtt.javascript
* https://github.com/eclipse/paho.mqtt.m2mqtt
* https://github.com/eclipse/paho.mqtt.python
* https://github.com/eclipse/paho.mqtt.ruby
* https://github.com/eclipse/paho.mqtt.rust
* https://github.com/eclipse/paho.mqtt.testing
## Cryptography
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.
This diff is collapsed.
# 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.
<!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>December 9, 2013</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 1.0 ("EPL") and Eclipse Distribution License Version 1.0 ("EDL").
A copy of the EPL is available at
<a href="http://www.eclipse.org/legal/epl-v20.html">http://www.eclipse.org/legal/epl-v20.html</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>
#!/bin/bash
#
# buildtst.sh
#
# Build test for the Paho C++ library.
#
# This is a local CI for testing the build on a dev machine.
#
# This test the build with a few compilers on Linux. It does a build using
# CMake, for the library, tests, and examples, then runs the unit tests.
# This is repeated for each of the compilers in the list. If a particular
# compiler is not installed on the system, it is just skipped.
#
# This is not meant to replace any CI on the repo server, but is a quick
# test to use locally during development.
#
COMPILERS="g++-9 g++-11 g++-13 clang++-14 clang++-17 clang++-20"
[ "$#" -gt 0 ] && COMPILERS="$@"
[ -z "${BUILD_JOBS}" ] && BUILD_JOBS=4
for COMPILER in $COMPILERS; do
if [ -z "$(which ${COMPILER})" ]; then
printf "Compiler not found: %s\n" "${COMPILER}"
else
printf "===== Testing: %s =====\n\n" "${COMPILER}"
rm -rf buildtst-build/
mkdir buildtst-build
pushd buildtst-build &> /dev/null
if ! cmake .. -DCMAKE_CXX_COMPILER=${COMPILER} -DPAHO_WITH_SSL=ON -DPAHO_BUILD_SAMPLES=ON -DPAHO_BUILD_TESTS=ON -DPAHO_WITH_MQTT_C=ON ; then
printf "\nCMake configuration failed for %s\n" "${COMPILER}"
exit 1
fi
if ! cmake --build . -j ${BUILD_JOBS} ; then
printf "\nBuild failed for %s\n" "${COMPILER}"
exit 2
fi
printf "\nRunning Catch2 Unit tests for %s:\n" "${COMPILER}"
if ! ./test/unit/unit_tests ; then
printf "\nCatch2 unit test failed for %s\n" "${COMPILER}"
exit 3
fi
popd &> /dev/null
fi
printf "\n"
done
rm -rf buildtst-build/
printf "\nAll builds completed successfully\n\n"
if ! cppcheck --enable=all --std=c++17 --force --quiet src/*.cpp ; then
printf "\ncppcheck failed\n"
exit 5
fi
printf "\n===== All tests completed successfully =====\n\n"
exit 0
# CMakeLists.txt
#
# CMake export file for the Paho C++ library.
#
#*******************************************************************************
# This is part of the Paho MQTT C++ client library.
#
# Copyright (c) 2017-2023, Frank Pagliughi
#
# 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
# http://www.eclipse.org/legal/epl-v20.html
# and the Eclipse Distribution License is available at
# http://www.eclipse.org/org/documents/edl-v10.php.
#*******************************************************************************/
set(package_name PahoMqttCpp)
configure_file(${package_name}Config.cmake.in ${package_name}Config.cmake @ONLY)
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/${package_name}ConfigVersion.cmake"
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion
)
export(EXPORT ${package_name}
FILE "${CMAKE_CURRENT_BINARY_DIR}/${package_name}Targets.cmake"
NAMESPACE ${package_name}::
)
install(EXPORT ${package_name}
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${package_name}
FILE ${package_name}Targets.cmake
NAMESPACE ${package_name}::
)
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/${package_name}Config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/${package_name}ConfigVersion.cmake"
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${package_name}
)
if(CPACK_GENERATOR MATCHES "DEB")
set(CPACK_PACKAGE_NAME "libpaho-mqtt.cpp")
set(CPACK_DEBIAN_PACKAGE_NAME ${CPACK_PACKAGE_NAME})
set(CPACK_PACKAGE_CONTACT "Eclipse")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Eclipse Paho MQTT C++ client")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER " <>")
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
set(CPACK_DEBIAN_PACKAGE_VERSION ${PACKAGE_VERSION})
set(CPACK_DEBIAN_PACKAGE_SECTION "net")
endif()
# save build-time options
set(PAHO_BUILD_STATIC @PAHO_BUILD_STATIC@)
set(PAHO_BUILD_SHARED @PAHO_BUILD_SHARED@)
set(PAHO_WITH_SSL @PAHO_WITH_SSL@)
set(PAHO_WITH_MQTT_C @PAHO_WITH_MQTT_C@)
include(CMakeFindDependencyMacro)
find_dependency(Threads REQUIRED)
if (NOT PAHO_WITH_MQTT_C)
find_dependency(eclipse-paho-mqtt-c REQUIRED)
endif()
if (PAHO_WITH_SSL)
find_dependency(OpenSSL REQUIRED)
endif()
if(NOT TARGET PahoMqttCpp::paho-mqttpp3-shared AND NOT TARGET PahoMqttCpp::paho-mqttpp3-static)
include("${CMAKE_CURRENT_LIST_DIR}/@package_name@Targets.cmake")
if(TARGET PahoMqttCpp::paho-mqttpp3-shared)
add_library(PahoMqttCpp::paho-mqttpp3 ALIAS PahoMqttCpp::paho-mqttpp3-shared)
else()
add_library(PahoMqttCpp::paho-mqttpp3 ALIAS PahoMqttCpp::paho-mqttpp3-static)
endif()
endif()
#!/bin/bash
#
# devenv.sh
#
# Sets up a development environment for working on the the Paho C++ Library on Linux,
# using the development tree of the Paho C library.
# This is _not_ necessary for building applications against the library once it has
# been installed - it's just for library developers.
#
# Source it into the current shell as:
# $ source devenv.sh
#
PAHO_C_DIR=$(readlink -e ../paho.mqtt.c)
export DEVELOP=1
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${PAHO_C_DIR}/build/output:${PWD}/lib
VERSION=1.0.0
check:
rpmlint -i dist/paho-cpp.spec
rpm-prep:
mkdir -p ${HOME}/rpmbuild/SOURCES/
tar --transform="s/\./paho-cpp-${VERSION}/" -cf ${HOME}/rpmbuild/SOURCES/v${VERSION}.tar.gz --exclude=./build.paho.cpp --exclude=.git --exclude=*.bz ./ --gzip
rpm: rpm-prep
rpmbuild -ba dist/paho-cpp.spec
Summary: MQTT CPP Client
Name: paho-cpp
Version: 1.5.4
Release: 0%{?dist}
License: Eclipse Eclipse Public License 2.0 and Distribution License 1.0
Group: Development/Tools
Source: https://github.com/eclipse/paho.mqtt.cpp/archive/v%{version}.tar.gz
URL: https://eclipse.org/paho/clients/cpp/
BuildRequires: cmake3
BuildRequires: gcc
BuildRequires: graphviz
BuildRequires: doxygen
BuildRequires: openssl-devel
BuildRequires: paho-c-devel
Requires: openssl
Requires: paho-c
%description
The Paho MQTT CPP Client is a fully fledged MQTT client written in ANSI standard C++ 17.
%package devel
Summary: MQTT CPP Client development kit
Group: Development/Libraries
Requires: paho-cpp
%description devel
Development files and samples for the the Paho MQTT CPP Client.
%package devel-docs
Summary: MQTT CPP Client development kit documentation
Group: Development/Libraries
%description devel-docs
Development documentation files for the the Paho MQTT CPP Client.
%prep
%autosetup -n paho-cpp-%{version}
%build
mkdir build.paho.cpp && cd build.paho.cpp
%cmake3 -DPAHO_WITH_SSL=TRUE -DPAHO_BUILD_DOCUMENTATION=TRUE -DPAHO_BUILD_EXAMPLES=TRUE ..
make %{?_smp_mflags}
%install
cd build.paho.cpp
make install DESTDIR=%{buildroot}
%files
%doc edl-v10 epl-v20
%{_libdir}/*
%files devel
%{_bindir}/*
%{_includedir}/*
%files devel-docs
%{_datadir}/*
%changelog
* Wed Oct 11 2017 Julien Courtat <julien.courtat@aqsacom.com> - 1.0.0
- Initial packaging
#*******************************************************************************
# Copyright (c) 2024, Frank Pagliughi
# Copyright (c) 2016, Guilherme Maciel Ferreira
#
# 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
# http://www.eclipse.org/legal/epl-v20.html
# and the Eclipse Distribution License is available at
# http://www.eclipse.org/org/documents/edl-v10.php.
#
# Contributors:
# Frank Pagliughi - Updated paths. Fixed conflict with Paho C
# Guilherme Maciel Ferreira - initial version
#*******************************************************************************/
## documentation settings
find_package(Doxygen REQUIRED)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc)
message(STATUS "Doxygen: ${DOXYGEN_EXECUTABLE}")
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.cmake
${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
@ONLY
)
add_custom_target(
paho-mqttpp3-doc.target
COMMAND ${DOXYGEN_EXECUTABLE} Doxyfile
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating API documentation with Doxygen"
VERBATIM
)
add_custom_target(paho-mqttpp3-doc ALL
DEPENDS paho-mqttpp3-doc.target
)
install(
DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc/
DESTINATION share/doc/EclipsePahoCpp
)
This diff is collapsed.
This diff is collapsed.
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.
This diff is collapsed.
async_publish
async_subscribe
sync_publish
ssl_publish
# CMakeLists.txt
#
# CMake file for the Paho C++ example applications.
#
#*******************************************************************************
# This is part of the Paho MQTT C++ client library.
#
# Copyright (c) 2016-2024
#
# 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
# http://www.eclipse.org/legal/epl-v20.html
# and the Eclipse Distribution License is available at
# http://www.eclipse.org/org/documents/edl-v10.php.
#
# Contributors:
# Guilherme Maciel Ferreira - initial version
# Frank Pagliughi - Updates for new samples
#*******************************************************************************/
## --- Library dependencies ---
set (THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
# The example applications
set(EXECUTABLES
async_publish
async_publish_time
async_subscribe
async_subscribe_v5
async_consume
async_consume_v5
async_message_consume
async_message_consume_v5
data_publish
mqttpp_chat
multithr_pub_sub
pub_speed_test
rpc_math_cli
rpc_math_srvr
server_props_v5
sync_publish
sync_consume
sync_consume_v5
sync_reconnect
topic_publish
ws_publish
)
# These will only be built if SSL selected
if(PAHO_WITH_SSL)
set(SSL_EXECUTABLES ssl_publish)
endif()
## Build the example apps
foreach(EXECUTABLE ${EXECUTABLES} ${SSL_EXECUTABLES})
add_executable(${EXECUTABLE} ${EXECUTABLE}.cpp)
target_link_libraries(${EXECUTABLE} PahoMqttCpp::paho-mqttpp3)
set_target_properties(${EXECUTABLE} PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON
CXX_EXTENSIONS OFF
)
if(PAHO_BUILD_SHARED)
target_compile_definitions(${EXECUTABLE} PRIVATE PAHO_MQTTPP_IMPORTS)
endif()
endforeach()
## Extra configuration for the SSL/TLS examples, if selected
foreach(EXECUTABLE ${SSL_EXECUTABLES})
target_compile_definitions(${EXECUTABLE} PUBLIC OPENSSL)
endforeach()
## install binaries
include(GNUInstallDirs)
install(TARGETS ${EXECUTABLES} ${SSL_EXECUTABLES}
EXPORT PahoMqttCppSamples
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
// async_consume.cpp
//
// This is a Paho MQTT C++ client, sample application.
//
// This application is an MQTT consumer/subscriber using the C++
// asynchronous client interface, employing the to receive messages
// and status updates.
//
// The sample demonstrates:
// - Connecting to an MQTT v3 server/broker.
// - Subscribing to a topic
// - Persistent subscriber session
// - Receiving messages through the synchronous queuing API
// - Auto reconnecting
//
/*******************************************************************************
* Copyright (c) 2013-2024 Frank Pagliughi <fpagliughi@mindspring.com>
*
* 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
* http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Frank Pagliughi - initial implementation and documentation
*******************************************************************************/
#include <cctype>
#include <chrono>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <thread>
#include "mqtt/async_client.h"
using namespace std;
const string DFLT_SERVER_URI{"mqtt://localhost:1883"};
const string CLIENT_ID{"paho_cpp_async_consume"};
const string TOPIC{"hello"};
const int QOS = 1;
/////////////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[])
{
auto serverUri = (argc > 1) ? string{argv[1]} : DFLT_SERVER_URI;
mqtt::async_client cli(serverUri, CLIENT_ID);
auto connOpts = mqtt::connect_options_builder::v3()
.keep_alive_interval(30s)
.clean_session(false)
.automatic_reconnect()
.finalize();
try {
// Start consumer before connecting to make sure to not miss any messages
cli.start_consuming();
// Connect to the server
cout << "Connecting to the MQTT server..." << flush;
auto tok = cli.connect(connOpts);
// Getting the connect response will block waiting for the
// connection to complete.
auto rsp = tok->get_connect_response();
// If there is no session present, then we need to subscribe, but if
// there is a session, then the server remembers us and our
// subscriptions.
if (!rsp.is_session_present()) {
cout << " No session present on server. Subscribing..." << flush;
cli.subscribe(TOPIC, QOS)->wait();
}
cout << "OK" << endl;
// Consume messages
cout << "\nWaiting for messages on topic: '" << TOPIC << "'" << endl;
// The client handles automatic reconnects, but we monitor
// the events here to report them to the user.
while (true) {
auto evt = cli.consume_event();
if (const auto* p = evt.get_message_if()) {
auto& msg = *p;
if (msg)
cout << msg->get_topic() << ": " << msg->to_string() << endl;
}
else if (evt.is_connected())
cout << "\n*** Connected ***" << endl;
else if (evt.is_connection_lost())
cout << "*** Connection Lost ***" << endl;
}
}
catch (const mqtt::exception& exc) {
cerr << "\n " << exc << endl;
return 1;
}
return 0;
}
// async_consume_v5.cpp
//
// This is a Paho MQTT C++ client, sample application.
//
// This application is an MQTT consumer/subscriber using the C++
// asynchronous client interface, employing the to receive messages
// and status updates.
//
// The sample demonstrates:
// - Connecting to an MQTT v5 server/broker.
// - Subscribing to a topic
// - Receiving messages through the consuming (queuing) API
//
/*******************************************************************************
* Copyright (c) 2013-2024 Frank Pagliughi <fpagliughi@mindspring.com>
*
* 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
* http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Frank Pagliughi - initial implementation and documentation
*******************************************************************************/
#include <cctype>
#include <chrono>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <thread>
#include "mqtt/async_client.h"
using namespace std;
const string DFLT_SERVER_URI{"mqtt://localhost:1883"};
const string CLIENT_ID{"PahoCppAsyncConsumeV5"};
const string TOPIC{"#"};
const int QOS = 1;
/////////////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[])
{
auto serverURI = (argc > 1) ? string{argv[1]} : DFLT_SERVER_URI;
auto cli = std::make_shared<mqtt::async_client>(serverURI, CLIENT_ID);
auto connOpts = mqtt::connect_options_builder::v5()
.clean_start(false)
.properties({{mqtt::property::SESSION_EXPIRY_INTERVAL, 604800}})
.finalize();
try {
// Start consumer before connecting to make sure to not miss messages
cli->start_consuming();
// Connect to the server
cout << "Connecting to the MQTT server..." << flush;
auto tok = cli->connect(connOpts);
// Getting the connect response will block waiting for the
// connection to complete.
auto rsp = tok->get_connect_response();
// Make sure we were granted a v5 connection.
if (rsp.get_mqtt_version() < MQTTVERSION_5) {
cout << "\n Did not get an MQTT v5 connection." << flush;
exit(1);
}
// If there is no session present, then we need to subscribe, but if
// there is a session, then the server remembers us and our
// subscriptions.
if (!rsp.is_session_present()) {
cout << "\n Session not present on broker. Subscribing..." << flush;
cli->subscribe(TOPIC, QOS)->wait();
}
cout << "\n OK" << endl;
// We'll signal the consumer to exit from another thread.
// (just to show that we can)
thread([cli] {
this_thread::sleep_for(60s);
cout << "\nClosing the consumer." << endl;
cli->stop_consuming();
}).detach();
// Consume messages
//
// This just exits if the consumer is closed or the client is
// disconnected. (See some other examples for auto or manual
// reconnect)
cout << "\nWaiting for messages on topic: '" << TOPIC << "'" << endl;
try {
while (true) {
auto evt = cli->consume_event();
if (const auto* p = evt.get_message_if()) {
auto& msg = *p;
if (!msg)
continue;
cout << msg->get_topic() << ": " << msg->to_string();
const auto& props = msg->get_properties();
if (size_t n = props.size(); n != 0) {
cout << "\n [";
for (size_t i = 0; i < n - 1; ++i) cout << props[i] << ", ";
cout << props[n - 1] << "]";
}
cout << endl;
}
else if (evt.is_connected()) {
cout << "\n*** Connected ***" << endl;
}
else if (evt.is_connection_lost()) {
cout << "*** Connection Lost ***" << endl;
break;
}
else if (const auto* p = evt.get_disconnected_if()) {
cout << "*** Disconnected. Reason [0x" << hex << int{p->reasonCode}
<< "]: " << p->reasonCode << " ***" << endl;
break;
}
}
}
catch (mqtt::queue_closed&) {
}
// If we're here, the client was almost certainly disconnected.
// But we check, just to make sure.
if (cli->is_connected()) {
cout << "\nShutting down and disconnecting from the MQTT server..." << flush;
cli->disconnect()->wait();
cout << "OK" << endl;
}
}
catch (const mqtt::exception& exc) {
cerr << "\n " << exc << endl;
return 1;
}
return 0;
}
// async_consume.cpp
//
// This is a Paho MQTT C++ client, sample application.
//
// This application is an MQTT consumer/subscriber using the C++
// asynchronous client interface, employing the to receive messages
// and status updates.
//
// The sample demonstrates:
// - Connecting to an MQTT v3 server/broker.
// - Subscribing to a topic
// - Persistent subscriber session
// - Receiving messages through the synchronous queuing API
// - Auto reconnecting
//
/*******************************************************************************
* Copyright (c) 2013-2024 Frank Pagliughi <fpagliughi@mindspring.com>
*
* 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
* http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Frank Pagliughi - initial implementation and documentation
*******************************************************************************/
#include <cctype>
#include <chrono>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <thread>
#include "mqtt/async_client.h"
using namespace std;
const string DFLT_SERVER_URI{"mqtt://localhost:1883"};
const string CLIENT_ID{"paho_cpp_async_consume"};
const string TOPIC{"hello"};
const int QOS = 1;
/////////////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[])
{
auto serverUri = (argc > 1) ? string{argv[1]} : DFLT_SERVER_URI;
mqtt::async_client cli(serverUri, CLIENT_ID);
auto connOpts = mqtt::connect_options_builder::v3()
.keep_alive_interval(30s)
.clean_session(false)
.automatic_reconnect()
.finalize();
// The client will handle automatic reconnects, but we add this
// callbacks to let the user know when we're reconnected.
cli.set_connected_handler([](const std::string&) {
cout << "\n*** Connected ***" << endl;
});
try {
// Start consumer before connecting to make sure to not miss any messages
cli.start_consuming();
// Connect to the server
cout << "Connecting to the MQTT server..." << flush;
auto tok = cli.connect(connOpts);
// Getting the connect response will block waiting for the
// connection to complete.
auto rsp = tok->get_connect_response();
// If there is no session present, then we need to subscribe, but if
// there is a session, then the server remembers us and our
// subscriptions.
if (!rsp.is_session_present()) {
cout << " No session present on server. Subscribing..." << flush;
cli.subscribe(TOPIC, QOS)->wait();
}
cout << "OK" << endl;
// Consume messages
cout << "\nWaiting for messages on topic: '" << TOPIC << "'" << endl;
while (true) {
auto msg = cli.consume_message();
if (msg)
cout << msg->get_topic() << ": " << msg->to_string() << endl;
else
cout << "*** Connection Lost ***" << endl;
}
}
catch (const mqtt::exception& exc) {
cerr << "\n " << exc << endl;
return 1;
}
return 0;
}
// async_consume_v5.cpp
//
// This is a Paho MQTT C++ client, sample application.
//
// This application is an MQTT consumer/subscriber using the C++
// asynchronous client interface, employing the to receive messages
// and status updates.
//
// The sample demonstrates:
// - Connecting to an MQTT v5 server/broker.
// - Subscribing to a topic
// - Receiving messages through the consuming (queuing) API
//
/*******************************************************************************
* Copyright (c) 2013-2024 Frank Pagliughi <fpagliughi@mindspring.com>
*
* 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
* http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Frank Pagliughi - initial implementation and documentation
*******************************************************************************/
#include <cctype>
#include <chrono>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <thread>
#include "mqtt/async_client.h"
using namespace std;
const string DFLT_SERVER_URI{"mqtt://localhost:1883"};
const string CLIENT_ID{"PahoCppAsyncConsumeV5"};
const string TOPIC{"hello"};
const int QOS = 1;
/////////////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[])
{
auto serverURI = (argc > 1) ? string{argv[1]} : DFLT_SERVER_URI;
mqtt::async_client cli(serverURI, CLIENT_ID);
auto connOpts = mqtt::connect_options_builder::v5()
.clean_start(false)
.properties({{mqtt::property::SESSION_EXPIRY_INTERVAL, 604800}})
.finalize();
try {
cli.set_connection_lost_handler([](const std::string&) {
cout << "*** Connection Lost ***" << endl;
});
cli.set_disconnected_handler([](const mqtt::properties&, mqtt::ReasonCode reason) {
cout << "*** Disconnected. Reason [0x" << hex << int{reason} << "]: " << reason
<< " ***" << endl;
});
// Start consumer before connecting to make sure to not miss messages
cli.start_consuming();
// Connect to the server
cout << "Connecting to the MQTT server..." << flush;
auto tok = cli.connect(connOpts);
// Getting the connect response will block waiting for the
// connection to complete.
auto rsp = tok->get_connect_response();
// Make sure we were granted a v5 connection.
if (rsp.get_mqtt_version() < MQTTVERSION_5) {
cout << "\n Did not get an MQTT v5 connection." << flush;
exit(1);
}
// If there is no session present, then we need to subscribe, but if
// there is a session, then the server remembers us and our
// subscriptions.
if (!rsp.is_session_present()) {
cout << "\n Session not present on broker. Subscribing..." << flush;
cli.subscribe(TOPIC, QOS)->wait();
}
cout << "\n OK" << endl;
// Consume messages
// This just exits if the client is disconnected.
// (See some other examples for auto or manual reconnect)
cout << "\nWaiting for messages on topic: '" << TOPIC << "'" << endl;
while (true) {
auto msg = cli.consume_message();
if (!msg)
break;
cout << msg->get_topic() << ": " << msg->to_string() << endl;
}
// If we're here, the client was almost certainly disconnected.
// But we check, just to make sure.
if (cli.is_connected()) {
cout << "\nShutting down and disconnecting from the MQTT server..." << flush;
cli.stop_consuming();
cli.disconnect()->wait();
cout << "OK" << endl;
}
else {
cout << "\nClient was disconnected" << endl;
}
}
catch (const mqtt::exception& exc) {
cerr << "\n " << exc << endl;
return 1;
}
return 0;
}
// async_publish.cpp
//
// This is a Paho MQTT C++ client, sample application.
//
// It's an example of how to send messages as an MQTT publisher using the
// C++ asynchronous client interface.
//
// The sample demonstrates:
// - Connecting to an MQTT server/broker
// - Using a connect timeout
// - Publishing messages
// - Default file persistence
// - Last will and testament
// - Using asynchronous tokens
// - Implementing callbacks and action listeners
//
/*******************************************************************************
* Copyright (c) 2013-2023 Frank Pagliughi <fpagliughi@mindspring.com>
*
* 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
* http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Frank Pagliughi - initial implementation and documentation
*******************************************************************************/
#include <atomic>
#include <chrono>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <thread>
#include "mqtt/async_client.h"
using namespace std;
using namespace std::chrono;
const string DFLT_SERVER_URI{"mqtt://localhost:1883"};
const string CLIENT_ID{"paho_cpp_async_publish"};
const mqtt::persistence_type PERSIST_DIR{"./persist"};
const string TOPIC{"hello"};
const string PAYLOAD1{"Hello World!"};
const string PAYLOAD2{"Hi there!"};
const string PAYLOAD3{"Is anyone listening?"};
const string PAYLOAD4{"Someone is always listening."};
const string LWT_PAYLOAD{"Last will and testament."};
const int QOS = 1;
const auto TIMEOUT = std::chrono::seconds(10);
/////////////////////////////////////////////////////////////////////////////
/**
* A callback class for use with the main MQTT client.
*/
class callback : public virtual mqtt::callback
{
public:
void connection_lost(const string& cause) override
{
cout << "\nConnection lost" << endl;
if (!cause.empty())
cout << "\tcause: " << cause << endl;
}
void delivery_complete(mqtt::delivery_token_ptr tok) override
{
cout << "\tDelivery complete for token: " << (tok ? tok->get_message_id() : -1)
<< endl;
}
};
/////////////////////////////////////////////////////////////////////////////
/**
* A base action listener.
*/
class action_listener : public virtual mqtt::iaction_listener
{
protected:
void on_failure(const mqtt::token& tok) override
{
cout << "\tListener failure for token: " << tok.get_message_id() << endl;
}
void on_success(const mqtt::token& tok) override
{
cout << "\tListener success for token: " << tok.get_message_id() << endl;
}
};
/////////////////////////////////////////////////////////////////////////////
/**
* A derived action listener for publish events.
*/
class delivery_action_listener : public action_listener
{
atomic<bool> done_;
void on_failure(const mqtt::token& tok) override
{
action_listener::on_failure(tok);
done_ = true;
}
void on_success(const mqtt::token& tok) override
{
action_listener::on_success(tok);
done_ = true;
}
public:
delivery_action_listener() : done_(false) {}
bool is_done() const { return done_; }
};
/////////////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[])
{
// A client that just publishes normally doesn't need a persistent
// session or Client ID unless it's using persistence, then the local
// library requires an ID to identify the persistence files.
string serverURI = (argc > 1) ? string{argv[1]} : DFLT_SERVER_URI,
clientID = (argc > 2) ? string{argv[2]} : CLIENT_ID;
cout << "Initializing for server '" << serverURI << "'..." << endl;
mqtt::async_client client(serverURI, clientID, PERSIST_DIR);
callback cb;
client.set_callback(cb);
auto connOpts = mqtt::connect_options_builder()
.connect_timeout(5s)
.clean_session()
.will(mqtt::message(TOPIC, LWT_PAYLOAD, QOS, false))
.finalize();
cout << " ...OK" << endl;
try {
cout << "\nConnecting..." << endl;
mqtt::token_ptr conntok = client.connect(connOpts);
cout << "Waiting for the connection..." << endl;
conntok->wait();
cout << " ...OK" << endl;
// First use a message pointer.
cout << "\nSending message..." << endl;
mqtt::message_ptr pubmsg = mqtt::make_message(TOPIC, PAYLOAD1);
pubmsg->set_qos(QOS);
client.publish(pubmsg)->wait_for(TIMEOUT);
cout << " ...OK" << endl;
// Now try with itemized publish.
cout << "\nSending next message..." << endl;
mqtt::delivery_token_ptr pubtok;
pubtok = client.publish(TOPIC, PAYLOAD2, QOS, false);
cout << " ...with token: " << pubtok->get_message_id() << endl;
cout << " ...for message with " << pubtok->get_message()->get_payload().size()
<< " bytes" << endl;
pubtok->wait_for(TIMEOUT);
cout << " ...OK" << endl;
// Now try with a listener
cout << "\nSending next message..." << endl;
action_listener listener;
pubmsg = mqtt::make_message(TOPIC, PAYLOAD3);
pubtok = client.publish(pubmsg, nullptr, listener);
pubtok->wait();
cout << " ...OK" << endl;
// Finally try with a listener, but no token
cout << "\nSending final message..." << endl;
delivery_action_listener deliveryListener;
pubmsg = mqtt::make_message(TOPIC, PAYLOAD4);
client.publish(pubmsg, nullptr, deliveryListener);
while (!deliveryListener.is_done()) {
this_thread::sleep_for(std::chrono::milliseconds(100));
}
cout << "OK" << endl;
// Double check that there are no pending tokens
auto toks = client.get_pending_delivery_tokens();
if (!toks.empty())
cout << "Error: There are pending delivery tokens!" << endl;
// Disconnect
cout << "\nDisconnecting..." << endl;
client.disconnect()->wait();
cout << " ...OK" << endl;
}
catch (const mqtt::exception& exc) {
cerr << exc.what() << endl;
return 1;
}
return 0;
}
// async_publish_time.cpp
//
// This is a Paho MQTT C++ client, sample application.
//
// It's a fairly contrived, but useful example of an MQTT data monitor and
// publisher, using the C++ asynchronous client interface. A fairly common
// usage for MQTT applications to monitor a sensor and publish the reading
// when it changes by a "significant" amount (whatever that may be).
// This might be temperature, pressure, humidity, soil moisture, CO2 levels,
// or anything like that.
//
// Since we don't have a universal sensor to use for this example, we simply
// use time itself as out input data. We periodically "sample" the time
// value and when it changes by more than our required delta amount, we
// publish the time. In this case we use the system clock, measuring the
// time with millisecond precision.
//
// The sample demonstrates:
// - Connecting to an MQTT server/broker
// - Sampling a value
// - Publishing messages using a `topic` object
// - Last will and testament
// - Callbacks with lambdas (on connect and disconnect)
// - Using `create_options`
// - Creating options with builder classes
// - Offline buffering in the client
//
/*******************************************************************************
* Copyright (c) 2019-2023 Frank Pagliughi <fpagliughi@mindspring.com>
*
* 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
* http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Frank Pagliughi - initial implementation and documentation
*******************************************************************************/
#include <atomic>
#include <chrono>
#include <csignal>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <thread> // For sleep
#include "mqtt/async_client.h"
using namespace std;
using namespace std::chrono;
const std::string DFLT_SERVER_URI{"mqtt://localhost:1883"};
// The QoS for sending data
const int QOS = 1;
// How often to sample the "data"
const auto SAMPLE_PERIOD = 5ms;
// How much the "data" needs to change before we publish a new value.
const int DELTA_MS = 100;
// How many to buffer while off-line
const int MAX_BUFFERED_MESSAGES = 1200;
// Atomic flag to tell the main loop to exit.
atomic<bool> quit{false};
// Handler for ^C (SIGINT)
void ctrlc_handler(int) { quit = true; }
// --------------------------------------------------------------------------
// Gets the current time as the number of milliseconds since the epoch:
// like a time_t with ms resolution.
uint64_t timestamp()
{
auto now = system_clock::now();
auto tse = now.time_since_epoch();
auto msTm = duration_cast<milliseconds>(tse);
return uint64_t(msTm.count());
}
// --------------------------------------------------------------------------
int main(int argc, char* argv[])
{
// The server URI (address)
string serverURI = (argc > 1) ? string{argv[1]} : DFLT_SERVER_URI;
// The amount of time to run (in ms). Zero means "run forever".
uint64_t trun = (argc > 2) ? stoll(argv[2]) : 0LL;
cout << "Initializing for server '" << serverURI << "'..." << endl;
// We configure to allow publishing to the client while off-line,
// and that it's OK to do so before the 1st successful connection.
auto createOpts = mqtt::create_options_builder()
.server_uri(serverURI)
.send_while_disconnected(true, true)
.max_buffered_messages(MAX_BUFFERED_MESSAGES)
.delete_oldest_messages()
.finalize();
mqtt::async_client cli(createOpts);
// Set callbacks for when connected and connection lost.
cli.set_connected_handler([&cli](const std::string&) {
std::cout << "*** Connected (" << timestamp() << ") ***" << std::endl;
});
cli.set_connection_lost_handler([&cli](const std::string&) {
std::cout << "*** Connection Lost (" << timestamp() << ") ***" << std::endl;
});
auto willMsg = mqtt::message("test/events", "Time publisher disconnected", 1, true);
auto connOpts = mqtt::connect_options_builder()
.clean_session()
.will(willMsg)
.keep_alive_interval(10s)
.automatic_reconnect(seconds(1), seconds(10))
.finalize();
try {
// Note that we start the connection, but don't wait for completion.
// We configured to allow publishing before a successful connection.
cout << "Starting connection..." << endl;
cli.connect(connOpts);
auto top = mqtt::topic(cli, "data/time", QOS);
cout << "Publishing data..." << endl;
// Install a ^C handler for user to signal when to exit
signal(SIGINT, ctrlc_handler);
// Sync clock to start of delta period
while (timestamp() % DELTA_MS != 0);
uint64_t t = timestamp(), tlast = t, tstart = t;
top.publish(to_string(t));
while (!quit) {
this_thread::sleep_for(SAMPLE_PERIOD);
t = timestamp();
if (abs(int(t - tlast)) >= DELTA_MS)
top.publish(to_string(tlast = t));
if (trun > 0 && t >= (trun + tstart))
break;
}
// Disconnect
cout << "\nDisconnecting..." << endl;
cli.disconnect()->wait();
cout << " ...OK" << endl;
}
catch (const mqtt::exception& exc) {
cerr << exc.what() << endl;
return 1;
}
return 0;
}
// async_subscribe.cpp
//
// This is a Paho MQTT C++ client, sample application.
//
// This application is an MQTT subscriber using the C++ asynchronous client
// interface, employing callbacks to receive messages and status updates.
//
// The sample demonstrates:
// - Connecting to an MQTT server/broker using MQTT v3.
// - Subscribing to a topic
// - Receiving messages through the callback API
// - Receiving network disconnect updates and attempting manual reconnects.
// - Using a "clean session" and manually re-subscribing to topics on
// reconnect.
//
/*******************************************************************************
* Copyright (c) 2013-2025 Frank Pagliughi <fpagliughi@mindspring.com>
*
* 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
* http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Frank Pagliughi - initial implementation and documentation
*******************************************************************************/
#include <cctype>
#include <chrono>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <thread>
#include "mqtt/async_client.h"
const std::string DFLT_SERVER_URI("mqtt://localhost:1883");
const std::string CLIENT_ID("paho_cpp_async_subscribe");
const std::string TOPIC("#");
const int QOS = 1;
const int N_RETRY_ATTEMPTS = 5;
/////////////////////////////////////////////////////////////////////////////
// Callbacks for the success or failures of requested actions.
// This could be used to initiate further action, but here we just log the
// results to the console.
class action_listener : public virtual mqtt::iaction_listener
{
std::string name_;
void on_failure(const mqtt::token& tok) override
{
std::cout << name_ << " failure";
if (tok.get_message_id() != 0)
std::cout << " for token: [" << tok.get_message_id() << "]" << std::endl;
std::cout << std::endl;
}
void on_success(const mqtt::token& tok) override
{
std::cout << name_ << " success";
if (tok.get_message_id() != 0)
std::cout << " for token: [" << tok.get_message_id() << "]" << std::endl;
auto top = tok.get_topics();
if (top && !top->empty())
std::cout << "\ttoken topic: '" << (*top)[0] << "', ..." << std::endl;
std::cout << std::endl;
}
public:
action_listener(const std::string& name) : name_(name) {}
};
/////////////////////////////////////////////////////////////////////////////
/**
* Local callback & listener class for use with the client connection.
* This is primarily intended to receive messages, but it will also monitor
* the connection to the broker. If the connection is lost, it will attempt
* to restore the connection and re-subscribe to the topic.
*/
class callback : public virtual mqtt::callback, public virtual mqtt::iaction_listener
{
// Counter for the number of connection retries
int nretry_;
// The MQTT client
mqtt::async_client& cli_;
// Options to use if we need to reconnect
mqtt::connect_options& connOpts_;
// An action listener to display the result of actions.
action_listener subListener_;
// This deomonstrates manually reconnecting to the broker by calling
// connect() again. This is a possibility for an application that keeps
// a copy of it's original connect_options, or if the app wants to
// reconnect with different options.
// Another way this can be done manually, if using the same options, is
// to just call the async_client::reconnect() method.
void reconnect()
{
std::this_thread::sleep_for(std::chrono::milliseconds(2500));
try {
cli_.connect(connOpts_, nullptr, *this);
}
catch (const mqtt::exception& exc) {
std::cerr << "Error: " << exc.what() << std::endl;
exit(1);
}
}
// Re-connection failure
void on_failure(const mqtt::token& tok) override
{
std::cout << "Connection attempt failed" << std::endl;
if (++nretry_ > N_RETRY_ATTEMPTS)
exit(1);
reconnect();
}
// (Re)connection success
// Either this or connected() can be used for callbacks.
void on_success(const mqtt::token& tok) override {}
// (Re)connection success
void connected(const std::string& cause) override
{
std::cout << "\nConnection success" << std::endl;
std::cout << "\nSubscribing to topic '" << TOPIC << "'\n"
<< "\tfor client " << CLIENT_ID << " using QoS" << QOS << "\n"
<< "\nPress Q<Enter> to quit\n"
<< std::endl;
cli_.subscribe(TOPIC, QOS, nullptr, subListener_);
}
// Callback for when the connection is lost.
// This will initiate the attempt to manually reconnect.
void connection_lost(const std::string& cause) override
{
std::cout << "\nConnection lost" << std::endl;
if (!cause.empty())
std::cout << "\tcause: " << cause << std::endl;
std::cout << "Reconnecting..." << std::endl;
nretry_ = 0;
reconnect();
}
// Callback for when a message arrives.
void message_arrived(mqtt::const_message_ptr msg) override
{
std::cout << "Message arrived" << std::endl;
std::cout << "\ttopic: '" << msg->get_topic() << "'" << std::endl;
std::cout << "\tpayload: '" << msg->to_string() << "'\n" << std::endl;
}
void delivery_complete(mqtt::delivery_token_ptr token) override {}
public:
callback(mqtt::async_client& cli, mqtt::connect_options& connOpts)
: nretry_(0), cli_(cli), connOpts_(connOpts), subListener_("Subscription")
{
}
};
/////////////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[])
{
// A subscriber often wants the server to remember its messages when its
// disconnected. In that case, it needs a unique ClientID and a
// non-clean session.
auto serverURI = (argc > 1) ? std::string{argv[1]} : DFLT_SERVER_URI;
mqtt::async_client cli(serverURI, CLIENT_ID);
mqtt::connect_options connOpts;
connOpts.set_clean_session(false);
// Install the callback(s) before connecting.
callback cb(cli, connOpts);
cli.set_callback(cb);
// Start the connection.
// When completed, the callback will subscribe to topic.
try {
std::cout << "Connecting to the MQTT server '" << serverURI << "'..." << std::flush;
cli.connect(connOpts, nullptr, cb);
}
catch (const mqtt::exception& exc) {
std::cerr << "\nERROR: Unable to connect to MQTT server: '" << serverURI << "'" << exc
<< std::endl;
return 1;
}
// Just block till user tells us to quit.
while (std::tolower(std::cin.get()) != 'q');
// Disconnect
try {
std::cout << "\nDisconnecting from the MQTT server..." << std::flush;
cli.disconnect()->wait();
std::cout << "OK" << std::endl;
}
catch (const mqtt::exception& exc) {
std::cerr << exc << std::endl;
return 1;
}
return 0;
}
// async_subscribe.cpp
//
// This is a Paho MQTT C++ client, sample application.
//
// This application is an MQTT subscriber using the C++ asynchronous client
// interface, employing callbacks to receive messages and status updates.
//
// The sample demonstrates:
// - Connecting to an MQTT server/broker using MQTT v5.
// - Subscribing to a topic
// - Receiving messages through the callback API
// - Displaying MQTT v5 message properties.
// - Receiving network disconnect updates and attempting manual reconnects.
// - Using a "clean session" and manually re-subscribing to topics on
// reconnect.
//
/*******************************************************************************
* Copyright (c) 2013-2025 Frank Pagliughi <fpagliughi@mindspring.com>
*
* 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
* http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Frank Pagliughi - initial implementation and documentation
*******************************************************************************/
#include <cctype>
#include <chrono>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <thread>
#include "mqtt/async_client.h"
const std::string DFLT_SERVER_URI("mqtt://localhost:1883");
const std::string CLIENT_ID("paho_cpp_async_subscribe");
const std::string TOPIC("#");
const int QOS = 1;
const int N_RETRY_ATTEMPTS = 5;
/////////////////////////////////////////////////////////////////////////////
// Callbacks for the success or failures of requested actions.
// This could be used to initiate further action, but here we just log the
// results to the console.
class action_listener : public virtual mqtt::iaction_listener
{
std::string name_;
void on_failure(const mqtt::token& tok) override
{
std::cout << name_ << " failure";
if (tok.get_message_id() != 0)
std::cout << " for token: [" << tok.get_message_id() << "]" << std::endl;
std::cout << std::endl;
}
void on_success(const mqtt::token& tok) override
{
std::cout << name_ << " success";
if (tok.get_message_id() != 0)
std::cout << " for token: [" << tok.get_message_id() << "]" << std::endl;
auto top = tok.get_topics();
if (top && !top->empty())
std::cout << "\ttoken topic: '" << (*top)[0] << "', ..." << std::endl;
std::cout << std::endl;
}
public:
action_listener(const std::string& name) : name_(name) {}
};
/////////////////////////////////////////////////////////////////////////////
/**
* Local callback & listener class for use with the client connection.
* This is primarily intended to receive messages, but it will also monitor
* the connection to the broker. If the connection is lost, it will attempt
* to restore the connection and re-subscribe to the topic.
*/
class callback : public virtual mqtt::callback, public virtual mqtt::iaction_listener
{
// Counter for the number of connection retries
int nretry_;
// The MQTT client
mqtt::async_client& cli_;
// Options to use if we need to reconnect
mqtt::connect_options& connOpts_;
// An action listener to display the result of actions.
action_listener subListener_;
// This deomonstrates manually reconnecting to the broker by calling
// connect() again. This is a possibility for an application that keeps
// a copy of it's original connect_options, or if the app wants to
// reconnect with different options.
// Another way this can be done manually, if using the same options, is
// to just call the async_client::reconnect() method.
void reconnect()
{
std::this_thread::sleep_for(std::chrono::milliseconds(2500));
try {
cli_.connect(connOpts_, nullptr, *this);
}
catch (const mqtt::exception& exc) {
std::cerr << "Error: " << exc.what() << std::endl;
exit(1);
}
}
// Re-connection failure
void on_failure(const mqtt::token& tok) override
{
std::cout << "Connection attempt failed" << std::endl;
if (++nretry_ > N_RETRY_ATTEMPTS)
exit(1);
reconnect();
}
// (Re)connection success
// Either this or connected() can be used for callbacks.
void on_success(const mqtt::token& tok) override {}
// (Re)connection success
void connected(const std::string& cause) override
{
std::cout << "\nConnection success" << std::endl;
std::cout << "\nSubscribing to topic '" << TOPIC << "'\n"
<< "\tfor client " << CLIENT_ID << " using QoS" << QOS << "\n"
<< "\nPress Q<Enter> to quit\n"
<< std::endl;
cli_.subscribe(TOPIC, QOS, nullptr, subListener_);
}
// Callback for when the connection is lost.
// This will initiate the attempt to manually reconnect.
void connection_lost(const std::string& cause) override
{
std::cout << "\nConnection lost" << std::endl;
if (!cause.empty())
std::cout << "\tcause: " << cause << std::endl;
std::cout << "Reconnecting..." << std::endl;
nretry_ = 0;
reconnect();
}
// Callback for when a message arrives.
void message_arrived(mqtt::const_message_ptr msg) override
{
std::cout << "\nMessage arrived" << std::endl;
std::cout << "\ttopic: '" << msg->get_topic() << "'" << std::endl;
std::cout << "\tpayload: '" << msg->to_string() << std::endl;
const mqtt::properties& props = msg->get_properties();
if (size_t n = props.size(); n != 0) {
std::cout << "\tproperties (" << n << "):\n\t [";
for (size_t i = 0; i < n - 1; ++i) std::cout << props[i] << ", ";
std::cout << props[n - 1] << "]" << std::endl;
}
}
void delivery_complete(mqtt::delivery_token_ptr token) override {}
public:
callback(mqtt::async_client& cli, mqtt::connect_options& connOpts)
: nretry_(0), cli_(cli), connOpts_(connOpts), subListener_("Subscription")
{
}
};
/////////////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[])
{
// A subscriber often wants the server to remember its messages when its
// disconnected. In that case, it needs a unique ClientID and a
// non-clean session.
auto serverURI = (argc > 1) ? std::string{argv[1]} : DFLT_SERVER_URI;
mqtt::async_client cli(serverURI, CLIENT_ID);
auto connOpts = mqtt::connect_options_builder::v5().clean_start(true).finalize();
// Install the callback(s) before connecting.
callback cb(cli, connOpts);
cli.set_callback(cb);
// Start the connection.
// When completed, the callback will subscribe to topic.
try {
std::cout << "Connecting to the MQTT server '" << serverURI << "'..." << std::flush;
cli.connect(connOpts, nullptr, cb);
}
catch (const mqtt::exception& exc) {
std::cerr << "\nERROR: Unable to connect to MQTT server: '" << serverURI << "'" << exc
<< std::endl;
return 1;
}
// Just block till user tells us to quit.
while (std::tolower(std::cin.get()) != 'q');
// Disconnect
try {
std::cout << "\nDisconnecting from the MQTT server..." << std::flush;
cli.disconnect()->wait();
std::cout << "OK" << std::endl;
}
catch (const mqtt::exception& exc) {
std::cerr << exc << std::endl;
return 1;
}
return 0;
}
This diff is collapsed.
// mqttpp_chat.cpp
//
// This is a Paho MQTT C++ client, sample application.
//
// The "chat" application is practically the "Hello World" application for
// messaging systems. This allows a user to type in message to send to a
// "group" while seeing all the messages that the other members of the group
// send.
//
// This application is an MQTT publisher/subscriber using the C++
// asynchronous client interface, employing callbacks to receive messages
// and status updates.
//
// The sample demonstrates:
// - Connecting to an MQTT server/broker.
// - Publishing messages.
// - Subscribing to a topic
// - Receiving messages (callbacks) through a lambda function
//
// USAGE:
// mqttpp_chat <user> <group>
/*******************************************************************************
* Copyright (c) 2019-2023 Frank Pagliughi <fpagliughi@mindspring.com>
*
* 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
* http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Frank Pagliughi - initial implementation and documentation
*******************************************************************************/
#include <cctype>
#include <chrono>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <thread>
#include "mqtt/async_client.h"
#include "mqtt/topic.h"
/////////////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[])
{
// The broker/server address
const std::string SERVER_ADDRESS("mqtt://localhost:1883");
// The QoS to use for publishing and subscribing
const int QOS = 1;
// Tell the broker we don't want our own messages sent back to us.
const bool NO_LOCAL = true;
if (argc != 3) {
std::cout << "USAGE: mqttpp_chat <user> <group>" << std::endl;
return 1;
}
std::string chatUser{argv[1]}, chatGroup{argv[2]}, chatTopic{"chat/" + chatGroup};
mqtt::async_client cli(SERVER_ADDRESS);
// LWT message is broadcast to other users if out connection is lost
auto lwt =
mqtt::message(chatTopic, "<<<" + chatUser + " was disconnected>>>", QOS, false);
// Set up the connect options
auto connOpts = mqtt::connect_options_builder::v5()
.properties({{mqtt::property::SESSION_EXPIRY_INTERVAL, 604800}})
.clean_start(false)
.will(std::move(lwt))
.keep_alive_interval(std::chrono::seconds(20))
.finalize();
// Set a callback for connection lost.
// This just exits the app.
cli.set_connection_lost_handler([](const std::string&) {
std::cout << "*** Connection Lost ***" << std::endl;
exit(2);
});
// Set the callback for incoming messages
cli.set_message_callback([](mqtt::const_message_ptr msg) {
std::cout << msg->get_payload_str() << std::endl;
});
// We publish and subscribe to one topic,
// so a 'topic' object is helpful.
mqtt::topic topic{cli, "chat/" + chatGroup, QOS};
// Start the connection.
try {
std::cout << "Connecting to the chat server at '" << SERVER_ADDRESS << "'..."
<< std::flush;
auto tok = cli.connect(connOpts);
tok->wait();
// Subscribe to the topic using "no local" so that
// we don't get own messages sent back to us
std::cout << "Ok\nJoining the group..." << std::flush;
auto subOpts = mqtt::subscribe_options(NO_LOCAL);
topic.subscribe(subOpts)->wait();
std::cout << "Ok" << std::endl;
}
catch (const mqtt::exception& exc) {
std::cerr << "\nERROR: Unable to connect. " << exc.what() << std::endl;
return 1;
}
// Let everyone know that a new user joined the conversation.
topic.publish("<<" + chatUser + " joined the group>>");
// Read messages from the console and publish them.
// Quit when the use enters an empty line.
std::string usrMsg;
while (std::getline(std::cin, usrMsg) && !usrMsg.empty()) {
usrMsg = chatUser + ": " + usrMsg;
topic.publish(usrMsg);
}
// Let everyone know that the user left the conversation.
topic.publish("<<" + chatUser + " left the group>>")->wait();
// Disconnect
try {
std::cout << "Disconnecting from the chat server..." << std::flush;
cli.disconnect()->wait();
std::cout << "OK" << std::endl;
}
catch (const mqtt::exception& exc) {
std::cerr << exc.what() << std::endl;
return 1;
}
return 0;
}
// async_subscribe.cpp
//
// This is a Paho MQTT C++ client, sample application.
//
// This application is an MQTT publisher/subscriber using the C++
// asynchronous client interface, demonstrating how you can share a client
// between multiple threads.
//
// The app will count the number of "data" messages arriving at the broker
// and then emit "events" with updated counts. A data message is any on a
// "data/#" topic, and counts are emitted on the "events/count" topic. It
// emits an event count around once every ten data messages.
//
// Note that this is a fairly contrived example, and it could be done much
// more easily in a single thread. It is meant to demonstrate how you can
// share a client amongst threads if and when that's a proper thing to do.
//
// At this time, there is a single callback or consumer queue for all
// incoming messages, so you would typically only have one thead receiving
// messages, although it _could_ send messages to multiple threads for
// processing, perhaps based on the topics. It could be common, however, to
// want to have multiple threads for publishing.
//
// This example demonstrates:
// - Creating a client and sharing it across threads using a shared_ptr<>
// - Using one thread to receive incoming messages from the broker and
// another thread to publish messages to it.
// - Connecting to an MQTT server/broker.
// - Automatic reconnect
// - Publishing messages
// - Subscribing to multiple topics
// - Using the asynchronous message consumer
// - Signaling consumer from another thread
//
/*******************************************************************************
* Copyright (c) 2020-2025 Frank Pagliughi <fpagliughi@mindspring.com>
*
* 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
* http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Frank Pagliughi - initial implementation and documentation
*******************************************************************************/
#include <cctype>
#include <chrono>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <memory>
#include <string>
#include <thread>
#include "mqtt/async_client.h"
using namespace std;
using namespace std::chrono;
const std::string DFLT_SERVER_ADDRESS{"mqtt://localhost:1883"};
const std::string CLIENT_ID{"multithr_pub_sub_cpp"};
/////////////////////////////////////////////////////////////////////////////
/**
* A thread-safe counter that can be used to occasionally signal a waiter on
* every 10th increment.
*/
class multithr_counter
{
using guard = std::unique_lock<std::mutex>;
size_t count_;
bool closed_;
mutable bool ready_;
mutable std::condition_variable cond_;
mutable std::mutex lock_;
public:
// Declare a pointer type for sharing a counter between threads
using ptr_t = std::shared_ptr<multithr_counter>;
// Create a new thread-safe counter with an initial count of zero.
multithr_counter() : count_(0), closed_(false), ready_(false) {}
// Determines if the counter has been closed.
bool closed() const
{
guard g(lock_);
return closed_;
}
// Close the counter and signal all waiters.
void close()
{
guard g(lock_);
closed_ = ready_ = true;
cond_.notify_all();
}
// Increments the count, and then signals once every 10 messages.
void incr()
{
guard g(lock_);
if (closed_)
throw string("Counter is closed");
if (++count_ % 10 == 0) {
ready_ = true;
g.unlock();
cond_.notify_all();
}
}
// This will block the caller until at least 10 new messages received.
size_t get_count() const
{
guard g(lock_);
cond_.wait(g, [this] { return ready_; });
ready_ = false;
return count_;
}
};
/////////////////////////////////////////////////////////////////////////////
// The MQTT publisher function will run in its own thread.
// It runs until the receiver thread closes the counter object.
void publisher_func(mqtt::async_client_ptr cli, multithr_counter::ptr_t counter)
{
while (true) {
size_t n = counter->get_count();
if (counter->closed())
break;
string payload = std::to_string(n);
cli->publish("events/count", payload)->wait();
}
}
/////////////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[])
{
string address = (argc > 1) ? string(argv[1]) : DFLT_SERVER_ADDRESS;
// Create an MQTT client using a smart pointer to be shared among threads.
auto cli = std::make_shared<mqtt::async_client>(address, CLIENT_ID);
// Make a counter object also with a shared pointer.
auto counter = std::make_shared<multithr_counter>();
// Connect options for a persistent session and automatic reconnects.
auto connOpts = mqtt::connect_options_builder()
.clean_session(false)
.automatic_reconnect(seconds(2), seconds(30))
.finalize();
auto TOPICS = mqtt::string_collection::create({"data/#", "command"});
const vector<int> QOS{0, 1};
try {
// Start consuming _before_ connecting, because we could get a flood
// of stored messages as soon as the connection completes since
// we're using a persistent (non-clean) session with the broker.
cli->start_consuming();
cout << "Connecting to the MQTT server at " << address << "..." << flush;
auto rsp = cli->connect(connOpts)->get_connect_response();
cout << "OK\n" << endl;
cout << "Now start an application such as 'async_publish_time'\n"
<< "that publishes to a 'data/' topic...\n"
<< endl;
// Subscribe if this is a new session with the server
if (!rsp.is_session_present())
cli->subscribe(TOPICS, QOS);
// Start the publisher thread
std::thread publisher(publisher_func, cli, counter);
// Start another thread to shut us down after a minute
std::thread{[cli] {
this_thread::sleep_for(30s);
cout << "Signaling the consumer to stop." << endl;
cli->stop_consuming();
}}.detach();
// Consume messages in this thread
// Remember that with the message consumer, we can't detect a
// reconnect We would need to register a connect callback or use the
// event consumer.
while (true) {
auto msg = cli->consume_message();
if (!msg) {
// Exit if the consumer was shut down
if (cli->consumer_closed())
break;
// Otherwise let auto-reconnect deal with it.
cout << "Disconnect detected. Attempting an auto-reconnect." << endl;
continue;
}
if (msg->get_topic() == "command" && msg->to_string() == "exit") {
cout << "Exit command received" << endl;
break;
}
cout << msg->get_topic() << ": " << msg->to_string() << endl;
counter->incr();
}
// Close the counter and wait for the publisher thread to complete
cout << "\nShutting down..." << flush;
counter->close();
publisher.join();
// Disconnect
cout << "OK\nDisconnecting..." << flush;
cli->disconnect();
cout << "OK" << endl;
}
catch (const mqtt::exception& exc) {
cerr << exc.what() << endl;
return 1;
}
return 0;
}
// pub_speed_test.cpp
//
// Paho C++ sample client application to do a simple test of the speed at
// which messages can be published.
//
/*******************************************************************************
* Copyright (c) 2013-2023 Frank Pagliughi <fpagliughi@mindspring.com>
*
* 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
* http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Frank Pagliughi - initial implementation and documentation
*******************************************************************************/
#include <atomic>
#include <chrono>
#include <cstdlib>
#include <cstring>
#include <future>
#include <iostream>
#include <string>
#include <thread>
#include "mqtt/async_client.h"
#include "mqtt/thread_queue.h"
using namespace std;
using namespace std::chrono;
const std::string DFLT_SERVER_ADDRESS{"mqtt://localhost:1883"};
const size_t DFLT_PAYLOAD_SIZE = 1024;
const int DFLT_N_MSG = 1000, DFLT_QOS = 1;
const string TOPIC{"test/speed"};
const char* LWT_PAYLOAD = "pub_speed_test died unexpectedly.";
// Queue for passing tokens to the wait thread
mqtt::thread_queue<mqtt::delivery_token_ptr> que;
// Get the current time on the steady clock
steady_clock::time_point now() { return steady_clock::now(); }
// Convert a duration to a count of milliseconds
template <class Rep, class Period>
int64_t msec(const std::chrono::duration<Rep, Period>& dur)
{
return (int64_t)duration_cast<milliseconds>(dur).count();
}
// --------------------------------------------------------------------------
// Thread function will wait for all the tokens to complete.
// Any exceptions thrown from here will be caught in main().
void token_wait_func()
{
while (true) {
mqtt::delivery_token_ptr tok = que.get();
if (!tok)
break;
// cout.put('x');
tok->wait();
}
}
// --------------------------------------------------------------------------
int main(int argc, char* argv[])
{
string address = (argc > 1) ? string(argv[1]) : DFLT_SERVER_ADDRESS;
int nMsg = (argc > 2) ? atoi(argv[2]) : DFLT_N_MSG;
size_t msgSz = (size_t)((argc > 3) ? atol(argv[3]) : DFLT_PAYLOAD_SIZE);
int qos = (argc > 4) ? atoi(argv[4]) : DFLT_QOS;
cout << "Initializing for server '" << address << "'..." << flush;
mqtt::async_client cli(address, "");
mqtt::message willmsg(TOPIC, LWT_PAYLOAD, 1, true);
mqtt::will_options will(willmsg);
mqtt::connect_options connOpts;
connOpts.set_clean_session(true);
connOpts.set_will(will);
// Create a payload
mqtt::binary payload;
for (size_t i = 0; i < msgSz; ++i) payload.push_back('a' + i % 26);
cout << "OK" << endl;
try {
// Create the message (move payload into it)
auto msg = mqtt::make_message(TOPIC, std::move(payload), qos, false);
// Connect to the broker
cout << "\nConnecting..." << flush;
auto start = now();
cli.connect(connOpts)->wait();
auto end = now();
cout << "OK" << endl;
cout << "Connected in " << msec(end - start) << "ms" << endl;
auto fut = std::async(launch::async, token_wait_func);
// Publish the messages
cout << "\nPublishing " << nMsg << " messages..." << flush;
start = now();
for (int i = 0; i < nMsg; ++i) {
auto dtok = cli.publish(msg);
// cout.put('^');
que.put(std::move(dtok));
}
auto pubend = now();
que.put(mqtt::delivery_token_ptr());
// Wait for all the tokens to complete
fut.get();
end = now();
cout << "OK" << endl;
auto ms = msec(pubend - start);
cout << "Published in " << ms << "ms " << (nMsg / ms) << "k msg/sec" << endl;
ms = msec(end - start);
cout << "Acknowledged in " << ms << "ms " << (nMsg / ms) << "k msg/sec" << endl;
// Disconnect
cout << "\nDisconnecting..." << flush;
start = now();
cli.disconnect(seconds(10))->wait();
end = now();
cout << "OK" << endl;
cout << "Disconnected in " << msec(end - start) << "ms" << endl;
}
catch (const mqtt::exception& exc) {
que.put(mqtt::delivery_token_ptr{});
cerr << exc.what() << endl;
return 1;
}
return 0;
}
// rpc_math_cli.cpp
//
// This is a Paho MQTT v5 C++ sample application.
//
// It's an example of how to create a client for performing remote procedure
// calls using MQTT with the 'response topic' and 'correlation data'
// properties.
//
// The sample demonstrates:
// - Connecting to an MQTT server/broker
// - Using MQTT v5 properties
// - Publishing RPC request messages
// - Using asynchronous tokens
// - Subscribing to reply topic
//
/*******************************************************************************
* Copyright (c) 2019-2024 Frank Pagliughi <fpagliughi@mindspring.com>
*
* 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
* http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Frank Pagliughi - initial implementation and documentation
*******************************************************************************/
#include <atomic>
#include <chrono>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <sstream>
#include <string>
#include <thread>
#include "mqtt/async_client.h"
#include "mqtt/properties.h"
using namespace std;
using namespace std::chrono;
const string SERVER_ADDRESS{"mqtt://localhost:1883"};
const auto TIMEOUT = std::chrono::seconds(10);
/////////////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[])
{
if (argc < 4) {
cout << "USAGE: rpc_math_cli <add|mult> <num1> <num2> [... numN]" << endl;
return 1;
}
constexpr int QOS = 1;
const string REQ_TOPIC_HDR{"requests/math/"};
// Create a client
mqtt::async_client cli(SERVER_ADDRESS, "");
cli.start_consuming();
try {
cout << "Connecting..." << flush;
auto connOpts = mqtt::connect_options::v5();
mqtt::token_ptr tok = cli.connect(connOpts);
auto connRsp = tok->get_connect_response();
cout << "OK (" << connRsp.get_server_uri() << ")" << endl;
// Since we gave an empty client ID, the server should create a
// unique one for us and send it back as ASSIGNED_CLIENT_IDENTIFIER
// in the connect properties.
string clientId =
get<string>(connRsp.get_properties(), mqtt::property::ASSIGNED_CLIENT_IDENTIFIER);
// So now we can create a unique RPC response topic using
// the assigned (unique) client ID.
string repTopic = "replies/" + clientId + "/math";
cout << " Reply topic: " << repTopic << endl;
// Subscribe to the reply topic and verify the QoS
tok = cli.subscribe(repTopic, QOS);
tok->wait();
if (int(tok->get_reason_code()) != QOS) {
cerr << "Error: Server doesn't support reply QoS: [" << tok->get_reason_code()
<< "]" << endl;
return 2;
}
// Create and send the request message
string req{argv[1]}, reqTopic{REQ_TOPIC_HDR + req};
mqtt::properties props{
{mqtt::property::RESPONSE_TOPIC, repTopic},
{mqtt::property::CORRELATION_DATA, "1"}
};
ostringstream os;
os << "[ ";
for (int i = 2; i < argc - 1; ++i) os << argv[i] << ", ";
os << argv[argc - 1] << " ]";
string reqArgs{os.str()};
cout << "\nSending '" << req << "' request " << os.str() << "..." << flush;
auto pubmsg = mqtt::message_ptr_builder()
.topic(reqTopic)
.payload(reqArgs)
.qos(QOS)
.properties(props)
.finalize();
cli.publish(pubmsg)->wait_for(TIMEOUT);
cout << "OK" << endl;
// Wait for reply.
auto msg = cli.try_consume_message_for(seconds(5));
if (!msg) {
cerr << "Didn't receive a reply from the service." << endl;
return 1;
}
cout << " Result: " << msg->to_string() << endl;
// Unsubscribe
cli.unsubscribe(repTopic)->wait();
// Disconnect
cout << "\nDisconnecting..." << flush;
cli.disconnect()->wait();
cout << "OK" << endl;
}
catch (const mqtt::exception& exc) {
cerr << exc.what() << endl;
return 1;
}
return 0;
}
// rpc_math_srvr.cpp
//
// This is a Paho MQTT C++ client, sample application.
//
// This application is an MQTT consumer/subscriber using the C++ synchronous
// client interface, which uses the queuing API to receive messages.
//
// The sample demonstrates:
// - Connecting to an MQTT server/broker
// - Subscribing to multiple topics
// - Receiving messages through the queueing consumer API
// - Receiving and acting upon commands via MQTT topics
// - Manual reconnects
// - Using a persistent (non-clean) session
//
/*******************************************************************************
* Copyright (c) 2019-2023 Frank Pagliughi <fpagliughi@mindspring.com>
*
* 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
* http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Frank Pagliughi - initial implementation and documentation
*******************************************************************************/
#include <cctype>
#include <chrono>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <sstream>
#include <string>
#include <thread>
#include "mqtt/client.h"
using namespace std;
using namespace std::chrono;
const string SERVER_ADDRESS{"mqtt://localhost:1883"};
const string CLIENT_ID{"rpc_math_srvr"};
constexpr auto RESPONSE_TOPIC = mqtt::property::RESPONSE_TOPIC;
constexpr auto CORRELATION_DATA = mqtt::property::CORRELATION_DATA;
// --------------------------------------------------------------------------
// Simple function to manually reconnect a client.
bool try_reconnect(mqtt::client& cli)
{
constexpr int N_ATTEMPT = 30;
for (int i = 0; i < N_ATTEMPT && !cli.is_connected(); ++i) {
try {
cli.reconnect();
return true;
}
catch (const mqtt::exception&) {
this_thread::sleep_for(seconds(1));
}
}
return false;
}
// --------------------------------------------------------------------------
// RPC function implementations
double add(const std::vector<double>& nums)
{
double sum = 0.0;
for (auto n : nums) sum += n;
return sum;
}
double mult(const std::vector<double>& nums)
{
double prod = 1.0;
for (auto n : nums) prod *= n;
return prod;
}
/////////////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[])
{
mqtt::client cli(SERVER_ADDRESS, CLIENT_ID);
auto connOpts = mqtt::connect_options_builder::v5()
.keep_alive_interval(seconds(20))
.clean_start()
.finalize();
const vector<string> TOPICS{"requests/math", "requests/math/#"};
const vector<int> QOS{1, 1};
try {
cout << "Connecting to the MQTT server..." << flush;
cli.connect(connOpts);
cli.subscribe(TOPICS, QOS);
cout << "OK\n" << endl;
// Consume messages
cout << "Waiting for RPC requests..." << endl;
while (true) {
auto msg = cli.consume_message();
if (!msg) {
if (!cli.is_connected()) {
cout << "Lost connection. Attempting reconnect" << endl;
if (try_reconnect(cli)) {
cli.subscribe(TOPICS, QOS);
cout << "Reconnected" << endl;
continue;
}
else {
cout << "Reconnect failed." << endl;
break;
}
}
else
break;
}
cout << "Received a request" << endl;
const mqtt::properties& props = msg->get_properties();
if (props.contains(RESPONSE_TOPIC) && props.contains(CORRELATION_DATA)) {
mqtt::binary corr_id = mqtt::get<string>(props, CORRELATION_DATA);
string reply_to = mqtt::get<string>(props, RESPONSE_TOPIC);
cout << "Client wants a reply to [" << corr_id << "] on '" << reply_to << "'"
<< endl;
cout << msg->get_topic() << ": " << msg->to_string() << endl;
char c;
double x;
vector<double> nums;
istringstream is(msg->to_string());
if (!(is >> c) || c != '[') {
cout << "Malformed arguments" << endl;
// Maybe send an error message to client.
continue;
}
c = ',';
while (c == ',' && (is >> x >> c)) nums.push_back(x);
if (c != ']') {
cout << "Bad closing delimiter" << endl;
continue;
}
x = 0.0;
if (msg->get_topic() == "requests/math/add")
x = add(nums);
else if (msg->get_topic() == "requests/math/mult")
x = mult(nums);
else {
cout << "Unknown request: " << msg->get_topic() << endl;
continue;
}
cout << " Result: " << x << endl;
auto reply_msg = mqtt::message::create(reply_to, to_string(x), 1, false);
cli.publish(reply_msg);
}
}
// Disconnect
cout << "\nDisconnecting from the MQTT server..." << flush;
cli.disconnect();
cout << "OK" << endl;
}
catch (const mqtt::exception& exc) {
cerr << exc.what() << endl;
return 1;
}
return 0;
}
// server_props_v5.cpp
//
// This is a Paho MQTT C++ client, sample application.
//
// This application is an MQTT client using the C++ asynchronous interface
// which shows how to check the server cofiguration for an MQTT v5
// connection.
//
// With an MQTT v5 connection, the server specify can some features that it
// doesn't supports, or limits in some way. It does this by adding v5
// properties to the CONNACK packet it sends back to the client in a connect
// transaction. The C++ application can retrieve these from the connect
// token via the `connect_response` object.
//
// It also shows short-lived persistent sessions. The client asks the server
// to just keep the session for 10sec. If you re-run the application in less
// than 10sec, it should report that the session exists. Any longer, and the
// session will be gone.
//
// Note that 10sec is probably *way too short* a time for real-world
// applications. This is just for demonstrating/testing the session expiry
// interval.
//
// The sample demonstrates:
// - Connecting to an MQTT v5 server/broker.
// - Specifying a short-lived (10sec) persistent session.
// - Retrieving the v5 properties from the connect response (i.e. CONNACK
// packet)
// - Iterating through v5 properties.
// - Displaying server properties to the user.
//
/*******************************************************************************
* Copyright (c) 2013-2024 Frank Pagliughi <fpagliughi@mindspring.com>
*
* 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
* http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Frank Pagliughi - initial implementation and documentation
*******************************************************************************/
#include <cctype>
#include <chrono>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <thread>
#include "mqtt/async_client.h"
using namespace std;
const string DFLT_SERVER_URI{"mqtt://localhost:1883"};
const string CLIENT_ID{"server_props_v5"};
/////////////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[])
{
auto serverURI = (argc > 1) ? string{argv[1]} : DFLT_SERVER_URI;
mqtt::async_client cli(serverURI, CLIENT_ID);
auto connOpts = mqtt::connect_options_builder::v5()
.clean_start(false)
.properties({{mqtt::property::SESSION_EXPIRY_INTERVAL, 10}})
.finalize();
try {
// Connect to the server
cout << "Connecting to the MQTT server at '" << serverURI << "'..." << flush;
auto tok = cli.connect(connOpts);
// Getting the connect response will block waiting for the
// connection to complete.
auto rsp = tok->get_connect_response();
cout << "OK" << endl;
// Make sure we were granted a v5 connection.
if (rsp.get_mqtt_version() < MQTTVERSION_5) {
cout << "Did not get an MQTT v5 connection." << endl;
exit(1);
}
// Does the server have a session for us?
cout << "\nThe session is " << (rsp.is_session_present() ? "" : "not ")
<< "present on the server." << endl;
// Show the v5 properties from the CONNACK, if any
cout << "\nConnection Properties:" << endl;
if (rsp.get_properties().empty()) {
cout << " <none>" << endl;
}
else {
for (const auto& prop : rsp.get_properties()) {
cout << " " << prop << endl;
}
}
// OK, we're done.
cli.disconnect()->wait();
}
catch (const mqtt::exception& exc) {
cerr << "\n " << exc << endl;
return 1;
}
return 0;
}
// ssl_publish.cpp
//
// This is a Paho MQTT C++ client, sample application.
//
// It's an example of how to connect to an MQTT broker securely, and then
// send messages as an MQTT publisher using the C++ asynchronous client
// interface.
//
// The sample demonstrates:
// - Connecting to an MQTT server/broker securely
// - Setting SSL/TLS options
// - Last will and testament
// - Publishing messages
// - Using asynchronous tokens
// - Implementing callbacks and action listeners
//
// We can test this using mosquitto configured with certificates in the
// Paho C library. The C library has an SSL/TSL test suite, and we can use
// that to test:
// $ cd paho.mqtt.c
// $ mosquitto -c test/tls-testing/mosquitto.conf
//
// Then use the files "test-root-ca.crt" and "client.pem" from the
// test/ssl directory (paho.mqtt.c/test/ssl) for the trust store and
// key_store, respectively, for this program.
//
/*******************************************************************************
* Copyright (c) 2013-2023 Frank Pagliughi <fpagliughi@mindspring.com>
*
* 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
* http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Frank Pagliughi - initial implementation and documentation
*******************************************************************************/
#include <chrono>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <string>
#include "mqtt/async_client.h"
const std::string DFLT_SERVER_URI{"mqtts://localhost:18884"};
const std::string DFLT_CLIENT_ID{"ssl_publish_cpp"};
const std::string KEY_STORE{"client.pem"};
const std::string TRUST_STORE{"test-root-ca.crt"};
const std::string LWT_TOPIC{"events/disconnect"};
const std::string LWT_PAYLOAD{"Last will and testament."};
const int QOS = 1;
const auto TIMEOUT = std::chrono::seconds(10);
/////////////////////////////////////////////////////////////////////////////
/**
* A callback class for use with the main MQTT client.
*/
class callback : public virtual mqtt::callback
{
public:
void connection_lost(const std::string& cause) override
{
std::cout << "\nConnection lost" << std::endl;
if (!cause.empty())
std::cout << "\tcause: " << cause << std::endl;
}
void delivery_complete(mqtt::delivery_token_ptr tok) override
{
std::cout << "\tDelivery complete for token: " << (tok ? tok->get_message_id() : -1)
<< std::endl;
}
};
/////////////////////////////////////////////////////////////////////////////
using namespace std;
int main(int argc, char* argv[])
{
string serverURI = (argc > 1) ? string{argv[1]} : DFLT_SERVER_URI,
clientID = (argc > 2) ? string{argv[2]} : DFLT_CLIENT_ID;
// Note that we don't actually need to open the trust or key stores.
// We just need a quick, portable way to check that they exist.
{
ifstream tstore(TRUST_STORE);
if (!tstore) {
cerr << "The trust store file does not exist: " << TRUST_STORE << endl;
cerr << " Get a copy from \"paho.mqtt.c/test/ssl/test-root-ca.crt\"" << endl;
;
return 1;
}
ifstream kstore(KEY_STORE);
if (!kstore) {
cerr << "The key store file does not exist: " << KEY_STORE << endl;
cerr << " Get a copy from \"paho.mqtt.c/test/ssl/client.pem\"" << endl;
return 1;
}
}
cout << "Initializing for server '" << serverURI << "'..." << endl;
mqtt::async_client client(serverURI, clientID);
callback cb;
client.set_callback(cb);
// Build the connect options, including SSL and a LWT message.
auto sslopts = mqtt::ssl_options_builder()
.trust_store(TRUST_STORE)
.key_store(KEY_STORE)
.error_handler([](const std::string& msg) {
std::cerr << "SSL Error: " << msg << std::endl;
})
.finalize();
auto willmsg = mqtt::message(LWT_TOPIC, LWT_PAYLOAD, QOS, true);
auto connopts = mqtt::connect_options_builder()
.user_name("testuser")
.password("testpassword")
.will(std::move(willmsg))
.ssl(std::move(sslopts))
.finalize();
cout << " ...OK" << endl;
try {
// Connect using SSL/TLS
cout << "\nConnecting..." << endl;
mqtt::token_ptr conntok = client.connect(connopts);
cout << "Waiting for the connection..." << endl;
conntok->wait();
cout << " ...OK" << endl;
// Send a message
cout << "\nSending message..." << endl;
auto msg = mqtt::make_message("hello", "Hello secure C++ world!", QOS, false);
client.publish(msg)->wait_for(TIMEOUT);
cout << " ...OK" << endl;
// Disconnect
cout << "\nDisconnecting..." << endl;
client.disconnect()->wait();
cout << " ...OK" << endl;
}
catch (const mqtt::exception& exc) {
cerr << exc.what() << endl;
return 1;
}
return 0;
}
// sync_consume.cpp
//
// This is a Paho MQTT C++ client, sample application.
//
// This application is an MQTT consumer/subscriber using the C++ synchronous
// client interface, which uses the queuing API to receive messages.
//
// The sample demonstrates:
// - Connecting to an MQTT server/broker
// - Using a persistent (non-clean) session
// - Subscribing to multiple topics
// - Receiving messages through the queueing consumer API
// - Receiving and acting upon commands via MQTT topics
// - Auto reconnect
// - Updating auto-reconnect data
//
/*******************************************************************************
* Copyright (c) 2013-2023 Frank Pagliughi <fpagliughi@mindspring.com>
*
* 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
* http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Frank Pagliughi - initial implementation and documentation
*******************************************************************************/
#include <cctype>
#include <chrono>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <thread>
#include "mqtt/client.h"
using namespace std;
using namespace std::chrono;
const string DFLT_SERVER_URI{"mqtt://localhost:1883"};
const string CLIENT_ID{"paho_cpp_sync_consume"};
/////////////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[])
{
auto serverURI = (argc > 1) ? std::string{argv[1]} : DFLT_SERVER_URI;
mqtt::client cli(serverURI, CLIENT_ID);
auto connOpts = mqtt::connect_options_builder::v3()
.user_name("user")
.password("passwd")
.keep_alive_interval(seconds(30))
.automatic_reconnect(seconds(2), seconds(30))
.clean_session(false)
.finalize();
// You can install a callback to change some connection data
// on auto reconnect attempts. To make a change, update the
// `connect_data` and return 'true'.
cli.set_update_connection_handler([](mqtt::connect_data& connData) {
string newUserName{"newuser"};
if (connData.get_user_name() == newUserName)
return false;
cout << "Previous user: '" << connData.get_user_name() << "'" << endl;
connData.set_user_name(newUserName);
cout << "New user name: '" << connData.get_user_name() << "'" << endl;
return true;
});
const vector<string> TOPICS{"data/#", "command"};
const vector<int> QOS{0, 1};
try {
cout << "Connecting to the MQTT server..." << flush;
mqtt::connect_response rsp = cli.connect(connOpts);
cout << "OK\n" << endl;
if (!rsp.is_session_present()) {
std::cout << "Subscribing to topics..." << std::flush;
cli.subscribe(TOPICS, QOS);
std::cout << "OK" << std::endl;
}
else {
cout << "Session already present. Skipping subscribe." << std::endl;
}
// Consume messages
while (true) {
auto msg = cli.consume_message();
if (msg) {
if (msg->get_topic() == "command" && msg->to_string() == "exit") {
cout << "Exit command received" << endl;
break;
}
cout << msg->get_topic() << ": " << msg->to_string() << endl;
}
else if (!cli.is_connected()) {
cout << "Lost connection" << endl;
while (!cli.is_connected()) {
this_thread::sleep_for(milliseconds(250));
}
cout << "Re-established connection" << endl;
}
}
// Disconnect
cout << "\nDisconnecting from the MQTT server..." << flush;
cli.disconnect();
cout << "OK" << endl;
}
catch (const mqtt::exception& exc) {
cerr << exc.what() << endl;
return 1;
}
return 0;
}
// sync_consume_v5.cpp
//
// This is a Paho MQTT C++ client, sample application.
//
// This application is an MQTT consumer/subscriber using the C++ synchronous
// client interface, which uses the queuing API to receive messages.
//
// The sample demonstrates:
// - Connecting to an MQTT server/broker
// - Using a persistent (non-clean) session
// - Subscribing to multiple topics
// - Receiving messages through the queueing consumer API
// - Receiving and acting upon commands via MQTT topics
// - Auto reconnect
// - Updating auto-reconnect data
//
/*******************************************************************************
* Copyright (c) 2020-2024 Frank Pagliughi <fpagliughi@mindspring.com>
*
* 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
* http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Frank Pagliughi - initial implementation and documentation
*******************************************************************************/
#include <cctype>
#include <chrono>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iostream>
#include <string>
#include <thread>
#include <vector>
#include "mqtt/client.h"
using namespace std;
using namespace std::chrono;
const string DFLT_SERVER_URI{"mqtt://localhost:1883"};
const string CLIENT_ID{"paho_cpp_sync_consume5"};
constexpr int QOS_0 = 0;
constexpr int QOS_1 = 1;
// Infinite time for session expiration
const uint32_t INFINITE = std::numeric_limits<uint32_t>::max();
/////////////////////////////////////////////////////////////////////////////
// Message table function signature
using handler_t = std::function<bool(const mqtt::message&)>;
// Handler for data messages (i.e. topic "data/#")
bool data_handler(const mqtt::message& msg)
{
cout << msg.get_topic() << ": " << msg.to_string() << endl;
return true;
}
// Handler for command messages (i.e. topic "command")
// Return false to exit the application
bool command_handler(const mqtt::message& msg)
{
if (msg.to_string() == "exit") {
cout << "Exit command received" << endl;
return false;
}
return true;
}
/////////////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[])
{
auto serverURI = (argc > 1) ? std::string{argv[1]} : DFLT_SERVER_URI;
mqtt::client cli(serverURI, CLIENT_ID);
auto connOpts = mqtt::connect_options_builder::v5()
.automatic_reconnect(seconds(2), seconds(30))
.clean_start(false)
.properties({{mqtt::property::SESSION_EXPIRY_INTERVAL, INFINITE}})
.finalize();
// Dispatch table to handle incoming messages based on Subscription ID's.
std::vector<handler_t> handler{data_handler, command_handler};
try {
cout << "Connecting to the MQTT server..." << flush;
mqtt::connect_response rsp = cli.connect(connOpts);
cout << "OK\n" << endl;
if (!rsp.is_session_present()) {
std::cout << "Subscribing to topics..." << std::flush;
mqtt::subscribe_options subOpts;
mqtt::properties props1{
{mqtt::property::SUBSCRIPTION_IDENTIFIER, 1},
};
cli.subscribe("data/#", QOS_0, subOpts, props1);
mqtt::properties props2{
{mqtt::property::SUBSCRIPTION_IDENTIFIER, 2},
};
cli.subscribe("command", QOS_1, subOpts, props2);
std::cout << "OK" << std::endl;
}
else {
cout << "Session already present. Skipping subscribe." << std::endl;
}
// Consume messages
while (true) {
auto msg = cli.consume_message();
// Note: In a real app, you'd want to do a lot more error
// and bounds checking than this.
if (msg) {
// Get the subscription ID from the incoming message
auto subId = mqtt::get<uint32_t>(
msg->get_properties(), mqtt::property::SUBSCRIPTION_IDENTIFIER
);
// Dispatch to a handler function based on the Subscription ID
if (!(handler[subId - 1])(*msg))
break;
}
else if (!cli.is_connected()) {
cout << "Lost connection" << endl;
while (!cli.is_connected()) {
this_thread::sleep_for(milliseconds(250));
}
cout << "Re-established connection" << endl;
}
}
// Disconnect
cout << "\nDisconnecting from the MQTT server..." << flush;
cli.disconnect();
cout << "OK" << endl;
}
catch (const mqtt::exception& exc) {
cerr << exc.what() << endl;
return 1;
}
return 0;
}
// sync_publish.cpp
//
// This is a Paho MQTT C++ client, sample application.
//
// It's an example of how to send messages as an MQTT publisher using the
// C++ synchronous client interface.
//
// The sample demonstrates:
// - Connecting to an MQTT server/broker
// - Publishing messages
// - User-defined persistence
//
/*******************************************************************************
* Copyright (c) 2013-2023 Frank Pagliughi <fpagliughi@mindspring.com>
*
* 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
* http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Frank Pagliughi - initial implementation and documentation
*******************************************************************************/
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include "mqtt/client.h"
const std::string DFLT_SERVER_URI{"mqtt://localhost:1883"};
const std::string TOPIC{"hello"};
const std::string PAYLOAD1{"Hello World!"};
const char* PAYLOAD2 = "Hi there!";
const char* PAYLOAD3 = "Is anyone listening?";
const int QOS = 1;
/////////////////////////////////////////////////////////////////////////////
// Example of a simple, in-memory persistence class.
//
// This is an extremely silly example, because if you want to use
// persistence, you actually need it to be out of process so that if the
// client crashes and restarts, the persistence data still exists.
//
// This is just here to show how the persistence API callbacks work. It maps
// well to key/value stores, like Redis, but only if it's on the local host,
// as it wouldn't make sense to persist data over the network, since that's
// what the MQTT client it trying to do.
//
class sample_mem_persistence : virtual public mqtt::iclient_persistence
{
// Whether the store is open
bool open_;
// Use an STL map to store shared persistence pointers
// against string keys.
std::map<std::string, std::string> store_;
public:
sample_mem_persistence() : open_(false) {}
// "Open" the store
void open(const std::string& clientId, const std::string& serverURI) override
{
std::cout << " [Opening persistence store for '" << clientId << "' at '" << serverURI
<< "']" << std::endl;
open_ = true;
}
// Close the persistent store that was previously opened.
void close() override
{
std::cout << " [Closing persistence store.]" << std::endl;
open_ = false;
}
// Clears persistence, so that it no longer contains any persisted data.
void clear() override
{
std::cout << " [Clearing persistence store.]" << std::endl;
store_.clear();
}
// Returns whether or not data is persisted using the specified key.
bool contains_key(const std::string& key) override
{
return store_.find(key) != store_.end();
}
// Returns the keys in this persistent data store.
mqtt::string_collection keys() const override
{
mqtt::string_collection ks;
for (const auto& k : store_) ks.push_back(k.first);
return ks;
}
// Puts the specified data into the persistent store.
void put(const std::string& key, const std::vector<mqtt::string_view>& bufs) override
{
std::cout << " [Persisting data with key '" << key << "']" << std::endl;
std::string str;
for (const auto& b : bufs) str.append(b.data(), b.size()); // += b.str();
store_[key] = std::move(str);
}
// Gets the specified data out of the persistent store.
std::string get(const std::string& key) const override
{
std::cout << " [Searching persistence for key '" << key << "']" << std::endl;
auto p = store_.find(key);
if (p == store_.end())
throw mqtt::persistence_exception();
std::cout << " [Found persistence data for key '" << key << "']" << std::endl;
return p->second;
}
// Remove the data for the specified key.
void remove(const std::string& key) override
{
std::cout << " [Persistence removing key '" << key << "']" << std::endl;
auto p = store_.find(key);
if (p == store_.end())
throw mqtt::persistence_exception();
store_.erase(p);
std::cout << " [Persistence key removed '" << key << "']" << std::endl;
}
};
/////////////////////////////////////////////////////////////////////////////
// Class to receive callbacks
class user_callback : public virtual mqtt::callback
{
void connection_lost(const std::string& cause) override
{
std::cout << "\nConnection lost" << std::endl;
if (!cause.empty())
std::cout << "\tcause: " << cause << std::endl;
}
void delivery_complete(mqtt::delivery_token_ptr tok) override
{
std::cout << "\n [Delivery complete for token: "
<< (tok ? tok->get_message_id() : -1) << "]" << std::endl;
}
public:
};
// --------------------------------------------------------------------------
int main(int argc, char* argv[])
{
auto serverURI = (argc > 1) ? std::string{argv[1]} : DFLT_SERVER_URI;
std::cout << "Initializing..." << std::endl;
sample_mem_persistence persist;
mqtt::client client(serverURI, "", &persist);
user_callback cb;
client.set_callback(cb);
mqtt::connect_options connOpts;
connOpts.set_keep_alive_interval(20);
connOpts.set_clean_session(true);
std::cout << "...OK" << std::endl;
try {
std::cout << "\nConnecting..." << std::endl;
client.connect(connOpts);
std::cout << "...OK" << std::endl;
// First use a message pointer.
std::cout << "\nSending message..." << std::endl;
auto pubmsg = mqtt::make_message(TOPIC, PAYLOAD1);
pubmsg->set_qos(QOS);
client.publish(pubmsg);
std::cout << "...OK" << std::endl;
// Now try with itemized publish.
std::cout << "\nSending next message..." << std::endl;
client.publish(TOPIC, PAYLOAD2, strlen(PAYLOAD2) + 1);
std::cout << "...OK" << std::endl;
// Now try with a listener, no token, and non-heap message
std::cout << "\nSending final message..." << std::endl;
client.publish(mqtt::message(TOPIC, PAYLOAD3, QOS, false));
std::cout << "OK" << std::endl;
// Disconnect
std::cout << "\nDisconnecting..." << std::endl;
client.disconnect();
std::cout << "...OK" << std::endl;
}
catch (const mqtt::persistence_exception& exc) {
std::cerr << "Persistence Error: " << exc.what() << " [" << exc.get_reason_code()
<< "]" << std::endl;
return 1;
}
catch (const mqtt::exception& exc) {
std::cerr << exc.what() << std::endl;
return 1;
}
std::cout << "\nExiting" << std::endl;
return 0;
}
// sync_reconnect.cpp
//
// This is a Paho MQTT C++ client, sample application.
//
// It's a fairly contrived, but useful example of an MQTT data monitor and
// publisher, using the C++ synchronous client interface. A fairly common
// usage for MQTT applications to stay offline for much of the time and only
// connect to the broker when there is data to send.
//
// Since we don't have a universal sensor to use for this example, we simply
// use time itself as out input data. We periodically "sample" the time
// value, connect, send the value, disconnect, and then sleep. In this case
// we use the system clock, measuring the time with millisecond precision.
//
// The sample demonstrates:
// - The synchronous client
// - Connecting to an MQTT server/broker
// - Periodically reconnecting to the broker
// - Publishing messages using a `topic` object
// - Using `connect_options` with builder classes
//
/*******************************************************************************
* Copyright (c) 2019-2023 Frank Pagliughi <fpagliughi@mindspring.com>
*
* 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
* http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Frank Pagliughi - initial implementation and documentation
*******************************************************************************/
#include <atomic>
#include <chrono>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <thread>
#include "mqtt/client.h"
using namespace std;
using namespace std::chrono;
const std::string DFLT_SERVER_URI{"mqtt://localhost:1883"};
// The QoS for sending data
const int QOS = 1;
// How often to sample the "data"
const auto SAMPLE_PERIOD = seconds(5);
// --------------------------------------------------------------------------
// Gets the current time as the number of milliseconds since the epoch:
// like a time_t with ms resolution.
uint64_t timestamp()
{
auto now = system_clock::now();
auto tse = now.time_since_epoch();
auto msTm = duration_cast<milliseconds>(tse);
return uint64_t(msTm.count());
}
// --------------------------------------------------------------------------
int main(int argc, char* argv[])
{
// The server URI (address)
string serverURI = (argc > 1) ? string{argv[1]} : DFLT_SERVER_URI;
// The amount of time to run (in sec). Zero means "run forever".
uint64_t trun = (argc > 2) ? stoll(argv[2]) : 0LL;
cout << "Initializing for server '" << serverURI << "'..." << endl;
mqtt::client cli(serverURI, "");
auto connOpts = mqtt::connect_options_builder().clean_session().finalize();
cli.set_timeout(seconds(3));
auto top = cli.get_topic("data/time", QOS);
uint64_t t = timestamp(), tstart = t;
try {
// We need to connect once before we can use reconnect()
cli.connect(connOpts);
while (true) {
cout << "\nCollecting data..." << endl;
// Collect some data
t = timestamp();
if (!cli.is_connected()) {
cout << "Reconnecting..." << endl;
cli.reconnect();
}
cout << "Publishing data: " << t << "..." << endl;
top.publish(to_string(t));
cout << "Disconnecting..." << endl;
cli.disconnect();
// Quit if it's past time
if (trun > 0 && t >= (trun + tstart))
break;
cout << "Going to sleep." << endl;
this_thread::sleep_for(SAMPLE_PERIOD);
}
}
catch (const mqtt::exception& exc) {
cerr << exc << endl;
return 1;
}
return 0;
}
// topic_publish.cpp
//
// This is a Paho MQTT C++ client, sample application.
//
// It's an example of how to send messages as an MQTT publisher using the
// C++ asynchronous client interface using a 'topic' object to repeatedly
// send data to the same topic.
//
// The sample demonstrates:
// - Connecting to an MQTT server/broker
// - Publishing messages
// - Use of the 'topic' class
//
/*******************************************************************************
* Copyright (c) 2019-2023 Frank Pagliughi <fpagliughi@mindspring.com>
*
* 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
* http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Frank Pagliughi - initial implementation and documentation
*******************************************************************************/
#include <atomic>
#include <chrono>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <thread> // For sleep
#include "mqtt/async_client.h"
using namespace std;
const string DFLT_SERVER_URI{"mqtt://localhost:1883"};
const string TOPIC{"test"};
const int QOS = 1;
const char* PAYLOADS[] = {
"Hello World!", "Hi there!", "Is anyone listening?", "Someone is always listening.",
nullptr
};
const auto TIMEOUT = std::chrono::seconds(10);
/////////////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[])
{
string serverURI = (argc > 1) ? string(argv[1]) : DFLT_SERVER_URI;
cout << "Initializing for server '" << serverURI << "'..." << endl;
mqtt::async_client cli(serverURI, "");
cout << " ...OK" << endl;
try {
cout << "\nConnecting..." << endl;
cli.connect()->wait();
cout << " ...OK" << endl;
cout << "\nPublishing messages..." << endl;
mqtt::topic top(cli, "test", QOS);
mqtt::token_ptr tok;
size_t i = 0;
while (PAYLOADS[i]) {
tok = top.publish(PAYLOADS[i++]);
}
tok->wait(); // Just wait for the last one to complete.
cout << "OK" << endl;
// Disconnect
cout << "\nDisconnecting..." << endl;
cli.disconnect()->wait();
cout << " ...OK" << endl;
}
catch (const mqtt::exception& exc) {
cerr << exc << endl;
return 1;
}
return 0;
}
// ws_publish.cpp
//
// This is a Paho MQTT C++ client, sample application.
//
// It's an example of how to connect to an MQTT broker using websockets with
// an optional proxy.
//
// The sample demonstrates:
// - Connecting to an MQTT server/broker using websockets
// - Publishing messages
// - Using asynchronous tokens
//
// This example requires a broker that is configured to accept websocket
// connections, and optionally, an HTTP proxy.
//
/*******************************************************************************
* Copyright (c) 2020-2023 Frank Pagliughi <fpagliughi@mindspring.com>
*
* 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
* http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Frank Pagliughi - initial implementation and documentation
*******************************************************************************/
#include <chrono>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <string>
#include "mqtt/async_client.h"
// Assume a local server with websocket support on port 8080
const std::string DFLT_SERVER_URI{"ws://localhost:8080"};
// A local proxy, like squid on port 3128
// Here assuming basic authentication with user "user" and password "pass".
const std::string DFLT_PROXY_ADDRESS{"http://user:pass@localhost:3128"};
// Quality of service for this app.
const int QOS = 1;
// Timeout for publish to complete
const auto TIMEOUT = std::chrono::seconds(10);
using namespace std;
/////////////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[])
{
string serverURI = (argc > 1) ? string{argv[1]} : DFLT_SERVER_URI,
proxy = (argc > 2) ? string{argv[2]} : DFLT_PROXY_ADDRESS;
cout << "Initializing for server '" << serverURI << "'..." << endl;
if (!proxy.empty())
cout << " with proxy '" << proxy << "'" << endl;
mqtt::async_client client(serverURI, "");
// Build the connect options.
auto connBuilder = mqtt::connect_options_builder::ws();
if (!proxy.empty())
connBuilder.http_proxy(proxy);
auto connOpts = connBuilder.keep_alive_interval(std::chrono::seconds(45)).finalize();
cout << " ...OK" << endl;
try {
// Connect to the server
cout << "\nConnecting..." << endl;
client.connect(connOpts)->wait();
cout << " ...OK" << endl;
// Send a message
cout << "\nSending message..." << endl;
auto msg = mqtt::make_message("hello", "Hello C++ websocket world!", QOS, false);
bool ok = client.publish(msg)->wait_for(TIMEOUT);
cout << " ..." << (ok ? "OK" : "Error") << endl;
// Disconnect
cout << "\nDisconnecting..." << endl;
client.disconnect()->wait();
cout << " ...OK" << endl;
}
catch (const mqtt::exception& exc) {
cerr << exc.get_error_str() << endl;
return 1;
}
return 0;
}
#!/bin/bash
#
# Runs clang format over the whole project tree, excluding
# the 'externals/' and 'build/' directories.
#
find . -type d \( -path './externals' -o -path './build' \) -prune -iname '*.h' -o -iname '*.cpp' | xargs clang-format -i
---
Language: Cpp
# BasedOnStyle: Google
AccessModifierOffset: -4
#AlignAfterOpenBracket: Align
AlignAfterOpenBracket: BlockIndent
AlignArrayOfStructures: None
AlignConsecutiveAssignments:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: true
AlignConsecutiveBitFields:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
AlignConsecutiveDeclarations:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
AlignConsecutiveMacros:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
# Clang-17
#AlignConsecutiveShortCaseStatements:
# Enabled: false
# AcrossEmptyLines: false
# AcrossComments: false
# AlignCaseColons: false
AlignEscapedNewlines: Left
AlignOperands: Align
AlignTrailingComments:
Kind: Always
OverEmptyLines: 0
AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
AttributeMacros:
- __capability
BinPackArguments: true
BinPackParameters: true
BitFieldColonSpacing: Both
BraceWrapping:
AfterCaseLabel: false
AfterClass: true
AfterControlStatement: Never
AfterEnum: false
AfterExternBlock: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: true
AfterUnion: false
BeforeCatch: true
BeforeElse: true
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakAfterAttributes: Never
BreakAfterJavaFieldAnnotations: false
BreakArrays: true
BreakBeforeBinaryOperators: None
BreakBeforeConceptDeclarations: Always
BreakBeforeBraces: Custom
BreakBeforeInlineASMColon: OnlyMultiline
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon
BreakStringLiterals: true
ColumnLimit: 94
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IfMacros:
- KJ_IF_MAYBE
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^<ext/.*\.h>'
Priority: 2
SortPriority: 0
CaseSensitive: false
- Regex: '^<.*\.h>'
Priority: 1
SortPriority: 0
CaseSensitive: false
- Regex: '^<.*'
Priority: 2
SortPriority: 0
CaseSensitive: false
- Regex: '.*'
Priority: 3
SortPriority: 0
CaseSensitive: false
IncludeIsMainRegex: '([-_](test|unittest))?$'
IncludeIsMainSourceRegex: ''
IndentAccessModifiers: false
IndentCaseBlocks: false
IndentCaseLabels: true
IndentExternBlock: AfterExternBlock
IndentGotoLabels: true
IndentPPDirectives: BeforeHash
IndentRequiresClause: true
IndentWidth: 4
IndentWrappedFunctionNames: false
InsertBraces: false
InsertNewlineAtEOF: true
InsertTrailingCommas: None
IntegerLiteralSeparator:
Binary: 0
BinaryMinDigits: 0
Decimal: 0
DecimalMinDigits: 0
Hex: 0
HexMinDigits: 0
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
KeepEmptyLinesAtEOF: false
LambdaBodyIndentation: Signature
LineEnding: DeriveLF
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Never
ObjCBlockIndentWidth: 2
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PackConstructorInitializers: NextLine
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakOpenParenthesis: 0
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyIndentedWhitespace: 0
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Left
PPIndentWidth: -1
QualifierAlignment: Leave
RawStringFormats:
- Language: Cpp
Delimiters:
- cc
- CC
- cpp
- Cpp
- CPP
- 'c++'
- 'C++'
CanonicalDelimiter: ''
BasedOnStyle: google
- Language: TextProto
Delimiters:
- pb
- PB
- proto
- PROTO
EnclosingFunctions:
- EqualsProto
- EquivToProto
- PARSE_PARTIAL_TEXT_PROTO
- PARSE_TEST_PROTO
- PARSE_TEXT_PROTO
- ParseTextOrDie
- ParseTextProtoOrDie
- ParseTestProto
- ParsePartialTestProto
CanonicalDelimiter: pb
BasedOnStyle: google
ReferenceAlignment: Pointer
ReflowComments: true
RemoveBracesLLVM: false
RemoveParentheses: Leave
RemoveSemicolon: false
RequiresClausePosition: OwnLine
RequiresExpressionIndentation: OuterScope
SeparateDefinitionBlocks: Leave
ShortNamespaceLines: 1
SortIncludes: CaseSensitive
SortJavaStaticImport: Before
SortUsingDeclarations: LexicographicNumeric
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceAroundPointerQualifiers: Default
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeJsonColon: false
SpaceBeforeParens: ControlStatements
SpaceBeforeParensOptions:
AfterControlStatements: true
AfterForeachMacros: true
AfterFunctionDefinitionName: false
AfterFunctionDeclarationName: false
AfterIfMacros: true
AfterOverloadedOperator: false
AfterRequiresInClause: false
AfterRequiresInExpression: false
BeforeNonEmptyParentheses: false
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: false
SpaceInEmptyBlock: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: Never
SpacesInContainerLiterals: true
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: -1
# Clang Format >v17
#SpacesInParens: Never
#SpacesInParensOptions:
# InCStyleCasts: false
# InConditionalStatements: false
# InEmptyParentheses: false
# Other: false
SpacesInSquareBrackets: false
Standard: Auto
StatementAttributeLikeMacros:
- Q_EMIT
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 4
UseTab: Never
VerilogBreakBetweenInstancePorts: true
WhitespaceSensitiveMacros:
- BOOST_PP_STRINGIZE
- CF_SWIFT_NAME
- NS_SWIFT_NAME
- PP_STRINGIZE
- STRINGIZE
...
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment