first commit
This commit is contained in:
168
.clang-format
Normal file
168
.clang-format
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
# BasedOnStyle: Google
|
||||||
|
AccessModifierOffset: -1
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
AlignConsecutiveMacros: false
|
||||||
|
AlignConsecutiveAssignments: false
|
||||||
|
AlignConsecutiveDeclarations: false
|
||||||
|
AlignEscapedNewlines: Left
|
||||||
|
AlignOperands: true
|
||||||
|
AlignTrailingComments: true
|
||||||
|
AllowAllArgumentsOnNextLine: true
|
||||||
|
AllowAllConstructorInitializersOnNextLine: true
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
|
AllowShortBlocksOnASingleLine: Never
|
||||||
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: All
|
||||||
|
AllowShortLambdasOnASingleLine: All
|
||||||
|
AllowShortIfStatementsOnASingleLine: WithoutElse
|
||||||
|
AllowShortLoopsOnASingleLine: true
|
||||||
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
AlwaysBreakBeforeMultilineStrings: true
|
||||||
|
AlwaysBreakTemplateDeclarations: Yes
|
||||||
|
BinPackArguments: true
|
||||||
|
BinPackParameters: true
|
||||||
|
BraceWrapping:
|
||||||
|
AfterCaseLabel: false
|
||||||
|
AfterClass: false
|
||||||
|
AfterControlStatement: false
|
||||||
|
AfterEnum: false
|
||||||
|
AfterFunction: false
|
||||||
|
AfterNamespace: false
|
||||||
|
AfterObjCDeclaration: false
|
||||||
|
AfterStruct: false
|
||||||
|
AfterUnion: false
|
||||||
|
AfterExternBlock: false
|
||||||
|
BeforeCatch: false
|
||||||
|
BeforeElse: false
|
||||||
|
IndentBraces: false
|
||||||
|
SplitEmptyFunction: true
|
||||||
|
SplitEmptyRecord: true
|
||||||
|
SplitEmptyNamespace: true
|
||||||
|
BreakBeforeBinaryOperators: None
|
||||||
|
BreakBeforeBraces: Attach
|
||||||
|
BreakBeforeInheritanceComma: false
|
||||||
|
BreakInheritanceList: BeforeColon
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
BreakConstructorInitializers: BeforeColon
|
||||||
|
BreakAfterJavaFieldAnnotations: false
|
||||||
|
BreakStringLiterals: true
|
||||||
|
ColumnLimit: 80
|
||||||
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
|
CompactNamespaces: false
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
|
ConstructorInitializerIndentWidth: 4
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
DeriveLineEnding: true
|
||||||
|
DerivePointerAlignment: true
|
||||||
|
DisableFormat: false
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
FixNamespaceComments: true
|
||||||
|
ForEachMacros:
|
||||||
|
- foreach
|
||||||
|
- Q_FOREACH
|
||||||
|
- BOOST_FOREACH
|
||||||
|
IncludeBlocks: Regroup
|
||||||
|
IncludeCategories:
|
||||||
|
- Regex: '^<ext/.*\.h>'
|
||||||
|
Priority: 2
|
||||||
|
SortPriority: 0
|
||||||
|
- Regex: '^<.*\.h>'
|
||||||
|
Priority: 1
|
||||||
|
SortPriority: 0
|
||||||
|
- Regex: '^<.*'
|
||||||
|
Priority: 2
|
||||||
|
SortPriority: 0
|
||||||
|
- Regex: '.*'
|
||||||
|
Priority: 3
|
||||||
|
SortPriority: 0
|
||||||
|
IncludeIsMainRegex: '([-_](test|unittest))?$'
|
||||||
|
IncludeIsMainSourceRegex: ''
|
||||||
|
IndentCaseLabels: true
|
||||||
|
IndentGotoLabels: true
|
||||||
|
IndentPPDirectives: None
|
||||||
|
IndentWidth: 2
|
||||||
|
IndentWrappedFunctionNames: false
|
||||||
|
JavaScriptQuotes: Leave
|
||||||
|
JavaScriptWrapImports: true
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
|
MacroBlockBegin: ''
|
||||||
|
MacroBlockEnd: ''
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
NamespaceIndentation: None
|
||||||
|
ObjCBinPackProtocolList: Never
|
||||||
|
ObjCBlockIndentWidth: 2
|
||||||
|
ObjCSpaceAfterProperty: false
|
||||||
|
ObjCSpaceBeforeProtocolList: true
|
||||||
|
PenaltyBreakAssignment: 2
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 1
|
||||||
|
PenaltyBreakComment: 300
|
||||||
|
PenaltyBreakFirstLessLess: 120
|
||||||
|
PenaltyBreakString: 1000
|
||||||
|
PenaltyBreakTemplateDeclaration: 10
|
||||||
|
PenaltyExcessCharacter: 1000000
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 200
|
||||||
|
PointerAlignment: Left
|
||||||
|
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
|
||||||
|
CanonicalDelimiter: ''
|
||||||
|
BasedOnStyle: google
|
||||||
|
ReflowComments: true
|
||||||
|
SortIncludes: true
|
||||||
|
SortUsingDeclarations: true
|
||||||
|
SpaceAfterCStyleCast: false
|
||||||
|
SpaceAfterLogicalNot: false
|
||||||
|
SpaceAfterTemplateKeyword: true
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeCpp11BracedList: false
|
||||||
|
SpaceBeforeCtorInitializerColon: true
|
||||||
|
SpaceBeforeInheritanceColon: true
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
SpaceBeforeRangeBasedForLoopColon: true
|
||||||
|
SpaceInEmptyBlock: false
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesBeforeTrailingComments: 2
|
||||||
|
SpacesInAngles: false
|
||||||
|
SpacesInConditionalStatement: false
|
||||||
|
SpacesInContainerLiterals: true
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInParentheses: false
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
SpaceBeforeSquareBrackets: false
|
||||||
|
Standard: Auto
|
||||||
|
StatementMacros:
|
||||||
|
- Q_UNUSED
|
||||||
|
- QT_REQUIRE_VERSION
|
||||||
|
TabWidth: 8
|
||||||
|
UseCRLF: false
|
||||||
|
UseTab: Never
|
||||||
|
...
|
||||||
|
|
||||||
11
.devcontainer/Dockerfile
Normal file
11
.devcontainer/Dockerfile
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
# [Choice] Debian / Ubuntu version: debian-10, debian-9, ubuntu-20.04, ubuntu-18.04
|
||||||
|
ARG VARIANT=buster
|
||||||
|
FROM mcr.microsoft.com/vscode/devcontainers/cpp:dev-${VARIANT}
|
||||||
|
|
||||||
|
# [Optional] Uncomment this section to install additional packages.
|
||||||
|
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
||||||
|
&& apt-get -y install --no-install-recommends lsb-release wget software-properties-common \
|
||||||
|
&& bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" \
|
||||||
|
&& apt-get -y install --no-install-recommends clang-format-11 clang-tidy-11 ninja-build rabbitmq-server \
|
||||||
|
libssl-dev librabbitmq-dev libboost-dev libboost-chrono-dev libboost-system-dev
|
||||||
12
.devcontainer/base.Dockerfile
Normal file
12
.devcontainer/base.Dockerfile
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# [Choice] Debian / Ubuntu version: debian-10, debian-9, ubuntu-20.04, ubuntu-18.04
|
||||||
|
ARG VARIANT=buster
|
||||||
|
FROM mcr.microsoft.com/vscode/devcontainers/base:${VARIANT}
|
||||||
|
|
||||||
|
# Install needed packages. Use a separate RUN statement to add your own dependencies.
|
||||||
|
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
||||||
|
&& apt-get -y install build-essential cmake cppcheck valgrind clang lldb llvm gdb \
|
||||||
|
&& apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# [Optional] Uncomment this section to install additional OS packages.
|
||||||
|
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
||||||
|
# && apt-get -y install --no-install-recommends <your-package-list-here>
|
||||||
35
.devcontainer/devcontainer.json
Normal file
35
.devcontainer/devcontainer.json
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"name": "C++",
|
||||||
|
"build": {
|
||||||
|
"dockerfile": "Dockerfile",
|
||||||
|
// Update 'VARIANT' to pick an Debian / Ubuntu OS version: debian-10, debian-9, ubuntu-20.04, ubuntu-18.04
|
||||||
|
"args": { "VARIANT": "ubuntu-20.04" }
|
||||||
|
},
|
||||||
|
"runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined"],
|
||||||
|
|
||||||
|
// Set *default* container specific settings.json values on container create.
|
||||||
|
"settings": {
|
||||||
|
"clangd.path": "clangd-11",
|
||||||
|
"cmake.copyCompileCommands": "${workspaceFolder}/compile_commands.json",
|
||||||
|
"workbench.colorTheme": "Solarized Dark",
|
||||||
|
"terminal.integrated.shell.linux": "/bin/bash"
|
||||||
|
},
|
||||||
|
|
||||||
|
// Add the IDs of extensions you want installed when the container is created.
|
||||||
|
"extensions": [
|
||||||
|
// "ms-vscode.cpptools",
|
||||||
|
"ms-vscode.cmake-tools",
|
||||||
|
"vscodevim.vim",
|
||||||
|
"llvm-vs-code-extensions.vscode-clangd",
|
||||||
|
"twxs.cmake",
|
||||||
|
],
|
||||||
|
|
||||||
|
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||||
|
// "forwardPorts": [],
|
||||||
|
|
||||||
|
// Use 'postCreateCommand' to run commands after the container is created.
|
||||||
|
// "postCreateCommand": "gcc -v",
|
||||||
|
|
||||||
|
// Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
|
||||||
|
"remoteUser": "vscode"
|
||||||
|
}
|
||||||
10
.gitattributes
vendored
Normal file
10
.gitattributes
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# Default for those who don't have core.autocrlf set
|
||||||
|
* text=auto
|
||||||
|
|
||||||
|
# Things that should be treated as text
|
||||||
|
*.cpp text
|
||||||
|
*.h text
|
||||||
|
CMakeLists.txt text
|
||||||
|
*.cmake text
|
||||||
|
*.md text
|
||||||
|
*.in text
|
||||||
72
.github/workflows/ci.yml
vendored
Normal file
72
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
name: ci
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ "master" ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ "master" ]
|
||||||
|
|
||||||
|
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]
|
||||||
|
build_type: [Release]
|
||||||
|
c_compiler: [gcc, clang, cl]
|
||||||
|
include:
|
||||||
|
- os: ubuntu-latest
|
||||||
|
c_compiler: gcc
|
||||||
|
cpp_compiler: g++
|
||||||
|
- os: ubuntu-latest
|
||||||
|
c_compiler: clang
|
||||||
|
cpp_compiler: clang++
|
||||||
|
exclude:
|
||||||
|
- os: ubuntu-latest
|
||||||
|
c_compiler: cl
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- 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: Install Deps
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install libboost-all-dev librabbitmq-dev
|
||||||
|
|
||||||
|
- name: Configure CMake
|
||||||
|
# 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 }}
|
||||||
|
-S ${{ github.workspace }}
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
# Build your program with the given configuration. Note that --config is needed 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
|
||||||
|
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 }}
|
||||||
20
.gitignore
vendored
Normal file
20
.gitignore
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
*~
|
||||||
|
.*.sw?
|
||||||
|
|
||||||
|
.cache/
|
||||||
|
.vscode/
|
||||||
|
build/
|
||||||
|
CMakeCache.txt
|
||||||
|
cmake_install.cmake
|
||||||
|
CMakeFiles/
|
||||||
|
Debug/
|
||||||
|
|
||||||
|
*.vcxproj*
|
||||||
|
*.sln
|
||||||
|
*.suo
|
||||||
|
*.*sdf
|
||||||
|
ipch/
|
||||||
|
install_manifest.txt
|
||||||
|
.ycm_extra_conf.py*
|
||||||
|
compile_commands.json
|
||||||
|
*.orig
|
||||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "third-party/googletest"]
|
||||||
|
path = third-party/googletest
|
||||||
|
url = https://github.com/google/googletest.git
|
||||||
55
.travis.yml
Normal file
55
.travis.yml
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
# Travis-CI Build for SimpleAmqpClient
|
||||||
|
# see travis-ci.org for details
|
||||||
|
|
||||||
|
language: cpp
|
||||||
|
|
||||||
|
os: linux
|
||||||
|
dist: xenial
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
include:
|
||||||
|
- compiler: gcc
|
||||||
|
env: FLAGS=""
|
||||||
|
- compiler: clang
|
||||||
|
env: FLAGS=""
|
||||||
|
- compiler: clang
|
||||||
|
env: FLAGS="-g -O1 -fsanitize=address,undefined -fno-omit-frame-pointer"
|
||||||
|
- compiler: clang
|
||||||
|
env: FLAGS="-g -O1 -fsanitize=thread -fno-omit-frame-pointer"
|
||||||
|
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- sourceline: deb http://dl.bintray.com/rabbitmq-erlang/debian xenial erlang
|
||||||
|
key_url: https://github.com/rabbitmq/signing-keys/releases/download/2.0/rabbitmq-release-signing-key.asc
|
||||||
|
- sourceline: deb https://dl.bintray.com/rabbitmq/debian xenial main
|
||||||
|
key_url: https://github.com/rabbitmq/signing-keys/releases/download/2.0/rabbitmq-release-signing-key.asc
|
||||||
|
packages:
|
||||||
|
- libboost-dev
|
||||||
|
- libboost-chrono-dev
|
||||||
|
- libboost-system-dev
|
||||||
|
- rabbitmq-server
|
||||||
|
- ninja-build
|
||||||
|
|
||||||
|
# install pre-reqs
|
||||||
|
install:
|
||||||
|
- mkdir -p _prereqs
|
||||||
|
- pushd _prereqs
|
||||||
|
- git clone https://github.com/alanxz/rabbitmq-c
|
||||||
|
- cd rabbitmq-c
|
||||||
|
- git checkout v0.10.0
|
||||||
|
- export RABBITMQC_DIR=`pwd`/../../_install
|
||||||
|
- cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${RABBITMQC_DIR} -DBUILD_EXAMPLES=OFF -DBUILD_TESTS=OFF -DBUILD_TOOLS=OFF .
|
||||||
|
- cmake --build . --target install
|
||||||
|
- popd
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
- mkdir _build
|
||||||
|
- cd _build
|
||||||
|
- pwd
|
||||||
|
|
||||||
|
# Run the Build script
|
||||||
|
script:
|
||||||
|
- cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="${FLAGS}" -DCMAKE_INSTALL_PREFIX=../_install -DENABLE_TESTING=ON -DRabbitmqc_DIR=${RABBITMQ_C_DIR} ..
|
||||||
|
- cmake --build . --target install
|
||||||
|
- AMQP_BROKER=localhost ASAN_OPTIONS=detect_leaks=1 ctest -V .
|
||||||
316
CMakeLists.txt
Normal file
316
CMakeLists.txt
Normal file
@@ -0,0 +1,316 @@
|
|||||||
|
# Most widely used distributions have cmake 3.5 or greater available as of March
|
||||||
|
# 2019. A notable exception is RHEL-7 (CentOS7). You can install a current
|
||||||
|
# version of CMake by first installing Extra Packages for Enterprise Linux
|
||||||
|
# (https://fedoraproject.org/wiki/EPEL#Extra_Packages_for_Enterprise_Linux_.28EPEL.29)
|
||||||
|
# and then issuing `yum install cmake3` on the command line.
|
||||||
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
|
project(SimpleAmqpClient LANGUAGES CXX)
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_CXX_STANDARD)
|
||||||
|
set(CMAKE_CXX_STANDARD 98)
|
||||||
|
endif()
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
|
# Follow all steps below in order to calculate new ABI version when updating the library
|
||||||
|
# NOTE: THIS IS UNRELATED to the actual project version
|
||||||
|
#
|
||||||
|
# 1. If the library source code has changed at all since the last update, then increment revision
|
||||||
|
# 2. If any interfaces have been added, removed, or changed since the last update, increment
|
||||||
|
# current and set revision to 0.
|
||||||
|
# 3. If any interfaces have been added since the last public release, then increment age.
|
||||||
|
# 4. If any interfaces have been removed since the last public release, then set age to 0.
|
||||||
|
|
||||||
|
set(SAC_SOVERSION_CURRENT 7)
|
||||||
|
set(SAC_SOVERSION_REVISION 1)
|
||||||
|
set(SAC_SOVERSION_AGE 0)
|
||||||
|
|
||||||
|
math(EXPR SAC_SOVERSION_MAJOR "${SAC_SOVERSION_CURRENT} - ${SAC_SOVERSION_AGE}")
|
||||||
|
math(EXPR SAC_SOVERSION_MINOR "${SAC_SOVERSION_AGE}")
|
||||||
|
math(EXPR SAC_SOVERSION_PATCH "${SAC_SOVERSION_REVISION}")
|
||||||
|
|
||||||
|
set(SAC_VERSION ${SAC_SOVERSION_MAJOR}.${SAC_SOVERSION_MINOR}.${SAC_SOVERSION_PATCH})
|
||||||
|
set(SAC_SOVERSION ${SAC_SOVERSION_MAJOR})
|
||||||
|
|
||||||
|
file(STRINGS src/SimpleAmqpClient/Version.h _API_VERSION_MAJOR REGEX "^#define SIMPLEAMQPCLIENT_VERSION_MAJOR [0-9]+$")
|
||||||
|
file(STRINGS src/SimpleAmqpClient/Version.h _API_VERSION_MINOR REGEX "^#define SIMPLEAMQPCLIENT_VERSION_MINOR [0-9]+$")
|
||||||
|
file(STRINGS src/SimpleAmqpClient/Version.h _API_VERSION_PATCH REGEX "^#define SIMPLEAMQPCLIENT_VERSION_PATCH [0-9]+$")
|
||||||
|
|
||||||
|
string(REGEX MATCH "[0-9]+" _API_VERSION_MAJOR ${_API_VERSION_MAJOR})
|
||||||
|
string(REGEX MATCH "[0-9]+" _API_VERSION_MINOR ${_API_VERSION_MINOR})
|
||||||
|
string(REGEX MATCH "[0-9]+" _API_VERSION_PATCH ${_API_VERSION_PATCH})
|
||||||
|
|
||||||
|
set(SAC_APIVERSION ${_API_VERSION_MAJOR}.${_API_VERSION_MINOR}.${_API_VERSION_PATCH})
|
||||||
|
|
||||||
|
option(BUILD_SHARED_LIBS "Build SimpleAmqpClient as a shared library" ON)
|
||||||
|
|
||||||
|
# Force the use of static boost library for static libraries
|
||||||
|
include(CMakeDependentOption)
|
||||||
|
|
||||||
|
cmake_dependent_option(
|
||||||
|
Boost_Dynamic_Linking_ENABLED
|
||||||
|
"Enable boost dynamic linking"
|
||||||
|
ON
|
||||||
|
"BUILD_SHARED_LIBS"
|
||||||
|
OFF
|
||||||
|
)
|
||||||
|
|
||||||
|
if(Boost_Dynamic_Linking_ENABLED)
|
||||||
|
set(Boost_USE_STATIC_LIBS OFF)
|
||||||
|
else()
|
||||||
|
set(Boost_USE_STATIC_LIBS ON)
|
||||||
|
endif()
|
||||||
|
set(Boost_USE_STATIC_RUNTIME OFF)
|
||||||
|
|
||||||
|
find_package(Boost 1.47.0 COMPONENTS chrono REQUIRED)
|
||||||
|
if(Boost_VERSION VERSION_LESS 1.89)
|
||||||
|
find_package(Boost 1.47.0 COMPONENTS chrono system REQUIRED)
|
||||||
|
endif()
|
||||||
|
include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
|
||||||
|
link_directories(${Boost_LIBRARY_DIRS})
|
||||||
|
|
||||||
|
# Try using the CMake config modules first
|
||||||
|
find_package(rabbitmq-c CONFIG QUIET)
|
||||||
|
if (rabbitmq-c_FOUND)
|
||||||
|
if (BUILD_SHARED_LIBS)
|
||||||
|
set(Rabbitmqc_LIBRARY rabbitmq::rabbitmq)
|
||||||
|
else()
|
||||||
|
set(Rabbitmqc_LIBRARY rabbitmq::rabbitmq-static)
|
||||||
|
endif()
|
||||||
|
get_target_property(Rabbitmqc_INCLUDE_DIRS ${Rabbitmqc_LIBRARY} INTERFACE_INCLUDE_DIRECTORIES)
|
||||||
|
else()
|
||||||
|
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/Modules)
|
||||||
|
find_package(Rabbitmqc REQUIRED)
|
||||||
|
INCLUDE_DIRECTORIES(SYSTEM ${Rabbitmqc_INCLUDE_DIRS})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
option(ENABLE_SSL_SUPPORT "Enable SSL support." ${Rabbitmqc_SSL_ENABLED})
|
||||||
|
|
||||||
|
if (ENABLE_SSL_SUPPORT)
|
||||||
|
add_definitions(-DSAC_SSL_SUPPORT_ENABLED)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (CMAKE_GENERATOR MATCHES ".*(Make|Ninja).*"
|
||||||
|
AND NOT CMAKE_BUILD_TYPE)
|
||||||
|
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel" FORCE)
|
||||||
|
message(STATUS "CMAKE_BUILD_TYPE not specified. Using ${CMAKE_BUILD_TYPE} build")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (CMAKE_CXX_FLAGS STREQUAL ""
|
||||||
|
AND NOT DEFINED SAC_CXX_FLAGS_SET)
|
||||||
|
if (CMAKE_COMPILER_IS_GNUCXX
|
||||||
|
OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
|
SET(CMAKE_CXX_FLAGS "-Wall -Wextra" CACHE STRING "Flags used by the compiler during all build types." FORCE)
|
||||||
|
endif ()
|
||||||
|
set(SAC_CXX_FLAGS_SET TRUE CACHE INTERNAL "Have the SAC default compiler flags been set?")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
include_directories(BEFORE src
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
set(SOCKET_LIBRARY ws2_32)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set(SAC_LIB_SRCS
|
||||||
|
src/SimpleAmqpClient/SimpleAmqpClient.h
|
||||||
|
|
||||||
|
src/SimpleAmqpClient/AmqpException.h
|
||||||
|
src/AmqpException.cpp
|
||||||
|
|
||||||
|
src/SimpleAmqpClient/Bytes.h
|
||||||
|
|
||||||
|
src/SimpleAmqpClient/Channel.h
|
||||||
|
src/Channel.cpp
|
||||||
|
|
||||||
|
src/SimpleAmqpClient/ChannelImpl.h
|
||||||
|
src/ChannelImpl.cpp
|
||||||
|
|
||||||
|
src/SimpleAmqpClient/BasicMessage.h
|
||||||
|
src/BasicMessage.cpp
|
||||||
|
|
||||||
|
src/SimpleAmqpClient/Util.h
|
||||||
|
|
||||||
|
src/SimpleAmqpClient/AmqpLibraryException.h
|
||||||
|
src/AmqpLibraryException.cpp
|
||||||
|
|
||||||
|
src/SimpleAmqpClient/AmqpResponseLibraryException.h
|
||||||
|
src/AmqpResponseLibraryException.cpp
|
||||||
|
|
||||||
|
src/SimpleAmqpClient/BadUriException.h
|
||||||
|
src/SimpleAmqpClient/ConnectionClosedException.h
|
||||||
|
src/SimpleAmqpClient/ConsumerTagNotFoundException.h
|
||||||
|
src/SimpleAmqpClient/MessageRejectedException.h
|
||||||
|
|
||||||
|
src/SimpleAmqpClient/Envelope.h
|
||||||
|
src/Envelope.cpp
|
||||||
|
|
||||||
|
src/SimpleAmqpClient/MessageReturnedException.h
|
||||||
|
src/MessageReturnedException.cpp
|
||||||
|
|
||||||
|
src/SimpleAmqpClient/Table.h
|
||||||
|
src/Table.cpp
|
||||||
|
|
||||||
|
src/SimpleAmqpClient/TableImpl.h
|
||||||
|
src/TableImpl.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
add_library(SimpleAmqpClient ${SAC_LIB_SRCS})
|
||||||
|
target_link_libraries(SimpleAmqpClient ${Rabbitmqc_LIBRARY} ${SOCKET_LIBRARY} ${Boost_LIBRARIES} $<$<BOOL:${Boost_Dynamic_Linking_ENABLED}>:Boost::dynamic_linking>)
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
if (NOT BUILD_SHARED_LIBS)
|
||||||
|
target_compile_definitions(SimpleAmqpClient PUBLIC SimpleAmqpClient_STATIC)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set_target_properties(SimpleAmqpClient PROPERTIES VERSION ${SAC_VERSION} OUTPUT_NAME SimpleAmqpClient.${SAC_SOVERSION})
|
||||||
|
else ()
|
||||||
|
set_target_properties(SimpleAmqpClient PROPERTIES VERSION ${SAC_VERSION} SOVERSION ${SAC_SOVERSION})
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
# Some smoke tests:
|
||||||
|
|
||||||
|
option(ENABLE_TESTING "Enable smoke tests" OFF)
|
||||||
|
|
||||||
|
if (ENABLE_TESTING)
|
||||||
|
enable_testing()
|
||||||
|
|
||||||
|
set(BUILD_GTEST ON CACHE BOOL "" FORCE)
|
||||||
|
set(BUILD_GMOCK OFF CACHE BOOL "" FORCE)
|
||||||
|
set(INSTALL_GTEST OFF CACHE BOOL "" FORCE)
|
||||||
|
|
||||||
|
# This only affects targets declared after this.
|
||||||
|
set(BUILD_SHARED_LIBS OFF)
|
||||||
|
|
||||||
|
mark_as_advanced(BUILD_GMOCK)
|
||||||
|
mark_as_advanced(BUILD_GTEST)
|
||||||
|
mark_as_advanced(INSTALL_GTEST)
|
||||||
|
mark_as_advanced(gmock_build_tests)
|
||||||
|
mark_as_advanced(gtest_build_samples)
|
||||||
|
mark_as_advanced(gtest_build_tests)
|
||||||
|
mark_as_advanced(gtest_disable_pthreads)
|
||||||
|
mark_as_advanced(gtest_force_shared_crt)
|
||||||
|
mark_as_advanced(gtest_hide_internal_symbols)
|
||||||
|
|
||||||
|
add_subdirectory(third-party/googletest)
|
||||||
|
add_subdirectory(testing)
|
||||||
|
endif (ENABLE_TESTING)
|
||||||
|
|
||||||
|
|
||||||
|
# Documentation generation
|
||||||
|
find_package(Doxygen COMPONENTS dot)
|
||||||
|
option(BUILD_API_DOCS "Build Doxygen API docs" ${DOXYGEN_FOUND})
|
||||||
|
|
||||||
|
if (BUILD_API_DOCS)
|
||||||
|
if (NOT DOXYGEN_FOUND)
|
||||||
|
message(FATAL_ERROR "Doxygen is required to build the API documentation")
|
||||||
|
endif ()
|
||||||
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/docs/Doxyfile @ONLY)
|
||||||
|
|
||||||
|
add_custom_target(docs ALL
|
||||||
|
COMMAND ${DOXYGEN_EXECUTABLE}
|
||||||
|
VERBATIM
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/docs
|
||||||
|
DEPENDS SimpleAmqpClient
|
||||||
|
COMMENT "Generating API documentation"
|
||||||
|
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in
|
||||||
|
)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
|
install(TARGETS SimpleAmqpClient
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
install(FILES
|
||||||
|
src/SimpleAmqpClient/AmqpException.h
|
||||||
|
src/SimpleAmqpClient/AmqpLibraryException.h
|
||||||
|
src/SimpleAmqpClient/AmqpResponseLibraryException.h
|
||||||
|
src/SimpleAmqpClient/BadUriException.h
|
||||||
|
src/SimpleAmqpClient/BasicMessage.h
|
||||||
|
src/SimpleAmqpClient/Channel.h
|
||||||
|
src/SimpleAmqpClient/ConnectionClosedException.h
|
||||||
|
src/SimpleAmqpClient/ConsumerCancelledException.h
|
||||||
|
src/SimpleAmqpClient/ConsumerTagNotFoundException.h
|
||||||
|
src/SimpleAmqpClient/Envelope.h
|
||||||
|
src/SimpleAmqpClient/MessageReturnedException.h
|
||||||
|
src/SimpleAmqpClient/MessageRejectedException.h
|
||||||
|
src/SimpleAmqpClient/SimpleAmqpClient.h
|
||||||
|
src/SimpleAmqpClient/Table.h
|
||||||
|
src/SimpleAmqpClient/Util.h
|
||||||
|
src/SimpleAmqpClient/Version.h
|
||||||
|
DESTINATION include/SimpleAmqpClient
|
||||||
|
)
|
||||||
|
|
||||||
|
set(prefix ${CMAKE_INSTALL_PREFIX})
|
||||||
|
set(exec_prefix "\${prefix}")
|
||||||
|
set(libdir "\${prefix}/${CMAKE_INSTALL_LIBDIR}")
|
||||||
|
set(includedir "\${prefix}/include")
|
||||||
|
if(WIN32)
|
||||||
|
get_target_property(SIMPLEAMQPCLIENT_LIB SimpleAmqpClient OUTPUT_NAME)
|
||||||
|
else(WIN32)
|
||||||
|
set(SIMPLEAMQPCLIENT_LIB SimpleAmqpClient)
|
||||||
|
endif(WIN32)
|
||||||
|
|
||||||
|
# Propagate package dependencies
|
||||||
|
if (BUILD_SHARED_LIBS)
|
||||||
|
set(requires_private "librabbitmq")
|
||||||
|
else (BUILD_SHARED_LIBS)
|
||||||
|
set(requires_public "librabbitmq")
|
||||||
|
endif (BUILD_SHARED_LIBS)
|
||||||
|
|
||||||
|
# Propagate interface compile definitions
|
||||||
|
set(SIMPLEAMQPCLIENT_DEFINITIONS "")
|
||||||
|
get_target_property(propagated_definitions SimpleAmqpClient INTERFACE_COMPILE_DEFINITIONS)
|
||||||
|
if (propagated_definitions)
|
||||||
|
foreach(_def ${propagated_definitions})
|
||||||
|
set(SIMPLEAMQPCLIENT_DEFINITIONS "${SIMPLEAMQPCLIENT_DEFINITIONS} -D${_def}")
|
||||||
|
endforeach()
|
||||||
|
endif(propagated_definitions)
|
||||||
|
|
||||||
|
# Propagate library dependencies
|
||||||
|
set(libs_private "")
|
||||||
|
set(libs_public "")
|
||||||
|
|
||||||
|
if (BUILD_SHARED_LIBS)
|
||||||
|
set(populate_libs "libs_private")
|
||||||
|
else (BUILD_SHARED_LIBS)
|
||||||
|
set(populate_libs "libs_public")
|
||||||
|
set(extra_win32_targets "${Rabbitmqc_LIBRARY};${SOCKET_LIBRARY}")
|
||||||
|
endif (BUILD_SHARED_LIBS)
|
||||||
|
|
||||||
|
foreach(_lib ${Boost_LIBRARIES} ${extra_win32_targets})
|
||||||
|
|
||||||
|
# Check if FindBoost.cmake provided actual library paths or targets
|
||||||
|
if(TARGET ${_lib})
|
||||||
|
get_target_property(_lib ${_lib} LOCATION)
|
||||||
|
message(WARNING "Using target ${_lib} as a library")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
get_filename_component(_LIBPATH ${_lib} PATH)
|
||||||
|
if (NOT _LIBPATH STREQUAL _LASTLIBPATH AND NOT _LIBPATH STREQUAL "")
|
||||||
|
set(${populate_libs} "${${populate_libs}} -L\"${_LIBPATH}\"")
|
||||||
|
set(_LASTLIBPATH ${_LIBPATH})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
get_filename_component(_LIBNAME ${_lib} NAME_WLE)
|
||||||
|
if (NOT _LIBNAME STREQUAL "debug" AND NOT _LIBNAME STREQUAL "optimized")
|
||||||
|
if (NOT WIN32)
|
||||||
|
string(REGEX REPLACE "^lib" "" _LIBNAME ${_LIBNAME})
|
||||||
|
endif()
|
||||||
|
set(_LIBNAME "-l${_LIBNAME}")
|
||||||
|
set(${populate_libs} "${${populate_libs}} ${_LIBNAME}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
configure_file(libSimpleAmqpClient.pc.in ${CMAKE_CURRENT_BINARY_DIR}/libSimpleAmqpClient.pc @ONLY)
|
||||||
|
|
||||||
|
install(FILES
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/libSimpleAmqpClient.pc
|
||||||
|
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
|
||||||
|
)
|
||||||
15
CONTRIBUTING.md
Normal file
15
CONTRIBUTING.md
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
Contributing to SimpleAmqpClient
|
||||||
|
===============================
|
||||||
|
|
||||||
|
Thanks for contributing to SimpleAmqpClient. I firmly believe that
|
||||||
|
participation help make open source software great. With that in mind there
|
||||||
|
are a few things you can do to make this interaction a bit smoother.
|
||||||
|
|
||||||
|
Please use the following guidelines when creating an issue or submitting
|
||||||
|
a pull request
|
||||||
|
|
||||||
|
Creating an issue
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Submitting a pull-request
|
||||||
|
------------------------
|
||||||
80
ChangeLog.md
Normal file
80
ChangeLog.md
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
# Changes since v2.5.0 (v2.5.1)
|
||||||
|
|
||||||
|
- fix: restore GNUInstallDirs that was mistakenly removed.
|
||||||
|
- refactor of Channel constructors
|
||||||
|
|
||||||
|
# Changes since v2.4 (v2.5)
|
||||||
|
|
||||||
|
NOTE: this release requires rabbitmq-c v0.8.0 or better.
|
||||||
|
|
||||||
|
- add: support timestamp values in `Table` (1057ed4)
|
||||||
|
- enh: improve efficiency of `BasicMessage` reducing number of copies (938b102)
|
||||||
|
- doc: many clarifications in documentation (47f4c79)
|
||||||
|
- add: support for BasicPublish message rejection due to queue full (ecfbbfc)
|
||||||
|
- add: support for additional parameters in creating SSL connection (56713c0, eaa6044)
|
||||||
|
- add: `Channel::GetSocketFD` to allow access to underlying channel socket. (7c14a2e)
|
||||||
|
- add: multiple flag on `Channel::BasicAck` (6323892)
|
||||||
|
- add: support for unsigned types in `Table` (20296d2)
|
||||||
|
- enh: support for RabbitMQ auth-failure extension (0b67021)
|
||||||
|
- fix: consumer prefetch difference on RabbitMQ v3.3+ (59a1e05)
|
||||||
|
- rabbitmq-c errors are wrapped in `AmqpLibraryException` (a3a3ef7)
|
||||||
|
|
||||||
|
|
||||||
|
Changes since v2.3 (v2.4):
|
||||||
|
- Add support for consumer cancellation notification (5d35698)
|
||||||
|
- Improvements in extra-frame bookkeeping reducing memory useage under certain
|
||||||
|
conditions (e9de652, f4980bc)
|
||||||
|
- API support for waiting for multiple consumers at a time (e7e701a)
|
||||||
|
- Add version header (0fc6cab)
|
||||||
|
- Add pkg-config on install (a13c99a)
|
||||||
|
- Add DeclareQueueWithCounts API (Kai Blaschke 7fbcd96)
|
||||||
|
- Support for C++11 (Alexandre Jacquin 57a8d85)
|
||||||
|
- Add BasicReject API (Luca Marturana 0c9478e)
|
||||||
|
- Upgrade gtest to v1.7.0 (8fe82fd)
|
||||||
|
|
||||||
|
Changes since v2.2 (v2.3):
|
||||||
|
NOTE: this release uses new rabbitmq-c interfaces introduced in v0.4.0, thus
|
||||||
|
requires rabbitmq-c v0.4.0 or later.
|
||||||
|
- Add support for SSL (Ashok Anand 44b8b4e)
|
||||||
|
- Use new rabbitmq-c socket interface (Nikita Vasiliev 9f6cdac)
|
||||||
|
- Use new rabbitmq-c error-string interface (a26da26)
|
||||||
|
- Code formatting and license header updates (752ae75, 5a2f64c, c3dec10, 2b82942)
|
||||||
|
- Use new rabbitmq-c timeout interface when reading frames (d4a9f31)
|
||||||
|
- Use new rabbitmq-c interface to release memory on a per-channel basis (49b8ba8)
|
||||||
|
|
||||||
|
Changes since v2.1 (v2.2):
|
||||||
|
NOTE: this is the last version targeting rabbitmq-c v0.3, newer versions will
|
||||||
|
target rabbitmq-c v0.4
|
||||||
|
- Disable building test suite by default (4f6af4e)
|
||||||
|
- Default to building Release build when none is specified (c60d0e9)
|
||||||
|
- Add -Wall -Wextra to default C++ flags (bf813e5)
|
||||||
|
- Improve documentation (f967758, 23151d3)
|
||||||
|
- BUG: throw std::bad_alloc when a 0-length table is received (6d17950, d694d4b)
|
||||||
|
- Improve Channel::BasicGet documentation (ead3936)
|
||||||
|
- Disable tests that exercise the immediate flag in basic.publish (48636b1)
|
||||||
|
- Add Channel::BasicAck() overload allowing basic.ack without keeping the whole Envelope obj (0dea3b8, fcd094a)
|
||||||
|
- Add method to create Channel from an AMQP URI (c8cae56, 8dd62b5)
|
||||||
|
- Updated examples (fcc1176, a9d4eec, 03bb42d)
|
||||||
|
|
||||||
|
Changes since v2.0-beta (v2.1)
|
||||||
|
- Add wrapping of amqp_table_t for passing table arguments to various
|
||||||
|
AMQP RPC methods (bae7b97)
|
||||||
|
- Fix for bug in BasicConsumeMessage default timeout (6412fcf3)
|
||||||
|
- Enable travis-ci continuous integration (44089d65)
|
||||||
|
- Ship google-test framework with library (8d86d2e4)
|
||||||
|
- Implement SOVERSION-ing (b44f3b7b)
|
||||||
|
- Missing include in AmqpException.cpp (20ccca9)
|
||||||
|
- Fix for memory leak in BasicPublish when exception is thrown (56e20b2)
|
||||||
|
- Fix for memory leak in BasicMessage when new body assigned (e5bf1157)
|
||||||
|
- Missing string.h include in AmqpException.h (ecee2104)
|
||||||
|
- Compile changes to compile cleanly under -Wall -Wextra (2b5a1a23)
|
||||||
|
- Fix for crash when AmqpException thrown without a class or method id (6a4fac62)
|
||||||
|
- Fix for incorrect timeout units when BasicConsumeMessage (3cdf94d9)
|
||||||
|
- Relicensed library under MIT license (a069444b)
|
||||||
|
- Fix sending unitialized data to broker (080bd9e9)
|
||||||
|
- Fix free strings returned by amqp_error_string (c7b0cfcc)
|
||||||
|
- Fix destroy amqp_connection_state object if an exception is thrown in Channel constructor (af936d0)
|
||||||
|
- Add ability to build as static library (50b6afd)
|
||||||
|
- Fix for macro redefinition (548084)
|
||||||
|
- Correct usage of stdint.h on VS2008 and earlier (795c0fea)
|
||||||
|
|
||||||
289
Doxyfile.in
Normal file
289
Doxyfile.in
Normal file
@@ -0,0 +1,289 @@
|
|||||||
|
# Doxyfile 1.8.2
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Project related configuration options
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
DOXYFILE_ENCODING = UTF-8
|
||||||
|
PROJECT_NAME = "SimpleAmqpClient"
|
||||||
|
PROJECT_NUMBER = "@SAC_VERSION@"
|
||||||
|
PROJECT_BRIEF = "A C++ wrapper around the rabbitmq-c AMQP client library"
|
||||||
|
PROJECT_LOGO =
|
||||||
|
OUTPUT_DIRECTORY = .
|
||||||
|
CREATE_SUBDIRS = NO
|
||||||
|
OUTPUT_LANGUAGE = English
|
||||||
|
BRIEF_MEMBER_DESC = YES
|
||||||
|
REPEAT_BRIEF = YES
|
||||||
|
ABBREVIATE_BRIEF =
|
||||||
|
ALWAYS_DETAILED_SEC = NO
|
||||||
|
INLINE_INHERITED_MEMB = NO
|
||||||
|
FULL_PATH_NAMES = NO
|
||||||
|
STRIP_FROM_PATH =
|
||||||
|
STRIP_FROM_INC_PATH =
|
||||||
|
SHORT_NAMES = NO
|
||||||
|
JAVADOC_AUTOBRIEF = YES
|
||||||
|
QT_AUTOBRIEF = NO
|
||||||
|
MULTILINE_CPP_IS_BRIEF = NO
|
||||||
|
INHERIT_DOCS = YES
|
||||||
|
SEPARATE_MEMBER_PAGES = NO
|
||||||
|
TAB_SIZE = 2
|
||||||
|
ALIASES =
|
||||||
|
TCL_SUBST =
|
||||||
|
OPTIMIZE_OUTPUT_FOR_C = NO
|
||||||
|
OPTIMIZE_OUTPUT_JAVA = NO
|
||||||
|
OPTIMIZE_FOR_FORTRAN = NO
|
||||||
|
OPTIMIZE_OUTPUT_VHDL = NO
|
||||||
|
EXTENSION_MAPPING =
|
||||||
|
MARKDOWN_SUPPORT = YES
|
||||||
|
AUTOLINK_SUPPORT = YES
|
||||||
|
BUILTIN_STL_SUPPORT = YES
|
||||||
|
CPP_CLI_SUPPORT = NO
|
||||||
|
SIP_SUPPORT = NO
|
||||||
|
IDL_PROPERTY_SUPPORT = YES
|
||||||
|
DISTRIBUTE_GROUP_DOC = NO
|
||||||
|
SUBGROUPING = YES
|
||||||
|
INLINE_GROUPED_CLASSES = NO
|
||||||
|
INLINE_SIMPLE_STRUCTS = NO
|
||||||
|
TYPEDEF_HIDES_STRUCT = NO
|
||||||
|
LOOKUP_CACHE_SIZE = 0
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Build related configuration options
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
EXTRACT_ALL = NO
|
||||||
|
EXTRACT_PRIVATE = NO
|
||||||
|
EXTRACT_PACKAGE = NO
|
||||||
|
EXTRACT_STATIC = YES
|
||||||
|
EXTRACT_LOCAL_CLASSES = YES
|
||||||
|
EXTRACT_LOCAL_METHODS = NO
|
||||||
|
EXTRACT_ANON_NSPACES = NO
|
||||||
|
HIDE_UNDOC_MEMBERS = NO
|
||||||
|
HIDE_UNDOC_CLASSES = NO
|
||||||
|
HIDE_FRIEND_COMPOUNDS = NO
|
||||||
|
HIDE_IN_BODY_DOCS = NO
|
||||||
|
INTERNAL_DOCS = NO
|
||||||
|
CASE_SENSE_NAMES = YES
|
||||||
|
HIDE_SCOPE_NAMES = NO
|
||||||
|
SHOW_INCLUDE_FILES = YES
|
||||||
|
FORCE_LOCAL_INCLUDES = NO
|
||||||
|
INLINE_INFO = YES
|
||||||
|
SORT_MEMBER_DOCS = NO
|
||||||
|
SORT_BRIEF_DOCS = NO
|
||||||
|
SORT_MEMBERS_CTORS_1ST = NO
|
||||||
|
SORT_GROUP_NAMES = NO
|
||||||
|
SORT_BY_SCOPE_NAME = NO
|
||||||
|
STRICT_PROTO_MATCHING = NO
|
||||||
|
GENERATE_TODOLIST = YES
|
||||||
|
GENERATE_TESTLIST = YES
|
||||||
|
GENERATE_BUGLIST = YES
|
||||||
|
GENERATE_DEPRECATEDLIST= YES
|
||||||
|
ENABLED_SECTIONS =
|
||||||
|
MAX_INITIALIZER_LINES = 30
|
||||||
|
SHOW_USED_FILES = YES
|
||||||
|
SHOW_FILES = YES
|
||||||
|
SHOW_NAMESPACES = YES
|
||||||
|
FILE_VERSION_FILTER =
|
||||||
|
LAYOUT_FILE =
|
||||||
|
CITE_BIB_FILES =
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to warning and progress messages
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
QUIET = YES
|
||||||
|
WARNINGS = YES
|
||||||
|
WARN_IF_UNDOCUMENTED = YES
|
||||||
|
WARN_IF_DOC_ERROR = YES
|
||||||
|
WARN_NO_PARAMDOC = NO
|
||||||
|
WARN_FORMAT = "$file:$line: $text"
|
||||||
|
WARN_LOGFILE =
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to the input files
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
INPUT = "@CMAKE_SOURCE_DIR@/src/SimpleAmqpClient"
|
||||||
|
INPUT += "@CMAKE_SOURCE_DIR@/README.md"
|
||||||
|
USE_MDFILE_AS_MAINPAGE = README.md
|
||||||
|
INPUT_ENCODING = UTF-8
|
||||||
|
FILE_PATTERNS = *.h
|
||||||
|
RECURSIVE = YES
|
||||||
|
EXCLUDE = *Impl.h
|
||||||
|
EXCLUDE_SYMLINKS = NO
|
||||||
|
EXCLUDE_PATTERNS = *Impl.h
|
||||||
|
EXCLUDE_SYMBOLS =
|
||||||
|
#EXAMPLE_PATH = "@CMAKE_CURRENT_SOURCE_DIR@/examples"
|
||||||
|
EXAMPLE_PATTERNS =
|
||||||
|
EXAMPLE_RECURSIVE = NO
|
||||||
|
IMAGE_PATH =
|
||||||
|
INPUT_FILTER =
|
||||||
|
FILTER_PATTERNS =
|
||||||
|
FILTER_SOURCE_FILES = NO
|
||||||
|
FILTER_SOURCE_PATTERNS =
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to source browsing
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
SOURCE_BROWSER = YES
|
||||||
|
INLINE_SOURCES = NO
|
||||||
|
STRIP_CODE_COMMENTS = YES
|
||||||
|
REFERENCED_BY_RELATION = YES
|
||||||
|
REFERENCES_RELATION = NO
|
||||||
|
REFERENCES_LINK_SOURCE = NO
|
||||||
|
USE_HTAGS = NO
|
||||||
|
VERBATIM_HEADERS = YES
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to the alphabetical class index
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
ALPHABETICAL_INDEX = NO
|
||||||
|
COLS_IN_ALPHA_INDEX = 5
|
||||||
|
IGNORE_PREFIX =
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to the HTML output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_HTML = YES
|
||||||
|
HTML_OUTPUT = html
|
||||||
|
HTML_FILE_EXTENSION = .html
|
||||||
|
HTML_HEADER =
|
||||||
|
HTML_FOOTER =
|
||||||
|
HTML_STYLESHEET =
|
||||||
|
HTML_EXTRA_STYLESHEET =
|
||||||
|
HTML_EXTRA_FILES =
|
||||||
|
HTML_COLORSTYLE_HUE = 220
|
||||||
|
HTML_COLORSTYLE_SAT = 100
|
||||||
|
HTML_COLORSTYLE_GAMMA = 80
|
||||||
|
HTML_TIMESTAMP = YES
|
||||||
|
HTML_DYNAMIC_SECTIONS = NO
|
||||||
|
HTML_INDEX_NUM_ENTRIES = 100
|
||||||
|
GENERATE_DOCSET = NO
|
||||||
|
DOCSET_FEEDNAME = "Doxygen generated docs"
|
||||||
|
DOCSET_BUNDLE_ID = org.doxygen.SimpleAmqpClient
|
||||||
|
DOCSET_PUBLISHER_ID = com.github.alanxz
|
||||||
|
DOCSET_PUBLISHER_NAME = Alan Antonuk
|
||||||
|
GENERATE_HTMLHELP = NO
|
||||||
|
CHM_FILE =
|
||||||
|
HHC_LOCATION =
|
||||||
|
GENERATE_CHI = NO
|
||||||
|
CHM_INDEX_ENCODING =
|
||||||
|
BINARY_TOC = NO
|
||||||
|
TOC_EXPAND = NO
|
||||||
|
GENERATE_QHP = NO
|
||||||
|
QCH_FILE =
|
||||||
|
QHP_NAMESPACE =
|
||||||
|
QHP_VIRTUAL_FOLDER = doc
|
||||||
|
QHP_CUST_FILTER_NAME =
|
||||||
|
QHP_CUST_FILTER_ATTRS =
|
||||||
|
QHP_SECT_FILTER_ATTRS =
|
||||||
|
QHG_LOCATION =
|
||||||
|
GENERATE_ECLIPSEHELP = NO
|
||||||
|
ECLIPSE_DOC_ID = org.doxygen.SimpleAmqpClient
|
||||||
|
DISABLE_INDEX = NO
|
||||||
|
GENERATE_TREEVIEW = NONE
|
||||||
|
ENUM_VALUES_PER_LINE = 4
|
||||||
|
TREEVIEW_WIDTH = 250
|
||||||
|
EXT_LINKS_IN_WINDOW = NO
|
||||||
|
FORMULA_FONTSIZE = 10
|
||||||
|
FORMULA_TRANSPARENT = YES
|
||||||
|
USE_MATHJAX = NO
|
||||||
|
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
|
||||||
|
MATHJAX_EXTENSIONS =
|
||||||
|
SEARCHENGINE = NO
|
||||||
|
SERVER_BASED_SEARCH = NO
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to the LaTeX output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_LATEX = NO
|
||||||
|
LATEX_OUTPUT = latex
|
||||||
|
LATEX_CMD_NAME = latex
|
||||||
|
MAKEINDEX_CMD_NAME = makeindex
|
||||||
|
COMPACT_LATEX = NO
|
||||||
|
PAPER_TYPE = a4
|
||||||
|
EXTRA_PACKAGES =
|
||||||
|
LATEX_HEADER =
|
||||||
|
LATEX_FOOTER =
|
||||||
|
PDF_HYPERLINKS = YES
|
||||||
|
USE_PDFLATEX = YES
|
||||||
|
LATEX_BATCHMODE = YES
|
||||||
|
LATEX_HIDE_INDICES = NO
|
||||||
|
LATEX_SOURCE_CODE = NO
|
||||||
|
LATEX_BIB_STYLE = plain
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to the RTF output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_RTF = NO
|
||||||
|
RTF_OUTPUT = rtf
|
||||||
|
COMPACT_RTF = NO
|
||||||
|
RTF_HYPERLINKS = NO
|
||||||
|
RTF_STYLESHEET_FILE =
|
||||||
|
RTF_EXTENSIONS_FILE =
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to the man page output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_MAN = NO
|
||||||
|
MAN_OUTPUT = man
|
||||||
|
MAN_EXTENSION = .3
|
||||||
|
MAN_LINKS = NO
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to the XML output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_XML = NO
|
||||||
|
XML_OUTPUT = xml
|
||||||
|
XML_PROGRAMLISTING = YES
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options for the AutoGen Definitions output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_AUTOGEN_DEF = NO
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# configuration options related to the Perl module output
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
GENERATE_PERLMOD = NO
|
||||||
|
PERLMOD_LATEX = NO
|
||||||
|
PERLMOD_PRETTY = YES
|
||||||
|
PERLMOD_MAKEVAR_PREFIX =
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Configuration options related to the preprocessor
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
ENABLE_PREPROCESSING = YES
|
||||||
|
MACRO_EXPANSION = YES
|
||||||
|
EXPAND_ONLY_PREDEF = NO
|
||||||
|
SEARCH_INCLUDES = YES
|
||||||
|
INCLUDE_PATH = @CMAKE_CURRENT_SOURCE_DIR@/src
|
||||||
|
INCLUDE_FILE_PATTERNS =
|
||||||
|
PREDEFINED = GENERATING_DOCUMENTATION
|
||||||
|
EXPAND_AS_DEFINED =
|
||||||
|
SKIP_FUNCTION_MACROS = YES
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Configuration::additions related to external references
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
TAGFILES =
|
||||||
|
GENERATE_TAGFILE =
|
||||||
|
ALLEXTERNALS = NO
|
||||||
|
EXTERNAL_GROUPS = YES
|
||||||
|
PERL_PATH = /usr/bin/perl
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# Configuration options related to the dot tool
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
CLASS_DIAGRAMS = YES
|
||||||
|
MSCGEN_PATH =
|
||||||
|
HIDE_UNDOC_RELATIONS = YES
|
||||||
|
HAVE_DOT = YES
|
||||||
|
DOT_NUM_THREADS = 0
|
||||||
|
#DOT_FONTNAME = FreeSans
|
||||||
|
DOT_FONTSIZE = 10
|
||||||
|
DOT_FONTPATH =
|
||||||
|
CLASS_GRAPH = YES
|
||||||
|
COLLABORATION_GRAPH = YES
|
||||||
|
GROUP_GRAPHS = YES
|
||||||
|
UML_LOOK = NO
|
||||||
|
UML_LIMIT_NUM_FIELDS = 10
|
||||||
|
TEMPLATE_RELATIONS = NO
|
||||||
|
INCLUDE_GRAPH = YES
|
||||||
|
INCLUDED_BY_GRAPH = YES
|
||||||
|
CALL_GRAPH = NO
|
||||||
|
CALLER_GRAPH = NO
|
||||||
|
GRAPHICAL_HIERARCHY = YES
|
||||||
|
DIRECTORY_GRAPH = YES
|
||||||
|
DOT_IMAGE_FORMAT = svg
|
||||||
|
INTERACTIVE_SVG = YES
|
||||||
|
DOT_PATH =
|
||||||
|
DOTFILE_DIRS =
|
||||||
|
MSCFILE_DIRS =
|
||||||
|
DOT_GRAPH_MAX_NODES = 50
|
||||||
|
MAX_DOT_GRAPH_DEPTH = 0
|
||||||
|
DOT_TRANSPARENT = YES
|
||||||
|
DOT_MULTI_TARGETS = NO
|
||||||
|
GENERATE_LEGEND = YES
|
||||||
|
DOT_CLEANUP = YES
|
||||||
23
LICENSE-MIT
Normal file
23
LICENSE-MIT
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2010-2014 Alan Antonuk. All Rights Reserved.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person
|
||||||
|
obtaining a copy of this software and associated documentation
|
||||||
|
files (the "Software"), to deal in the Software without
|
||||||
|
restriction, including without limitation the rights to use, copy,
|
||||||
|
modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
32
Modules/FindRabbitmqc.cmake
Normal file
32
Modules/FindRabbitmqc.cmake
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#Find the Rabbitmq C library
|
||||||
|
|
||||||
|
INCLUDE(LibFindMacros)
|
||||||
|
|
||||||
|
# Find the include directories
|
||||||
|
FIND_PATH(Rabbitmqc_INCLUDE_DIR
|
||||||
|
NAMES amqp.h
|
||||||
|
HINTS ${Rabbitmqc_DIR}/include
|
||||||
|
)
|
||||||
|
|
||||||
|
FIND_LIBRARY(Rabbitmqc_LIBRARY
|
||||||
|
NAMES rabbitmq
|
||||||
|
HINTS ${Rabbitmqc_DIR}/lib
|
||||||
|
)
|
||||||
|
|
||||||
|
SET(Rabbitmqc_PROCESS_INCLUDES Rabbitmqc_INCLUDE_DIR)
|
||||||
|
SET(Rabbitmqc_PROCESS_LIBS Rabbitmqc_LIBRARY)
|
||||||
|
|
||||||
|
LIBFIND_PROCESS(Rabbitmqc)
|
||||||
|
|
||||||
|
find_file(_Rabbitmqc_SSL_HEADER
|
||||||
|
NAMES amqp_ssl_socket.h
|
||||||
|
PATHS ${Rabbitmqc_INCLUDE_DIR}
|
||||||
|
NO_DEFAULT_PATH
|
||||||
|
)
|
||||||
|
|
||||||
|
string(COMPARE NOTEQUAL "${_Rabbitmqc_SSL_HEADER}"
|
||||||
|
"_Rabbitmqc_SSL_HEADER-NOTFOUND" _rmqc_ssl_enabled)
|
||||||
|
|
||||||
|
set(Rabbitmqc_SSL_ENABLED ${_rmqc_ssl_enabled} CACHE BOOL
|
||||||
|
"Rabbitmqc is SSL Enabled" FORCE)
|
||||||
|
mark_as_advanced(_Rabbitmqc_SSL_HEADER Rabbitmqc_SSL_ENABLED)
|
||||||
99
Modules/LibFindMacros.cmake
Normal file
99
Modules/LibFindMacros.cmake
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
# Works the same as find_package, but forwards the "REQUIRED" and "QUIET" arguments
|
||||||
|
# used for the current package. For this to work, the first parameter must be the
|
||||||
|
# prefix of the current package, then the prefix of the new package etc, which are
|
||||||
|
# passed to find_package.
|
||||||
|
macro (libfind_package PREFIX)
|
||||||
|
set (LIBFIND_PACKAGE_ARGS ${ARGN})
|
||||||
|
if (${PREFIX}_FIND_QUIETLY)
|
||||||
|
set (LIBFIND_PACKAGE_ARGS ${LIBFIND_PACKAGE_ARGS} QUIET)
|
||||||
|
endif (${PREFIX}_FIND_QUIETLY)
|
||||||
|
if (${PREFIX}_FIND_REQUIRED)
|
||||||
|
set (LIBFIND_PACKAGE_ARGS ${LIBFIND_PACKAGE_ARGS} REQUIRED)
|
||||||
|
endif (${PREFIX}_FIND_REQUIRED)
|
||||||
|
find_package(${LIBFIND_PACKAGE_ARGS})
|
||||||
|
endmacro (libfind_package)
|
||||||
|
|
||||||
|
# CMake developers made the UsePkgConfig system deprecated in the same release (2.6)
|
||||||
|
# where they added pkg_check_modules. Consequently I need to support both in my scripts
|
||||||
|
# to avoid those deprecated warnings. Here's a helper that does just that.
|
||||||
|
# Works identically to pkg_check_modules, except that no checks are needed prior to use.
|
||||||
|
macro (libfind_pkg_check_modules PREFIX PKGNAME)
|
||||||
|
if (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
|
||||||
|
include(UsePkgConfig)
|
||||||
|
pkgconfig(${PKGNAME} ${PREFIX}_INCLUDE_DIRS ${PREFIX}_LIBRARY_DIRS ${PREFIX}_LDFLAGS ${PREFIX}_CFLAGS)
|
||||||
|
else (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
|
||||||
|
find_package(PkgConfig)
|
||||||
|
if (PKG_CONFIG_FOUND)
|
||||||
|
pkg_check_modules(${PREFIX} ${PKGNAME})
|
||||||
|
endif (PKG_CONFIG_FOUND)
|
||||||
|
endif (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
|
||||||
|
endmacro (libfind_pkg_check_modules)
|
||||||
|
|
||||||
|
# Do the final processing once the paths have been detected.
|
||||||
|
# If include dirs are needed, ${PREFIX}_PROCESS_INCLUDES should be set to contain
|
||||||
|
# all the variables, each of which contain one include directory.
|
||||||
|
# Ditto for ${PREFIX}_PROCESS_LIBS and library files.
|
||||||
|
# Will set ${PREFIX}_FOUND, ${PREFIX}_INCLUDE_DIRS and ${PREFIX}_LIBRARIES.
|
||||||
|
# Also handles errors in case library detection was required, etc.
|
||||||
|
macro (libfind_process PREFIX)
|
||||||
|
# Skip processing if already processed during this run
|
||||||
|
if (NOT ${PREFIX}_FOUND)
|
||||||
|
# Start with the assumption that the library was found
|
||||||
|
set (${PREFIX}_FOUND TRUE)
|
||||||
|
|
||||||
|
# Process all includes and set _FOUND to false if any are missing
|
||||||
|
foreach (i ${${PREFIX}_PROCESS_INCLUDES})
|
||||||
|
if (${i})
|
||||||
|
set (${PREFIX}_INCLUDE_DIRS ${${PREFIX}_INCLUDE_DIRS} ${${i}})
|
||||||
|
mark_as_advanced(${i})
|
||||||
|
else (${i})
|
||||||
|
set (${PREFIX}_FOUND FALSE)
|
||||||
|
endif (${i})
|
||||||
|
endforeach (i)
|
||||||
|
|
||||||
|
# Process all libraries and set _FOUND to false if any are missing
|
||||||
|
foreach (i ${${PREFIX}_PROCESS_LIBS})
|
||||||
|
if (${i})
|
||||||
|
set (${PREFIX}_LIBRARIES ${${PREFIX}_LIBRARIES} ${${i}})
|
||||||
|
mark_as_advanced(${i})
|
||||||
|
else (${i})
|
||||||
|
set (${PREFIX}_FOUND FALSE)
|
||||||
|
endif (${i})
|
||||||
|
endforeach (i)
|
||||||
|
|
||||||
|
# Print message and/or exit on fatal error
|
||||||
|
if (${PREFIX}_FOUND)
|
||||||
|
if (NOT ${PREFIX}_FIND_QUIETLY)
|
||||||
|
message (STATUS "Found ${PREFIX} ${${PREFIX}_VERSION}")
|
||||||
|
endif (NOT ${PREFIX}_FIND_QUIETLY)
|
||||||
|
else (${PREFIX}_FOUND)
|
||||||
|
if (${PREFIX}_FIND_REQUIRED)
|
||||||
|
foreach (i ${${PREFIX}_PROCESS_INCLUDES} ${${PREFIX}_PROCESS_LIBS})
|
||||||
|
message("${i}=${${i}}")
|
||||||
|
endforeach (i)
|
||||||
|
message (FATAL_ERROR "Required library ${PREFIX} NOT FOUND.\nInstall the library (dev version) and try again. If the library is already installed, use ccmake to set the missing variables manually.")
|
||||||
|
endif (${PREFIX}_FIND_REQUIRED)
|
||||||
|
endif (${PREFIX}_FOUND)
|
||||||
|
endif (NOT ${PREFIX}_FOUND)
|
||||||
|
endmacro (libfind_process)
|
||||||
|
|
||||||
|
macro(libfind_library PREFIX basename)
|
||||||
|
set(TMP "")
|
||||||
|
if(MSVC80)
|
||||||
|
set(TMP -vc80)
|
||||||
|
endif(MSVC80)
|
||||||
|
if(MSVC90)
|
||||||
|
set(TMP -vc90)
|
||||||
|
endif(MSVC90)
|
||||||
|
set(${PREFIX}_LIBNAMES ${basename}${TMP})
|
||||||
|
if(${ARGC} GREATER 2)
|
||||||
|
set(${PREFIX}_LIBNAMES ${basename}${TMP}-${ARGV2})
|
||||||
|
string(REGEX REPLACE "\\." "_" TMP ${${PREFIX}_LIBNAMES})
|
||||||
|
set(${PREFIX}_LIBNAMES ${${PREFIX}_LIBNAMES} ${TMP})
|
||||||
|
endif(${ARGC} GREATER 2)
|
||||||
|
find_library(${PREFIX}_LIBRARY
|
||||||
|
NAMES ${${PREFIX}_LIBNAMES}
|
||||||
|
PATHS ${${PREFIX}_PKGCONF_LIBRARY_DIRS}
|
||||||
|
)
|
||||||
|
endmacro(libfind_library)
|
||||||
|
|
||||||
101
README.md
Normal file
101
README.md
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
SimpleAmqpClient
|
||||||
|
==================
|
||||||
|
|
||||||
|
[SimpleAmqpClient](https://github.com/alanxz/SimpleAmqpClient) is an easy-to-use C++
|
||||||
|
wrapper around the [rabbitmq-c](https://github.com/alanxz/rabbitmq-c) C library.
|
||||||
|
It derives inspiration from the [puka](https://github.com/majek/puka) AMQP library
|
||||||
|
in that it abstracts away the underlying AMQP wire concept of channels and uses them
|
||||||
|
as an error/consumer scope. This should make writing simple single-threaded AMQP-enabled apps easy.
|
||||||
|
|
||||||
|
Installing
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Known to work in the following environments:
|
||||||
|
- Windows 10 (MSVC 2019, Win64)
|
||||||
|
- Windows 7 (MSVC 10, Win64, Win32). Likely to work in others, but has not been tested
|
||||||
|
- Linux (RHEL 6.0, GCC-4.4.5, 32 and 64 bit). Likely to work on other configurations, but has not been tested
|
||||||
|
- Mac OS X (10.7, 10.6, gcc-4.2, 32 and 64-bit). Likely to work on older version, but has not been tested
|
||||||
|
|
||||||
|
### Pre-requisites
|
||||||
|
+ [boost-1.47.0](http://www.boost.org/) or newer (uses chrono, system internally in addition to other header based libraries such as sharedptr and noncopyable)
|
||||||
|
+ [rabbitmq-c](http://github.com/alanxz/rabbitmq-c) you'll need version 0.8.0 or better.
|
||||||
|
+ [cmake 3.5+](http://www.cmake.org/) what is needed for the build system
|
||||||
|
+ [Doxygen](http://www.stack.nl/~dimitri/doxygen/) OPTIONAL only necessary to generate API documentation
|
||||||
|
|
||||||
|
### Build procedure
|
||||||
|
This is a typical cmake project, it should work like most typical cmake projects:
|
||||||
|
|
||||||
|
In a sibling directory to where you extracted the source code:
|
||||||
|
|
||||||
|
mkdir simpleamqpclient-build
|
||||||
|
cd simpleamqpclient-build
|
||||||
|
cmake ..
|
||||||
|
|
||||||
|
Then use your the appropriate build utility to build the library (make, msbuild)
|
||||||
|
|
||||||
|
Interesting targets
|
||||||
|
+ test - will build and run the tests
|
||||||
|
+ install - will install the library and headers to whatever `CMAKE_INSTALL_PREFIX` is defined to
|
||||||
|
+ doc - will generate API documentation if you have doxygen setup
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
+ The test google-test based test suite can be enabled by passing `-DENABLE_TESTING=ON` to
|
||||||
|
cmake
|
||||||
|
|
||||||
|
### Build procedure for Windows
|
||||||
|
|
||||||
|
Boost libraries are needed, so you can install them using nuget:
|
||||||
|
```
|
||||||
|
nuget install boost_chrono-vc142 -Version 1.77.0
|
||||||
|
nuget install boost_system-vc142 -Version 1.77.0
|
||||||
|
nuget install boost -Version 1.77.0
|
||||||
|
```
|
||||||
|
To build and install succesfully, [rabbitmq-c](https://github.com/alanxz/rabbitmq-c) should be built **as shared library**.
|
||||||
|
|
||||||
|
Let *boost_chrono* and *boost_system* be in same directory ```C:\boost```, [rabbitmq-c](https://github.com/alanxz/rabbitmq-c) be on ```C:\rabbitmq-c```,
|
||||||
|
SSL be OFF, and VS2019 is used, than CMake CLI is:
|
||||||
|
```
|
||||||
|
cd cmake -G "Visual Studio 16" -A x64 -DBoost_INCLUDE_DIR="C:/boost.XX.XX.X.X/lib/native/include" -DBOOST_ROOT="C:/boost.X.XX.X.X" -DBOOST_LIBRARYDIR="C:/boost" -DRabbitmqc_INCLUDE_DIR="C:/rabbitmq-c/include" -DRabbitmqc_LIBRARY="C:/rabbitmq-c/lib/rabbitmq.4.lib" -DBoost_USE_STATIC_LIBS=ON -DBUILD_STATIC_LIBS=ON -DENABLE_SSL_SUPPORT=OFF ..
|
||||||
|
```
|
||||||
|
|
||||||
|
Using the library
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
#include <SimpleAmqpClient/SimpleAmqpClient.h>
|
||||||
|
|
||||||
|
Will include all the headers necessary to use the library.
|
||||||
|
The corresponding library is SimpleAmqpClient
|
||||||
|
|
||||||
|
The main interface to the library is the AmqpClient::Channel class. It represents
|
||||||
|
a connection to an AMQP broker, the connection is established on construction of an
|
||||||
|
instance of this class.
|
||||||
|
|
||||||
|
AmqpClient::Channel::ptr_t connection = AmqpClient::Channel::Create("localhost");
|
||||||
|
|
||||||
|
All classes have a typedef ptr_t which is equivalent to boost::shared_ptr<> of the
|
||||||
|
containing class. All classes also have a Create() method does the job creating a new
|
||||||
|
ptr_t using boost::make_shared<>(). It is recommended that you use these methods
|
||||||
|
to construct objects in the library.
|
||||||
|
|
||||||
|
Commands dealing with declaring/binding/unbinding/deleting exchanges and queues are
|
||||||
|
all done with the above AmqpClient::Channel object. If one of these commands
|
||||||
|
fails to complete a AmqpClient::ChannelException will be thrown, which can be caught
|
||||||
|
and the AmqpClient::Channel object is still useable. If a more severe error occurs
|
||||||
|
a AmqpClient::ConnectionException or AmqpClient::AmqpResponseLibraryException maybe
|
||||||
|
thrown, in which case the Channel object is no longer in a usable state and further
|
||||||
|
use will only generate more exceptions.
|
||||||
|
|
||||||
|
Consuming messages is done by setting up a consumer using the BasicConsume method.
|
||||||
|
This method returns a consumer tag that should be used with the BasicConsumeMessage
|
||||||
|
BasicQos, BasicRecover, and BasicCancel.
|
||||||
|
|
||||||
|
std::string consumer_tag = channel->BasicConsume("my_queue", "");
|
||||||
|
Envelope::ptr_t envelope = channel->BasicConsumeMessage(consumer_tag);
|
||||||
|
// Alternatively:
|
||||||
|
Envelope::ptr_t envelope;
|
||||||
|
channel->BasicConsumeMessage(consumer_tag, envelope, 10); // 10 ms timeout
|
||||||
|
// To ack:
|
||||||
|
channel->BasicAck(envelope);
|
||||||
|
// To cancel:
|
||||||
|
channel->BasicCancel(consumer_tag);
|
||||||
|
|
||||||
12
libSimpleAmqpClient.pc.in
Normal file
12
libSimpleAmqpClient.pc.in
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
prefix=@prefix@
|
||||||
|
exec_prefix=@exec_prefix@
|
||||||
|
libdir=@libdir@
|
||||||
|
includedir=@includedir@
|
||||||
|
|
||||||
|
Name: SimpleAmqpClient
|
||||||
|
Description: C++ wrapper of rabbitmq-c AMQP client library
|
||||||
|
Version: @SAC_APIVERSION@
|
||||||
|
Requires.private: librabbitmq
|
||||||
|
Libs: -L${libdir} -l@SIMPLEAMQPCLIENT_LIB@ @libs_public@
|
||||||
|
Libs.private: @libs_private@
|
||||||
|
CFlags: -I${includedir} -I"@Boost_INCLUDE_DIRS@" @SIMPLEAMQPCLIENT_DEFINITIONS@
|
||||||
201
src/AmqpException.cpp
Normal file
201
src/AmqpException.cpp
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SimpleAmqpClient/AmqpException.h"
|
||||||
|
|
||||||
|
#include <amqp.h>
|
||||||
|
#include <amqp_framing.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
|
namespace AmqpClient {
|
||||||
|
|
||||||
|
const boost::uint16_t ContentTooLargeException::REPLY_CODE =
|
||||||
|
AMQP_CONTENT_TOO_LARGE;
|
||||||
|
const boost::uint16_t NoRouteException::REPLY_CODE = AMQP_NO_ROUTE;
|
||||||
|
const boost::uint16_t NoConsumersException::REPLY_CODE = AMQP_NO_CONSUMERS;
|
||||||
|
const boost::uint16_t AccessRefusedException::REPLY_CODE = AMQP_ACCESS_REFUSED;
|
||||||
|
const boost::uint16_t NotFoundException::REPLY_CODE = AMQP_NOT_FOUND;
|
||||||
|
const boost::uint16_t ResourceLockedException::REPLY_CODE =
|
||||||
|
AMQP_RESOURCE_LOCKED;
|
||||||
|
const boost::uint16_t PreconditionFailedException::REPLY_CODE =
|
||||||
|
AMQP_PRECONDITION_FAILED;
|
||||||
|
const boost::uint16_t ConnectionForcedException::REPLY_CODE =
|
||||||
|
AMQP_CONNECTION_FORCED;
|
||||||
|
const boost::uint16_t InvalidPathException::REPLY_CODE = AMQP_INVALID_PATH;
|
||||||
|
const boost::uint16_t FrameErrorException::REPLY_CODE = AMQP_FRAME_ERROR;
|
||||||
|
const boost::uint16_t SyntaxErrorException::REPLY_CODE = AMQP_SYNTAX_ERROR;
|
||||||
|
const boost::uint16_t CommandInvalidException::REPLY_CODE =
|
||||||
|
AMQP_COMMAND_INVALID;
|
||||||
|
const boost::uint16_t ChannelErrorException::REPLY_CODE = AMQP_CHANNEL_ERROR;
|
||||||
|
const boost::uint16_t UnexpectedFrameException::REPLY_CODE =
|
||||||
|
AMQP_UNEXPECTED_FRAME;
|
||||||
|
const boost::uint16_t ResourceErrorException::REPLY_CODE = AMQP_RESOURCE_ERROR;
|
||||||
|
const boost::uint16_t NotAllowedException::REPLY_CODE = AMQP_NOT_ALLOWED;
|
||||||
|
const boost::uint16_t NotImplementedException::REPLY_CODE =
|
||||||
|
AMQP_NOT_IMPLEMENTED;
|
||||||
|
const boost::uint16_t InternalErrorException::REPLY_CODE = AMQP_INTERNAL_ERROR;
|
||||||
|
|
||||||
|
void AmqpException::Throw(const amqp_rpc_reply_t &reply) {
|
||||||
|
assert(reply.reply_type == AMQP_RESPONSE_SERVER_EXCEPTION);
|
||||||
|
|
||||||
|
switch (reply.reply.id) {
|
||||||
|
case AMQP_CONNECTION_CLOSE_METHOD:
|
||||||
|
Throw(
|
||||||
|
*(reinterpret_cast<amqp_connection_close_t *>(reply.reply.decoded)));
|
||||||
|
break;
|
||||||
|
case AMQP_CHANNEL_CLOSE_METHOD:
|
||||||
|
Throw(*(reinterpret_cast<amqp_channel_close_t *>(reply.reply.decoded)));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw std::logic_error(
|
||||||
|
std::string(
|
||||||
|
"Programming error: unknown server exception class/method")
|
||||||
|
.append(boost::lexical_cast<std::string>(reply.reply.id)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmqpException::Throw(const amqp_channel_close_t &reply) {
|
||||||
|
std::ostringstream what;
|
||||||
|
|
||||||
|
std::string reply_text;
|
||||||
|
if (reply.reply_text.bytes != NULL) {
|
||||||
|
reply_text =
|
||||||
|
std::string((char *)reply.reply_text.bytes, reply.reply_text.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *method_name =
|
||||||
|
amqp_method_name(((reply.class_id << 16) | reply.method_id));
|
||||||
|
if (method_name != NULL) {
|
||||||
|
what << "channel error: " << reply.reply_code << ": " << method_name
|
||||||
|
<< " caused: " << reply_text;
|
||||||
|
} else {
|
||||||
|
what << "channel error: " << reply.reply_code << ": " << reply_text;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (reply.reply_code) {
|
||||||
|
case ContentTooLargeException::REPLY_CODE:
|
||||||
|
throw ContentTooLargeException(what.str(), reply_text, reply.class_id,
|
||||||
|
reply.method_id);
|
||||||
|
case NoRouteException::REPLY_CODE:
|
||||||
|
throw NoRouteException(what.str(), reply_text, reply.class_id,
|
||||||
|
reply.method_id);
|
||||||
|
case NoConsumersException::REPLY_CODE:
|
||||||
|
throw NoConsumersException(what.str(), reply_text, reply.class_id,
|
||||||
|
reply.method_id);
|
||||||
|
case AccessRefusedException::REPLY_CODE:
|
||||||
|
throw AccessRefusedException(what.str(), reply_text, reply.class_id,
|
||||||
|
reply.method_id);
|
||||||
|
case NotFoundException::REPLY_CODE:
|
||||||
|
throw NotFoundException(what.str(), reply_text, reply.class_id,
|
||||||
|
reply.method_id);
|
||||||
|
case ResourceLockedException::REPLY_CODE:
|
||||||
|
throw ResourceLockedException(what.str(), reply_text, reply.class_id,
|
||||||
|
reply.method_id);
|
||||||
|
case PreconditionFailedException::REPLY_CODE:
|
||||||
|
throw PreconditionFailedException(what.str(), reply_text, reply.class_id,
|
||||||
|
reply.method_id);
|
||||||
|
default:
|
||||||
|
throw std::logic_error(
|
||||||
|
std::string("Programming error: unknown channel reply code: ")
|
||||||
|
.append(boost::lexical_cast<std::string>(reply.reply_code)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmqpException::Throw(const amqp_connection_close_t &reply) {
|
||||||
|
std::ostringstream what;
|
||||||
|
const char *method_name =
|
||||||
|
amqp_method_name(((reply.class_id << 16) | reply.method_id));
|
||||||
|
|
||||||
|
std::string reply_text;
|
||||||
|
if (reply.reply_text.bytes != NULL) {
|
||||||
|
reply_text =
|
||||||
|
std::string((char *)reply.reply_text.bytes, reply.reply_text.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (method_name != NULL) {
|
||||||
|
what << "connection error: " << reply.reply_code << ": " << method_name
|
||||||
|
<< " caused: " << reply_text;
|
||||||
|
} else {
|
||||||
|
what << "connection error: " << reply.reply_code << ": " << reply_text;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (reply.reply_code) {
|
||||||
|
case ConnectionForcedException::REPLY_CODE:
|
||||||
|
throw ConnectionForcedException(what.str(), reply_text, reply.class_id,
|
||||||
|
reply.method_id);
|
||||||
|
case InvalidPathException::REPLY_CODE:
|
||||||
|
throw InvalidPathException(what.str(), reply_text, reply.class_id,
|
||||||
|
reply.method_id);
|
||||||
|
case FrameErrorException::REPLY_CODE:
|
||||||
|
throw FrameErrorException(what.str(), reply_text, reply.class_id,
|
||||||
|
reply.method_id);
|
||||||
|
case SyntaxErrorException::REPLY_CODE:
|
||||||
|
throw SyntaxErrorException(what.str(), reply_text, reply.class_id,
|
||||||
|
reply.method_id);
|
||||||
|
case CommandInvalidException::REPLY_CODE:
|
||||||
|
throw CommandInvalidException(what.str(), reply_text, reply.class_id,
|
||||||
|
reply.method_id);
|
||||||
|
case ChannelErrorException::REPLY_CODE:
|
||||||
|
throw ChannelErrorException(what.str(), reply_text, reply.class_id,
|
||||||
|
reply.method_id);
|
||||||
|
case UnexpectedFrameException::REPLY_CODE:
|
||||||
|
throw UnexpectedFrameException(what.str(), reply_text, reply.class_id,
|
||||||
|
reply.method_id);
|
||||||
|
case ResourceErrorException::REPLY_CODE:
|
||||||
|
throw ResourceErrorException(what.str(), reply_text, reply.class_id,
|
||||||
|
reply.method_id);
|
||||||
|
case NotAllowedException::REPLY_CODE:
|
||||||
|
throw NotAllowedException(what.str(), reply_text, reply.class_id,
|
||||||
|
reply.method_id);
|
||||||
|
case NotImplementedException::REPLY_CODE:
|
||||||
|
throw NotImplementedException(what.str(), reply_text, reply.class_id,
|
||||||
|
reply.method_id);
|
||||||
|
case InternalErrorException::REPLY_CODE:
|
||||||
|
throw InternalErrorException(what.str(), reply_text, reply.class_id,
|
||||||
|
reply.method_id);
|
||||||
|
case AccessRefusedException::REPLY_CODE:
|
||||||
|
throw AccessRefusedException(what.str(), reply_text, reply.class_id,
|
||||||
|
reply.method_id);
|
||||||
|
default:
|
||||||
|
throw std::logic_error(
|
||||||
|
std::string("Programming error: unknown connection reply code: ")
|
||||||
|
.append(boost::lexical_cast<std::string>(reply.reply_code)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AmqpException::AmqpException(const std::string &what,
|
||||||
|
const std::string &reply_text,
|
||||||
|
boost::uint16_t class_id,
|
||||||
|
boost::uint16_t method_id) throw()
|
||||||
|
: std::runtime_error(what),
|
||||||
|
m_reply_text(reply_text),
|
||||||
|
m_class_id(class_id),
|
||||||
|
m_method_id(method_id) {}
|
||||||
|
} // namespace AmqpClient
|
||||||
56
src/AmqpLibraryException.cpp
Normal file
56
src/AmqpLibraryException.cpp
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Put these first to avoid warnings about INT#_C macro redefinition
|
||||||
|
#include "SimpleAmqpClient/AmqpLibraryException.h"
|
||||||
|
|
||||||
|
#include <amqp.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
namespace AmqpClient {
|
||||||
|
|
||||||
|
AmqpLibraryException AmqpLibraryException::CreateException(int error_code) {
|
||||||
|
std::string message(amqp_error_string2(error_code));
|
||||||
|
|
||||||
|
return AmqpLibraryException(message, error_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
AmqpLibraryException AmqpLibraryException::CreateException(
|
||||||
|
int error_code, const std::string &context) {
|
||||||
|
std::string message(context);
|
||||||
|
message.append(": ");
|
||||||
|
message.append(amqp_error_string2(error_code));
|
||||||
|
|
||||||
|
return AmqpLibraryException(message, error_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
AmqpLibraryException::AmqpLibraryException(const std::string &message,
|
||||||
|
int error_code) throw()
|
||||||
|
: std::runtime_error(message), m_errorCode(error_code) {}
|
||||||
|
|
||||||
|
} // namespace AmqpClient
|
||||||
50
src/AmqpResponseLibraryException.cpp
Normal file
50
src/AmqpResponseLibraryException.cpp
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Put these first to avoid warnings about INT#_C macro redefinition
|
||||||
|
#include "SimpleAmqpClient/AmqpResponseLibraryException.h"
|
||||||
|
|
||||||
|
#include <amqp.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
namespace AmqpClient {
|
||||||
|
|
||||||
|
AmqpResponseLibraryException AmqpResponseLibraryException::CreateException(
|
||||||
|
const amqp_rpc_reply_t_ &reply, const std::string &context) {
|
||||||
|
std::string message(context);
|
||||||
|
message.append(": ");
|
||||||
|
message.append(amqp_error_string2(reply.library_error));
|
||||||
|
|
||||||
|
return AmqpResponseLibraryException(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
AmqpResponseLibraryException::AmqpResponseLibraryException(
|
||||||
|
const std::string &message) throw()
|
||||||
|
: std::runtime_error(message) {}
|
||||||
|
|
||||||
|
} // namespace AmqpClient
|
||||||
315
src/BasicMessage.cpp
Normal file
315
src/BasicMessage.cpp
Normal file
@@ -0,0 +1,315 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Put these first to avoid warnings about INT#_C macro redefinition
|
||||||
|
#include "SimpleAmqpClient/BasicMessage.h"
|
||||||
|
|
||||||
|
#include <amqp.h>
|
||||||
|
#include <amqp_framing.h>
|
||||||
|
|
||||||
|
#include <boost/optional/optional.hpp>
|
||||||
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "SimpleAmqpClient/TableImpl.h"
|
||||||
|
|
||||||
|
namespace AmqpClient {
|
||||||
|
|
||||||
|
struct BasicMessage::Impl {
|
||||||
|
std::string body;
|
||||||
|
boost::optional<std::string> content_type;
|
||||||
|
boost::optional<std::string> content_encoding;
|
||||||
|
boost::optional<delivery_mode_t> delivery_mode;
|
||||||
|
boost::optional<boost::uint8_t> priority;
|
||||||
|
boost::optional<std::string> correlation_id;
|
||||||
|
boost::optional<std::string> reply_to;
|
||||||
|
boost::optional<std::string> expiration;
|
||||||
|
boost::optional<std::string> message_id;
|
||||||
|
boost::optional<boost::uint64_t> timestamp;
|
||||||
|
boost::optional<std::string> type;
|
||||||
|
boost::optional<std::string> user_id;
|
||||||
|
boost::optional<std::string> app_id;
|
||||||
|
boost::optional<std::string> cluster_id;
|
||||||
|
boost::optional<Table> header_table;
|
||||||
|
};
|
||||||
|
|
||||||
|
BasicMessage::BasicMessage() : m_impl(new Impl) {}
|
||||||
|
|
||||||
|
BasicMessage::BasicMessage(const std::string& body) : m_impl(new Impl) {
|
||||||
|
Body(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicMessage::~BasicMessage() {}
|
||||||
|
|
||||||
|
const std::string& BasicMessage::Body() const { return m_impl->body; }
|
||||||
|
|
||||||
|
std::string& BasicMessage::Body() { return m_impl->body; }
|
||||||
|
|
||||||
|
void BasicMessage::Body(const std::string& body) { m_impl->body = body; }
|
||||||
|
|
||||||
|
const std::string& BasicMessage::ContentType() const {
|
||||||
|
if (ContentTypeIsSet()) {
|
||||||
|
return m_impl->content_type.get();
|
||||||
|
}
|
||||||
|
static const std::string empty;
|
||||||
|
return empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BasicMessage::ContentType(const std::string& content_type) {
|
||||||
|
m_impl->content_type = content_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BasicMessage::ContentTypeIsSet() const {
|
||||||
|
return m_impl->content_type.is_initialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BasicMessage::ContentTypeClear() { m_impl->content_type.reset(); }
|
||||||
|
|
||||||
|
const std::string& BasicMessage::ContentEncoding() const {
|
||||||
|
if (ContentEncodingIsSet()) {
|
||||||
|
return m_impl->content_encoding.get();
|
||||||
|
}
|
||||||
|
static const std::string empty;
|
||||||
|
return empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BasicMessage::ContentEncoding(const std::string& content_encoding) {
|
||||||
|
m_impl->content_encoding = content_encoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BasicMessage::ContentEncodingIsSet() const {
|
||||||
|
return m_impl->content_encoding.is_initialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BasicMessage::ContentEncodingClear() { m_impl->content_encoding.reset(); }
|
||||||
|
|
||||||
|
BasicMessage::delivery_mode_t BasicMessage::DeliveryMode() const {
|
||||||
|
return m_impl->delivery_mode.value_or(dm_notset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BasicMessage::DeliveryMode(delivery_mode_t delivery_mode) {
|
||||||
|
m_impl->delivery_mode = delivery_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BasicMessage::DeliveryModeIsSet() const {
|
||||||
|
return m_impl->delivery_mode.is_initialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BasicMessage::DeliveryModeClear() { m_impl->delivery_mode.reset(); }
|
||||||
|
|
||||||
|
boost::uint8_t BasicMessage::Priority() const {
|
||||||
|
return m_impl->priority.value_or(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BasicMessage::Priority(boost::uint8_t priority) {
|
||||||
|
m_impl->priority = priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BasicMessage::PriorityIsSet() const {
|
||||||
|
return m_impl->priority.is_initialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BasicMessage::PriorityClear() { m_impl->priority.reset(); }
|
||||||
|
|
||||||
|
const std::string& BasicMessage::CorrelationId() const {
|
||||||
|
if (CorrelationIdIsSet()) {
|
||||||
|
return m_impl->correlation_id.get();
|
||||||
|
}
|
||||||
|
static const std::string empty;
|
||||||
|
return empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BasicMessage::CorrelationId(const std::string& correlation_id) {
|
||||||
|
m_impl->correlation_id = correlation_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BasicMessage::CorrelationIdIsSet() const {
|
||||||
|
return m_impl->correlation_id.is_initialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BasicMessage::CorrelationIdClear() { m_impl->correlation_id.reset(); }
|
||||||
|
|
||||||
|
const std::string& BasicMessage::ReplyTo() const {
|
||||||
|
if (ReplyToIsSet()) {
|
||||||
|
return m_impl->reply_to.get();
|
||||||
|
}
|
||||||
|
static const std::string empty;
|
||||||
|
return empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BasicMessage::ReplyTo(const std::string& reply_to) {
|
||||||
|
m_impl->reply_to = reply_to;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BasicMessage::ReplyToIsSet() const {
|
||||||
|
return m_impl->reply_to.is_initialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BasicMessage::ReplyToClear() { m_impl->reply_to.reset(); }
|
||||||
|
|
||||||
|
const std::string& BasicMessage::Expiration() const {
|
||||||
|
if (ExpirationIsSet()) {
|
||||||
|
return m_impl->expiration.get();
|
||||||
|
}
|
||||||
|
static const std::string empty;
|
||||||
|
return empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BasicMessage::Expiration(const std::string& expiration) {
|
||||||
|
m_impl->expiration = expiration;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BasicMessage::ExpirationIsSet() const {
|
||||||
|
return m_impl->expiration.is_initialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BasicMessage::ExpirationClear() { m_impl->expiration.reset(); }
|
||||||
|
|
||||||
|
const std::string& BasicMessage::MessageId() const {
|
||||||
|
if (MessageIdIsSet()) {
|
||||||
|
return m_impl->message_id.get();
|
||||||
|
}
|
||||||
|
static const std::string empty;
|
||||||
|
return empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BasicMessage::MessageId(const std::string& message_id) {
|
||||||
|
m_impl->message_id = message_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BasicMessage::MessageIdIsSet() const {
|
||||||
|
return m_impl->message_id.is_initialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BasicMessage::MessageIdClear() { m_impl->message_id.reset(); }
|
||||||
|
|
||||||
|
boost::uint64_t BasicMessage::Timestamp() const {
|
||||||
|
return m_impl->timestamp.value_or(0);
|
||||||
|
}
|
||||||
|
void BasicMessage::Timestamp(boost::uint64_t timestamp) {
|
||||||
|
m_impl->timestamp = timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BasicMessage::TimestampIsSet() const {
|
||||||
|
return m_impl->timestamp.is_initialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BasicMessage::TimestampClear() { m_impl->timestamp.reset(); }
|
||||||
|
|
||||||
|
const std::string& BasicMessage::Type() const {
|
||||||
|
if (TypeIsSet()) {
|
||||||
|
return m_impl->type.get();
|
||||||
|
}
|
||||||
|
static const std::string empty;
|
||||||
|
return empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BasicMessage::Type(const std::string& type) { m_impl->type = type; }
|
||||||
|
|
||||||
|
bool BasicMessage::TypeIsSet() const { return m_impl->type.is_initialized(); }
|
||||||
|
|
||||||
|
void BasicMessage::TypeClear() { m_impl->type.reset(); }
|
||||||
|
|
||||||
|
const std::string& BasicMessage::UserId() const {
|
||||||
|
if (UserIdIsSet()) {
|
||||||
|
return m_impl->user_id.get();
|
||||||
|
}
|
||||||
|
static const std::string empty;
|
||||||
|
return empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BasicMessage::UserId(const std::string& user_id) {
|
||||||
|
m_impl->user_id = user_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BasicMessage::UserIdIsSet() const {
|
||||||
|
return m_impl->user_id.is_initialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BasicMessage::UserIdClear() { m_impl->user_id.reset(); }
|
||||||
|
|
||||||
|
const std::string& BasicMessage::AppId() const {
|
||||||
|
if (AppIdIsSet()) {
|
||||||
|
return m_impl->app_id.get();
|
||||||
|
}
|
||||||
|
static const std::string empty;
|
||||||
|
return empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BasicMessage::AppId(const std::string& app_id) { m_impl->app_id = app_id; }
|
||||||
|
|
||||||
|
bool BasicMessage::AppIdIsSet() const {
|
||||||
|
return m_impl->app_id.is_initialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BasicMessage::AppIdClear() { m_impl->app_id.reset(); }
|
||||||
|
|
||||||
|
const std::string& BasicMessage::ClusterId() const {
|
||||||
|
if (ClusterIdIsSet()) {
|
||||||
|
return m_impl->cluster_id.get();
|
||||||
|
}
|
||||||
|
static const std::string empty;
|
||||||
|
return empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BasicMessage::ClusterId(const std::string& cluster_id) {
|
||||||
|
m_impl->cluster_id = cluster_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BasicMessage::ClusterIdIsSet() const {
|
||||||
|
return m_impl->cluster_id.is_initialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BasicMessage::ClusterIdClear() { m_impl->cluster_id.reset(); }
|
||||||
|
|
||||||
|
Table& BasicMessage::HeaderTable() {
|
||||||
|
if (!HeaderTableIsSet()) {
|
||||||
|
m_impl->header_table = Table();
|
||||||
|
}
|
||||||
|
return m_impl->header_table.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
const Table& BasicMessage::HeaderTable() const {
|
||||||
|
if (HeaderTableIsSet()) {
|
||||||
|
return m_impl->header_table.get();
|
||||||
|
}
|
||||||
|
static const Table empty;
|
||||||
|
return empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BasicMessage::HeaderTable(const Table& header_table) {
|
||||||
|
m_impl->header_table = header_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BasicMessage::HeaderTableIsSet() const {
|
||||||
|
return m_impl->header_table.is_initialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BasicMessage::HeaderTableClear() { m_impl->header_table.reset(); }
|
||||||
|
|
||||||
|
} // namespace AmqpClient
|
||||||
1086
src/Channel.cpp
Normal file
1086
src/Channel.cpp
Normal file
File diff suppressed because it is too large
Load Diff
571
src/ChannelImpl.cpp
Normal file
571
src/ChannelImpl.cpp
Normal file
@@ -0,0 +1,571 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define NOMINMAX
|
||||||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#endif
|
||||||
|
#include <Winsock2.h>
|
||||||
|
#else
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/algorithm/string/classification.hpp>
|
||||||
|
#include <boost/algorithm/string/split.hpp>
|
||||||
|
#include <boost/array.hpp>
|
||||||
|
|
||||||
|
#include "SimpleAmqpClient/AmqpException.h"
|
||||||
|
#include "SimpleAmqpClient/AmqpLibraryException.h"
|
||||||
|
#include "SimpleAmqpClient/AmqpResponseLibraryException.h"
|
||||||
|
#include "SimpleAmqpClient/ChannelImpl.h"
|
||||||
|
#include "SimpleAmqpClient/ConnectionClosedException.h"
|
||||||
|
#include "SimpleAmqpClient/ConsumerTagNotFoundException.h"
|
||||||
|
#include "SimpleAmqpClient/TableImpl.h"
|
||||||
|
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
|
#define BROKER_HEARTBEAT 0
|
||||||
|
|
||||||
|
namespace AmqpClient {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
std::string BytesToString(amqp_bytes_t bytes) {
|
||||||
|
return std::string(reinterpret_cast<char *>(bytes.bytes), bytes.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetMessageProperties(BasicMessage &mes,
|
||||||
|
const amqp_basic_properties_t &props) {
|
||||||
|
if (0 != (props._flags & AMQP_BASIC_CONTENT_TYPE_FLAG)) {
|
||||||
|
mes.ContentType(BytesToString(props.content_type));
|
||||||
|
}
|
||||||
|
if (0 != (props._flags & AMQP_BASIC_CONTENT_ENCODING_FLAG)) {
|
||||||
|
mes.ContentEncoding(BytesToString(props.content_encoding));
|
||||||
|
}
|
||||||
|
if (0 != (props._flags & AMQP_BASIC_DELIVERY_MODE_FLAG)) {
|
||||||
|
mes.DeliveryMode(
|
||||||
|
static_cast<BasicMessage::delivery_mode_t>(props.delivery_mode));
|
||||||
|
}
|
||||||
|
if (0 != (props._flags & AMQP_BASIC_PRIORITY_FLAG)) {
|
||||||
|
mes.Priority(props.priority);
|
||||||
|
}
|
||||||
|
if (0 != (props._flags & AMQP_BASIC_CORRELATION_ID_FLAG)) {
|
||||||
|
mes.CorrelationId(BytesToString(props.correlation_id));
|
||||||
|
}
|
||||||
|
if (0 != (props._flags & AMQP_BASIC_REPLY_TO_FLAG)) {
|
||||||
|
mes.ReplyTo(BytesToString(props.reply_to));
|
||||||
|
}
|
||||||
|
if (0 != (props._flags & AMQP_BASIC_EXPIRATION_FLAG)) {
|
||||||
|
mes.Expiration(BytesToString(props.expiration));
|
||||||
|
}
|
||||||
|
if (0 != (props._flags & AMQP_BASIC_MESSAGE_ID_FLAG)) {
|
||||||
|
mes.MessageId(BytesToString(props.message_id));
|
||||||
|
}
|
||||||
|
if (0 != (props._flags & AMQP_BASIC_TIMESTAMP_FLAG)) {
|
||||||
|
mes.Timestamp(props.timestamp);
|
||||||
|
}
|
||||||
|
if (0 != (props._flags & AMQP_BASIC_TYPE_FLAG)) {
|
||||||
|
mes.Type(BytesToString(props.type));
|
||||||
|
}
|
||||||
|
if (0 != (props._flags & AMQP_BASIC_USER_ID_FLAG)) {
|
||||||
|
mes.UserId(BytesToString(props.user_id));
|
||||||
|
}
|
||||||
|
if (0 != (props._flags & AMQP_BASIC_APP_ID_FLAG)) {
|
||||||
|
mes.AppId(BytesToString(props.app_id));
|
||||||
|
}
|
||||||
|
if (0 != (props._flags & AMQP_BASIC_CLUSTER_ID_FLAG)) {
|
||||||
|
mes.ClusterId(BytesToString(props.cluster_id));
|
||||||
|
}
|
||||||
|
if (0 != (props._flags & AMQP_BASIC_HEADERS_FLAG)) {
|
||||||
|
mes.HeaderTable(Detail::TableValueImpl::CreateTable(props.headers));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
Channel::ChannelImpl::ChannelImpl()
|
||||||
|
: m_last_used_channel(0), m_is_connected(false) {
|
||||||
|
m_channels.push_back(CS_Used);
|
||||||
|
}
|
||||||
|
|
||||||
|
Channel::ChannelImpl::~ChannelImpl() {}
|
||||||
|
|
||||||
|
void Channel::ChannelImpl::DoLogin(const std::string &username,
|
||||||
|
const std::string &password,
|
||||||
|
const std::string &vhost, int frame_max,
|
||||||
|
bool sasl_external) {
|
||||||
|
amqp_table_entry_t capabilties[1];
|
||||||
|
amqp_table_entry_t capability_entry;
|
||||||
|
amqp_table_t client_properties;
|
||||||
|
|
||||||
|
capabilties[0].key = amqp_cstring_bytes("consumer_cancel_notify");
|
||||||
|
capabilties[0].value.kind = AMQP_FIELD_KIND_BOOLEAN;
|
||||||
|
capabilties[0].value.value.boolean = 1;
|
||||||
|
|
||||||
|
capability_entry.key = amqp_cstring_bytes("capabilities");
|
||||||
|
capability_entry.value.kind = AMQP_FIELD_KIND_TABLE;
|
||||||
|
capability_entry.value.value.table.num_entries =
|
||||||
|
sizeof(capabilties) / sizeof(amqp_table_entry_t);
|
||||||
|
capability_entry.value.value.table.entries = capabilties;
|
||||||
|
|
||||||
|
client_properties.num_entries = 1;
|
||||||
|
client_properties.entries = &capability_entry;
|
||||||
|
|
||||||
|
if (sasl_external) {
|
||||||
|
CheckRpcReply(0, amqp_login_with_properties(
|
||||||
|
m_connection, vhost.c_str(), 0, frame_max,
|
||||||
|
BROKER_HEARTBEAT, &client_properties,
|
||||||
|
AMQP_SASL_METHOD_EXTERNAL, username.c_str()));
|
||||||
|
} else {
|
||||||
|
CheckRpcReply(
|
||||||
|
0, amqp_login_with_properties(m_connection, vhost.c_str(), 0, frame_max,
|
||||||
|
BROKER_HEARTBEAT, &client_properties,
|
||||||
|
AMQP_SASL_METHOD_PLAIN, username.c_str(),
|
||||||
|
password.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_brokerVersion = ComputeBrokerVersion(m_connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_channel_t Channel::ChannelImpl::GetNextChannelId() {
|
||||||
|
channel_state_list_t::iterator unused_channel =
|
||||||
|
std::find(m_channels.begin(), m_channels.end(), CS_Closed);
|
||||||
|
|
||||||
|
if (m_channels.end() == unused_channel) {
|
||||||
|
int max_channels = amqp_get_channel_max(m_connection);
|
||||||
|
if (0 == max_channels) {
|
||||||
|
max_channels = std::numeric_limits<uint16_t>::max();
|
||||||
|
}
|
||||||
|
if (static_cast<size_t>(max_channels) < m_channels.size()) {
|
||||||
|
throw std::runtime_error("Too many channels open");
|
||||||
|
}
|
||||||
|
|
||||||
|
m_channels.push_back(CS_Closed);
|
||||||
|
unused_channel = m_channels.end() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return unused_channel - m_channels.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_channel_t Channel::ChannelImpl::CreateNewChannel() {
|
||||||
|
amqp_channel_t new_channel = GetNextChannelId();
|
||||||
|
|
||||||
|
static const boost::array<boost::uint32_t, 1> OPEN_OK = {
|
||||||
|
{AMQP_CHANNEL_OPEN_OK_METHOD}};
|
||||||
|
amqp_channel_open_t channel_open = {};
|
||||||
|
DoRpcOnChannel<boost::array<boost::uint32_t, 1> >(
|
||||||
|
new_channel, AMQP_CHANNEL_OPEN_METHOD, &channel_open, OPEN_OK);
|
||||||
|
|
||||||
|
static const boost::array<boost::uint32_t, 1> CONFIRM_OK = {
|
||||||
|
{AMQP_CONFIRM_SELECT_OK_METHOD}};
|
||||||
|
amqp_confirm_select_t confirm_select = {};
|
||||||
|
DoRpcOnChannel<boost::array<boost::uint32_t, 1> >(
|
||||||
|
new_channel, AMQP_CONFIRM_SELECT_METHOD, &confirm_select, CONFIRM_OK);
|
||||||
|
|
||||||
|
m_channels.at(new_channel) = CS_Open;
|
||||||
|
|
||||||
|
return new_channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_channel_t Channel::ChannelImpl::GetChannel() {
|
||||||
|
if (CS_Open == m_channels.at(m_last_used_channel)) {
|
||||||
|
m_channels[m_last_used_channel] = CS_Used;
|
||||||
|
return m_last_used_channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
channel_state_list_t::iterator it =
|
||||||
|
std::find(m_channels.begin(), m_channels.end(), CS_Open);
|
||||||
|
|
||||||
|
if (m_channels.end() == it) {
|
||||||
|
amqp_channel_t new_channel = CreateNewChannel();
|
||||||
|
m_channels.at(new_channel) = CS_Used;
|
||||||
|
return new_channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
*it = CS_Used;
|
||||||
|
return it - m_channels.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Channel::ChannelImpl::ReturnChannel(amqp_channel_t channel) {
|
||||||
|
m_channels.at(channel) = CS_Open;
|
||||||
|
m_last_used_channel = channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Channel::ChannelImpl::IsChannelOpen(amqp_channel_t channel) {
|
||||||
|
return CS_Closed != m_channels.at(channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Channel::ChannelImpl::FinishCloseChannel(amqp_channel_t channel) {
|
||||||
|
m_channels.at(channel) = CS_Closed;
|
||||||
|
|
||||||
|
amqp_channel_close_ok_t close_ok;
|
||||||
|
CheckForError(amqp_send_method(m_connection, channel,
|
||||||
|
AMQP_CHANNEL_CLOSE_OK_METHOD, &close_ok));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Channel::ChannelImpl::FinishCloseConnection() {
|
||||||
|
SetIsConnected(false);
|
||||||
|
amqp_connection_close_ok_t close_ok;
|
||||||
|
amqp_send_method(m_connection, 0, AMQP_CONNECTION_CLOSE_OK_METHOD, &close_ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Channel::ChannelImpl::CheckRpcReply(amqp_channel_t channel,
|
||||||
|
const amqp_rpc_reply_t &reply) {
|
||||||
|
switch (reply.reply_type) {
|
||||||
|
case AMQP_RESPONSE_NORMAL:
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AMQP_RESPONSE_LIBRARY_EXCEPTION:
|
||||||
|
// If we're getting this likely is the socket is already closed
|
||||||
|
throw AmqpResponseLibraryException::CreateException(reply, "");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AMQP_RESPONSE_SERVER_EXCEPTION:
|
||||||
|
if (reply.reply.id == AMQP_CHANNEL_CLOSE_METHOD) {
|
||||||
|
FinishCloseChannel(channel);
|
||||||
|
} else if (reply.reply.id == AMQP_CONNECTION_CLOSE_METHOD) {
|
||||||
|
FinishCloseConnection();
|
||||||
|
}
|
||||||
|
AmqpException::Throw(reply);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
AmqpException::Throw(reply);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Channel::ChannelImpl::CheckForError(int ret) {
|
||||||
|
if (ret < 0) {
|
||||||
|
throw AmqpLibraryException::CreateException(ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageReturnedException Channel::ChannelImpl::CreateMessageReturnedException(
|
||||||
|
amqp_basic_return_t &return_method, amqp_channel_t channel) {
|
||||||
|
const int reply_code = return_method.reply_code;
|
||||||
|
const std::string reply_text((char *)return_method.reply_text.bytes,
|
||||||
|
return_method.reply_text.len);
|
||||||
|
const std::string exchange((char *)return_method.exchange.bytes,
|
||||||
|
return_method.exchange.len);
|
||||||
|
const std::string routing_key((char *)return_method.routing_key.bytes,
|
||||||
|
return_method.routing_key.len);
|
||||||
|
BasicMessage::ptr_t content = ReadContent(channel);
|
||||||
|
return MessageReturnedException(content, reply_code, reply_text, exchange,
|
||||||
|
routing_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicMessage::ptr_t Channel::ChannelImpl::ReadContent(amqp_channel_t channel) {
|
||||||
|
amqp_frame_t frame;
|
||||||
|
|
||||||
|
GetNextFrameOnChannel(channel, frame);
|
||||||
|
|
||||||
|
if (frame.frame_type != AMQP_FRAME_HEADER) {
|
||||||
|
// TODO: We should connection.close here
|
||||||
|
throw std::runtime_error(
|
||||||
|
"Channel::BasicConsumeMessage: received unexpected frame type (was "
|
||||||
|
"expected AMQP_FRAME_HEADER)");
|
||||||
|
}
|
||||||
|
|
||||||
|
// The memory for this is allocated in a pool associated with the connection
|
||||||
|
// The BasicMessage constructor does a deep copy of the properties structure
|
||||||
|
amqp_basic_properties_t *properties =
|
||||||
|
reinterpret_cast<amqp_basic_properties_t *>(
|
||||||
|
frame.payload.properties.decoded);
|
||||||
|
|
||||||
|
// size_t could possibly be 32-bit, body_size is always 64-bit
|
||||||
|
assert(frame.payload.properties.body_size <
|
||||||
|
static_cast<uint64_t>(std::numeric_limits<size_t>::max()));
|
||||||
|
|
||||||
|
size_t body_size = static_cast<size_t>(frame.payload.properties.body_size);
|
||||||
|
size_t received_size = 0;
|
||||||
|
|
||||||
|
BasicMessage::ptr_t message = BasicMessage::Create();
|
||||||
|
message->Body().reserve(body_size);
|
||||||
|
|
||||||
|
// frame #3 and up:
|
||||||
|
while (received_size < body_size) {
|
||||||
|
GetNextFrameOnChannel(channel, frame);
|
||||||
|
|
||||||
|
if (frame.frame_type != AMQP_FRAME_BODY)
|
||||||
|
// TODO: we should connection.close here
|
||||||
|
throw std::runtime_error(
|
||||||
|
"Channel::BasicConsumeMessage: received unexpected frame type (was "
|
||||||
|
"expecting AMQP_FRAME_BODY)");
|
||||||
|
|
||||||
|
message->Body().append(
|
||||||
|
reinterpret_cast<char *>(frame.payload.body_fragment.bytes),
|
||||||
|
frame.payload.body_fragment.len);
|
||||||
|
received_size += frame.payload.body_fragment.len;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetMessageProperties(*message, *properties);
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Channel::ChannelImpl::CheckFrameForClose(amqp_frame_t &frame,
|
||||||
|
amqp_channel_t channel) {
|
||||||
|
if (frame.frame_type == AMQP_FRAME_METHOD) {
|
||||||
|
switch (frame.payload.method.id) {
|
||||||
|
case AMQP_CHANNEL_CLOSE_METHOD:
|
||||||
|
FinishCloseChannel(channel);
|
||||||
|
AmqpException::Throw(*reinterpret_cast<amqp_channel_close_t *>(
|
||||||
|
frame.payload.method.decoded));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AMQP_CONNECTION_CLOSE_METHOD:
|
||||||
|
FinishCloseConnection();
|
||||||
|
AmqpException::Throw(*reinterpret_cast<amqp_connection_close_t *>(
|
||||||
|
frame.payload.method.decoded));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Channel::ChannelImpl::AddConsumer(const std::string &consumer_tag,
|
||||||
|
amqp_channel_t channel) {
|
||||||
|
m_consumer_channel_map.insert(std::make_pair(consumer_tag, channel));
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_channel_t Channel::ChannelImpl::RemoveConsumer(
|
||||||
|
const std::string &consumer_tag) {
|
||||||
|
std::map<std::string, amqp_channel_t>::iterator it =
|
||||||
|
m_consumer_channel_map.find(consumer_tag);
|
||||||
|
if (it == m_consumer_channel_map.end()) {
|
||||||
|
throw ConsumerTagNotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_channel_t result = it->second;
|
||||||
|
|
||||||
|
m_consumer_channel_map.erase(it);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_channel_t Channel::ChannelImpl::GetConsumerChannel(
|
||||||
|
const std::string &consumer_tag) {
|
||||||
|
std::map<std::string, amqp_channel_t>::const_iterator it =
|
||||||
|
m_consumer_channel_map.find(consumer_tag);
|
||||||
|
if (it == m_consumer_channel_map.end()) {
|
||||||
|
throw ConsumerTagNotFoundException();
|
||||||
|
}
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<amqp_channel_t> Channel::ChannelImpl::GetAllConsumerChannels()
|
||||||
|
const {
|
||||||
|
std::vector<amqp_channel_t> ret;
|
||||||
|
for (consumer_map_t::const_iterator it = m_consumer_channel_map.begin();
|
||||||
|
it != m_consumer_channel_map.end(); ++it) {
|
||||||
|
ret.push_back(it->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Channel::ChannelImpl::CheckForQueuedMessageOnChannel(
|
||||||
|
amqp_channel_t channel) const {
|
||||||
|
frame_queue_t::const_iterator it =
|
||||||
|
std::find_if(m_frame_queue.begin(), m_frame_queue.end(),
|
||||||
|
boost::bind(&Channel::ChannelImpl::is_method_on_channel, _1,
|
||||||
|
AMQP_BASIC_DELIVER_METHOD, channel));
|
||||||
|
|
||||||
|
if (it == m_frame_queue.end()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
it = std::find_if(
|
||||||
|
it + 1, m_frame_queue.end(),
|
||||||
|
boost::bind(&Channel::ChannelImpl::is_on_channel, _1, channel));
|
||||||
|
|
||||||
|
if (it == m_frame_queue.end()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (it->frame_type != AMQP_FRAME_HEADER) {
|
||||||
|
throw std::runtime_error("Protocol error");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t body_length = it->payload.properties.body_size;
|
||||||
|
uint64_t body_received = 0;
|
||||||
|
|
||||||
|
while (body_received < body_length) {
|
||||||
|
it = std::find_if(
|
||||||
|
it + 1, m_frame_queue.end(),
|
||||||
|
boost::bind(&Channel::ChannelImpl::is_on_channel, _1, channel));
|
||||||
|
|
||||||
|
if (it == m_frame_queue.end()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (it->frame_type != AMQP_FRAME_BODY) {
|
||||||
|
throw std::runtime_error("Protocol error");
|
||||||
|
}
|
||||||
|
body_received += it->payload.body_fragment.len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Channel::ChannelImpl::AddToFrameQueue(const amqp_frame_t &frame) {
|
||||||
|
m_frame_queue.push_back(frame);
|
||||||
|
|
||||||
|
if (CheckForQueuedMessageOnChannel(frame.channel)) {
|
||||||
|
boost::array<amqp_channel_t, 1> channel = {{frame.channel}};
|
||||||
|
Envelope::ptr_t envelope;
|
||||||
|
if (!ConsumeMessageOnChannelInner(channel, envelope, -1)) {
|
||||||
|
throw std::logic_error(
|
||||||
|
"ConsumeMessageOnChannelInner returned false unexpectedly");
|
||||||
|
}
|
||||||
|
|
||||||
|
m_delivered_messages.push_back(envelope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Channel::ChannelImpl::GetNextFrameFromBroker(
|
||||||
|
amqp_frame_t &frame, boost::chrono::microseconds timeout) {
|
||||||
|
struct timeval *tvp = NULL;
|
||||||
|
struct timeval tv_timeout;
|
||||||
|
memset(&tv_timeout, 0, sizeof(tv_timeout));
|
||||||
|
|
||||||
|
if (timeout != boost::chrono::microseconds::max()) {
|
||||||
|
// boost::chrono::seconds.count() returns boost::int_atleast64_t,
|
||||||
|
// long can be 32 or 64 bit depending on the platform/arch
|
||||||
|
// unless the timeout is something absurd cast to long will be ok, but
|
||||||
|
// lets guard against the case where someone does something silly
|
||||||
|
assert(
|
||||||
|
boost::chrono::duration_cast<boost::chrono::seconds>(timeout).count() <
|
||||||
|
static_cast<boost::chrono::seconds::rep>(
|
||||||
|
std::numeric_limits<long>::max()));
|
||||||
|
|
||||||
|
tv_timeout.tv_sec = static_cast<long>(
|
||||||
|
boost::chrono::duration_cast<boost::chrono::seconds>(timeout).count());
|
||||||
|
tv_timeout.tv_usec = static_cast<long>(
|
||||||
|
(timeout - boost::chrono::seconds(tv_timeout.tv_sec)).count());
|
||||||
|
|
||||||
|
tvp = &tv_timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = amqp_simple_wait_frame_noblock(m_connection, &frame, tvp);
|
||||||
|
|
||||||
|
if (AMQP_STATUS_TIMEOUT == ret) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
CheckForError(ret);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Channel::ChannelImpl::GetNextFrameOnChannel(
|
||||||
|
amqp_channel_t channel, amqp_frame_t &frame,
|
||||||
|
boost::chrono::microseconds timeout) {
|
||||||
|
frame_queue_t::iterator it = std::find_if(
|
||||||
|
m_frame_queue.begin(), m_frame_queue.end(),
|
||||||
|
boost::bind(&Channel::ChannelImpl::is_on_channel, _1, channel));
|
||||||
|
|
||||||
|
if (m_frame_queue.end() != it) {
|
||||||
|
frame = *it;
|
||||||
|
m_frame_queue.erase(it);
|
||||||
|
|
||||||
|
if (AMQP_FRAME_METHOD == frame.frame_type &&
|
||||||
|
AMQP_CHANNEL_CLOSE_METHOD == frame.payload.method.id) {
|
||||||
|
FinishCloseChannel(channel);
|
||||||
|
AmqpException::Throw(*reinterpret_cast<amqp_channel_close_t *>(
|
||||||
|
frame.payload.method.decoded));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::array<amqp_channel_t, 1> channels = {{channel}};
|
||||||
|
return GetNextFrameFromBrokerOnChannel(channels, frame, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Channel::ChannelImpl::MaybeReleaseBuffersOnChannel(
|
||||||
|
amqp_channel_t channel) {
|
||||||
|
if (m_frame_queue.end() ==
|
||||||
|
std::find_if(
|
||||||
|
m_frame_queue.begin(), m_frame_queue.end(),
|
||||||
|
boost::bind(&Channel::ChannelImpl::is_on_channel, _1, channel))) {
|
||||||
|
amqp_maybe_release_buffers_on_channel(m_connection, channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Channel::ChannelImpl::CheckIsConnected() {
|
||||||
|
if (!m_is_connected) {
|
||||||
|
throw ConnectionClosedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
bool bytesEqual(amqp_bytes_t r, amqp_bytes_t l) {
|
||||||
|
if (r.len == l.len) {
|
||||||
|
if (0 == memcmp(r.bytes, l.bytes, r.len)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
boost::uint32_t Channel::ChannelImpl::ComputeBrokerVersion(
|
||||||
|
amqp_connection_state_t state) {
|
||||||
|
const amqp_table_t *properties = amqp_get_server_properties(state);
|
||||||
|
const amqp_bytes_t version = amqp_cstring_bytes("version");
|
||||||
|
amqp_table_entry_t *version_entry = NULL;
|
||||||
|
|
||||||
|
for (int i = 0; i < properties->num_entries; ++i) {
|
||||||
|
if (bytesEqual(properties->entries[i].key, version)) {
|
||||||
|
version_entry = &properties->entries[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (NULL == version_entry) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string version_string(
|
||||||
|
static_cast<char *>(version_entry->value.value.bytes.bytes),
|
||||||
|
version_entry->value.value.bytes.len);
|
||||||
|
std::vector<std::string> version_components;
|
||||||
|
boost::split(version_components, version_string, boost::is_any_of("."));
|
||||||
|
if (version_components.size() != 3) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
boost::uint32_t version_major =
|
||||||
|
boost::lexical_cast<boost::uint32_t>(version_components[0]);
|
||||||
|
boost::uint32_t version_minor =
|
||||||
|
boost::lexical_cast<boost::uint32_t>(version_components[1]);
|
||||||
|
boost::uint32_t version_patch =
|
||||||
|
boost::lexical_cast<boost::uint32_t>(version_components[2]);
|
||||||
|
return (version_major & 0xFF) << 16 | (version_minor & 0xFF) << 8 |
|
||||||
|
(version_patch & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace AmqpClient
|
||||||
48
src/Envelope.cpp
Normal file
48
src/Envelope.cpp
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SimpleAmqpClient/Envelope.h"
|
||||||
|
|
||||||
|
namespace AmqpClient {
|
||||||
|
|
||||||
|
Envelope::Envelope(const BasicMessage::ptr_t message,
|
||||||
|
const std::string &consumer_tag,
|
||||||
|
const boost::uint64_t delivery_tag,
|
||||||
|
const std::string &exchange, bool redelivered,
|
||||||
|
const std::string &routing_key,
|
||||||
|
const boost::uint16_t delivery_channel)
|
||||||
|
: m_message(message),
|
||||||
|
m_consumerTag(consumer_tag),
|
||||||
|
m_deliveryTag(delivery_tag),
|
||||||
|
m_exchange(exchange),
|
||||||
|
m_redelivered(redelivered),
|
||||||
|
m_routingKey(routing_key),
|
||||||
|
m_deliveryChannel(delivery_channel) {}
|
||||||
|
|
||||||
|
Envelope::~Envelope() {}
|
||||||
|
} // namespace AmqpClient
|
||||||
49
src/MessageReturnedException.cpp
Normal file
49
src/MessageReturnedException.cpp
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SimpleAmqpClient/MessageReturnedException.h"
|
||||||
|
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
|
namespace AmqpClient {
|
||||||
|
MessageReturnedException::MessageReturnedException(
|
||||||
|
BasicMessage::ptr_t message, boost::uint32_t reply_code,
|
||||||
|
const std::string &reply_text, const std::string &exchange,
|
||||||
|
const std::string &routing_key) throw()
|
||||||
|
: std::runtime_error(
|
||||||
|
std::string("Message returned. Reply code: ")
|
||||||
|
.append(boost::lexical_cast<std::string>(reply_code))
|
||||||
|
.append(" ")
|
||||||
|
.append(reply_text)),
|
||||||
|
m_message(message),
|
||||||
|
m_reply_code(reply_code),
|
||||||
|
m_reply_text(reply_text),
|
||||||
|
m_exchange(exchange),
|
||||||
|
m_routing_key(routing_key) {}
|
||||||
|
|
||||||
|
} // namespace AmqpClient
|
||||||
572
src/SimpleAmqpClient/AmqpException.h
Normal file
572
src/SimpleAmqpClient/AmqpException.h
Normal file
@@ -0,0 +1,572 @@
|
|||||||
|
#ifndef SIMPLEAMQPCLIENT_AMQPEXCEPTION_H
|
||||||
|
#define SIMPLEAMQPCLIENT_AMQPEXCEPTION_H
|
||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <boost/cstdint.hpp>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "Util.h"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4251 4275)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// @file SimpleAmqpClient/AmqpException.h
|
||||||
|
/// Defines AmqpClient::AmqpException
|
||||||
|
|
||||||
|
struct amqp_rpc_reply_t_;
|
||||||
|
struct amqp_channel_close_t_;
|
||||||
|
struct amqp_connection_close_t_;
|
||||||
|
|
||||||
|
namespace AmqpClient {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base-class for exceptions from the broker
|
||||||
|
*/
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT AmqpException : public std::runtime_error {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Construct an AmqpException from an amqp_rpc_reply_t and throw it
|
||||||
|
*
|
||||||
|
* @param [in] reply the reply from the RPC call
|
||||||
|
*/
|
||||||
|
static void Throw(const amqp_rpc_reply_t_ &reply);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct an AmqpException from an amqp_channel_close_t and throw it
|
||||||
|
*
|
||||||
|
* @param [in] reply the channel.close AMQP method
|
||||||
|
*/
|
||||||
|
static void Throw(const amqp_channel_close_t_ &reply);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct an AmqpException from an amqp_connection_close_t and throw it
|
||||||
|
*
|
||||||
|
* @param [in] reply the connection.close AMQP method
|
||||||
|
*/
|
||||||
|
static void Throw(const amqp_connection_close_t_ &reply);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param [in] what the error string to pass to the std::runtime_error
|
||||||
|
* base-class
|
||||||
|
* @param [in] reply_text the error message (if any) from the broker
|
||||||
|
* @param [in] class_id the class id of the method that caused the error
|
||||||
|
* @param [in] method_id the method id of the method that caused the error
|
||||||
|
*/
|
||||||
|
explicit AmqpException(const std::string &what, const std::string &reply_text,
|
||||||
|
boost::uint16_t class_id,
|
||||||
|
boost::uint16_t method_id) throw();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor
|
||||||
|
*/
|
||||||
|
virtual ~AmqpException() throw() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query to see if the error is soft
|
||||||
|
*
|
||||||
|
* A soft error is generally recoverable, meaning the Channel
|
||||||
|
* object that it originated from can be reused. If its a hard error
|
||||||
|
* the Channel object is closed and will throw exceptions if its used
|
||||||
|
* again.
|
||||||
|
*
|
||||||
|
* @returns `true` if its a soft error, `false` otherwise
|
||||||
|
*/
|
||||||
|
virtual bool is_soft_error() const throw() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the error code returned from the broker
|
||||||
|
*
|
||||||
|
* @returns the error code
|
||||||
|
*/
|
||||||
|
virtual boost::uint16_t reply_code() const throw() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the class id of the method that caused the error
|
||||||
|
*
|
||||||
|
* @returns the class id
|
||||||
|
*/
|
||||||
|
virtual boost::uint16_t class_id() const throw() { return m_class_id; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the method id of the method that caused the error
|
||||||
|
*
|
||||||
|
* @returns the method id
|
||||||
|
*/
|
||||||
|
virtual boost::uint16_t method_id() const throw() { return m_method_id; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the error string returned from the broker
|
||||||
|
*
|
||||||
|
* @returns the error string from the broker
|
||||||
|
*/
|
||||||
|
virtual std::string reply_text() const throw() { return m_reply_text; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/** @cond INTERNAL */
|
||||||
|
std::string m_reply_text;
|
||||||
|
boost::uint16_t m_class_id;
|
||||||
|
boost::uint16_t m_method_id;
|
||||||
|
/** @endcond */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for exceptions that result in the connection being closed
|
||||||
|
*
|
||||||
|
* If the program receives this kind of exception, the Channel object that
|
||||||
|
* threw the exception is now disconnected from the broker and any further
|
||||||
|
* use of the channel will cause further errors
|
||||||
|
*/
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT ConnectionException : public AmqpException {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param [in] what
|
||||||
|
* @param [in] reply_text
|
||||||
|
* @param [in] class_id
|
||||||
|
* @param [in] method_id
|
||||||
|
*/
|
||||||
|
explicit ConnectionException(const std::string &what,
|
||||||
|
const std::string &reply_text,
|
||||||
|
boost::uint16_t class_id,
|
||||||
|
boost::uint16_t method_id) throw()
|
||||||
|
: AmqpException(what, reply_text, class_id, method_id) {}
|
||||||
|
|
||||||
|
virtual bool is_soft_error() const throw() { return false; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for exceptions that are soft errors
|
||||||
|
*
|
||||||
|
* If the program receives this kind of exception, the Channel object
|
||||||
|
* that threw the exception will continue to be functional.
|
||||||
|
*/
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT ChannelException : public AmqpException {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param [in] what
|
||||||
|
* @param [in] reply_text
|
||||||
|
* @param [in] class_id
|
||||||
|
* @param [in] method_id
|
||||||
|
*/
|
||||||
|
explicit ChannelException(const std::string &what,
|
||||||
|
const std::string &reply_text,
|
||||||
|
boost::uint16_t class_id,
|
||||||
|
boost::uint16_t method_id) throw()
|
||||||
|
: AmqpException(what, reply_text, class_id, method_id) {}
|
||||||
|
|
||||||
|
virtual bool is_soft_error() const throw() { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The connection was force closed by an operator
|
||||||
|
*/
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT ConnectionForcedException
|
||||||
|
: public ConnectionException {
|
||||||
|
public:
|
||||||
|
/** reply code */
|
||||||
|
static const boost::uint16_t REPLY_CODE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
explicit ConnectionForcedException(const std::string &what,
|
||||||
|
const std::string &reply_text,
|
||||||
|
boost::uint16_t class_id,
|
||||||
|
boost::uint16_t method_id) throw()
|
||||||
|
: ConnectionException(what, reply_text, class_id, method_id) {}
|
||||||
|
|
||||||
|
virtual boost::uint16_t reply_code() const throw() { return REPLY_CODE; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The client tried to work with an invalid virtual host
|
||||||
|
*/
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT InvalidPathException
|
||||||
|
: public ConnectionException {
|
||||||
|
public:
|
||||||
|
/** reply code */
|
||||||
|
static const boost::uint16_t REPLY_CODE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
explicit InvalidPathException(const std::string &what,
|
||||||
|
const std::string &reply_text,
|
||||||
|
boost::uint16_t class_id,
|
||||||
|
boost::uint16_t method_id) throw()
|
||||||
|
: ConnectionException(what, reply_text, class_id, method_id) {}
|
||||||
|
|
||||||
|
virtual boost::uint16_t reply_code() const throw() { return REPLY_CODE; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The broker received a malformed frame.
|
||||||
|
*
|
||||||
|
* This likely indicates a bug in SimpleAmqpClient
|
||||||
|
*/
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT FrameErrorException : public ConnectionException {
|
||||||
|
public:
|
||||||
|
/** reply code */
|
||||||
|
static const boost::uint16_t REPLY_CODE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
explicit FrameErrorException(const std::string &what,
|
||||||
|
const std::string &reply_text,
|
||||||
|
boost::uint16_t class_id,
|
||||||
|
boost::uint16_t method_id) throw()
|
||||||
|
: ConnectionException(what, reply_text, class_id, method_id) {}
|
||||||
|
|
||||||
|
virtual boost::uint16_t reply_code() const throw() { return REPLY_CODE; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The client sent a frame with bad values (out of range)
|
||||||
|
*
|
||||||
|
* This likely indicates a bug in SimpleAmqpClient
|
||||||
|
*/
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT SyntaxErrorException
|
||||||
|
: public ConnectionException {
|
||||||
|
public:
|
||||||
|
/** reply code */
|
||||||
|
static const boost::uint16_t REPLY_CODE;
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
explicit SyntaxErrorException(const std::string &what,
|
||||||
|
const std::string &reply_text,
|
||||||
|
boost::uint16_t class_id,
|
||||||
|
boost::uint16_t method_id) throw()
|
||||||
|
: ConnectionException(what, reply_text, class_id, method_id) {}
|
||||||
|
|
||||||
|
virtual boost::uint16_t reply_code() const throw() { return REPLY_CODE; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The client sent an invalid sequence of frames
|
||||||
|
*
|
||||||
|
* This likely indicates a bug in SimpleAmqpClient
|
||||||
|
*/
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT CommandInvalidException
|
||||||
|
: public ConnectionException {
|
||||||
|
public:
|
||||||
|
/** reply code */
|
||||||
|
static const boost::uint16_t REPLY_CODE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
explicit CommandInvalidException(const std::string &what,
|
||||||
|
const std::string &reply_text,
|
||||||
|
boost::uint16_t class_id,
|
||||||
|
boost::uint16_t method_id) throw()
|
||||||
|
: ConnectionException(what, reply_text, class_id, method_id) {}
|
||||||
|
|
||||||
|
virtual boost::uint16_t reply_code() const throw() { return REPLY_CODE; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The client tried to use a Channel that isn't open
|
||||||
|
*
|
||||||
|
* This likely indicates a bug in SimpleAmqpClient
|
||||||
|
*/
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT ChannelErrorException
|
||||||
|
: public ConnectionException {
|
||||||
|
public:
|
||||||
|
/** reply code */
|
||||||
|
static const boost::uint16_t REPLY_CODE;
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
explicit ChannelErrorException(const std::string &what,
|
||||||
|
const std::string &reply_text,
|
||||||
|
boost::uint16_t class_id,
|
||||||
|
boost::uint16_t method_id) throw()
|
||||||
|
: ConnectionException(what, reply_text, class_id, method_id) {}
|
||||||
|
|
||||||
|
virtual boost::uint16_t reply_code() const throw() { return REPLY_CODE; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The client sent a frame the broker wasn't expecting
|
||||||
|
*
|
||||||
|
* This likely indicates a bug in SimpleAmqpClient
|
||||||
|
*/
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT UnexpectedFrameException
|
||||||
|
: public ConnectionException {
|
||||||
|
public:
|
||||||
|
/** reply code */
|
||||||
|
static const boost::uint16_t REPLY_CODE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
explicit UnexpectedFrameException(const std::string &what,
|
||||||
|
const std::string &reply_text,
|
||||||
|
boost::uint16_t class_id,
|
||||||
|
boost::uint16_t method_id) throw()
|
||||||
|
: ConnectionException(what, reply_text, class_id, method_id) {}
|
||||||
|
|
||||||
|
virtual boost::uint16_t reply_code() const throw() { return REPLY_CODE; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The broker could not complete the request because of lack of resources
|
||||||
|
*
|
||||||
|
* Likely due to clients creating too many of something
|
||||||
|
*/
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT ResourceErrorException
|
||||||
|
: public ConnectionException {
|
||||||
|
public:
|
||||||
|
/** reply code */
|
||||||
|
static const boost::uint16_t REPLY_CODE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
explicit ResourceErrorException(const std::string &what,
|
||||||
|
const std::string &reply_text,
|
||||||
|
boost::uint16_t class_id,
|
||||||
|
boost::uint16_t method_id) throw()
|
||||||
|
: ConnectionException(what, reply_text, class_id, method_id) {}
|
||||||
|
|
||||||
|
virtual boost::uint16_t reply_code() const throw() { return REPLY_CODE; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The client tried to work with some entity in a manner that is prohibited by
|
||||||
|
* the server.
|
||||||
|
*
|
||||||
|
* Like due to security settings or by some other criteria.
|
||||||
|
*/
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT NotAllowedException : public ConnectionException {
|
||||||
|
public:
|
||||||
|
/** reply code */
|
||||||
|
static const boost::uint16_t REPLY_CODE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
explicit NotAllowedException(const std::string &what,
|
||||||
|
const std::string &reply_text,
|
||||||
|
boost::uint16_t class_id,
|
||||||
|
boost::uint16_t method_id) throw()
|
||||||
|
: ConnectionException(what, reply_text, class_id, method_id) {}
|
||||||
|
|
||||||
|
virtual boost::uint16_t reply_code() const throw() { return REPLY_CODE; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The client tried to use a method that isn't implemented by the broker
|
||||||
|
*/
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT NotImplementedException
|
||||||
|
: public ConnectionException {
|
||||||
|
public:
|
||||||
|
/** reply code */
|
||||||
|
static const boost::uint16_t REPLY_CODE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
explicit NotImplementedException(const std::string &what,
|
||||||
|
const std::string &reply_text,
|
||||||
|
boost::uint16_t class_id,
|
||||||
|
boost::uint16_t method_id) throw()
|
||||||
|
: ConnectionException(what, reply_text, class_id, method_id) {}
|
||||||
|
|
||||||
|
virtual boost::uint16_t reply_code() const throw() { return REPLY_CODE; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An internal error occurred on the broker
|
||||||
|
*/
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT InternalErrorException
|
||||||
|
: public ConnectionException {
|
||||||
|
public:
|
||||||
|
/** reply code */
|
||||||
|
static const boost::uint16_t REPLY_CODE;
|
||||||
|
|
||||||
|
/** Constructor */
|
||||||
|
explicit InternalErrorException(const std::string &what,
|
||||||
|
const std::string &reply_text,
|
||||||
|
boost::uint16_t class_id,
|
||||||
|
boost::uint16_t method_id) throw()
|
||||||
|
: ConnectionException(what, reply_text, class_id, method_id) {}
|
||||||
|
|
||||||
|
virtual boost::uint16_t reply_code() const throw() { return REPLY_CODE; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The client tried to send content that was too large
|
||||||
|
*
|
||||||
|
* Try sending the content at a later time
|
||||||
|
*/
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT ContentTooLargeException
|
||||||
|
: public ChannelException {
|
||||||
|
public:
|
||||||
|
/** reply code */
|
||||||
|
static const boost::uint16_t REPLY_CODE;
|
||||||
|
|
||||||
|
/** Constructor */
|
||||||
|
explicit ContentTooLargeException(const std::string &what,
|
||||||
|
const std::string reply_text,
|
||||||
|
boost::uint16_t class_id,
|
||||||
|
boost::uint16_t method_id) throw()
|
||||||
|
: ChannelException(what, reply_text, class_id, method_id) {}
|
||||||
|
|
||||||
|
virtual boost::uint16_t reply_code() const throw() { return REPLY_CODE; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AMQP_NO_ROUTE error, occurs when the IP stack cannot route our data to the
|
||||||
|
* broker.
|
||||||
|
*/
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT NoRouteException : public ChannelException {
|
||||||
|
public:
|
||||||
|
/** reply code */
|
||||||
|
static const boost::uint16_t REPLY_CODE;
|
||||||
|
/** Constructor */
|
||||||
|
explicit NoRouteException(const std::string &what,
|
||||||
|
const std::string reply_text,
|
||||||
|
boost::uint16_t class_id,
|
||||||
|
boost::uint16_t method_id) throw()
|
||||||
|
: ChannelException(what, reply_text, class_id, method_id) {}
|
||||||
|
|
||||||
|
virtual boost::uint16_t reply_code() const throw() { return REPLY_CODE; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AMQP_NO_CONSUMERS error. When the exchange cannot deliver to a consumer when
|
||||||
|
* the immediate flag is set. As a result of pending data on the queue or the
|
||||||
|
* absence of any consumers of the queue.
|
||||||
|
*/
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT NoConsumersException : public ChannelException {
|
||||||
|
public:
|
||||||
|
/** reply code */
|
||||||
|
static const boost::uint16_t REPLY_CODE;
|
||||||
|
/** Constructor */
|
||||||
|
explicit NoConsumersException(const std::string &what,
|
||||||
|
const std::string reply_text,
|
||||||
|
boost::uint16_t class_id,
|
||||||
|
boost::uint16_t method_id) throw()
|
||||||
|
: ChannelException(what, reply_text, class_id, method_id) {}
|
||||||
|
|
||||||
|
virtual boost::uint16_t reply_code() const throw() { return REPLY_CODE; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AMQP_ACCESS_REFUSED error. The client attempted to work with a server entity
|
||||||
|
* to which it has no access due to security settings.
|
||||||
|
*/
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT AccessRefusedException : public ChannelException {
|
||||||
|
public:
|
||||||
|
/** reply code */
|
||||||
|
static const boost::uint16_t REPLY_CODE;
|
||||||
|
/** Constructor */
|
||||||
|
explicit AccessRefusedException(const std::string &what,
|
||||||
|
const std::string reply_text,
|
||||||
|
boost::uint16_t class_id,
|
||||||
|
boost::uint16_t method_id) throw()
|
||||||
|
: ChannelException(what, reply_text, class_id, method_id) {}
|
||||||
|
|
||||||
|
virtual boost::uint16_t reply_code() const throw() { return REPLY_CODE; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AMQP_NOT_FOUND error. The client attempted to work with a server entity that
|
||||||
|
* does not exist.
|
||||||
|
*/
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT NotFoundException : public ChannelException {
|
||||||
|
public:
|
||||||
|
/** reply code */
|
||||||
|
static const boost::uint16_t REPLY_CODE;
|
||||||
|
/** Constructor */
|
||||||
|
explicit NotFoundException(const std::string &what,
|
||||||
|
const std::string reply_text,
|
||||||
|
boost::uint16_t class_id,
|
||||||
|
boost::uint16_t method_id) throw()
|
||||||
|
: ChannelException(what, reply_text, class_id, method_id) {}
|
||||||
|
|
||||||
|
virtual boost::uint16_t reply_code() const throw() { return REPLY_CODE; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The client attempted to work with a server entity to which it has no access
|
||||||
|
* because another client is working with it.
|
||||||
|
*/
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT ResourceLockedException
|
||||||
|
: public ChannelException {
|
||||||
|
public:
|
||||||
|
/** reply code */
|
||||||
|
static const boost::uint16_t REPLY_CODE;
|
||||||
|
/** Constructor */
|
||||||
|
explicit ResourceLockedException(const std::string &what,
|
||||||
|
const std::string reply_text,
|
||||||
|
boost::uint16_t class_id,
|
||||||
|
boost::uint16_t method_id) throw()
|
||||||
|
: ChannelException(what, reply_text, class_id, method_id) {}
|
||||||
|
|
||||||
|
virtual boost::uint16_t reply_code() const throw() { return REPLY_CODE; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The client requested a method that was not allowed because some precondition
|
||||||
|
* failed.
|
||||||
|
*/
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT PreconditionFailedException
|
||||||
|
: public ChannelException {
|
||||||
|
public:
|
||||||
|
/** reply code */
|
||||||
|
static const boost::uint16_t REPLY_CODE;
|
||||||
|
/** Constructor */
|
||||||
|
explicit PreconditionFailedException(const std::string &what,
|
||||||
|
const std::string reply_text,
|
||||||
|
boost::uint16_t class_id,
|
||||||
|
boost::uint16_t method_id) throw()
|
||||||
|
: ChannelException(what, reply_text, class_id, method_id) {}
|
||||||
|
|
||||||
|
virtual boost::uint16_t reply_code() const throw() { return REPLY_CODE; }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace AmqpClient
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // SIMPLEAMQPCLIENT_AMQPEXCEPTION_H
|
||||||
84
src/SimpleAmqpClient/AmqpLibraryException.h
Normal file
84
src/SimpleAmqpClient/AmqpLibraryException.h
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
#ifndef SIMPLEAMQPCLIENT_AMQPLIBRARYEXCEPTION_H
|
||||||
|
#define SIMPLEAMQPCLIENT_AMQPLIBRARYEXCEPTION_H
|
||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "SimpleAmqpClient/Util.h"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4251 4275)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// @file SimpleAmqpClient/AmqpLibraryException.h
|
||||||
|
/// Defines SimpleAmqpClient::AmqpLibraryException
|
||||||
|
|
||||||
|
struct amqp_rpc_reply_t_;
|
||||||
|
|
||||||
|
namespace AmqpClient {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Errors arising from incorrect usage of this library APIs
|
||||||
|
*/
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT AmqpLibraryException : public std::runtime_error {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Factory-construct with an error code
|
||||||
|
*/
|
||||||
|
static AmqpLibraryException CreateException(int error_code);
|
||||||
|
/**
|
||||||
|
* Factory-construct with an error code and a string context
|
||||||
|
*/
|
||||||
|
static AmqpLibraryException CreateException(int error_code,
|
||||||
|
const std::string &context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error code getter
|
||||||
|
*/
|
||||||
|
int ErrorCode() const { return m_errorCode; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/** @cond INTERNAL */
|
||||||
|
explicit AmqpLibraryException(const std::string &message,
|
||||||
|
int error_code) throw();
|
||||||
|
/** @endcond@ */
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_errorCode;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace AmqpClient
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // SIMPLEAMQPCLIENT_AMQPLIBRARYEXCEPTION_H
|
||||||
70
src/SimpleAmqpClient/AmqpResponseLibraryException.h
Normal file
70
src/SimpleAmqpClient/AmqpResponseLibraryException.h
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
#ifndef SIMPLEAMQPCLIENT_AMQPRESPONSELIBRARYEXCEPTION_H
|
||||||
|
#define SIMPLEAMQPCLIENT_AMQPRESPONSELIBRARYEXCEPTION_H
|
||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <boost/cstdint.hpp>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "SimpleAmqpClient/Util.h"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4251 4275)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// @file SimpleAmqpClient/AmqpResponseLibraryException.h
|
||||||
|
/// Defines AmqpClient::AmqpResponseLibraryException
|
||||||
|
|
||||||
|
struct amqp_rpc_reply_t_;
|
||||||
|
|
||||||
|
namespace AmqpClient {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `AMQP_RESPONSE_LIBRARY_EXCEPTION`: an RPC response returned a library error
|
||||||
|
*/
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT AmqpResponseLibraryException
|
||||||
|
: public std::runtime_error {
|
||||||
|
public:
|
||||||
|
/// Factory-construct from RPC reply and a string context
|
||||||
|
static AmqpResponseLibraryException CreateException(
|
||||||
|
const amqp_rpc_reply_t_ &reply, const std::string &context);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/// Construct an instance with exact message
|
||||||
|
explicit AmqpResponseLibraryException(const std::string &message) throw();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace AmqpClient
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // SIMPLEAMQPCLIENT_AMQPRESPONSELIBRARYEXCEPTION_H
|
||||||
46
src/SimpleAmqpClient/BadUriException.h
Normal file
46
src/SimpleAmqpClient/BadUriException.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#ifndef SIMPLEAMQPCLIENT_BADURIEXCEPTION_H
|
||||||
|
#define SIMPLEAMQPCLIENT_BADURIEXCEPTION_H
|
||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include "SimpleAmqpClient/Util.h"
|
||||||
|
|
||||||
|
/// @file SimpleAmqpClient/BadUriException.h
|
||||||
|
/// Defines AmqpClient::BadUriException
|
||||||
|
|
||||||
|
namespace AmqpClient {
|
||||||
|
|
||||||
|
/** "URI is malformed" exception */
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT BadUriException : public std::runtime_error {
|
||||||
|
public:
|
||||||
|
explicit BadUriException() : std::runtime_error("URI is malformed") {}
|
||||||
|
};
|
||||||
|
} // namespace AmqpClient
|
||||||
|
#endif // SIMPLEAMQPCLIENT_BADURIEXCEPTION_H
|
||||||
354
src/SimpleAmqpClient/BasicMessage.h
Normal file
354
src/SimpleAmqpClient/BasicMessage.h
Normal file
@@ -0,0 +1,354 @@
|
|||||||
|
#ifndef SIMPLEAMQPCLIENT_BASICMESSAGE_H
|
||||||
|
#define SIMPLEAMQPCLIENT_BASICMESSAGE_H
|
||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <boost/cstdint.hpp>
|
||||||
|
#include <boost/make_shared.hpp>
|
||||||
|
#include <boost/scoped_ptr.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <boost/utility.hpp>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "SimpleAmqpClient/Table.h"
|
||||||
|
#include "SimpleAmqpClient/Util.h"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4275 4251)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// @file SimpleAmqpClient/BasicMessage.h
|
||||||
|
/// The AmqpClient::BasicMessage class is defined in this header file.
|
||||||
|
|
||||||
|
namespace AmqpClient {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An AMQP BasicMessage
|
||||||
|
*/
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT BasicMessage : boost::noncopyable {
|
||||||
|
public:
|
||||||
|
/// A shared pointer to BasicMessage
|
||||||
|
typedef boost::shared_ptr<BasicMessage> ptr_t;
|
||||||
|
|
||||||
|
/// With durable queues, messages can be requested to persist or not
|
||||||
|
enum delivery_mode_t {
|
||||||
|
dm_notset = 0,
|
||||||
|
dm_nonpersistent = 1,
|
||||||
|
dm_persistent = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new empty BasicMessage object
|
||||||
|
*/
|
||||||
|
static ptr_t Create() { return boost::make_shared<BasicMessage>(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new BasicMessage object with given body
|
||||||
|
*
|
||||||
|
* @param body the message body.
|
||||||
|
* @returns a new BasicMessage object
|
||||||
|
*/
|
||||||
|
static ptr_t Create(const std::string& body) {
|
||||||
|
return boost::make_shared<BasicMessage>(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct empty BasicMessage
|
||||||
|
BasicMessage();
|
||||||
|
/// Construct BasicMessage with given body
|
||||||
|
BasicMessage(const std::string& body);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Destructor
|
||||||
|
*/
|
||||||
|
virtual ~BasicMessage();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the message body as a std::string
|
||||||
|
*/
|
||||||
|
const std::string& Body() const;
|
||||||
|
std::string& Body();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the message body as a std::string
|
||||||
|
*/
|
||||||
|
void Body(const std::string& body);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the content type property
|
||||||
|
*/
|
||||||
|
const std::string& ContentType() const;
|
||||||
|
/**
|
||||||
|
* Sets the content type property
|
||||||
|
*/
|
||||||
|
void ContentType(const std::string& content_type);
|
||||||
|
/**
|
||||||
|
* Determines whether the content type property is set
|
||||||
|
*/
|
||||||
|
bool ContentTypeIsSet() const;
|
||||||
|
/**
|
||||||
|
* Unsets the content type property if it is set
|
||||||
|
*/
|
||||||
|
void ContentTypeClear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the content encoding property
|
||||||
|
*/
|
||||||
|
const std::string& ContentEncoding() const;
|
||||||
|
/**
|
||||||
|
* Sets the content encoding property
|
||||||
|
*/
|
||||||
|
void ContentEncoding(const std::string& content_encoding);
|
||||||
|
/**
|
||||||
|
* Determines whether the content encoding property is set
|
||||||
|
*/
|
||||||
|
bool ContentEncodingIsSet() const;
|
||||||
|
/**
|
||||||
|
* Unsets the content encoding property if it is set
|
||||||
|
*/
|
||||||
|
void ContentEncodingClear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the delivery mode property
|
||||||
|
*/
|
||||||
|
delivery_mode_t DeliveryMode() const;
|
||||||
|
/**
|
||||||
|
* Sets the delivery mode property
|
||||||
|
*/
|
||||||
|
void DeliveryMode(delivery_mode_t delivery_mode);
|
||||||
|
/**
|
||||||
|
* Determines whether the delivery mode property is set
|
||||||
|
*/
|
||||||
|
bool DeliveryModeIsSet() const;
|
||||||
|
/**
|
||||||
|
* Unsets the delivery mode property if it is set
|
||||||
|
*/
|
||||||
|
void DeliveryModeClear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the priority property
|
||||||
|
*/
|
||||||
|
boost::uint8_t Priority() const;
|
||||||
|
/**
|
||||||
|
* Sets the priority property
|
||||||
|
*/
|
||||||
|
void Priority(boost::uint8_t priority);
|
||||||
|
/**
|
||||||
|
* Determines whether the priority property is set
|
||||||
|
*/
|
||||||
|
bool PriorityIsSet() const;
|
||||||
|
/**
|
||||||
|
* Unsets the priority property if it is set
|
||||||
|
*/
|
||||||
|
void PriorityClear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the correlation id property
|
||||||
|
*/
|
||||||
|
const std::string& CorrelationId() const;
|
||||||
|
/**
|
||||||
|
* Sets the correlation id property
|
||||||
|
*/
|
||||||
|
void CorrelationId(const std::string& correlation_id);
|
||||||
|
/**
|
||||||
|
* Determines whether the correlation id property is set
|
||||||
|
*/
|
||||||
|
bool CorrelationIdIsSet() const;
|
||||||
|
/**
|
||||||
|
* Unsets the correlation id property
|
||||||
|
*/
|
||||||
|
void CorrelationIdClear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the reply to property
|
||||||
|
*/
|
||||||
|
const std::string& ReplyTo() const;
|
||||||
|
/**
|
||||||
|
* Sets the reply to property
|
||||||
|
*/
|
||||||
|
void ReplyTo(const std::string& reply_to);
|
||||||
|
/**
|
||||||
|
* Determines whether the reply to property is set
|
||||||
|
*/
|
||||||
|
bool ReplyToIsSet() const;
|
||||||
|
/**
|
||||||
|
* Unsets the reply to property
|
||||||
|
*/
|
||||||
|
void ReplyToClear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the expiration property
|
||||||
|
*/
|
||||||
|
const std::string& Expiration() const;
|
||||||
|
/**
|
||||||
|
* Sets the expiration property
|
||||||
|
*/
|
||||||
|
void Expiration(const std::string& expiration);
|
||||||
|
/**
|
||||||
|
* Determines whether the expiration property is set
|
||||||
|
*/
|
||||||
|
bool ExpirationIsSet() const;
|
||||||
|
/**
|
||||||
|
* Unsets the expiration property
|
||||||
|
*/
|
||||||
|
void ExpirationClear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the message id property
|
||||||
|
*/
|
||||||
|
const std::string& MessageId() const;
|
||||||
|
/**
|
||||||
|
* Sets the message id property
|
||||||
|
*/
|
||||||
|
void MessageId(const std::string& message_id);
|
||||||
|
/**
|
||||||
|
* Determines if the message id property is set
|
||||||
|
*/
|
||||||
|
bool MessageIdIsSet() const;
|
||||||
|
/**
|
||||||
|
* Unsets the message id property
|
||||||
|
*/
|
||||||
|
void MessageIdClear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the timestamp property
|
||||||
|
*/
|
||||||
|
boost::uint64_t Timestamp() const;
|
||||||
|
/**
|
||||||
|
* Sets the timestamp property
|
||||||
|
*/
|
||||||
|
void Timestamp(boost::uint64_t timestamp);
|
||||||
|
/**
|
||||||
|
* Determines whether the timestamp property is set
|
||||||
|
*/
|
||||||
|
bool TimestampIsSet() const;
|
||||||
|
/**
|
||||||
|
* Unsets the timestamp property
|
||||||
|
*/
|
||||||
|
void TimestampClear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the type property
|
||||||
|
*/
|
||||||
|
const std::string& Type() const;
|
||||||
|
/**
|
||||||
|
* Sets the type property
|
||||||
|
*/
|
||||||
|
void Type(const std::string& type);
|
||||||
|
/**
|
||||||
|
* Determines whether the type property is set
|
||||||
|
*/
|
||||||
|
bool TypeIsSet() const;
|
||||||
|
/**
|
||||||
|
* Unsets the type property
|
||||||
|
*/
|
||||||
|
void TypeClear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the user id property
|
||||||
|
*/
|
||||||
|
const std::string& UserId() const;
|
||||||
|
/**
|
||||||
|
* Sets the user id property
|
||||||
|
*/
|
||||||
|
void UserId(const std::string& user_id);
|
||||||
|
/**
|
||||||
|
* Determines whether the user id property is set
|
||||||
|
*/
|
||||||
|
bool UserIdIsSet() const;
|
||||||
|
/**
|
||||||
|
* Unsets the user id property
|
||||||
|
*/
|
||||||
|
void UserIdClear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the app id property
|
||||||
|
*/
|
||||||
|
const std::string& AppId() const;
|
||||||
|
/**
|
||||||
|
* Sets the app id property
|
||||||
|
*/
|
||||||
|
void AppId(const std::string& app_id);
|
||||||
|
/**
|
||||||
|
* Determines whether the app id property is set
|
||||||
|
*/
|
||||||
|
bool AppIdIsSet() const;
|
||||||
|
/**
|
||||||
|
* Unsets the app id property
|
||||||
|
*/
|
||||||
|
void AppIdClear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the cluster id property
|
||||||
|
*/
|
||||||
|
const std::string& ClusterId() const;
|
||||||
|
/**
|
||||||
|
* Sets the custer id property
|
||||||
|
*/
|
||||||
|
void ClusterId(const std::string& cluster_id);
|
||||||
|
/**
|
||||||
|
* Determines if the cluster id property is set
|
||||||
|
*/
|
||||||
|
bool ClusterIdIsSet() const;
|
||||||
|
/**
|
||||||
|
* Unsets the cluster id property
|
||||||
|
*/
|
||||||
|
void ClusterIdClear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the header table property
|
||||||
|
*/
|
||||||
|
Table& HeaderTable();
|
||||||
|
const Table& HeaderTable() const;
|
||||||
|
/**
|
||||||
|
* Sets the header table property
|
||||||
|
*/
|
||||||
|
void HeaderTable(const Table& header_table);
|
||||||
|
/**
|
||||||
|
* Is there a header table associated with the message
|
||||||
|
*/
|
||||||
|
bool HeaderTableIsSet() const;
|
||||||
|
/**
|
||||||
|
* Unsets the header table property
|
||||||
|
*/
|
||||||
|
void HeaderTableClear();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
struct Impl;
|
||||||
|
/// PIMPL idiom
|
||||||
|
boost::scoped_ptr<Impl> m_impl;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace AmqpClient
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // SIMPLEAMQPCLIENT_BASICMESSAGE_H
|
||||||
26
src/SimpleAmqpClient/Bytes.h
Normal file
26
src/SimpleAmqpClient/Bytes.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef SIMPLEAMQPCLIENT_BYTES_H
|
||||||
|
#define SIMPLEAMQPCLIENT_BYTES_H
|
||||||
|
|
||||||
|
#include <amqp.h>
|
||||||
|
#include <boost/utility/string_ref.hpp>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace AmqpClient {
|
||||||
|
|
||||||
|
amqp_bytes_t StringToBytes(const std::string& str) {
|
||||||
|
amqp_bytes_t ret;
|
||||||
|
ret.bytes = reinterpret_cast<void*>(const_cast<char*>(str.data()));
|
||||||
|
ret.len = str.length();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_bytes_t StringRefToBytes(boost::string_ref str) {
|
||||||
|
amqp_bytes_t ret;
|
||||||
|
ret.bytes = reinterpret_cast<void*>(const_cast<char*>(str.data()));
|
||||||
|
ret.len = str.length();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace AmqpClient
|
||||||
|
#endif // SIMPLEAMQPCLIENT_BYTES_H
|
||||||
946
src/SimpleAmqpClient/Channel.h
Normal file
946
src/SimpleAmqpClient/Channel.h
Normal file
@@ -0,0 +1,946 @@
|
|||||||
|
#ifndef SIMPLEAMQPCLIENT_CHANNEL_H
|
||||||
|
#define SIMPLEAMQPCLIENT_CHANNEL_H
|
||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <boost/cstdint.hpp>
|
||||||
|
#include <boost/make_shared.hpp>
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
#include <boost/scoped_ptr.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <boost/utility.hpp>
|
||||||
|
#include <boost/utility/string_ref.hpp>
|
||||||
|
#include <boost/variant.hpp>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "SimpleAmqpClient/BasicMessage.h"
|
||||||
|
#include "SimpleAmqpClient/Envelope.h"
|
||||||
|
#include "SimpleAmqpClient/Table.h"
|
||||||
|
#include "SimpleAmqpClient/Util.h"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4251 4275)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// @file SimpleAmqpClient/Channel.h
|
||||||
|
/// The AmqpClient::Channel class is defined in this header file.
|
||||||
|
|
||||||
|
namespace AmqpClient {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A single channel multiplexed in an AMQP connection
|
||||||
|
*
|
||||||
|
* Represents a logical AMQP channel multiplexed over a connection
|
||||||
|
*/
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT Channel : boost::noncopyable {
|
||||||
|
public:
|
||||||
|
/// a `shared_ptr` to Channel
|
||||||
|
typedef boost::shared_ptr<Channel> ptr_t;
|
||||||
|
|
||||||
|
static const std::string
|
||||||
|
EXCHANGE_TYPE_DIRECT; ///< `"direct"` string constant
|
||||||
|
static const std::string
|
||||||
|
EXCHANGE_TYPE_FANOUT; ///< `"fanout"` string constant
|
||||||
|
static const std::string EXCHANGE_TYPE_TOPIC; ///< `"topic"` string constant
|
||||||
|
|
||||||
|
struct SIMPLEAMQPCLIENT_EXPORT OpenOpts {
|
||||||
|
/// Use username and password to authenticate with the broker.
|
||||||
|
struct SIMPLEAMQPCLIENT_EXPORT BasicAuth {
|
||||||
|
std::string username;
|
||||||
|
std::string password;
|
||||||
|
|
||||||
|
BasicAuth() {}
|
||||||
|
BasicAuth(const std::string &username, const std::string &password)
|
||||||
|
: username(username), password(password) {}
|
||||||
|
bool operator==(const BasicAuth &) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Use External SASL method to authenticate with the broker.
|
||||||
|
struct SIMPLEAMQPCLIENT_EXPORT ExternalSaslAuth {
|
||||||
|
std::string identity;
|
||||||
|
|
||||||
|
ExternalSaslAuth() {}
|
||||||
|
explicit ExternalSaslAuth(const std::string &identity)
|
||||||
|
: identity(identity) {}
|
||||||
|
bool operator==(const ExternalSaslAuth &) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Parameters
|
||||||
|
struct SIMPLEAMQPCLIENT_EXPORT TLSParams {
|
||||||
|
std::string client_key_path; ///< Path to client key.
|
||||||
|
std::string client_cert_path; ///< Path to client cert.
|
||||||
|
std::string ca_cert_path; ///< Path to CA cert.
|
||||||
|
bool verify_hostname; ///< Verify host matches certificate. Default: true
|
||||||
|
bool verify_peer; ///< Verify presented certificate. Default: true
|
||||||
|
|
||||||
|
TLSParams() : verify_hostname(true), verify_peer(true) {}
|
||||||
|
bool operator==(const TLSParams &) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string host; ///< Broker hostname. Required.
|
||||||
|
std::string vhost; ///< Virtualhost on the broker. Default '/', required.
|
||||||
|
int port; ///< Port to connect to, default is 5672.
|
||||||
|
int frame_max; ///< Max frame size in bytes. Default 128KB.
|
||||||
|
/// One of BasicAuth or ExternalSaslAuth is required.
|
||||||
|
boost::variant<BasicAuth, ExternalSaslAuth> auth;
|
||||||
|
/// Connect using TLS/SSL when set, otherwise use an unencrypted channel.
|
||||||
|
boost::optional<TLSParams> tls_params;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an OpenOpts struct from a URI.
|
||||||
|
*
|
||||||
|
* URIs look like amqp[s]://[username[:password]@]host[:port]/[vhost].
|
||||||
|
* Unspecified parts of the URL will take default values:
|
||||||
|
* - username: guest
|
||||||
|
* - password: guest
|
||||||
|
* - host: localhost
|
||||||
|
* - port: 5672 for 'amqp', and 5671 for 'amqps'
|
||||||
|
* - vhost: '/'
|
||||||
|
*
|
||||||
|
* NOTE: for TLS/SSL connections, additional configuration is required.
|
||||||
|
*/
|
||||||
|
static OpenOpts FromUri(const std::string &uri);
|
||||||
|
|
||||||
|
OpenOpts() : vhost("/"), port(5672), frame_max(131072) {}
|
||||||
|
bool operator==(const OpenOpts &) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a new channel to the broker.
|
||||||
|
*
|
||||||
|
* See documentation for \ref OpenOpts for details on what can be
|
||||||
|
* passed into this function.
|
||||||
|
*/
|
||||||
|
static ptr_t Open(const OpenOpts &opts);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new channel object
|
||||||
|
*
|
||||||
|
* Creates a new connection to an AMQP broker using the supplied parameters
|
||||||
|
* and opens a single channel for use
|
||||||
|
* @param host The hostname or IP address of the AMQP broker
|
||||||
|
* @param port The port to connect to the AMQP broker on
|
||||||
|
* @param username The username used to authenticate with the AMQP broker
|
||||||
|
* @param password The password corresponding to the username used to
|
||||||
|
* authenticate with the AMQP broker
|
||||||
|
* @param vhost The virtual host on the AMQP we should connect to
|
||||||
|
* @param frame_max Request that the server limit the maximum size of any
|
||||||
|
* frame to this value
|
||||||
|
* @return a new Channel object pointer
|
||||||
|
*/
|
||||||
|
SAC_DEPRECATED("Channel::Create is deprecated. Use Channel::Open.")
|
||||||
|
static ptr_t Create(const std::string &host = "127.0.0.1", int port = 5672,
|
||||||
|
const std::string &username = "guest",
|
||||||
|
const std::string &password = "guest",
|
||||||
|
const std::string &vhost = "/", int frame_max = 131072);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new channel object
|
||||||
|
* Creates a new connection to an AMQP broker using the supplied parameters
|
||||||
|
* and opens a single channel for use
|
||||||
|
* This channel uses the EXTERNAL SASL method for authentication to the broker
|
||||||
|
* @param host The hostname or IP address of the AMQP broker
|
||||||
|
* @param port The port to connect to the AMQP broker on
|
||||||
|
* @param identity The identity used to authenticate with the AMQP broker
|
||||||
|
* @param vhost The virtual host on the AMQP we should connect to
|
||||||
|
* @param channel_max Request that the server limit the number of channels
|
||||||
|
* for
|
||||||
|
* this connection to the specified parameter, a value of zero will use the
|
||||||
|
* broker-supplied value
|
||||||
|
* @param frame_max Request that the server limit the maximum size of any
|
||||||
|
* frame to this value
|
||||||
|
* @return a new Channel object pointer
|
||||||
|
*/
|
||||||
|
SAC_DEPRECATED(
|
||||||
|
"Channel::CreateSaslExternal is deprecated. Use Channel::Open.")
|
||||||
|
static ptr_t CreateSaslExternal(const std::string &host = "127.0.0.1",
|
||||||
|
int port = 5672,
|
||||||
|
const std::string &identity = "guest",
|
||||||
|
const std::string &vhost = "/",
|
||||||
|
int frame_max = 131072);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new channel object, using TLS
|
||||||
|
*
|
||||||
|
* Creates a new connection to an AMQP broker using the supplied parameters
|
||||||
|
* and opens a single channel for use
|
||||||
|
* @param path_to_ca_cert Path to CA certificate file
|
||||||
|
* @param host The hostname or IP address of the AMQP broker
|
||||||
|
* @param path_to_client_key Path to client key file
|
||||||
|
* @param path_to_client_cert Path to client certificate file
|
||||||
|
* @param port The port to connect to the AMQP broker on
|
||||||
|
* @param username The username used to authenticate with the AMQP broker
|
||||||
|
* @param password The password corresponding to the username used to
|
||||||
|
* authenticate with the AMQP broker
|
||||||
|
* @param vhost The virtual host on the AMQP we should connect to
|
||||||
|
* @param frame_max Request that the server limit the maximum size of any
|
||||||
|
* frame to this value
|
||||||
|
* @param verify_hostname Verify the hostname against the certificate when
|
||||||
|
* opening the SSL connection.
|
||||||
|
*
|
||||||
|
* @return a new Channel object pointer
|
||||||
|
*/
|
||||||
|
SAC_DEPRECATED("Channel::CreateSecure is deprecated. Use Channel::Open.")
|
||||||
|
static ptr_t CreateSecure(const std::string &path_to_ca_cert = "",
|
||||||
|
const std::string &host = "127.0.0.1",
|
||||||
|
const std::string &path_to_client_key = "",
|
||||||
|
const std::string &path_to_client_cert = "",
|
||||||
|
int port = 5671,
|
||||||
|
const std::string &username = "guest",
|
||||||
|
const std::string &password = "guest",
|
||||||
|
const std::string &vhost = "/",
|
||||||
|
int frame_max = 131072,
|
||||||
|
bool verify_hostname_and_peer = true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new channel object
|
||||||
|
* Creates a new connection to an AMQP broker using the supplied parameters
|
||||||
|
* and opens a single channel for use
|
||||||
|
* @param path_to_ca_cert Path to ca certificate file
|
||||||
|
* @param host The hostname or IP address of the AMQP broker
|
||||||
|
* @param path_to_client_key Path to client key file
|
||||||
|
* @param path_to_client_cert Path to client certificate file
|
||||||
|
* @param port The port to connect to the AMQP broker on
|
||||||
|
* @param username The username used to authenticate with the AMQP broker
|
||||||
|
* @param password The password corresponding to the username used to
|
||||||
|
* authenticate with the AMQP broker
|
||||||
|
* @param vhost The virtual host on the AMQP we should connect to
|
||||||
|
* @param channel_max Request that the server limit the number of channels for
|
||||||
|
* this connection to the specified parameter, a value of zero will use the
|
||||||
|
* broker-supplied value
|
||||||
|
* @param frame_max Request that the server limit the maximum size of any
|
||||||
|
* frame to this value
|
||||||
|
* @param verify_host Verify the hostname against the certificate when
|
||||||
|
* opening the SSL connection.
|
||||||
|
* @param verify_peer Verify the certificate chain that is sent by the broker
|
||||||
|
* when opening the SSL connection.
|
||||||
|
*
|
||||||
|
* @return a new Channel object pointer
|
||||||
|
*/
|
||||||
|
SAC_DEPRECATED("Channel::CreateSecure is deprecated. Use Channel::Open.")
|
||||||
|
static ptr_t CreateSecure(const std::string &path_to_ca_cert,
|
||||||
|
const std::string &host,
|
||||||
|
const std::string &path_to_client_key,
|
||||||
|
const std::string &path_to_client_cert, int port,
|
||||||
|
const std::string &username,
|
||||||
|
const std::string &password,
|
||||||
|
const std::string &vhost, int frame_max,
|
||||||
|
bool verify_hostname, bool verify_peer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new channel object
|
||||||
|
* Creates a new connection to an AMQP broker using the supplied parameters
|
||||||
|
* and opens a single channel for use
|
||||||
|
* This channel uses the EXTERNAL SASL method for authentication to the broker
|
||||||
|
* @param path_to_ca_cert Path to ca certificate file
|
||||||
|
* @param host The hostname or IP address of the AMQP broker
|
||||||
|
* @param path_to_client_key Path to client key file
|
||||||
|
* @param path_to_client_cert Path to client certificate file
|
||||||
|
* @param port The port to connect to the AMQP broker on
|
||||||
|
* @param identity The identity used to authenticate with the AMQP broker
|
||||||
|
* @param vhost The virtual host on the AMQP we should connect to
|
||||||
|
* @param channel_max Request that the server limit the number of channels for
|
||||||
|
* this connection to the specified parameter, a value of zero will use the
|
||||||
|
* broker-supplied value
|
||||||
|
* @param frame_max Request that the server limit the maximum size of any
|
||||||
|
* frame to this value
|
||||||
|
* @param verify_host Verify the hostname against the certificate when
|
||||||
|
* opening the SSL connection.
|
||||||
|
* @param verify_peer Verify the certificate chain that is sent by the broker
|
||||||
|
* when opening the SSL connection.
|
||||||
|
*
|
||||||
|
* @return a new Channel object pointer
|
||||||
|
*/
|
||||||
|
SAC_DEPRECATED(
|
||||||
|
"Channel::CreateSecureSaslExternal is deprecated. Use Channel::Open.")
|
||||||
|
static ptr_t CreateSecureSaslExternal(const std::string &path_to_ca_cert,
|
||||||
|
const std::string &host,
|
||||||
|
const std::string &path_to_client_key,
|
||||||
|
const std::string &path_to_client_cert,
|
||||||
|
int port, const std::string &identity,
|
||||||
|
const std::string &vhost, int frame_max,
|
||||||
|
bool verify_hostname, bool verify_peer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Channel object from an AMQP URI
|
||||||
|
*
|
||||||
|
* @param uri a URI of the form:
|
||||||
|
* `amqp://[username:password@]{HOSTNAME}[:PORT][/VHOST]`
|
||||||
|
* @param frame_max requests that the broker limit the maximum size of
|
||||||
|
* any frame to this value
|
||||||
|
* @returns a new Channel object
|
||||||
|
*/
|
||||||
|
SAC_DEPRECATED("Channel::CreateFromUri is deprecated. Use Channel::Open.")
|
||||||
|
static ptr_t CreateFromUri(const std::string &uri, int frame_max = 131072);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Channel object from an AMQP URI, secured with SSL.
|
||||||
|
* If URI should start with amqps://
|
||||||
|
*
|
||||||
|
* @param uri a URI of the form:
|
||||||
|
* `amqp[s]://[username:password@]{HOSTNAME}[:PORT][/VHOST]`
|
||||||
|
* @param path_to_ca_cert Path to ca certificate file
|
||||||
|
* @param path_to_client_key Path to client key file
|
||||||
|
* @param path_to_client_cert Path to client certificate file
|
||||||
|
* @param verify_hostname Verify the hostname against the certificate when
|
||||||
|
* opening the SSL connection and the certificate chain that is sent by the
|
||||||
|
* broker.
|
||||||
|
* @param frame_max requests that the broker limit the maximum size of
|
||||||
|
* any frame to this value
|
||||||
|
* @returns a new Channel object
|
||||||
|
*/
|
||||||
|
SAC_DEPRECATED(
|
||||||
|
"Channel::CreateSecureFromUri is deprecated. Use Channel::Open.")
|
||||||
|
static ptr_t CreateSecureFromUri(const std::string &uri,
|
||||||
|
const std::string &path_to_ca_cert,
|
||||||
|
const std::string &path_to_client_key = "",
|
||||||
|
const std::string &path_to_client_cert = "",
|
||||||
|
bool verify_hostname_and_peer = true,
|
||||||
|
int frame_max = 131072);
|
||||||
|
|
||||||
|
private:
|
||||||
|
class ChannelImpl;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit Channel(ChannelImpl *impl);
|
||||||
|
virtual ~Channel();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exposes the underlying socket handle
|
||||||
|
* @returns file descriptor number associated with the connection socket
|
||||||
|
*
|
||||||
|
* @warning This function exposes an internal implementation detail
|
||||||
|
* of SimpleAmqpClient. Manipulating the socket descriptor will result in
|
||||||
|
* undefined behavior of the library. Additionally SimpleAmqpClient's use of
|
||||||
|
* the socket will change depending on what version of rabbitmq-c and
|
||||||
|
* SimpleAmqpClient are used. Test carefully before depending on any specific
|
||||||
|
* behavior.
|
||||||
|
*/
|
||||||
|
int GetSocketFD() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks to see if an exchange exists on the broker.
|
||||||
|
*
|
||||||
|
* @param exchange_name the name of the exchange to check for.
|
||||||
|
* @returns true if the exchange exists on the broker, false otherwise.
|
||||||
|
*/
|
||||||
|
bool CheckExchangeExists(boost::string_ref exchange_name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Declares an exchange
|
||||||
|
*
|
||||||
|
* Creates an exchange on the AMQP broker if it does not already exist
|
||||||
|
* @param exchange_name the name of the exchange
|
||||||
|
* @param exchange_type the type of exchange to be declared. Defaults to
|
||||||
|
* `direct`; other types that could be used: `fanout`, `topic`
|
||||||
|
* @param passive Indicates how the broker should react if the exchange does
|
||||||
|
* not exist. If passive is `true` and the exhange does not exist the broker
|
||||||
|
* will respond with an error and not create the exchange; exchange is created
|
||||||
|
* otherwise. Defaults to `false` (exchange is created if needed)
|
||||||
|
* @param durable Indicates whether the exchange is durable - e.g., will it
|
||||||
|
* survive a broker restart.
|
||||||
|
* @param auto_delete Indicates whether the exchange will automatically be
|
||||||
|
* removed when no queues are bound to it.
|
||||||
|
*/
|
||||||
|
void DeclareExchange(
|
||||||
|
const std::string &exchange_name,
|
||||||
|
const std::string &exchange_type = Channel::EXCHANGE_TYPE_DIRECT,
|
||||||
|
bool passive = false, bool durable = false, bool auto_delete = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Declares an exchange
|
||||||
|
*
|
||||||
|
* Creates an exchange on the AMQP broker if it does not already exist
|
||||||
|
* @param exchange_name the name of the exchange
|
||||||
|
* @param exchange_type the type of exchange to be declared. Defaults to
|
||||||
|
* `direct`; other types that could be used: `fanout`, `topic`
|
||||||
|
* @param passive Indicates how the broker should react if the exchange does
|
||||||
|
* not exist. If passive is `true` and the exhange does not exist the broker
|
||||||
|
* will respond with an error and not create the exchange; exchange is created
|
||||||
|
* otherwise. Defaults to `false` (exchange is created if needed)
|
||||||
|
* @param durable Indicates whether the exchange is durable - e.g., will it
|
||||||
|
* survive a broker restart
|
||||||
|
* @param auto_delete Indicates whether the exchange will automatically be
|
||||||
|
* removed when no queues are bound to it.
|
||||||
|
* @param arguments A table of additional arguments used when creating the
|
||||||
|
* exchange
|
||||||
|
*/
|
||||||
|
void DeclareExchange(const std::string &exchange_name,
|
||||||
|
const std::string &exchange_type, bool passive,
|
||||||
|
bool durable, bool auto_delete, const Table &arguments);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes an exchange on the AMQP broker
|
||||||
|
*
|
||||||
|
* @param exchange_name the name of the exchange to be deleted
|
||||||
|
* @param if_unused when `true`, delete the exchange only if it has no queues
|
||||||
|
* bound to it, or throw `AmqpResponseServerException`. Default `false` -
|
||||||
|
* delete regardless.
|
||||||
|
*/
|
||||||
|
void DeleteExchange(const std::string &exchange_name, bool if_unused = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Binds one exchange to another exchange using a given key
|
||||||
|
* @param destination the name of the exchange to route messages to
|
||||||
|
* @param source the name of the exchange to route messages from
|
||||||
|
* @param routing_key the routing key to use when binding
|
||||||
|
*/
|
||||||
|
void BindExchange(const std::string &destination, const std::string &source,
|
||||||
|
const std::string &routing_key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Binds one exchange to another exchange using a given key
|
||||||
|
* @param destination the name of the exchange to route messages to
|
||||||
|
* @param source the name of the exchange to route messages from
|
||||||
|
* @param routing_key the routing key to use when binding
|
||||||
|
* @param arguments A table of additional arguments used when creating the
|
||||||
|
* binding
|
||||||
|
*/
|
||||||
|
void BindExchange(const std::string &destination, const std::string &source,
|
||||||
|
const std::string &routing_key, const Table &arguments);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unbind an existing exchange-exchange binding
|
||||||
|
* @see BindExchange
|
||||||
|
* @param destination the name of the exchange to route messages to
|
||||||
|
* @param source the name of the exchange to route messages from
|
||||||
|
* @param routing_key the routing key to use when binding
|
||||||
|
*/
|
||||||
|
void UnbindExchange(const std::string &destination, const std::string &source,
|
||||||
|
const std::string &routing_key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unbind an existing exchange-exchange binding
|
||||||
|
* @see BindExchange
|
||||||
|
* @param destination the name of the exchange to route messages to
|
||||||
|
* @param source the name of the exchange to route messages from
|
||||||
|
* @param routing_key the routing key to use when binding
|
||||||
|
* @param arguments A table of additional arguments when unbinding the
|
||||||
|
* exchange
|
||||||
|
*/
|
||||||
|
void UnbindExchange(const std::string &destination, const std::string &source,
|
||||||
|
const std::string &routing_key, const Table &arguments);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks to see if a queue exists on the broker.
|
||||||
|
*
|
||||||
|
* @param queue_name the name of the exchange to check for.
|
||||||
|
* @returns true if the exchange exists on the broker, false otherwise.
|
||||||
|
*/
|
||||||
|
bool CheckQueueExists(boost::string_ref queue_name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Declare a queue
|
||||||
|
*
|
||||||
|
* Creates a queue on the AMQP broker if it does not already exist.
|
||||||
|
* @param queue_name The desired name of the queue. If this is an empty
|
||||||
|
* string, the broker will generate a queue name that this method will return.
|
||||||
|
* @param passive Indicated how the broker should react if the queue does not
|
||||||
|
* exist. The broker will raise an error if the queue doesn't already exist
|
||||||
|
* and passive is `true`. With passive `false` (the default), the queue gets
|
||||||
|
* created automatically, if needed.
|
||||||
|
* @param durable Indicates whether the exchange is durable - e.g., will it
|
||||||
|
* survive a broker restart.
|
||||||
|
* @param exclusive Indicates that only client can use the queue. Defaults to
|
||||||
|
* true. An exclusive queue is deleted when the connection is closed.
|
||||||
|
* @param auto_delete the queue will be deleted after at least one exchange
|
||||||
|
* has been bound to it, then has been unbound
|
||||||
|
* @returns The name of the queue created on the broker. Used mostly when the
|
||||||
|
* broker is asked to create a unique queue by not providing a queue name.
|
||||||
|
*/
|
||||||
|
std::string DeclareQueue(const std::string &queue_name, bool passive = false,
|
||||||
|
bool durable = false, bool exclusive = true,
|
||||||
|
bool auto_delete = true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Declares a queue
|
||||||
|
*
|
||||||
|
* Creates a queue on the AMQP broker if it does not already exist.
|
||||||
|
* @param queue_name The desired name of the queue. If this is an empty
|
||||||
|
* string, the broker will generate a queue name that this method will return.
|
||||||
|
* @param passive Indicated how the broker should react if the queue does not
|
||||||
|
* exist. The broker will raise an error if the queue doesn't already exist
|
||||||
|
* and passive is `true`. With passive `false` (the default), the queue gets
|
||||||
|
* created automatically, if needed.
|
||||||
|
* @param durable Indicates whether the exchange is durable - e.g., will it
|
||||||
|
* survive a broker restart.
|
||||||
|
* @param exclusive Indicates that only client can use the queue. Defaults to
|
||||||
|
* true. An exclusive queue is deleted when the connection is closed.
|
||||||
|
* @param auto_delete the queue will be deleted after at least one exchange
|
||||||
|
* has been bound to it, then has been unbound
|
||||||
|
* @param arguments A table of additional arguments
|
||||||
|
* @returns The name of the queue created on the broker. Used mostly when the
|
||||||
|
* broker is asked to create a unique queue by not providing a queue name.
|
||||||
|
*/
|
||||||
|
std::string DeclareQueue(const std::string &queue_name, bool passive,
|
||||||
|
bool durable, bool exclusive, bool auto_delete,
|
||||||
|
const Table &arguments);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Declares a queue and returns current message- and consumer counts
|
||||||
|
*
|
||||||
|
* Creates a queue on the AMQP broker if it does not already exist.
|
||||||
|
* @param queue_name The desired name of the queue. If this is an empty
|
||||||
|
* string, the broker will generate a queue name that this method will return.
|
||||||
|
* @param [out] message_count The current number of messages in the declared
|
||||||
|
* queue gets passed out through this argument.
|
||||||
|
* @param [out] consumer_count The current number of consumers of the declared
|
||||||
|
* queue gets passed out through this argument.
|
||||||
|
* @param passive Indicated how the broker should react if the queue does not
|
||||||
|
* exist. The broker will raise an error if the queue doesn't already exist
|
||||||
|
* and passive is `true`. With passive `false` (the default), the queue gets
|
||||||
|
* created automatically, if needed.
|
||||||
|
* @param durable Indicates whether the exchange is durable - e.g., will it
|
||||||
|
* survive a broker restart.
|
||||||
|
* @param exclusive Indicates that only client can use the queue. Defaults to
|
||||||
|
* true. An exclusive queue is deleted when the connection is closed.
|
||||||
|
* @param auto_delete the queue will be deleted after at least one exchange
|
||||||
|
* has been bound to it, then has been unbound
|
||||||
|
* @returns The name of the queue created on the broker. Used mostly when the
|
||||||
|
* broker is asked to create a unique queue by not providing a queue name.
|
||||||
|
*/
|
||||||
|
std::string DeclareQueueWithCounts(const std::string &queue_name,
|
||||||
|
boost::uint32_t &message_count,
|
||||||
|
boost::uint32_t &consumer_count,
|
||||||
|
bool passive = false, bool durable = false,
|
||||||
|
bool exclusive = true,
|
||||||
|
bool auto_delete = true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Declares a queue and returns current message- and consumer counts
|
||||||
|
*
|
||||||
|
* Creates a queue on the AMQP broker if it does not already exist.
|
||||||
|
* @param queue_name The desired name of the queue. If this is an empty
|
||||||
|
* string, the broker will generate a queue name that this method will return.
|
||||||
|
* @param [out] message_count The current number of messages in the declared
|
||||||
|
* queue gets passed out through this argument.
|
||||||
|
* @param [out] consumer_count The current number of consumers of the declared
|
||||||
|
* queue gets passed out through this argument.
|
||||||
|
* @param passive Indicated how the broker should react if the queue does not
|
||||||
|
* exist. The broker will raise an error if the queue doesn't already exist
|
||||||
|
* and passive is `true`. With passive `false` (the default), the queue gets
|
||||||
|
* created automatically, if needed.
|
||||||
|
* @param durable Indicates whether the exchange is durable - e.g., will it
|
||||||
|
* survive a broker restart.
|
||||||
|
* @param exclusive Indicates that only client can use the queue. Defaults to
|
||||||
|
* true. An exclusive queue is deleted when the connection is closed.
|
||||||
|
* @param auto_delete the queue will be deleted after at least one exchange
|
||||||
|
* has been bound to it, then has been unbound
|
||||||
|
* @param arguments A table of additional arguments
|
||||||
|
* @returns The name of the queue created on the broker. Used mostly when the
|
||||||
|
* broker is asked to create a unique queue by not providing a queue name.
|
||||||
|
*/
|
||||||
|
std::string DeclareQueueWithCounts(const std::string &queue_name,
|
||||||
|
boost::uint32_t &message_count,
|
||||||
|
boost::uint32_t &consumer_count,
|
||||||
|
bool passive, bool durable, bool exclusive,
|
||||||
|
bool auto_delete, const Table &arguments);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a queue
|
||||||
|
*
|
||||||
|
* Removes a queue from the broker. There is no indication of whether the
|
||||||
|
* queue was actually deleted on the broker.
|
||||||
|
* @param queue_name The name of the queue to remove.
|
||||||
|
* @param if_unused Only deletes the queue if the queue doesn't have any
|
||||||
|
* active consumers.
|
||||||
|
* @param if_empty Only deletes the queue if the queue is empty.
|
||||||
|
*/
|
||||||
|
void DeleteQueue(const std::string &queue_name, bool if_unused = false,
|
||||||
|
bool if_empty = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Binds a queue to an exchange
|
||||||
|
*
|
||||||
|
* Connects a queue to an exchange on the broker.
|
||||||
|
* @param queue_name The name of the queue to bind.
|
||||||
|
* @param exchange_name The name of the exchange to bind to.
|
||||||
|
* @param routing_key Defines the routing key of the binding. Only messages
|
||||||
|
* with matching routing key will be delivered to the queue from the exchange.
|
||||||
|
* Defaults to `""` which means all messages will be delivered.
|
||||||
|
*/
|
||||||
|
void BindQueue(const std::string &queue_name,
|
||||||
|
const std::string &exchange_name,
|
||||||
|
const std::string &routing_key = "");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Binds a queue to an exchange
|
||||||
|
*
|
||||||
|
* Connects a queue to an exchange on the broker.
|
||||||
|
* @param queue_name The name of the queue to bind.
|
||||||
|
* @param exchange_name The name of the exchange to bind to.
|
||||||
|
* @param routing_key Defines the routing key of the binding. Only messages
|
||||||
|
* with matching routing key will be delivered to the queue from the exchange.
|
||||||
|
* Defaults to `""` which means all messages will be delivered.
|
||||||
|
* @param arguments A table of additional arguments used when binding the
|
||||||
|
* queue
|
||||||
|
*/
|
||||||
|
void BindQueue(const std::string &queue_name,
|
||||||
|
const std::string &exchange_name,
|
||||||
|
const std::string &routing_key, const Table &arguments);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unbinds a queue from an exchange
|
||||||
|
*
|
||||||
|
* Disconnects a queue from an exchange.
|
||||||
|
* @param queue_name The name of the queue to unbind.
|
||||||
|
* @param exchange_name The name of the exchange to unbind.
|
||||||
|
* @param routing_key This must match the routing_key of the binding.
|
||||||
|
* @see BindQueue
|
||||||
|
*/
|
||||||
|
void UnbindQueue(const std::string &queue_name,
|
||||||
|
const std::string &exchange_name,
|
||||||
|
const std::string &routing_key = "");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unbinds a queue from an exchange
|
||||||
|
*
|
||||||
|
* Disconnects a queue from an exchange.
|
||||||
|
* @param queue_name The name of the queue to unbind.
|
||||||
|
* @param exchange_name The name of the exchange to unbind.
|
||||||
|
* @param routing_key This must match the routing_key of the binding.
|
||||||
|
* @param arguments A table of additional arguments.
|
||||||
|
* @see BindQueue
|
||||||
|
*/
|
||||||
|
void UnbindQueue(const std::string &queue_name,
|
||||||
|
const std::string &exchange_name,
|
||||||
|
const std::string &routing_key, const Table &arguments);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Purges a queue
|
||||||
|
*
|
||||||
|
* Removes all messages in a queue on the broker. The queue will become empty.
|
||||||
|
* @param queue_name The name of the queue to purge.
|
||||||
|
*/
|
||||||
|
void PurgeQueue(const std::string &queue_name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Acknowledges a Basic message
|
||||||
|
*
|
||||||
|
* Acknowledges a message delievered using \ref BasicGet or \ref BasicConsume.
|
||||||
|
* @param message The message that is being ack'ed.
|
||||||
|
*/
|
||||||
|
void BasicAck(const Envelope::ptr_t &message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Acknowledges a Basic message
|
||||||
|
*
|
||||||
|
* Acknowledges a message delivered using \ref BasicGet or \ref BasicConsume.
|
||||||
|
* This overload doesn't require the \ref Envelope object to acknowledge.
|
||||||
|
*
|
||||||
|
* @param info The `delivery-tag` of the message to acknowledge.
|
||||||
|
*/
|
||||||
|
void BasicAck(const Envelope::DeliveryInfo &info);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Acknowledges a Basic message
|
||||||
|
*
|
||||||
|
* Acknowledges a message delivered using \ref BasicGet or \ref BasicConsume.
|
||||||
|
* This overload doesn't require the \ref Envelope object to acknowledge.
|
||||||
|
*
|
||||||
|
* @note Ack'ing multiple messages (using `multiple=true`) is
|
||||||
|
* scoped to messages delivered on a given AMQP channel. Since
|
||||||
|
* SimpleAmqpClient uses one channel per consumer, this means that
|
||||||
|
* multiple-ack will acknowledge messages up to and including the current
|
||||||
|
* message id *for a given consumer*.
|
||||||
|
*
|
||||||
|
* @param info The `delivery-tag` of the message to acknowledge.
|
||||||
|
* @param multiple If `true`, ack all messages in this channel up to this
|
||||||
|
* delivery tag. If `false`, ack only this delivery tag.
|
||||||
|
*/
|
||||||
|
void BasicAck(const Envelope::DeliveryInfo &info, bool multiple);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reject (NAck) a Basic message
|
||||||
|
*
|
||||||
|
* Rejects a message delivered using \ref BasicGet or \ref BasicConsume
|
||||||
|
* @param message The message that is being nack'ed.
|
||||||
|
* @param requeue Tells the broker to requeue the message or not.
|
||||||
|
* @param multiple If `true`, reject all messages in this channel up to this.
|
||||||
|
*/
|
||||||
|
void BasicReject(const Envelope::ptr_t &message, bool requeue,
|
||||||
|
bool multiple = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reject (NAck) a Basic message
|
||||||
|
*
|
||||||
|
* Rejects a message delivered using \ref BasicGet or \ref BasicConsume.
|
||||||
|
* This overload doesn't require the \ref Envelope object to Reject
|
||||||
|
* @param info The `delivery-tag` of the message to Reject.
|
||||||
|
* @param requeue Tells the broker to requeue the message or not.
|
||||||
|
* @param multiple If `true`, reject all messages in this channel up to this.
|
||||||
|
*/
|
||||||
|
void BasicReject(const Envelope::DeliveryInfo &info, bool requeue,
|
||||||
|
bool multiple = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Publishes a Basic message
|
||||||
|
*
|
||||||
|
* Publishes a Basic message to an exchange
|
||||||
|
* @param exchange_name The name of the exchange to publish the message to
|
||||||
|
* @param routing_key The routing key to publish with, this is used to route
|
||||||
|
* to corresponding queue(s).
|
||||||
|
* @param message The \ref BasicMessage object to publish to the queue.
|
||||||
|
* @param mandatory Requires the message to be delivered to a queue. A
|
||||||
|
* \ref MessageReturnedException is thrown if the message cannot be routed to
|
||||||
|
* a queue.
|
||||||
|
* @param immediate Requires the message to be both routed to a queue, and
|
||||||
|
* immediately delivered to a consumer. If the message is not routed, or a
|
||||||
|
* consumer cannot immediately deliver the message,
|
||||||
|
* a \ref MessageReturnedException is thrown. This has no effect when using
|
||||||
|
* RabbitMQ v3.0 and newer.
|
||||||
|
*/
|
||||||
|
void BasicPublish(const std::string &exchange_name,
|
||||||
|
const std::string &routing_key,
|
||||||
|
const BasicMessage::ptr_t message, bool mandatory = false,
|
||||||
|
bool immediate = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronously consume a message from a queue
|
||||||
|
*
|
||||||
|
* This function will not wait for a message to arrive in a queue, it will
|
||||||
|
* return `false` if the queue is empty.
|
||||||
|
* @note This function effectively polls the broker for a message; in general,
|
||||||
|
* better performance is realized using \ref BasicConsume / \ref
|
||||||
|
* BasicConsumeMessage.
|
||||||
|
* @param [out] message A message envelope pointer that will be populated if a
|
||||||
|
* message is delivered.
|
||||||
|
* @param queue The name of the queue to try to get the message from.
|
||||||
|
* @param no_ack Can the message be un-ack'ed. Default `true` (message does
|
||||||
|
* not need to be acked).
|
||||||
|
* @returns `true` if a message was delivered, `false` if the queue was empty.
|
||||||
|
*/
|
||||||
|
bool BasicGet(Envelope::ptr_t &message, const std::string &queue,
|
||||||
|
bool no_ack = true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redeliver unacknowledged messages from the broker
|
||||||
|
* @param consumer The consumer to recover message from
|
||||||
|
*/
|
||||||
|
void BasicRecover(const std::string &consumer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts consuming Basic messages on a queue
|
||||||
|
*
|
||||||
|
* Subscribes as a consumer to a queue, so all future messages on a queue
|
||||||
|
* will be Basic.Delivered
|
||||||
|
* @note Due to a limitation to how things are done, it is only possible to
|
||||||
|
* reliably have **a single consumer per channel**; calling this
|
||||||
|
* more than once per channel may result in undefined results.
|
||||||
|
* @param queue The name of the queue to subscribe to.
|
||||||
|
* @param consumer_tag The name of the consumer. This is used to do
|
||||||
|
* operations with a consumer.
|
||||||
|
* @param no_local Defaults to true
|
||||||
|
* @param no_ack If `true`, ack'ing the message is automatically done when the
|
||||||
|
* message is delivered. Defaults to `true` (message does not have to be
|
||||||
|
* ack'ed).
|
||||||
|
* @param exclusive Means only this consumer can access the queue.
|
||||||
|
* @param message_prefetch_count Number of unacked messages the broker will
|
||||||
|
* deliver. Setting this to more than 1 will allow the broker to deliver
|
||||||
|
* messages while a current message is being processed. A value of
|
||||||
|
* 0 means no limit. This option is ignored if `no_ack = true`.
|
||||||
|
* @returns the consumer tag
|
||||||
|
*/
|
||||||
|
std::string BasicConsume(const std::string &queue,
|
||||||
|
const std::string &consumer_tag = "",
|
||||||
|
bool no_local = true, bool no_ack = true,
|
||||||
|
bool exclusive = true,
|
||||||
|
boost::uint16_t message_prefetch_count = 1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts consuming Basic messages on a queue
|
||||||
|
*
|
||||||
|
* Subscribes as a consumer to a queue, so all future messages on a queue
|
||||||
|
* will be Basic.Delivered
|
||||||
|
* @note Due to a limitation to how things are done, it is only possible to
|
||||||
|
* reliably have **a single consumer per channel**; calling this
|
||||||
|
* more than once per channel may result in undefined results.
|
||||||
|
* @param queue The name of the queue to subscribe to.
|
||||||
|
* @param consumer_tag The name of the consumer. This is used to do
|
||||||
|
* operations with a consumer.
|
||||||
|
* @param no_local Defaults to true
|
||||||
|
* @param no_ack If `true`, ack'ing the message is automatically done when the
|
||||||
|
* message is delivered. Defaults to `true` (message does not have to be
|
||||||
|
* ack'ed).
|
||||||
|
* @param exclusive Means only this consumer can access the queue.
|
||||||
|
* @param message_prefetch_count Number of unacked messages the broker will
|
||||||
|
* deliver. Setting this to more than 1 will allow the broker to deliver
|
||||||
|
* messages while a current message is being processed. A value of
|
||||||
|
* 0 means no limit. This option is ignored if `no_ack = true`.
|
||||||
|
* @param arguments A table of additional arguments when creating the consumer
|
||||||
|
* @returns the consumer tag
|
||||||
|
*/
|
||||||
|
std::string BasicConsume(const std::string &queue,
|
||||||
|
const std::string &consumer_tag, bool no_local,
|
||||||
|
bool no_ack, bool exclusive,
|
||||||
|
boost::uint16_t message_prefetch_count,
|
||||||
|
const Table &arguments);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modify consumer's message prefetch count
|
||||||
|
*
|
||||||
|
* Sets the number of unacknowledged messages that will be delivered
|
||||||
|
* by the broker to a consumer.
|
||||||
|
*
|
||||||
|
* Has no effect for consumer with `no_ack` set.
|
||||||
|
*
|
||||||
|
* @param consumer_tag The consumer tag to adjust the prefetch for.
|
||||||
|
* @param message_prefetch_count The number of unacknowledged message the
|
||||||
|
* broker will deliver. A value of 0 means no limit.
|
||||||
|
*/
|
||||||
|
void BasicQos(const std::string &consumer_tag,
|
||||||
|
boost::uint16_t message_prefetch_count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancels a previously created Consumer
|
||||||
|
*
|
||||||
|
* Unsubscribes a consumer from a queue. In other words undoes what
|
||||||
|
* \ref BasicConsume does.
|
||||||
|
* @param consumer_tag The same `consumer_tag` used when the consumer was
|
||||||
|
* created with \ref BasicConsume.
|
||||||
|
* @see BasicConsume
|
||||||
|
*/
|
||||||
|
void BasicCancel(const std::string &consumer_tag);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consumes a single message
|
||||||
|
*
|
||||||
|
* Waits for a single Basic message to be Delivered.
|
||||||
|
*
|
||||||
|
* This function only works after `BasicConsume` has successfully been called.
|
||||||
|
*
|
||||||
|
* @param consumer_tag Consumer ID (returned from \ref BasicConsume).
|
||||||
|
* @returns The next message on the queue
|
||||||
|
*/
|
||||||
|
Envelope::ptr_t BasicConsumeMessage(const std::string &consumer_tag);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consumes a single message from multiple consumers
|
||||||
|
*
|
||||||
|
* Waits for a single message to be delivered from a list of consumers.
|
||||||
|
*
|
||||||
|
* This function only works after \ref BasicConsume has been called.
|
||||||
|
*
|
||||||
|
* @returns The next message delivered from the broker
|
||||||
|
*/
|
||||||
|
Envelope::ptr_t BasicConsumeMessage(
|
||||||
|
const std::vector<std::string> &consumer_tags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consumes a single message from any open consumers
|
||||||
|
*
|
||||||
|
* Waits for a message from any consumer open on this Channel object.
|
||||||
|
*
|
||||||
|
* This function only works after \ref BasicConsume has been called.
|
||||||
|
*
|
||||||
|
* @returns The next message delivered from the broker
|
||||||
|
*/
|
||||||
|
Envelope::ptr_t BasicConsumeMessage();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consumes a single message with a timeout (gets an envelope object)
|
||||||
|
*
|
||||||
|
* Waits for a single Basic message to be Delivered or the timeout to expire.
|
||||||
|
*
|
||||||
|
* This function only works after \ref BasicConsume as been successfully
|
||||||
|
* called.
|
||||||
|
*
|
||||||
|
* This function returns an envelope object which contains more information
|
||||||
|
* about the message delivered.
|
||||||
|
*
|
||||||
|
* @param consumer_tag Consumer ID (returned from \ref BasicConsume).
|
||||||
|
* @param [out] envelope The message object to save to. Empty pointer is ok.
|
||||||
|
* @param timeout Timeout, in ms, for the first part of the message to be
|
||||||
|
* delivered
|
||||||
|
* @throws MessageReturnedException If a `basic.return` is received while
|
||||||
|
* waiting for a message.
|
||||||
|
* @returns `false` on timeout, `true` on message delivery
|
||||||
|
*/
|
||||||
|
bool BasicConsumeMessage(const std::string &consumer_tag,
|
||||||
|
Envelope::ptr_t &envelope, int timeout = -1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consumes a single message with a timeout from multiple consumers
|
||||||
|
*
|
||||||
|
* Waits for a single message to be delivered to one of the listed consumer
|
||||||
|
* tags, or for the timeout to expire.
|
||||||
|
*
|
||||||
|
* This function only works after `BasicConsume` has been successfully called.
|
||||||
|
*
|
||||||
|
* @param consumer_tags A list of the consumer tags to wait from.
|
||||||
|
* @param [out] envelope The message object that is delivered.
|
||||||
|
* @param timeout The timeout in milliseconds for the message to be
|
||||||
|
* delivered. 0 works like a non-blocking read, -1 is an infinite timeout.
|
||||||
|
* @returns `true` on message delivery, `false` on timeout.
|
||||||
|
*/
|
||||||
|
bool BasicConsumeMessage(const std::vector<std::string> &consumer_tags,
|
||||||
|
Envelope::ptr_t &envelope, int timeout = -1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consumes a single message from any consumer on a Channel
|
||||||
|
*
|
||||||
|
* Waits for a single message to be delivered to one of the consumers opened
|
||||||
|
* on this Channel, or for the timeout to occur.
|
||||||
|
*
|
||||||
|
* This function only works after \ref BasicConsume has been successfully
|
||||||
|
* called.
|
||||||
|
*
|
||||||
|
* @param [out] envelope The message object that is delivered.
|
||||||
|
* @param timeout The timeout in milliseconds for the message to be delivered.
|
||||||
|
* 0 works like a non-blocking read, -1 is an infinite timeout.
|
||||||
|
* @returns `true` on message delivery, `false` on timeout.
|
||||||
|
*/
|
||||||
|
bool BasicConsumeMessage(Envelope::ptr_t &envelope, int timeout = -1);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static ChannelImpl *OpenChannel(const std::string &host, int port,
|
||||||
|
const std::string &username,
|
||||||
|
const std::string &password,
|
||||||
|
const std::string &vhost, int frame_max,
|
||||||
|
bool sasl_external);
|
||||||
|
|
||||||
|
static ChannelImpl *OpenSecureChannel(const std::string &host, int port,
|
||||||
|
const std::string &username,
|
||||||
|
const std::string &password,
|
||||||
|
const std::string &vhost, int frame_max,
|
||||||
|
const OpenOpts::TLSParams &tls_params,
|
||||||
|
bool sasl_external);
|
||||||
|
|
||||||
|
/// PIMPL idiom
|
||||||
|
boost::scoped_ptr<ChannelImpl> m_impl;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace AmqpClient
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // SIMPLEAMQPCLIENT_CHANNEL_H
|
||||||
369
src/SimpleAmqpClient/ChannelImpl.h
Normal file
369
src/SimpleAmqpClient/ChannelImpl.h
Normal file
@@ -0,0 +1,369 @@
|
|||||||
|
#ifndef SIMPLEAMQPCLIENT_CHANNELIMPL_H
|
||||||
|
#define SIMPLEAMQPCLIENT_CHANNELIMPL_H
|
||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Put these first to avoid warnings about INT#_C macro redefinition
|
||||||
|
#include <amqp.h>
|
||||||
|
#include <amqp_framing.h>
|
||||||
|
|
||||||
|
#include <boost/array.hpp>
|
||||||
|
|
||||||
|
#include "SimpleAmqpClient/AmqpException.h"
|
||||||
|
#include "SimpleAmqpClient/BasicMessage.h"
|
||||||
|
#include "SimpleAmqpClient/Channel.h"
|
||||||
|
#include "SimpleAmqpClient/ConsumerCancelledException.h"
|
||||||
|
#include "SimpleAmqpClient/Envelope.h"
|
||||||
|
#include "SimpleAmqpClient/MessageReturnedException.h"
|
||||||
|
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
#include <boost/chrono.hpp>
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace AmqpClient {
|
||||||
|
|
||||||
|
class Channel::ChannelImpl : boost::noncopyable {
|
||||||
|
public:
|
||||||
|
ChannelImpl();
|
||||||
|
virtual ~ChannelImpl();
|
||||||
|
|
||||||
|
typedef std::vector<amqp_channel_t> channel_list_t;
|
||||||
|
typedef std::vector<amqp_frame_t> frame_queue_t;
|
||||||
|
typedef std::map<amqp_channel_t, frame_queue_t> channel_map_t;
|
||||||
|
typedef channel_map_t::iterator channel_map_iterator_t;
|
||||||
|
|
||||||
|
void DoLogin(const std::string &username, const std::string &password,
|
||||||
|
const std::string &vhost, int frame_max,
|
||||||
|
bool sasl_external = false);
|
||||||
|
amqp_channel_t GetChannel();
|
||||||
|
void ReturnChannel(amqp_channel_t channel);
|
||||||
|
bool IsChannelOpen(amqp_channel_t channel);
|
||||||
|
|
||||||
|
bool GetNextFrameFromBroker(amqp_frame_t &frame,
|
||||||
|
boost::chrono::microseconds timeout);
|
||||||
|
|
||||||
|
bool CheckForQueuedMessageOnChannel(amqp_channel_t message_on_channel) const;
|
||||||
|
void AddToFrameQueue(const amqp_frame_t &frame);
|
||||||
|
|
||||||
|
template <class ChannelListType>
|
||||||
|
bool GetNextFrameFromBrokerOnChannel(const ChannelListType channels,
|
||||||
|
amqp_frame_t &frame_out,
|
||||||
|
boost::chrono::microseconds timeout =
|
||||||
|
boost::chrono::microseconds::max()) {
|
||||||
|
boost::chrono::steady_clock::time_point end_point;
|
||||||
|
boost::chrono::microseconds timeout_left = timeout;
|
||||||
|
if (timeout != boost::chrono::microseconds::max()) {
|
||||||
|
end_point = boost::chrono::steady_clock::now() + timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_frame_t frame;
|
||||||
|
while (GetNextFrameFromBroker(frame, timeout_left)) {
|
||||||
|
if (channels.end() !=
|
||||||
|
std::find(channels.begin(), channels.end(), frame.channel)) {
|
||||||
|
frame_out = frame;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frame.channel == 0) {
|
||||||
|
// Only thing we care to handle on the channel0 is the connection.close
|
||||||
|
// method
|
||||||
|
if (AMQP_FRAME_METHOD == frame.frame_type &&
|
||||||
|
AMQP_CONNECTION_CLOSE_METHOD == frame.payload.method.id) {
|
||||||
|
FinishCloseConnection();
|
||||||
|
AmqpException::Throw(*reinterpret_cast<amqp_connection_close_t *>(
|
||||||
|
frame.payload.method.decoded));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
AddToFrameQueue(frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeout != boost::chrono::microseconds::max()) {
|
||||||
|
boost::chrono::steady_clock::time_point now =
|
||||||
|
boost::chrono::steady_clock::now();
|
||||||
|
if (now >= end_point) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
timeout_left =
|
||||||
|
boost::chrono::duration_cast<boost::chrono::microseconds>(
|
||||||
|
end_point - now);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetNextFrameOnChannel(
|
||||||
|
amqp_channel_t channel, amqp_frame_t &frame,
|
||||||
|
boost::chrono::microseconds timeout = boost::chrono::microseconds::max());
|
||||||
|
|
||||||
|
static bool is_on_channel(const amqp_frame_t frame, amqp_channel_t channel) {
|
||||||
|
return channel == frame.channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_frame_type_on_channel(const amqp_frame_t frame,
|
||||||
|
uint8_t frame_type,
|
||||||
|
amqp_channel_t channel) {
|
||||||
|
return frame.frame_type == frame_type && frame.channel == channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_method_on_channel(const amqp_frame_t frame,
|
||||||
|
amqp_method_number_t method,
|
||||||
|
amqp_channel_t channel) {
|
||||||
|
return frame.channel == channel && frame.frame_type == AMQP_FRAME_METHOD &&
|
||||||
|
frame.payload.method.id == method;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ChannelListType, class ResponseListType>
|
||||||
|
static bool is_expected_method_on_channel(
|
||||||
|
const amqp_frame_t &frame, const ChannelListType channels,
|
||||||
|
const ResponseListType &expected_responses) {
|
||||||
|
return channels.end() !=
|
||||||
|
std::find(channels.begin(), channels.end(), frame.channel) &&
|
||||||
|
AMQP_FRAME_METHOD == frame.frame_type &&
|
||||||
|
expected_responses.end() != std::find(expected_responses.begin(),
|
||||||
|
expected_responses.end(),
|
||||||
|
frame.payload.method.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ChannelListType, class ResponseListType>
|
||||||
|
bool GetMethodOnChannel(const ChannelListType channels, amqp_frame_t &frame,
|
||||||
|
const ResponseListType &expected_responses,
|
||||||
|
boost::chrono::microseconds timeout =
|
||||||
|
boost::chrono::microseconds::max()) {
|
||||||
|
frame_queue_t::iterator desired_frame = std::find_if(
|
||||||
|
m_frame_queue.begin(), m_frame_queue.end(),
|
||||||
|
boost::bind(
|
||||||
|
&ChannelImpl::is_expected_method_on_channel<ChannelListType,
|
||||||
|
ResponseListType>,
|
||||||
|
_1, channels, expected_responses));
|
||||||
|
|
||||||
|
if (m_frame_queue.end() != desired_frame) {
|
||||||
|
frame = *desired_frame;
|
||||||
|
m_frame_queue.erase(desired_frame);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::chrono::steady_clock::time_point end_point;
|
||||||
|
boost::chrono::microseconds timeout_left = timeout;
|
||||||
|
if (timeout != boost::chrono::microseconds::max()) {
|
||||||
|
end_point = boost::chrono::steady_clock::now() + timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_frame_t incoming_frame;
|
||||||
|
while (GetNextFrameFromBrokerOnChannel(channels, incoming_frame,
|
||||||
|
timeout_left)) {
|
||||||
|
if (is_expected_method_on_channel(incoming_frame, channels,
|
||||||
|
expected_responses)) {
|
||||||
|
frame = incoming_frame;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (AMQP_FRAME_METHOD == incoming_frame.frame_type &&
|
||||||
|
AMQP_CHANNEL_CLOSE_METHOD == incoming_frame.payload.method.id) {
|
||||||
|
FinishCloseChannel(incoming_frame.channel);
|
||||||
|
try {
|
||||||
|
AmqpException::Throw(*reinterpret_cast<amqp_channel_close_t *>(
|
||||||
|
incoming_frame.payload.method.decoded));
|
||||||
|
} catch (AmqpException &) {
|
||||||
|
MaybeReleaseBuffersOnChannel(incoming_frame.channel);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_frame_queue.push_back(incoming_frame);
|
||||||
|
|
||||||
|
if (timeout != boost::chrono::microseconds::max()) {
|
||||||
|
boost::chrono::steady_clock::time_point now =
|
||||||
|
boost::chrono::steady_clock::now();
|
||||||
|
if (now >= end_point) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
timeout_left =
|
||||||
|
boost::chrono::duration_cast<boost::chrono::microseconds>(
|
||||||
|
end_point - now);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ResponseListType>
|
||||||
|
amqp_frame_t DoRpcOnChannel(amqp_channel_t channel, boost::uint32_t method_id,
|
||||||
|
void *decoded,
|
||||||
|
const ResponseListType &expected_responses) {
|
||||||
|
CheckForError(amqp_send_method(m_connection, channel, method_id, decoded));
|
||||||
|
|
||||||
|
amqp_frame_t response;
|
||||||
|
boost::array<amqp_channel_t, 1> channels = {{channel}};
|
||||||
|
|
||||||
|
GetMethodOnChannel(channels, response, expected_responses);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ResponseListType>
|
||||||
|
amqp_frame_t DoRpc(boost::uint32_t method_id, void *decoded,
|
||||||
|
const ResponseListType &expected_responses) {
|
||||||
|
amqp_channel_t channel = GetChannel();
|
||||||
|
amqp_frame_t ret =
|
||||||
|
DoRpcOnChannel(channel, method_id, decoded, expected_responses);
|
||||||
|
ReturnChannel(channel);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ChannelListType>
|
||||||
|
static bool envelope_on_channel(const Envelope::ptr_t &envelope,
|
||||||
|
const ChannelListType channels) {
|
||||||
|
return channels.end() != std::find(channels.begin(), channels.end(),
|
||||||
|
envelope->DeliveryChannel());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ChannelListType>
|
||||||
|
bool ConsumeMessageOnChannel(const ChannelListType channels,
|
||||||
|
Envelope::ptr_t &message, int timeout) {
|
||||||
|
envelope_list_t::iterator it = std::find_if(
|
||||||
|
m_delivered_messages.begin(), m_delivered_messages.end(),
|
||||||
|
boost::bind(ChannelImpl::envelope_on_channel<ChannelListType>, _1,
|
||||||
|
channels));
|
||||||
|
|
||||||
|
if (it != m_delivered_messages.end()) {
|
||||||
|
message = *it;
|
||||||
|
m_delivered_messages.erase(it);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ConsumeMessageOnChannelInner(channels, message, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ChannelListType>
|
||||||
|
bool ConsumeMessageOnChannelInner(const ChannelListType channels,
|
||||||
|
Envelope::ptr_t &message, int timeout) {
|
||||||
|
const boost::array<boost::uint32_t, 2> DELIVER_OR_CANCEL = {
|
||||||
|
{AMQP_BASIC_DELIVER_METHOD, AMQP_BASIC_CANCEL_METHOD}};
|
||||||
|
|
||||||
|
boost::chrono::microseconds real_timeout =
|
||||||
|
(timeout >= 0 ? boost::chrono::milliseconds(timeout)
|
||||||
|
: boost::chrono::microseconds::max());
|
||||||
|
|
||||||
|
amqp_frame_t deliver;
|
||||||
|
if (!GetMethodOnChannel(channels, deliver, DELIVER_OR_CANCEL,
|
||||||
|
real_timeout)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AMQP_BASIC_CANCEL_METHOD == deliver.payload.method.id) {
|
||||||
|
amqp_basic_cancel_t *cancel_method =
|
||||||
|
reinterpret_cast<amqp_basic_cancel_t *>(
|
||||||
|
deliver.payload.method.decoded);
|
||||||
|
std::string consumer_tag((char *)cancel_method->consumer_tag.bytes,
|
||||||
|
cancel_method->consumer_tag.len);
|
||||||
|
|
||||||
|
RemoveConsumer(consumer_tag);
|
||||||
|
ReturnChannel(deliver.channel);
|
||||||
|
MaybeReleaseBuffersOnChannel(deliver.channel);
|
||||||
|
|
||||||
|
throw ConsumerCancelledException(consumer_tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_basic_deliver_t *deliver_method =
|
||||||
|
reinterpret_cast<amqp_basic_deliver_t *>(
|
||||||
|
deliver.payload.method.decoded);
|
||||||
|
|
||||||
|
const std::string exchange((char *)deliver_method->exchange.bytes,
|
||||||
|
deliver_method->exchange.len);
|
||||||
|
const std::string routing_key((char *)deliver_method->routing_key.bytes,
|
||||||
|
deliver_method->routing_key.len);
|
||||||
|
const std::string in_consumer_tag(
|
||||||
|
(char *)deliver_method->consumer_tag.bytes,
|
||||||
|
deliver_method->consumer_tag.len);
|
||||||
|
const boost::uint64_t delivery_tag = deliver_method->delivery_tag;
|
||||||
|
const bool redelivered = (deliver_method->redelivered == 0 ? false : true);
|
||||||
|
MaybeReleaseBuffersOnChannel(deliver.channel);
|
||||||
|
|
||||||
|
BasicMessage::ptr_t content = ReadContent(deliver.channel);
|
||||||
|
MaybeReleaseBuffersOnChannel(deliver.channel);
|
||||||
|
|
||||||
|
message = Envelope::Create(content, in_consumer_tag, delivery_tag, exchange,
|
||||||
|
redelivered, routing_key, deliver.channel);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_channel_t CreateNewChannel();
|
||||||
|
amqp_channel_t GetNextChannelId();
|
||||||
|
|
||||||
|
void CheckRpcReply(amqp_channel_t channel, const amqp_rpc_reply_t &reply);
|
||||||
|
void CheckForError(int ret);
|
||||||
|
|
||||||
|
void CheckFrameForClose(amqp_frame_t &frame, amqp_channel_t channel);
|
||||||
|
void FinishCloseChannel(amqp_channel_t channel);
|
||||||
|
void FinishCloseConnection();
|
||||||
|
|
||||||
|
MessageReturnedException CreateMessageReturnedException(
|
||||||
|
amqp_basic_return_t &return_method, amqp_channel_t channel);
|
||||||
|
AmqpClient::BasicMessage::ptr_t ReadContent(amqp_channel_t channel);
|
||||||
|
|
||||||
|
void AddConsumer(const std::string &consumer_tag, amqp_channel_t channel);
|
||||||
|
amqp_channel_t RemoveConsumer(const std::string &consumer_tag);
|
||||||
|
amqp_channel_t GetConsumerChannel(const std::string &consumer_tag);
|
||||||
|
std::vector<amqp_channel_t> GetAllConsumerChannels() const;
|
||||||
|
|
||||||
|
void MaybeReleaseBuffersOnChannel(amqp_channel_t channel);
|
||||||
|
void CheckIsConnected();
|
||||||
|
void SetIsConnected(bool state) { m_is_connected = state; }
|
||||||
|
|
||||||
|
// The RabbitMQ broker changed the way that basic.qos worked as of v3.3.0.
|
||||||
|
// See: http://www.rabbitmq.com/consumer-prefetch.html
|
||||||
|
// Newer versions of RabbitMQ basic.qos.global set to false applies to new
|
||||||
|
// consumers made on the channel, and true applies to all consumers on the
|
||||||
|
// channel (not connection).
|
||||||
|
bool BrokerHasNewQosBehavior() const { return 0x030300 <= m_brokerVersion; }
|
||||||
|
|
||||||
|
amqp_connection_state_t m_connection;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static boost::uint32_t ComputeBrokerVersion(
|
||||||
|
const amqp_connection_state_t state);
|
||||||
|
|
||||||
|
frame_queue_t m_frame_queue;
|
||||||
|
|
||||||
|
typedef std::vector<Envelope::ptr_t> envelope_list_t;
|
||||||
|
envelope_list_t m_delivered_messages;
|
||||||
|
|
||||||
|
typedef std::map<std::string, amqp_channel_t> consumer_map_t;
|
||||||
|
consumer_map_t m_consumer_channel_map;
|
||||||
|
|
||||||
|
enum channel_state_t { CS_Closed = 0, CS_Open, CS_Used };
|
||||||
|
typedef std::vector<channel_state_t> channel_state_list_t;
|
||||||
|
|
||||||
|
channel_state_list_t m_channels;
|
||||||
|
boost::uint32_t m_brokerVersion;
|
||||||
|
// A channel that is likely to be an CS_Open state
|
||||||
|
amqp_channel_t m_last_used_channel;
|
||||||
|
|
||||||
|
bool m_is_connected;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace AmqpClient
|
||||||
|
#endif // SIMPLEAMQPCLIENT_CHANNELIMPL_H
|
||||||
51
src/SimpleAmqpClient/ConnectionClosedException.h
Normal file
51
src/SimpleAmqpClient/ConnectionClosedException.h
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
#ifndef SIMPLEAMQPCLIENT_CONNECTIONCLOSEDEXCEPTION_H
|
||||||
|
#define SIMPLEAMQPCLIENT_CONNECTIONCLOSEDEXCEPTION_H
|
||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include "SimpleAmqpClient/Util.h"
|
||||||
|
|
||||||
|
/// @file SimpleAmqpClient/ConnectionClosedException.h
|
||||||
|
/// Defines AmqpClient::ConnectionClosedException
|
||||||
|
|
||||||
|
namespace AmqpClient {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "Connection is closed" exception
|
||||||
|
*/
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT ConnectionClosedException
|
||||||
|
: public std::runtime_error {
|
||||||
|
public:
|
||||||
|
/// Constructor
|
||||||
|
explicit ConnectionClosedException()
|
||||||
|
: std::runtime_error("Connection is closed") {}
|
||||||
|
};
|
||||||
|
} // namespace AmqpClient
|
||||||
|
#endif // SIMPLEAMQPCLIENT_CONNECTIONCLOSEDEXCEPTION_H
|
||||||
67
src/SimpleAmqpClient/ConsumerCancelledException.h
Normal file
67
src/SimpleAmqpClient/ConsumerCancelledException.h
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#ifndef SIMPLEAMQPCLIENT_CONSUMERCANCELLEDEXCEPTION_H
|
||||||
|
#define SIMPLEAMQPCLIENT_CONSUMERCANCELLEDEXCEPTION_H
|
||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "SimpleAmqpClient/Util.h"
|
||||||
|
|
||||||
|
/// @file SimpleAmqpClient/ConsumerCancelledException.h
|
||||||
|
/// Defines AmqpClient::ConsumerCancelledException
|
||||||
|
|
||||||
|
namespace AmqpClient {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "Consumer was cancelled" exception
|
||||||
|
*
|
||||||
|
* Happens when the server ends a consumer subscription, e.g. when the
|
||||||
|
* subscribed queue is being deleted, or when a client issues basic.cancel
|
||||||
|
* request.
|
||||||
|
*/
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT ConsumerCancelledException
|
||||||
|
: public std::runtime_error {
|
||||||
|
public:
|
||||||
|
/// Constructor
|
||||||
|
explicit ConsumerCancelledException(const std::string &consumer_tag) throw()
|
||||||
|
: std::runtime_error(
|
||||||
|
std::string("Consumer was cancelled: ").append(consumer_tag)),
|
||||||
|
m_consumer_tag(consumer_tag) {}
|
||||||
|
|
||||||
|
/// Destructor
|
||||||
|
virtual ~ConsumerCancelledException() throw() {}
|
||||||
|
|
||||||
|
/// Getter of the consumer tag
|
||||||
|
std::string GetConsumerTag() const { return m_consumer_tag; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_consumer_tag;
|
||||||
|
};
|
||||||
|
} // namespace AmqpClient
|
||||||
|
#endif // SIMPLEAMQPCLIENT_CONSUMERCANCELLEDEXCEPTION_H
|
||||||
61
src/SimpleAmqpClient/ConsumerTagNotFoundException.h
Normal file
61
src/SimpleAmqpClient/ConsumerTagNotFoundException.h
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
#ifndef SIMPLEAMQPCLIENT_CONSUMERTAGNOTFOUND_H
|
||||||
|
#define SIMPLEAMQPCLIENT_CONSUMERTAGNOTFOUND_H
|
||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include "Util.h"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4251 4275)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// @file SimpleAmqpClient/ConsumerTagNotFoundException.h
|
||||||
|
/// Defines AmqpClient::ConsumerTagNotFoundException
|
||||||
|
|
||||||
|
namespace AmqpClient {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "Consumer tag not found" exception
|
||||||
|
*
|
||||||
|
* @see BasicConsume
|
||||||
|
*/
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT ConsumerTagNotFoundException
|
||||||
|
: public std::runtime_error {
|
||||||
|
public:
|
||||||
|
/// Constructor
|
||||||
|
ConsumerTagNotFoundException() throw()
|
||||||
|
: std::runtime_error("The specified consumer tag is unknown") {}
|
||||||
|
/// Destructor
|
||||||
|
virtual ~ConsumerTagNotFoundException() throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace AmqpClient
|
||||||
|
#endif // SIMPLEAMQPCLIENT_CONSUMERTAGNOTFOUND_H
|
||||||
211
src/SimpleAmqpClient/Envelope.h
Normal file
211
src/SimpleAmqpClient/Envelope.h
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
#ifndef SIMPLEAMQPCLIENT_ENVELOPE_H
|
||||||
|
#define SIMPLEAMQPCLIENT_ENVELOPE_H
|
||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <boost/cstdint.hpp>
|
||||||
|
#include <boost/make_shared.hpp>
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "SimpleAmqpClient/BasicMessage.h"
|
||||||
|
#include "SimpleAmqpClient/Util.h"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4275 4251)
|
||||||
|
#endif // _MSC_VER
|
||||||
|
|
||||||
|
/// @file SimpleAmqpClient/Envelope.h
|
||||||
|
/// The AmqpClient::Envelope class is defined in this header file.
|
||||||
|
|
||||||
|
namespace AmqpClient {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A "message envelope" object containing the message body and delivery metadata
|
||||||
|
*/
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT Envelope : boost::noncopyable {
|
||||||
|
public:
|
||||||
|
/// a `shared_ptr` pointer to Envelope
|
||||||
|
typedef boost::shared_ptr<Envelope> ptr_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an new envelope object
|
||||||
|
* @param message the payload
|
||||||
|
* @param consumer_tag the consumer tag the message was delivered to
|
||||||
|
* @param delivery_tag the delivery tag that the broker assigned to the
|
||||||
|
* message
|
||||||
|
* @param exchange the name of the exchange that the message was published to
|
||||||
|
* @param redelivered a flag indicating whether the message consumed as a
|
||||||
|
* result of a redelivery
|
||||||
|
* @param routing_key the routing key that the message was published with
|
||||||
|
* @param delivery_channel channel ID of the delivery (see DeliveryInfo)
|
||||||
|
* @returns a boost::shared_ptr to an envelope object
|
||||||
|
*/
|
||||||
|
static ptr_t Create(const BasicMessage::ptr_t message,
|
||||||
|
const std::string &consumer_tag,
|
||||||
|
const boost::uint64_t delivery_tag,
|
||||||
|
const std::string &exchange, bool redelivered,
|
||||||
|
const std::string &routing_key,
|
||||||
|
const boost::uint16_t delivery_channel) {
|
||||||
|
return boost::make_shared<Envelope>(message, consumer_tag, delivery_tag,
|
||||||
|
exchange, redelivered, routing_key,
|
||||||
|
delivery_channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new Envelope object
|
||||||
|
* @param message the payload
|
||||||
|
* @param consumer_tag the consumer tag the message was delivered to
|
||||||
|
* @param delivery_tag the delivery tag that the broker assigned to the
|
||||||
|
* message
|
||||||
|
* @param exchange the name of the exchange that the message was published to
|
||||||
|
* @param redelivered a flag indicating whether the message consumed as a
|
||||||
|
* result of a redelivery
|
||||||
|
* @param routing_key the routing key that the message was published with
|
||||||
|
* @param delivery_channel channel ID of the delivery (see DeliveryInfo)
|
||||||
|
*/
|
||||||
|
explicit Envelope(const BasicMessage::ptr_t message,
|
||||||
|
const std::string &consumer_tag,
|
||||||
|
const boost::uint64_t delivery_tag,
|
||||||
|
const std::string &exchange, bool redelivered,
|
||||||
|
const std::string &routing_key,
|
||||||
|
const boost::uint16_t delivery_channel);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* destructor
|
||||||
|
*/
|
||||||
|
virtual ~Envelope();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the payload of the envelope
|
||||||
|
*
|
||||||
|
* @returns the message
|
||||||
|
*/
|
||||||
|
inline BasicMessage::ptr_t Message() const { return m_message; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the consumer tag for the consumer that delivered the message
|
||||||
|
*
|
||||||
|
* @returns the consumer that delivered the message
|
||||||
|
*/
|
||||||
|
inline std::string ConsumerTag() const { return m_consumerTag; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the delivery tag for the message.
|
||||||
|
*
|
||||||
|
* The delivery tag is a unique tag for a given message assigned by the
|
||||||
|
* broker
|
||||||
|
* This tag is used when Ack'ing a message
|
||||||
|
*
|
||||||
|
* @returns the delivery tag for a message
|
||||||
|
*/
|
||||||
|
inline boost::uint64_t DeliveryTag() const { return m_deliveryTag; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of the exchange that the message was published to
|
||||||
|
*
|
||||||
|
* @returns the name of the exchange the message was published to
|
||||||
|
*/
|
||||||
|
inline std::string Exchange() const { return m_exchange; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the flag that indicates whether the message was redelivered
|
||||||
|
*
|
||||||
|
* A flag that indicates whether the message was redelievered means
|
||||||
|
* the broker tried to deliver the message and the client did not Ack
|
||||||
|
* the message, so the message was requeued, or the client asked the broker
|
||||||
|
* to Recover which forced all non-Acked messages to be redelivered
|
||||||
|
*
|
||||||
|
* @return a boolean flag indicating whether the message was redelivered
|
||||||
|
*/
|
||||||
|
inline bool Redelivered() const { return m_redelivered; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the routing key that the message was published with
|
||||||
|
*
|
||||||
|
* @returns a string containing the routing key the message was published
|
||||||
|
* with
|
||||||
|
*/
|
||||||
|
inline std::string RoutingKey() const { return m_routingKey; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the delivery channel
|
||||||
|
*/
|
||||||
|
inline boost::uint16_t DeliveryChannel() const { return m_deliveryChannel; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A POD carrier of delivery-tag
|
||||||
|
*
|
||||||
|
* This is server-assigned and channel-specific.
|
||||||
|
*
|
||||||
|
* The delivery tag is valid only within the channel from which the message
|
||||||
|
* was received. I.e. a client MUST NOT receive a message on one channel and
|
||||||
|
* then acknowledge it on another.
|
||||||
|
*
|
||||||
|
* The server MUST NOT use a zero value for delivery tags. Zero is reserved
|
||||||
|
* for client use, meaning "all messages so far received".
|
||||||
|
*/
|
||||||
|
struct DeliveryInfo {
|
||||||
|
/// A delivery tag, assigned by the broker to identify this delivery within
|
||||||
|
/// a channel
|
||||||
|
boost::uint64_t delivery_tag;
|
||||||
|
/// An ID of the delivery channel
|
||||||
|
boost::uint16_t delivery_channel;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter of the delivery-tag
|
||||||
|
*/
|
||||||
|
inline DeliveryInfo GetDeliveryInfo() const {
|
||||||
|
DeliveryInfo info;
|
||||||
|
info.delivery_tag = m_deliveryTag;
|
||||||
|
info.delivery_channel = m_deliveryChannel;
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const BasicMessage::ptr_t m_message;
|
||||||
|
const std::string m_consumerTag;
|
||||||
|
const boost::uint64_t m_deliveryTag;
|
||||||
|
const std::string m_exchange;
|
||||||
|
const bool m_redelivered;
|
||||||
|
const std::string m_routingKey;
|
||||||
|
const boost::uint16_t m_deliveryChannel;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace AmqpClient
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif // _MSC_VER
|
||||||
|
|
||||||
|
#endif // SIMPLEAMQPCLIENT_ENVELOPE_H
|
||||||
70
src/SimpleAmqpClient/MessageRejectedException.h
Normal file
70
src/SimpleAmqpClient/MessageRejectedException.h
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
#ifndef SIMPLEAMQPCLIENT_MESSAGEREJECTEDEXCEPTION_H
|
||||||
|
#define SIMPLEAMQPCLIENT_MESSAGEREJECTEDEXCEPTION_H
|
||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <boost/cstdint.hpp>
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include "SimpleAmqpClient/BasicMessage.h"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4251 4275)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// @file SimpleAmqpClient/MessageReturnedException.h
|
||||||
|
/// Defines AmqpClient::MessageReturnedException
|
||||||
|
|
||||||
|
namespace AmqpClient {
|
||||||
|
|
||||||
|
/// "Message rejected" exception
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT MessageRejectedException
|
||||||
|
: public std::runtime_error {
|
||||||
|
public:
|
||||||
|
MessageRejectedException(uint64_t delivery_tag)
|
||||||
|
: std::runtime_error(
|
||||||
|
std::string("Message rejected: ")
|
||||||
|
.append(boost::lexical_cast<std::string>(delivery_tag))),
|
||||||
|
m_delivery_tag(delivery_tag) {}
|
||||||
|
|
||||||
|
/// `delivery_tag` getter
|
||||||
|
uint64_t GetDeliveryTag() { return m_delivery_tag; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint64_t m_delivery_tag;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace AmqpClient
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // SIMPLEAMQPCLIENT_MESSAGEREJECTEDEXCEPTION_H
|
||||||
85
src/SimpleAmqpClient/MessageReturnedException.h
Normal file
85
src/SimpleAmqpClient/MessageReturnedException.h
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
#ifndef SIMPLEAMQPCLIENT_MESSAGERETURNEDEXCEPTION_H
|
||||||
|
#define SIMPLEAMQPCLIENT_MESSAGERETURNEDEXCEPTION_H
|
||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <boost/cstdint.hpp>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include "SimpleAmqpClient/BasicMessage.h"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4251 4275)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// @file SimpleAmqpClient/MessageReturnedException.h
|
||||||
|
/// Defines AmqpClient::MessageReturnedException
|
||||||
|
|
||||||
|
namespace AmqpClient {
|
||||||
|
|
||||||
|
/// "Message returned" exception.
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT MessageReturnedException
|
||||||
|
: public std::runtime_error {
|
||||||
|
public:
|
||||||
|
/// Constructor.
|
||||||
|
explicit MessageReturnedException(BasicMessage::ptr_t message,
|
||||||
|
boost::uint32_t reply_code,
|
||||||
|
const std::string &reply_text,
|
||||||
|
const std::string &exchange,
|
||||||
|
const std::string &routing_key) throw();
|
||||||
|
|
||||||
|
virtual ~MessageReturnedException() throw() {}
|
||||||
|
|
||||||
|
/// `message` getter
|
||||||
|
BasicMessage::ptr_t message() const throw() { return m_message; }
|
||||||
|
/// `reply_code` getter
|
||||||
|
boost::uint32_t reply_code() const throw() { return m_reply_code; }
|
||||||
|
/// `reply_text` getter
|
||||||
|
std::string reply_text() const throw() { return m_reply_text; }
|
||||||
|
/// Exchange name getter
|
||||||
|
std::string exchange() const throw() { return m_exchange; }
|
||||||
|
/// Routing key getter
|
||||||
|
std::string routing_key() const throw() { return m_routing_key; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
BasicMessage::ptr_t m_message;
|
||||||
|
boost::uint32_t m_reply_code;
|
||||||
|
std::string m_reply_text;
|
||||||
|
std::string m_exchange;
|
||||||
|
std::string m_routing_key;
|
||||||
|
mutable std::string m_what;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace AmqpClient
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // SIMPLEAMQPCLIENT_MESSAGERETURNEDEXCEPTION_H
|
||||||
49
src/SimpleAmqpClient/SimpleAmqpClient.h
Normal file
49
src/SimpleAmqpClient/SimpleAmqpClient.h
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#ifndef SIMPLEAMQPCLIENT_SIMPLEAMQPCLIENT_H
|
||||||
|
#define SIMPLEAMQPCLIENT_SIMPLEAMQPCLIENT_H
|
||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// @file SimpleAmqpClient/SimpleAmqpClient.h
|
||||||
|
/// This "include all" header file re-exports all of SimpleAmqpClient public API
|
||||||
|
|
||||||
|
#include "SimpleAmqpClient/AmqpException.h"
|
||||||
|
#include "SimpleAmqpClient/AmqpLibraryException.h"
|
||||||
|
#include "SimpleAmqpClient/AmqpResponseLibraryException.h"
|
||||||
|
#include "SimpleAmqpClient/BadUriException.h"
|
||||||
|
#include "SimpleAmqpClient/BasicMessage.h"
|
||||||
|
#include "SimpleAmqpClient/Channel.h"
|
||||||
|
#include "SimpleAmqpClient/ConnectionClosedException.h"
|
||||||
|
#include "SimpleAmqpClient/ConsumerCancelledException.h"
|
||||||
|
#include "SimpleAmqpClient/ConsumerTagNotFoundException.h"
|
||||||
|
#include "SimpleAmqpClient/Envelope.h"
|
||||||
|
#include "SimpleAmqpClient/MessageRejectedException.h"
|
||||||
|
#include "SimpleAmqpClient/MessageReturnedException.h"
|
||||||
|
#include "SimpleAmqpClient/Table.h"
|
||||||
|
#include "SimpleAmqpClient/Version.h"
|
||||||
|
|
||||||
|
#endif // SIMPLEAMQPCLIENT_SIMPLEAMQPCLIENT_H
|
||||||
501
src/SimpleAmqpClient/Table.h
Normal file
501
src/SimpleAmqpClient/Table.h
Normal file
@@ -0,0 +1,501 @@
|
|||||||
|
#ifndef SIMPLEAMQPCLIENT_TABLE_H
|
||||||
|
#define SIMPLEAMQPCLIENT_TABLE_H
|
||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <boost/cstdint.hpp>
|
||||||
|
#include <boost/scoped_ptr.hpp>
|
||||||
|
#include <ctime>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "SimpleAmqpClient/Util.h"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4251)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// @file SimpleAmqpClient/Table.h
|
||||||
|
/// The AmqpClient::TableValue variant is defined in this header file
|
||||||
|
|
||||||
|
namespace AmqpClient {
|
||||||
|
|
||||||
|
namespace Detail {
|
||||||
|
class TableValueImpl;
|
||||||
|
} // namespace Detail
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table key
|
||||||
|
*
|
||||||
|
* Note this must be less than 128 bytes long
|
||||||
|
*/
|
||||||
|
typedef std::string TableKey;
|
||||||
|
|
||||||
|
class TableValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array field value
|
||||||
|
*/
|
||||||
|
typedef std::vector<TableValue> Array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Field table
|
||||||
|
*
|
||||||
|
* Is just an STL map
|
||||||
|
*/
|
||||||
|
typedef std::map<TableKey, TableValue> Table;
|
||||||
|
|
||||||
|
typedef Table::value_type TableEntry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A variant type for the Table Value
|
||||||
|
*/
|
||||||
|
class SIMPLEAMQPCLIENT_EXPORT TableValue {
|
||||||
|
public:
|
||||||
|
friend class Detail::TableValueImpl;
|
||||||
|
|
||||||
|
/** Types enumeration */
|
||||||
|
enum ValueType {
|
||||||
|
VT_void = 0, ///< void type
|
||||||
|
VT_bool = 1, ///< boolean type
|
||||||
|
VT_int8 = 2, ///< 1-byte/char signed type
|
||||||
|
VT_int16 = 3, ///< 2-byte/short signed type
|
||||||
|
VT_int32 = 4, ///< 4-byte/int signed type
|
||||||
|
VT_int64 = 5, ///< 8-byte/long long int signed type
|
||||||
|
VT_float = 6, ///< single-precision floating point type
|
||||||
|
VT_double = 7, ///< double-precision floating point type
|
||||||
|
VT_string = 8, ///< string type
|
||||||
|
VT_array = 9, ///< array of TableValues type
|
||||||
|
VT_table = 10, ///< a table type
|
||||||
|
VT_uint8 = 11, ///< 1-byte/char unsigned type
|
||||||
|
VT_uint16 = 12, ///< 2-byte/short unsigned type
|
||||||
|
VT_uint32 = 13, ///< 4-byte/int unsigned type
|
||||||
|
VT_timestamp = 14, ///< std::time_t type
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct void table value
|
||||||
|
*
|
||||||
|
* A table value that doesn't have any value associated with it
|
||||||
|
*/
|
||||||
|
TableValue();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a boolean table value
|
||||||
|
*
|
||||||
|
* @param [in] value the value
|
||||||
|
*/
|
||||||
|
TableValue(bool value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a 1-byte unsigned integer value
|
||||||
|
*
|
||||||
|
* @param [in] value the value
|
||||||
|
*/
|
||||||
|
TableValue(boost::uint8_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a 1-byte signed integer value
|
||||||
|
*
|
||||||
|
* @param [in] value the value
|
||||||
|
*/
|
||||||
|
TableValue(boost::int8_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a 2-byte unsigned integer value
|
||||||
|
*
|
||||||
|
* @param [in] value the value
|
||||||
|
*/
|
||||||
|
TableValue(boost::uint16_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a 2-byte signed integer value
|
||||||
|
*
|
||||||
|
* @param [in] value the value
|
||||||
|
*/
|
||||||
|
TableValue(boost::int16_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a 4-byte unsigned integer value
|
||||||
|
*
|
||||||
|
* @param [in] value the value
|
||||||
|
*/
|
||||||
|
TableValue(boost::uint32_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a 4-byte signed integer value
|
||||||
|
*
|
||||||
|
* @param [in] value the value
|
||||||
|
*/
|
||||||
|
TableValue(boost::int32_t value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Private
|
||||||
|
*
|
||||||
|
* RabbitMQ does not support unsigned 64-bit values in tables,
|
||||||
|
* however, timestamps are used for this.
|
||||||
|
*/
|
||||||
|
TableValue(boost::uint64_t value);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Construct an AMQP timestamp TableValue
|
||||||
|
*
|
||||||
|
* This seconds since epoch.
|
||||||
|
*
|
||||||
|
* @param [in] value the value
|
||||||
|
*/
|
||||||
|
static TableValue Timestamp(std::time_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a 8-byte signed integer value
|
||||||
|
*
|
||||||
|
* @param [in] value the value
|
||||||
|
*/
|
||||||
|
TableValue(boost::int64_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a single-precision floating point value
|
||||||
|
*
|
||||||
|
* @param [in] value the value
|
||||||
|
*/
|
||||||
|
TableValue(float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a double-precision floating point value
|
||||||
|
*
|
||||||
|
* @param [in] value the value
|
||||||
|
*/
|
||||||
|
TableValue(double value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a character string value
|
||||||
|
*
|
||||||
|
* @param [in] value the value
|
||||||
|
*/
|
||||||
|
TableValue(const char *value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a character string value
|
||||||
|
*
|
||||||
|
* @param [in] value the value
|
||||||
|
*/
|
||||||
|
TableValue(const std::string &value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct an array value
|
||||||
|
*
|
||||||
|
* @param [in] values the value
|
||||||
|
*/
|
||||||
|
TableValue(const std::vector<TableValue> &values);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a Table value
|
||||||
|
*
|
||||||
|
* @param [in] value the value
|
||||||
|
*/
|
||||||
|
TableValue(const Table &value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy-constructor
|
||||||
|
*/
|
||||||
|
TableValue(const TableValue &l);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assignment operator
|
||||||
|
*/
|
||||||
|
TableValue &operator=(const TableValue &l);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Equality operator
|
||||||
|
*/
|
||||||
|
bool operator==(const TableValue &l) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In-equality operator
|
||||||
|
*/
|
||||||
|
bool operator!=(const TableValue &l) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor
|
||||||
|
*/
|
||||||
|
virtual ~TableValue();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the type
|
||||||
|
*/
|
||||||
|
ValueType GetType() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the boolean value
|
||||||
|
*
|
||||||
|
* @returns the value if its a VT_bool type, false otherwise
|
||||||
|
*/
|
||||||
|
bool GetBool() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the uint8 value
|
||||||
|
*
|
||||||
|
* @returns the value if its a VT_uint8 type, 0 otherwise
|
||||||
|
*/
|
||||||
|
boost::uint8_t GetUint8() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the int8 value
|
||||||
|
*
|
||||||
|
* @returns the value if its a VT_int8 type, 0 otherwise
|
||||||
|
*/
|
||||||
|
boost::int8_t GetInt8() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the uint16 value
|
||||||
|
*
|
||||||
|
* @returns the value if its a VT_uint16 type, 0 otherwise
|
||||||
|
*/
|
||||||
|
boost::uint16_t GetUint16() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the int16 value
|
||||||
|
*
|
||||||
|
* @returns the value if its a VT_int16 type, 0 otherwise
|
||||||
|
*/
|
||||||
|
boost::int16_t GetInt16() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the uint32 value
|
||||||
|
*
|
||||||
|
* @returns the value if its a VT_uint32 type, 0 otherwise
|
||||||
|
*/
|
||||||
|
boost::uint32_t GetUint32() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the int32 value
|
||||||
|
*
|
||||||
|
* @returns the value if its a VT_int32 type, 0 otherwise
|
||||||
|
*/
|
||||||
|
boost::int32_t GetInt32() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the uint64 value
|
||||||
|
*
|
||||||
|
* @returns the value if its a VT_uint64 type, 0 otherwise
|
||||||
|
*/
|
||||||
|
boost::uint64_t GetUint64() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the timestamp value
|
||||||
|
*
|
||||||
|
* @returns the value if its a VT_timestamp type, 0 otherwise
|
||||||
|
*/
|
||||||
|
std::time_t GetTimestamp() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the int64 value
|
||||||
|
*
|
||||||
|
* @returns the value if its a VT_int64 type, 0 otherwise
|
||||||
|
*/
|
||||||
|
boost::int64_t GetInt64() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an integral number
|
||||||
|
*
|
||||||
|
* Works for uint64 up to std::numeric_limits<int64_t>::max(),
|
||||||
|
* will throw a std::overflow_error otherwise. If the entire range
|
||||||
|
* of uint64_t is possible, please use GetUint64()
|
||||||
|
*
|
||||||
|
* @returns an integer number if the ValueType is VT_uint8, VT_int8,
|
||||||
|
* VT_uint16, VT_int16, VT_uint32, VT_int32,or VT_int64 type, 0 otherwise.
|
||||||
|
*/
|
||||||
|
boost::int64_t GetInteger() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a float value
|
||||||
|
*
|
||||||
|
* @returns the value if its a VT_float type, 0. otherwise
|
||||||
|
*/
|
||||||
|
float GetFloat() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a double value
|
||||||
|
*
|
||||||
|
* @returns the value if its a VT_double type, 0. otherwise
|
||||||
|
*/
|
||||||
|
double GetDouble() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a floating-point value
|
||||||
|
*
|
||||||
|
* @returns the value if its a VT_float or VT_double type, 0. otherwise
|
||||||
|
*/
|
||||||
|
double GetReal() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a string value
|
||||||
|
*
|
||||||
|
* @returns the value if its a VT_string type, an empty string otherwise
|
||||||
|
*/
|
||||||
|
std::string GetString() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an array
|
||||||
|
*
|
||||||
|
* @returns the value if its a VT_array type, an empty array otherwise
|
||||||
|
*/
|
||||||
|
std::vector<TableValue> GetArray() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a table
|
||||||
|
*
|
||||||
|
* @returns the value if its a VT_table type, an empty table otherwise
|
||||||
|
*/
|
||||||
|
Table GetTable() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the value as a void value
|
||||||
|
*/
|
||||||
|
void Set();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value as a boolean
|
||||||
|
*
|
||||||
|
* @param [in] value the value
|
||||||
|
*/
|
||||||
|
void Set(bool value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value as a uint8_t
|
||||||
|
*
|
||||||
|
* @param [in] value the value
|
||||||
|
*/
|
||||||
|
void Set(boost::uint8_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value as a int8_t
|
||||||
|
*
|
||||||
|
* @param [in] value the value
|
||||||
|
*/
|
||||||
|
void Set(boost::int8_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value as a uint16_t
|
||||||
|
*
|
||||||
|
* @param [in] value the value
|
||||||
|
*/
|
||||||
|
void Set(boost::uint16_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value as a int16_t
|
||||||
|
*
|
||||||
|
* @param [in] value the value
|
||||||
|
*/
|
||||||
|
void Set(boost::int16_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value as a uint32_t
|
||||||
|
*
|
||||||
|
* @param [in] value the value
|
||||||
|
*/
|
||||||
|
void Set(boost::uint32_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value as a int32_t
|
||||||
|
*
|
||||||
|
* @param [in] value the value
|
||||||
|
*/
|
||||||
|
void Set(boost::int32_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value as a timestamp.
|
||||||
|
*
|
||||||
|
* @param [in] value the value
|
||||||
|
*/
|
||||||
|
void SetTimestamp(std::time_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value as a int64_t
|
||||||
|
*
|
||||||
|
* @param [in] value the value
|
||||||
|
*/
|
||||||
|
void Set(boost::int64_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value as a float
|
||||||
|
*
|
||||||
|
* @param [in] value the value
|
||||||
|
*/
|
||||||
|
void Set(float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value as a double
|
||||||
|
*
|
||||||
|
* @param [in] value the value
|
||||||
|
*/
|
||||||
|
void Set(double value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value as a string
|
||||||
|
*
|
||||||
|
* @param [in] value the value
|
||||||
|
*/
|
||||||
|
void Set(const char *value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value as a string
|
||||||
|
*
|
||||||
|
* @param [in] value the value
|
||||||
|
*/
|
||||||
|
void Set(const std::string &value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value as an array
|
||||||
|
*
|
||||||
|
* @param [in] value the value
|
||||||
|
*/
|
||||||
|
void Set(const std::vector<TableValue> &value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value as a table
|
||||||
|
*
|
||||||
|
* @param [in] value the value
|
||||||
|
*/
|
||||||
|
void Set(const Table &value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
boost::scoped_ptr<Detail::TableValueImpl> m_impl;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace AmqpClient
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // SIMPLEAMQPCLIENT_TABLE_H
|
||||||
113
src/SimpleAmqpClient/TableImpl.h
Normal file
113
src/SimpleAmqpClient/TableImpl.h
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
#ifndef SIMPLEAMQPCLIENT_TABLEIMPL_H
|
||||||
|
#define SIMPLEAMQPCLIENT_TABLEIMPL_H
|
||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <amqp.h>
|
||||||
|
|
||||||
|
#include <boost/cstdint.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <boost/variant/variant.hpp>
|
||||||
|
#include <ctime>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "SimpleAmqpClient/Table.h"
|
||||||
|
|
||||||
|
namespace AmqpClient {
|
||||||
|
namespace Detail {
|
||||||
|
|
||||||
|
typedef boost::shared_ptr<amqp_pool_t> amqp_pool_ptr_t;
|
||||||
|
|
||||||
|
struct void_t {};
|
||||||
|
|
||||||
|
inline bool operator==(const void_t &, const void_t &) { return true; }
|
||||||
|
|
||||||
|
typedef std::vector<TableValue> array_t;
|
||||||
|
|
||||||
|
typedef boost::variant<void_t, bool, boost::int8_t, boost::int16_t,
|
||||||
|
boost::int32_t, boost::int64_t, float, double,
|
||||||
|
std::string, array_t, Table, boost::uint8_t,
|
||||||
|
boost::uint16_t, boost::uint32_t, boost::uint64_t>
|
||||||
|
value_t;
|
||||||
|
|
||||||
|
class TableValueImpl {
|
||||||
|
public:
|
||||||
|
explicit TableValueImpl(const value_t &v) : m_value(v) {}
|
||||||
|
virtual ~TableValueImpl() {}
|
||||||
|
|
||||||
|
value_t m_value;
|
||||||
|
|
||||||
|
static amqp_table_t CreateAmqpTable(const Table &table,
|
||||||
|
amqp_pool_ptr_t &pool);
|
||||||
|
|
||||||
|
static Table CreateTable(const amqp_table_t &table);
|
||||||
|
|
||||||
|
static amqp_table_t CopyTable(const amqp_table_t &table,
|
||||||
|
amqp_pool_ptr_t &pool);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static amqp_table_t CreateAmqpTableInner(const Table &table,
|
||||||
|
amqp_pool_t &pool);
|
||||||
|
static TableValue CreateTableValue(const amqp_field_value_t &entry);
|
||||||
|
static amqp_table_t CopyTableInner(const amqp_table_t &table,
|
||||||
|
amqp_pool_t &pool);
|
||||||
|
static amqp_field_value_t CopyValue(const amqp_field_value_t value,
|
||||||
|
amqp_pool_t &pool);
|
||||||
|
|
||||||
|
public:
|
||||||
|
class generate_field_value
|
||||||
|
: public boost::static_visitor<amqp_field_value_t> {
|
||||||
|
public:
|
||||||
|
explicit generate_field_value(amqp_pool_t &p) : pool(p) {}
|
||||||
|
virtual ~generate_field_value() {}
|
||||||
|
|
||||||
|
amqp_field_value_t operator()(const void_t) const;
|
||||||
|
amqp_field_value_t operator()(const bool value) const;
|
||||||
|
amqp_field_value_t operator()(const boost::uint8_t value) const;
|
||||||
|
amqp_field_value_t operator()(const boost::int8_t value) const;
|
||||||
|
amqp_field_value_t operator()(const boost::uint16_t value) const;
|
||||||
|
amqp_field_value_t operator()(const boost::int16_t value) const;
|
||||||
|
amqp_field_value_t operator()(const boost::uint32_t value) const;
|
||||||
|
amqp_field_value_t operator()(const boost::int32_t value) const;
|
||||||
|
amqp_field_value_t operator()(const boost::uint64_t value) const;
|
||||||
|
amqp_field_value_t operator()(const boost::int64_t value) const;
|
||||||
|
amqp_field_value_t operator()(const float value) const;
|
||||||
|
amqp_field_value_t operator()(const double value) const;
|
||||||
|
amqp_field_value_t operator()(const std::string &value) const;
|
||||||
|
amqp_field_value_t operator()(const array_t &value) const;
|
||||||
|
amqp_field_value_t operator()(const Table &value) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
amqp_pool_t &pool;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Detail
|
||||||
|
} // namespace AmqpClient
|
||||||
|
#endif // SIMPLEAMQPCLIENT_TABLEIMPL_H
|
||||||
49
src/SimpleAmqpClient/Util.h
Normal file
49
src/SimpleAmqpClient/Util.h
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#ifndef SIMPLEAMQPCLIENT_UTIL_H
|
||||||
|
#define SIMPLEAMQPCLIENT_UTIL_H
|
||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(WIN32) && !defined(SimpleAmqpClient_STATIC)
|
||||||
|
# ifdef SimpleAmqpClient_EXPORTS
|
||||||
|
# define SIMPLEAMQPCLIENT_EXPORT __declspec(dllexport)
|
||||||
|
# else
|
||||||
|
# define SIMPLEAMQPCLIENT_EXPORT __declspec(dllimport)
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# define SIMPLEAMQPCLIENT_EXPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
|
#define SAC_DEPRECATED(msg) __attribute__((deprecated(msg)))
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
#define SAC_DEPRECATED(msg) __declspec(deprecated(msg))
|
||||||
|
#else
|
||||||
|
#define SAC_DEPRECATED(msg)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // SIMPLEAMQPCLIENT_UTIL_H
|
||||||
35
src/SimpleAmqpClient/Version.h
Normal file
35
src/SimpleAmqpClient/Version.h
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#ifndef SIMPLEAMQPCLIENT_VERSION_H
|
||||||
|
#define SIMPLEAMQPCLIENT_VERSION_H
|
||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SIMPLEAMQPCLIENT_VERSION_MAJOR 2
|
||||||
|
#define SIMPLEAMQPCLIENT_VERSION_MINOR 6
|
||||||
|
#define SIMPLEAMQPCLIENT_VERSION_PATCH 0
|
||||||
|
|
||||||
|
#endif // SIMPLEAMQPCLIENT_VERSION_H
|
||||||
264
src/Table.cpp
Normal file
264
src/Table.cpp
Normal file
@@ -0,0 +1,264 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SimpleAmqpClient/Table.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <boost/type_traits/remove_cv.hpp>
|
||||||
|
#include <boost/variant/get.hpp>
|
||||||
|
#include <ctime>
|
||||||
|
#include <iterator>
|
||||||
|
#include <limits>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include "SimpleAmqpClient/TableImpl.h"
|
||||||
|
|
||||||
|
namespace AmqpClient {
|
||||||
|
TableValue::TableValue()
|
||||||
|
: m_impl(new Detail::TableValueImpl(Detail::void_t())) {}
|
||||||
|
|
||||||
|
TableValue::TableValue(bool value)
|
||||||
|
: m_impl(new Detail::TableValueImpl(value)) {}
|
||||||
|
|
||||||
|
TableValue::TableValue(boost::uint8_t value)
|
||||||
|
: m_impl(new Detail::TableValueImpl(value)) {}
|
||||||
|
|
||||||
|
TableValue::TableValue(boost::int8_t value)
|
||||||
|
: m_impl(new Detail::TableValueImpl(value)) {}
|
||||||
|
|
||||||
|
TableValue::TableValue(boost::uint16_t value)
|
||||||
|
: m_impl(new Detail::TableValueImpl(value)) {}
|
||||||
|
|
||||||
|
TableValue::TableValue(boost::int16_t value)
|
||||||
|
: m_impl(new Detail::TableValueImpl(value)) {}
|
||||||
|
|
||||||
|
TableValue::TableValue(boost::uint32_t value)
|
||||||
|
: m_impl(new Detail::TableValueImpl(value)) {}
|
||||||
|
|
||||||
|
TableValue::TableValue(boost::int32_t value)
|
||||||
|
: m_impl(new Detail::TableValueImpl(value)) {}
|
||||||
|
|
||||||
|
TableValue::TableValue(boost::uint64_t value)
|
||||||
|
: m_impl(new Detail::TableValueImpl(value)) {}
|
||||||
|
|
||||||
|
TableValue TableValue::Timestamp(std::time_t ts) {
|
||||||
|
return TableValue(static_cast<boost::uint64_t>(ts));
|
||||||
|
}
|
||||||
|
|
||||||
|
TableValue::TableValue(boost::int64_t value)
|
||||||
|
: m_impl(new Detail::TableValueImpl(value)) {}
|
||||||
|
|
||||||
|
TableValue::TableValue(float value)
|
||||||
|
: m_impl(new Detail::TableValueImpl(value)) {}
|
||||||
|
|
||||||
|
TableValue::TableValue(double value)
|
||||||
|
: m_impl(new Detail::TableValueImpl(value)) {}
|
||||||
|
|
||||||
|
TableValue::TableValue(const char *value)
|
||||||
|
: m_impl(new Detail::TableValueImpl(std::string(value))) {}
|
||||||
|
|
||||||
|
TableValue::TableValue(const std::string &value)
|
||||||
|
: m_impl(new Detail::TableValueImpl(value)) {}
|
||||||
|
|
||||||
|
TableValue::TableValue(const std::vector<TableValue> &values)
|
||||||
|
: m_impl(new Detail::TableValueImpl(values)) {}
|
||||||
|
|
||||||
|
TableValue::TableValue(const Table &value)
|
||||||
|
: m_impl(new Detail::TableValueImpl(value)) {}
|
||||||
|
|
||||||
|
TableValue::TableValue(const TableValue &l)
|
||||||
|
: m_impl(new Detail::TableValueImpl(l.m_impl->m_value)) {}
|
||||||
|
|
||||||
|
TableValue &TableValue::operator=(const TableValue &l) {
|
||||||
|
if (this != &l) {
|
||||||
|
m_impl->m_value = l.m_impl->m_value;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const Array &l, const Array &r) {
|
||||||
|
if (l.size() == r.size()) {
|
||||||
|
return std::equal(l.begin(), l.end(), r.begin());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const Table &l, const Table &r) {
|
||||||
|
if (l.size() == r.size()) {
|
||||||
|
return std::equal(l.begin(), l.end(), r.begin());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TableValue::operator==(const TableValue &l) const {
|
||||||
|
if (this == &l) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_impl->m_value == l.m_impl->m_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TableValue::operator!=(const TableValue &l) const {
|
||||||
|
if (this == &l) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !(m_impl->m_value == l.m_impl->m_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
TableValue::~TableValue() {}
|
||||||
|
|
||||||
|
TableValue::ValueType TableValue::GetType() const {
|
||||||
|
return static_cast<ValueType>(m_impl->m_value.which());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TableValue::GetBool() const { return boost::get<bool>(m_impl->m_value); }
|
||||||
|
|
||||||
|
boost::uint8_t TableValue::GetUint8() const {
|
||||||
|
return boost::get<boost::uint8_t>(m_impl->m_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::int8_t TableValue::GetInt8() const {
|
||||||
|
return boost::get<boost::int8_t>(m_impl->m_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::uint16_t TableValue::GetUint16() const {
|
||||||
|
return boost::get<boost::uint16_t>(m_impl->m_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::int16_t TableValue::GetInt16() const {
|
||||||
|
return boost::get<boost::int16_t>(m_impl->m_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::uint32_t TableValue::GetUint32() const {
|
||||||
|
return boost::get<boost::uint32_t>(m_impl->m_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::int32_t TableValue::GetInt32() const {
|
||||||
|
return boost::get<boost::int32_t>(m_impl->m_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::time_t TableValue::GetTimestamp() const {
|
||||||
|
return static_cast<std::time_t>(boost::get<boost::uint64_t>(m_impl->m_value));
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::int64_t TableValue::GetInt64() const {
|
||||||
|
return boost::get<boost::int64_t>(m_impl->m_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::int64_t TableValue::GetInteger() const {
|
||||||
|
switch (m_impl->m_value.which()) {
|
||||||
|
case VT_uint8:
|
||||||
|
return GetUint8();
|
||||||
|
case VT_int8:
|
||||||
|
return GetInt8();
|
||||||
|
case VT_uint16:
|
||||||
|
return GetUint16();
|
||||||
|
case VT_int16:
|
||||||
|
return GetInt16();
|
||||||
|
case VT_uint32:
|
||||||
|
return GetUint32();
|
||||||
|
case VT_int32:
|
||||||
|
return GetInt32();
|
||||||
|
case VT_int64:
|
||||||
|
return GetInt64();
|
||||||
|
default:
|
||||||
|
throw boost::bad_get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float TableValue::GetFloat() const {
|
||||||
|
return boost::get<float>(m_impl->m_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
double TableValue::GetDouble() const {
|
||||||
|
return boost::get<double>(m_impl->m_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
double TableValue::GetReal() const {
|
||||||
|
switch (m_impl->m_value.which()) {
|
||||||
|
case VT_float:
|
||||||
|
return GetFloat();
|
||||||
|
case VT_double:
|
||||||
|
return GetDouble();
|
||||||
|
default:
|
||||||
|
throw boost::bad_get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string TableValue::GetString() const {
|
||||||
|
return boost::get<std::string>(m_impl->m_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<TableValue> TableValue::GetArray() const {
|
||||||
|
return boost::get<Detail::array_t>(m_impl->m_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Table TableValue::GetTable() const {
|
||||||
|
return boost::get<Table>(m_impl->m_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TableValue::Set() { m_impl->m_value = Detail::void_t(); }
|
||||||
|
|
||||||
|
void TableValue::Set(bool value) { m_impl->m_value = value; }
|
||||||
|
|
||||||
|
void TableValue::Set(boost::uint8_t value) { m_impl->m_value = value; }
|
||||||
|
|
||||||
|
void TableValue::Set(boost::int8_t value) { m_impl->m_value = value; }
|
||||||
|
|
||||||
|
void TableValue::Set(boost::uint16_t value) { m_impl->m_value = value; }
|
||||||
|
|
||||||
|
void TableValue::Set(boost::int16_t value) { m_impl->m_value = value; }
|
||||||
|
|
||||||
|
void TableValue::Set(boost::uint32_t value) { m_impl->m_value = value; }
|
||||||
|
|
||||||
|
void TableValue::Set(boost::int32_t value) { m_impl->m_value = value; }
|
||||||
|
|
||||||
|
void TableValue::SetTimestamp(std::time_t value) {
|
||||||
|
m_impl->m_value = static_cast<boost::uint64_t>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TableValue::Set(boost::int64_t value) { m_impl->m_value = value; }
|
||||||
|
|
||||||
|
void TableValue::Set(float value) { m_impl->m_value = value; }
|
||||||
|
|
||||||
|
void TableValue::Set(double value) { m_impl->m_value = value; }
|
||||||
|
|
||||||
|
void TableValue::Set(const char *value) {
|
||||||
|
m_impl->m_value = std::string(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TableValue::Set(const std::string &value) { m_impl->m_value = value; }
|
||||||
|
|
||||||
|
void TableValue::Set(const std::vector<TableValue> &value) {
|
||||||
|
m_impl->m_value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TableValue::Set(const Table &value) { m_impl->m_value = value; }
|
||||||
|
|
||||||
|
} // namespace AmqpClient
|
||||||
361
src/TableImpl.cpp
Normal file
361
src/TableImpl.cpp
Normal file
@@ -0,0 +1,361 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define _SCL_SECURE_NO_WARNINGS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "SimpleAmqpClient/TableImpl.h"
|
||||||
|
|
||||||
|
#include <amqp.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
#include <boost/variant/apply_visitor.hpp>
|
||||||
|
#include <boost/variant/static_visitor.hpp>
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(disable : 4800)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace AmqpClient {
|
||||||
|
namespace Detail {
|
||||||
|
|
||||||
|
amqp_field_value_t TableValueImpl::generate_field_value::operator()(
|
||||||
|
const void_t) const {
|
||||||
|
amqp_field_value_t v;
|
||||||
|
v.kind = AMQP_FIELD_KIND_VOID;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_field_value_t TableValueImpl::generate_field_value::operator()(
|
||||||
|
const bool value) const {
|
||||||
|
amqp_field_value_t v;
|
||||||
|
v.kind = AMQP_FIELD_KIND_BOOLEAN;
|
||||||
|
v.value.boolean = value;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_field_value_t TableValueImpl::generate_field_value::operator()(
|
||||||
|
const boost::uint8_t value) const {
|
||||||
|
amqp_field_value_t v;
|
||||||
|
v.kind = AMQP_FIELD_KIND_U8;
|
||||||
|
v.value.u8 = value;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_field_value_t TableValueImpl::generate_field_value::operator()(
|
||||||
|
const boost::int8_t value) const {
|
||||||
|
amqp_field_value_t v;
|
||||||
|
v.kind = AMQP_FIELD_KIND_I8;
|
||||||
|
v.value.i8 = value;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_field_value_t TableValueImpl::generate_field_value::operator()(
|
||||||
|
const boost::uint16_t value) const {
|
||||||
|
amqp_field_value_t v;
|
||||||
|
v.kind = AMQP_FIELD_KIND_U16;
|
||||||
|
v.value.u16 = value;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_field_value_t TableValueImpl::generate_field_value::operator()(
|
||||||
|
const boost::int16_t value) const {
|
||||||
|
amqp_field_value_t v;
|
||||||
|
v.kind = AMQP_FIELD_KIND_I16;
|
||||||
|
v.value.i16 = value;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_field_value_t TableValueImpl::generate_field_value::operator()(
|
||||||
|
const boost::uint32_t value) const {
|
||||||
|
amqp_field_value_t v;
|
||||||
|
v.kind = AMQP_FIELD_KIND_U32;
|
||||||
|
v.value.u32 = value;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_field_value_t TableValueImpl::generate_field_value::operator()(
|
||||||
|
const boost::int32_t value) const {
|
||||||
|
amqp_field_value_t v;
|
||||||
|
v.kind = AMQP_FIELD_KIND_I32;
|
||||||
|
v.value.i32 = value;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_field_value_t TableValueImpl::generate_field_value::operator()(
|
||||||
|
const boost::uint64_t value) const {
|
||||||
|
amqp_field_value_t v;
|
||||||
|
v.kind = AMQP_FIELD_KIND_TIMESTAMP;
|
||||||
|
v.value.u64 = value;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_field_value_t TableValueImpl::generate_field_value::operator()(
|
||||||
|
const boost::int64_t value) const {
|
||||||
|
amqp_field_value_t v;
|
||||||
|
v.kind = AMQP_FIELD_KIND_I64;
|
||||||
|
v.value.i64 = value;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_field_value_t TableValueImpl::generate_field_value::operator()(
|
||||||
|
const float value) const {
|
||||||
|
amqp_field_value_t v;
|
||||||
|
v.kind = AMQP_FIELD_KIND_F32;
|
||||||
|
v.value.f32 = value;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_field_value_t TableValueImpl::generate_field_value::operator()(
|
||||||
|
const double value) const {
|
||||||
|
amqp_field_value_t v;
|
||||||
|
v.kind = AMQP_FIELD_KIND_F64;
|
||||||
|
v.value.f64 = value;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_field_value_t TableValueImpl::generate_field_value::operator()(
|
||||||
|
const std::string &value) const {
|
||||||
|
amqp_field_value_t v;
|
||||||
|
v.kind = AMQP_FIELD_KIND_UTF8;
|
||||||
|
amqp_pool_alloc_bytes(&pool, value.size(), &v.value.bytes);
|
||||||
|
memcpy(v.value.bytes.bytes, value.data(), v.value.bytes.len);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_field_value_t TableValueImpl::generate_field_value::operator()(
|
||||||
|
const array_t &value) const {
|
||||||
|
amqp_field_value_t v;
|
||||||
|
v.kind = AMQP_FIELD_KIND_ARRAY;
|
||||||
|
v.value.array.num_entries = value.size();
|
||||||
|
v.value.array.entries = (amqp_field_value_t *)amqp_pool_alloc(
|
||||||
|
&pool, sizeof(amqp_field_value_t) * value.size());
|
||||||
|
if (NULL == v.value.array.entries) {
|
||||||
|
throw std::bad_alloc();
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_field_value_t *output_iterator = v.value.array.entries;
|
||||||
|
for (array_t::const_iterator it = value.begin(); it != value.end();
|
||||||
|
++it, ++output_iterator) {
|
||||||
|
*output_iterator =
|
||||||
|
boost::apply_visitor(generate_field_value(pool), it->m_impl->m_value);
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_field_value_t TableValueImpl::generate_field_value::operator()(
|
||||||
|
const Table &value) const {
|
||||||
|
amqp_field_value_t v;
|
||||||
|
v.kind = AMQP_FIELD_KIND_TABLE;
|
||||||
|
v.value.table = CreateAmqpTableInner(value, pool);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_pool(amqp_pool_t *pool) {
|
||||||
|
empty_amqp_pool(pool);
|
||||||
|
delete pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_table_t TableValueImpl::CreateAmqpTable(const Table &table,
|
||||||
|
amqp_pool_ptr_t &pool) {
|
||||||
|
if (0 == table.size()) {
|
||||||
|
return AMQP_EMPTY_TABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
pool = boost::shared_ptr<amqp_pool_t>(new amqp_pool_t, free_pool);
|
||||||
|
init_amqp_pool(pool.get(), 1024);
|
||||||
|
|
||||||
|
return CreateAmqpTableInner(table, *pool.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_table_t TableValueImpl::CreateAmqpTableInner(const Table &table,
|
||||||
|
amqp_pool_t &pool) {
|
||||||
|
amqp_table_t new_table;
|
||||||
|
|
||||||
|
new_table.num_entries = table.size();
|
||||||
|
|
||||||
|
new_table.entries = (amqp_table_entry_t *)amqp_pool_alloc(
|
||||||
|
&pool, sizeof(amqp_table_entry_t) * table.size());
|
||||||
|
|
||||||
|
if (NULL == new_table.entries) {
|
||||||
|
throw std::bad_alloc();
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_table_entry_t *output_it = new_table.entries;
|
||||||
|
|
||||||
|
for (Table::const_iterator it = table.begin(); it != table.end();
|
||||||
|
++it, ++output_it) {
|
||||||
|
amqp_pool_alloc_bytes(&pool, it->first.size(), &output_it->key);
|
||||||
|
if (NULL == output_it->key.bytes) {
|
||||||
|
throw std::bad_alloc();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::copy(it->first.begin(), it->first.end(), (char *)output_it->key.bytes);
|
||||||
|
|
||||||
|
output_it->value = boost::apply_visitor(
|
||||||
|
TableValueImpl::generate_field_value(pool), it->second.m_impl->m_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
Table TableValueImpl::CreateTable(const amqp_table_t &table) {
|
||||||
|
Table new_table;
|
||||||
|
|
||||||
|
for (int i = 0; i < table.num_entries; ++i) {
|
||||||
|
amqp_table_entry_t *entry = &table.entries[i];
|
||||||
|
|
||||||
|
std::string key((char *)entry->key.bytes, entry->key.len);
|
||||||
|
|
||||||
|
new_table.insert(TableEntry(key, CreateTableValue(entry->value)));
|
||||||
|
}
|
||||||
|
return new_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
TableValue TableValueImpl::CreateTableValue(const amqp_field_value_t &entry) {
|
||||||
|
switch (entry.kind) {
|
||||||
|
case AMQP_FIELD_KIND_VOID:
|
||||||
|
return TableValue();
|
||||||
|
case AMQP_FIELD_KIND_BOOLEAN:
|
||||||
|
return TableValue((bool)entry.value.boolean);
|
||||||
|
case AMQP_FIELD_KIND_U8:
|
||||||
|
return TableValue(entry.value.u8);
|
||||||
|
case AMQP_FIELD_KIND_I8:
|
||||||
|
return TableValue(entry.value.i8);
|
||||||
|
case AMQP_FIELD_KIND_U16:
|
||||||
|
return TableValue(entry.value.u16);
|
||||||
|
case AMQP_FIELD_KIND_I16:
|
||||||
|
return TableValue(entry.value.i16);
|
||||||
|
case AMQP_FIELD_KIND_U32:
|
||||||
|
return TableValue(entry.value.u32);
|
||||||
|
case AMQP_FIELD_KIND_I32:
|
||||||
|
return TableValue(entry.value.i32);
|
||||||
|
case AMQP_FIELD_KIND_TIMESTAMP:
|
||||||
|
return TableValue(entry.value.u64);
|
||||||
|
case AMQP_FIELD_KIND_I64:
|
||||||
|
return TableValue(entry.value.i64);
|
||||||
|
case AMQP_FIELD_KIND_F32:
|
||||||
|
return TableValue(entry.value.f32);
|
||||||
|
case AMQP_FIELD_KIND_F64:
|
||||||
|
return TableValue(entry.value.f64);
|
||||||
|
case AMQP_FIELD_KIND_UTF8:
|
||||||
|
case AMQP_FIELD_KIND_BYTES:
|
||||||
|
return TableValue(
|
||||||
|
std::string((char *)entry.value.bytes.bytes, entry.value.bytes.len));
|
||||||
|
case AMQP_FIELD_KIND_ARRAY: {
|
||||||
|
amqp_array_t array = entry.value.array;
|
||||||
|
Detail::array_t new_array;
|
||||||
|
|
||||||
|
for (int i = 0; i < array.num_entries; ++i) {
|
||||||
|
new_array.push_back(CreateTableValue(array.entries[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return TableValue(new_array);
|
||||||
|
}
|
||||||
|
case AMQP_FIELD_KIND_TABLE:
|
||||||
|
return TableValue(CreateTable(entry.value.table));
|
||||||
|
case AMQP_FIELD_KIND_DECIMAL:
|
||||||
|
// uint64_t is unsupported by RabbitMQ.
|
||||||
|
case AMQP_FIELD_KIND_U64:
|
||||||
|
default:
|
||||||
|
return TableValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_table_t TableValueImpl::CopyTable(const amqp_table_t &table,
|
||||||
|
amqp_pool_ptr_t &pool) {
|
||||||
|
if (0 == table.num_entries) {
|
||||||
|
return AMQP_EMPTY_TABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
pool = boost::shared_ptr<amqp_pool_t>(new amqp_pool_t, free_pool);
|
||||||
|
init_amqp_pool(pool.get(), 1024);
|
||||||
|
|
||||||
|
return CopyTableInner(table, *pool.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_table_t TableValueImpl::CopyTableInner(const amqp_table_t &table,
|
||||||
|
amqp_pool_t &pool) {
|
||||||
|
amqp_table_t new_table;
|
||||||
|
|
||||||
|
new_table.num_entries = table.num_entries;
|
||||||
|
new_table.entries = (amqp_table_entry_t *)amqp_pool_alloc(
|
||||||
|
&pool, sizeof(amqp_table_entry_t) * table.num_entries);
|
||||||
|
if (NULL == new_table.entries) {
|
||||||
|
throw std::bad_alloc();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < table.num_entries; ++i) {
|
||||||
|
amqp_table_entry_t *entry = &new_table.entries[i];
|
||||||
|
amqp_pool_alloc_bytes(&pool, table.entries[i].key.len, &entry->key);
|
||||||
|
|
||||||
|
if (NULL == entry->key.bytes) {
|
||||||
|
throw std::bad_alloc();
|
||||||
|
}
|
||||||
|
memcpy(entry->key.bytes, table.entries[i].key.bytes, entry->key.len);
|
||||||
|
|
||||||
|
entry->value = CopyValue(table.entries[i].value, pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
amqp_field_value_t TableValueImpl::CopyValue(const amqp_field_value_t value,
|
||||||
|
amqp_pool_t &pool) {
|
||||||
|
amqp_field_value_t new_value = value;
|
||||||
|
|
||||||
|
switch (value.kind) {
|
||||||
|
case AMQP_FIELD_KIND_UTF8:
|
||||||
|
case AMQP_FIELD_KIND_BYTES:
|
||||||
|
amqp_pool_alloc_bytes(&pool, value.value.bytes.len,
|
||||||
|
&new_value.value.bytes);
|
||||||
|
memcpy(new_value.value.bytes.bytes, value.value.bytes.bytes,
|
||||||
|
value.value.bytes.len);
|
||||||
|
return new_value;
|
||||||
|
case AMQP_FIELD_KIND_ARRAY: {
|
||||||
|
new_value.value.array.entries = (amqp_field_value_t *)amqp_pool_alloc(
|
||||||
|
&pool, sizeof(amqp_field_value_t) * value.value.array.num_entries);
|
||||||
|
for (int i = 0; i < value.value.array.num_entries; ++i) {
|
||||||
|
new_value.value.array.entries[i] =
|
||||||
|
CopyValue(value.value.array.entries[i], pool);
|
||||||
|
}
|
||||||
|
return new_value;
|
||||||
|
}
|
||||||
|
case AMQP_FIELD_KIND_TABLE:
|
||||||
|
new_value.value.table = CopyTableInner(value.value.table, pool);
|
||||||
|
return new_value;
|
||||||
|
default:
|
||||||
|
return new_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace Detail
|
||||||
|
} // namespace AmqpClient
|
||||||
19
testing/CMakeLists.txt
Normal file
19
testing/CMakeLists.txt
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
include_directories(BEFORE SYSTEM ${gtest_SOURCE_DIR}/include)
|
||||||
|
include_directories(../src)
|
||||||
|
|
||||||
|
add_executable(test_api
|
||||||
|
connected_test.h
|
||||||
|
test_connect.cpp
|
||||||
|
test_channels.cpp
|
||||||
|
test_exchange.cpp
|
||||||
|
test_queue.cpp
|
||||||
|
test_publish.cpp
|
||||||
|
test_get.cpp
|
||||||
|
test_consume.cpp
|
||||||
|
test_message.cpp
|
||||||
|
test_table.cpp
|
||||||
|
test_ack.cpp
|
||||||
|
test_nack.cpp
|
||||||
|
)
|
||||||
|
target_link_libraries(test_api SimpleAmqpClient gtest gtest_main)
|
||||||
|
add_test(test_api test_api)
|
||||||
58
testing/connected_test.h
Normal file
58
testing/connected_test.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
#ifndef CONNECTED_TEST_H
|
||||||
|
#define CONNECTED_TEST_H
|
||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <SimpleAmqpClient/SimpleAmqpClient.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
using namespace AmqpClient;
|
||||||
|
|
||||||
|
class connected_test : public ::testing::Test {
|
||||||
|
public:
|
||||||
|
virtual void SetUp() { channel = Channel::Open(GetTestOpenOpts()); }
|
||||||
|
|
||||||
|
Channel::ptr_t channel;
|
||||||
|
|
||||||
|
static Channel::OpenOpts GetTestOpenOpts() {
|
||||||
|
Channel::OpenOpts ret;
|
||||||
|
ret.host = GetBrokerHost();
|
||||||
|
ret.auth = Channel::OpenOpts::BasicAuth("guest", "guest");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string GetBrokerHost() {
|
||||||
|
const char *host = getenv("AMQP_BROKER");
|
||||||
|
if (NULL != host) {
|
||||||
|
return std::string(host);
|
||||||
|
}
|
||||||
|
return std::string("");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CONNECTED_TEST_H
|
||||||
61
testing/test_ack.cpp
Normal file
61
testing/test_ack.cpp
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "connected_test.h"
|
||||||
|
|
||||||
|
using namespace AmqpClient;
|
||||||
|
|
||||||
|
TEST_F(connected_test, basic_ack_envelope) {
|
||||||
|
const BasicMessage::ptr_t message = BasicMessage::Create("Message Body");
|
||||||
|
std::string queue = channel->DeclareQueue("");
|
||||||
|
channel->BasicPublish("", queue, message);
|
||||||
|
|
||||||
|
std::string consumer = channel->BasicConsume(queue, "", true, false);
|
||||||
|
|
||||||
|
Envelope::ptr_t env = channel->BasicConsumeMessage(consumer);
|
||||||
|
|
||||||
|
channel->BasicAck(env);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, basic_ack_deliveryinfo) {
|
||||||
|
const BasicMessage::ptr_t message = BasicMessage::Create("Message Body");
|
||||||
|
std::string queue = channel->DeclareQueue("");
|
||||||
|
channel->BasicPublish("", queue, message);
|
||||||
|
|
||||||
|
std::string consumer = channel->BasicConsume(queue, "", true, false);
|
||||||
|
|
||||||
|
Envelope::DeliveryInfo info;
|
||||||
|
{
|
||||||
|
Envelope::ptr_t env = channel->BasicConsumeMessage(consumer);
|
||||||
|
info = env->GetDeliveryInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
channel->BasicAck(info);
|
||||||
|
}
|
||||||
147
testing/test_channels.cpp
Normal file
147
testing/test_channels.cpp
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "connected_test.h"
|
||||||
|
|
||||||
|
using namespace AmqpClient;
|
||||||
|
|
||||||
|
TEST_F(connected_test, first_channel) {
|
||||||
|
channel->DeclareExchange("test_channel_exchange",
|
||||||
|
Channel::EXCHANGE_TYPE_FANOUT, false, false, true);
|
||||||
|
channel->DeleteExchange("test_channel_exchange");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check to see that channels are reused properly
|
||||||
|
TEST_F(connected_test, channel_reuse) {
|
||||||
|
channel->DeclareExchange("test_channel_exchange1",
|
||||||
|
Channel::EXCHANGE_TYPE_FANOUT, false, false, true);
|
||||||
|
channel->DeclareExchange("test_channel_exchange2",
|
||||||
|
Channel::EXCHANGE_TYPE_FANOUT, false, false, true);
|
||||||
|
channel->DeleteExchange("test_channel_exchange1");
|
||||||
|
channel->DeleteExchange("test_channel_exchange2");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check to see that a new channel is created when a channel is put in an
|
||||||
|
// exception state
|
||||||
|
TEST_F(connected_test, channel_recover_from_error) {
|
||||||
|
EXPECT_THROW(channel->DeclareExchange("test_channel_exchangedoesnotexist",
|
||||||
|
Channel::EXCHANGE_TYPE_FANOUT, true,
|
||||||
|
false, true),
|
||||||
|
ChannelException);
|
||||||
|
|
||||||
|
channel->DeclareExchange("test_channel_exchange",
|
||||||
|
Channel::EXCHANGE_TYPE_FANOUT, false, false, true);
|
||||||
|
channel->DeleteExchange("test_channel_exchange");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, channel_publish_success1) {
|
||||||
|
BasicMessage::ptr_t message = BasicMessage::Create("Test message");
|
||||||
|
|
||||||
|
channel->BasicPublish("", "test_channel_routingkey", message, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, channel_publish_success2) {
|
||||||
|
BasicMessage::ptr_t message = BasicMessage::Create("Test message");
|
||||||
|
|
||||||
|
channel->BasicPublish("", "test_channel_routingkey", message, false, false);
|
||||||
|
channel->BasicPublish("", "test_channel_routingkey", message, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, channel_publish_returned_mandatory) {
|
||||||
|
BasicMessage::ptr_t message = BasicMessage::Create("Test message");
|
||||||
|
|
||||||
|
EXPECT_THROW(
|
||||||
|
channel->BasicPublish("", "test_channel_noqueue", message, true, false),
|
||||||
|
MessageReturnedException);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, channel_publish_full_rejected) {
|
||||||
|
BasicMessage::ptr_t message = BasicMessage::Create("Test message");
|
||||||
|
Table args;
|
||||||
|
args.insert(TableEntry("x-max-length", 0));
|
||||||
|
args.insert(TableEntry("x-overflow", "reject-publish"));
|
||||||
|
std::string queue = channel->DeclareQueue("", false, false, true, true, args);
|
||||||
|
|
||||||
|
EXPECT_THROW(channel->BasicPublish("", queue, message),
|
||||||
|
MessageRejectedException);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, channel_publish_bad_exchange) {
|
||||||
|
BasicMessage::ptr_t message = BasicMessage::Create("Test message");
|
||||||
|
|
||||||
|
EXPECT_THROW(channel->BasicPublish("test_channel_badexchange",
|
||||||
|
"test_channel_rk", message, false, false),
|
||||||
|
ChannelException);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, channel_publish_bad_exchange_recover) {
|
||||||
|
BasicMessage::ptr_t message = BasicMessage::Create("Test message");
|
||||||
|
|
||||||
|
EXPECT_THROW(channel->BasicPublish("test_channel_badexchange",
|
||||||
|
"test_channel_rk", message, false, false),
|
||||||
|
ChannelException);
|
||||||
|
|
||||||
|
channel->BasicPublish("", "test_channel_rk", message, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, channel_consume_success) {
|
||||||
|
BasicMessage::ptr_t message = BasicMessage::Create("Test message");
|
||||||
|
std::string queue = channel->DeclareQueue("");
|
||||||
|
channel->BasicPublish("", queue, message);
|
||||||
|
|
||||||
|
std::string consumer = channel->BasicConsume(queue);
|
||||||
|
|
||||||
|
Envelope::ptr_t consumed_envelope;
|
||||||
|
EXPECT_TRUE(channel->BasicConsumeMessage(consumer, consumed_envelope));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, channel_consume_success_timeout) {
|
||||||
|
BasicMessage::ptr_t message = BasicMessage::Create("Test message");
|
||||||
|
std::string queue = channel->DeclareQueue("");
|
||||||
|
|
||||||
|
std::string consumer = channel->BasicConsume(queue, "", true, false);
|
||||||
|
channel->BasicPublish("", queue, message);
|
||||||
|
|
||||||
|
Envelope::ptr_t consumed_envelope;
|
||||||
|
EXPECT_TRUE(channel->BasicConsumeMessage(consumer, consumed_envelope, 5000));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(test_channels, big_message) {
|
||||||
|
Channel::OpenOpts opts = connected_test::GetTestOpenOpts();
|
||||||
|
opts.frame_max = 4096;
|
||||||
|
Channel::ptr_t channel = Channel::Open(opts);
|
||||||
|
BasicMessage::ptr_t message = BasicMessage::Create(std::string(4099, 'a'));
|
||||||
|
|
||||||
|
std::string queue = channel->DeclareQueue("");
|
||||||
|
|
||||||
|
std::string consumer = channel->BasicConsume(queue);
|
||||||
|
channel->BasicPublish("", queue, message);
|
||||||
|
|
||||||
|
Envelope::ptr_t consumed_envelope;
|
||||||
|
EXPECT_TRUE(channel->BasicConsumeMessage(consumer, consumed_envelope));
|
||||||
|
}
|
||||||
131
testing/test_connect.cpp
Normal file
131
testing/test_connect.cpp
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "SimpleAmqpClient/SimpleAmqpClient.h"
|
||||||
|
#include "connected_test.h"
|
||||||
|
|
||||||
|
using namespace AmqpClient;
|
||||||
|
|
||||||
|
TEST(connecting_test, connect_default) {
|
||||||
|
Channel::ptr_t channel = Channel::Create(connected_test::GetBrokerHost());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(connecting_test, connect_badhost) {
|
||||||
|
EXPECT_THROW(Channel::ptr_t channel = Channel::Create("HostDoesntExist"),
|
||||||
|
std::runtime_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(connecting_test, open_badhost) {
|
||||||
|
Channel::OpenOpts opts = connected_test::GetTestOpenOpts();
|
||||||
|
opts.host = "HostDoesNotExist";
|
||||||
|
EXPECT_THROW(Channel::ptr_t channel = Channel::Open(opts),
|
||||||
|
std::runtime_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(connecting_test, connect_badauth) {
|
||||||
|
EXPECT_THROW(Channel::ptr_t channel = Channel::Create(
|
||||||
|
connected_test::GetBrokerHost(), 5672, "baduser", "badpass"),
|
||||||
|
AccessRefusedException);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(connecting_test, open_badauth) {
|
||||||
|
Channel::OpenOpts opts = connected_test::GetTestOpenOpts();
|
||||||
|
opts.auth = Channel::OpenOpts::BasicAuth("baduser", "badpass");
|
||||||
|
EXPECT_THROW(Channel::ptr_t channel = Channel::Open(opts),
|
||||||
|
AccessRefusedException);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(connecting_test, connect_badframesize) {
|
||||||
|
// AMQP Spec says we have a minimum frame size of 4096
|
||||||
|
EXPECT_THROW(
|
||||||
|
Channel::ptr_t channel = Channel::Create(
|
||||||
|
connected_test::GetBrokerHost(), 5672, "guest", "guest", "/", 400),
|
||||||
|
AmqpResponseLibraryException);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(connecting_test, open_badframesize) {
|
||||||
|
// AMQP Spec says we have a minimum frame size of 4096
|
||||||
|
Channel::OpenOpts opts = connected_test::GetTestOpenOpts();
|
||||||
|
opts.frame_max = 400;
|
||||||
|
EXPECT_THROW(Channel::ptr_t channel = Channel::Open(opts),
|
||||||
|
AmqpResponseLibraryException);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(connecting_test, connect_badvhost) {
|
||||||
|
EXPECT_THROW(Channel::ptr_t channel =
|
||||||
|
Channel::Create(connected_test::GetBrokerHost(), 5672,
|
||||||
|
"guest", "guest", "nonexitant_vhost"),
|
||||||
|
NotAllowedException);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(connecting_test, open_badvhost) {
|
||||||
|
Channel::OpenOpts opts = connected_test::GetTestOpenOpts();
|
||||||
|
opts.vhost = "bad_vhost";
|
||||||
|
EXPECT_THROW(Channel::ptr_t channel = Channel::Open(opts),
|
||||||
|
NotAllowedException);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(connecting_test, connect_using_uri) {
|
||||||
|
std::string host_uri = "amqp://" + connected_test::GetBrokerHost();
|
||||||
|
Channel::ptr_t channel = Channel::CreateFromUri(host_uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(connecting_test, openopts_from_uri) {
|
||||||
|
Channel::OpenOpts expected;
|
||||||
|
expected.host = "host";
|
||||||
|
expected.vhost = "vhost";
|
||||||
|
expected.port = 123;
|
||||||
|
expected.auth = Channel::OpenOpts::BasicAuth("user", "pass");
|
||||||
|
|
||||||
|
EXPECT_EQ(expected,
|
||||||
|
Channel::OpenOpts::FromUri("amqp://user:pass@host:123/vhost"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(connecting_test, openopts_from_uri_defaults) {
|
||||||
|
Channel::OpenOpts expected;
|
||||||
|
expected.host = "host";
|
||||||
|
expected.vhost = "/";
|
||||||
|
expected.port = 5672;
|
||||||
|
expected.auth = Channel::OpenOpts::BasicAuth("guest", "guest");
|
||||||
|
EXPECT_EQ(expected, Channel::OpenOpts::FromUri("amqp://host"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(connecting_test, openopts_from_amqps_uri) {
|
||||||
|
Channel::OpenOpts expected;
|
||||||
|
expected.host = "host";
|
||||||
|
expected.vhost = "vhost";
|
||||||
|
expected.port = 123;
|
||||||
|
expected.auth = Channel::OpenOpts::BasicAuth("user", "pass");
|
||||||
|
expected.tls_params = Channel::OpenOpts::TLSParams();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(connecting_test, openopts_fromuri_bad) {
|
||||||
|
EXPECT_THROW(Channel::OpenOpts::FromUri("not-a-valid-uri"), BadUriException);
|
||||||
|
}
|
||||||
228
testing/test_consume.cpp
Normal file
228
testing/test_consume.cpp
Normal file
@@ -0,0 +1,228 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "connected_test.h"
|
||||||
|
|
||||||
|
using namespace AmqpClient;
|
||||||
|
|
||||||
|
TEST_F(connected_test, basic_consume) {
|
||||||
|
std::string queue = channel->DeclareQueue("");
|
||||||
|
std::string consumer = channel->BasicConsume(queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, basic_consume_badqueue) {
|
||||||
|
EXPECT_THROW(channel->BasicConsume("test_consume_noexistqueue"),
|
||||||
|
ChannelException);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, basic_consume_duplicatetag) {
|
||||||
|
std::string queue = channel->DeclareQueue("");
|
||||||
|
std::string consumer = channel->BasicConsume(queue);
|
||||||
|
EXPECT_THROW(channel->BasicConsume(queue, consumer), ChannelException);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, basic_cancel_consumer) {
|
||||||
|
std::string queue = channel->DeclareQueue("");
|
||||||
|
std::string consumer = channel->BasicConsume(queue);
|
||||||
|
channel->BasicCancel(consumer);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, basic_cancel_bad_consumer) {
|
||||||
|
EXPECT_THROW(channel->BasicCancel("test_consume_noexistconsumer"),
|
||||||
|
ConsumerTagNotFoundException);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, basic_cancel_cancelled_consumer) {
|
||||||
|
std::string queue = channel->DeclareQueue("");
|
||||||
|
std::string consumer = channel->BasicConsume(queue);
|
||||||
|
channel->BasicCancel(consumer);
|
||||||
|
EXPECT_THROW(channel->BasicCancel(consumer), ConsumerTagNotFoundException);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, basic_consume_message) {
|
||||||
|
BasicMessage::ptr_t message = BasicMessage::Create("Message Body");
|
||||||
|
std::string queue = channel->DeclareQueue("");
|
||||||
|
std::string consumer = channel->BasicConsume(queue);
|
||||||
|
channel->BasicPublish("", queue, message);
|
||||||
|
|
||||||
|
Envelope::ptr_t delivered;
|
||||||
|
EXPECT_TRUE(channel->BasicConsumeMessage(consumer, delivered, -1));
|
||||||
|
EXPECT_EQ(consumer, delivered->ConsumerTag());
|
||||||
|
EXPECT_EQ("", delivered->Exchange());
|
||||||
|
EXPECT_EQ(queue, delivered->RoutingKey());
|
||||||
|
EXPECT_EQ(message->Body(), delivered->Message()->Body());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, basic_consume_message_bad_consumer) {
|
||||||
|
EXPECT_THROW(channel->BasicConsumeMessage("test_consume_noexistconsumer"),
|
||||||
|
ConsumerTagNotFoundException);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, basic_consume_inital_qos) {
|
||||||
|
BasicMessage::ptr_t message1 = BasicMessage::Create("Message1");
|
||||||
|
BasicMessage::ptr_t message2 = BasicMessage::Create("Message2");
|
||||||
|
BasicMessage::ptr_t message3 = BasicMessage::Create("Message3");
|
||||||
|
|
||||||
|
std::string queue = channel->DeclareQueue("");
|
||||||
|
channel->BasicPublish("", queue, message1, true);
|
||||||
|
channel->BasicPublish("", queue, message2, true);
|
||||||
|
channel->BasicPublish("", queue, message3, true);
|
||||||
|
|
||||||
|
std::string consumer = channel->BasicConsume(queue, "", true, false);
|
||||||
|
Envelope::ptr_t received1, received2;
|
||||||
|
ASSERT_TRUE(channel->BasicConsumeMessage(consumer, received1, 100));
|
||||||
|
|
||||||
|
EXPECT_FALSE(channel->BasicConsumeMessage(consumer, received2, 100));
|
||||||
|
channel->BasicAck(received1);
|
||||||
|
|
||||||
|
EXPECT_TRUE(channel->BasicConsumeMessage(consumer, received2, 100));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, basic_consume_2consumers) {
|
||||||
|
BasicMessage::ptr_t message1 = BasicMessage::Create("Message1");
|
||||||
|
BasicMessage::ptr_t message2 = BasicMessage::Create("Message2");
|
||||||
|
BasicMessage::ptr_t message3 = BasicMessage::Create("Message3");
|
||||||
|
|
||||||
|
std::string queue1 = channel->DeclareQueue("");
|
||||||
|
std::string queue2 = channel->DeclareQueue("");
|
||||||
|
std::string queue3 = channel->DeclareQueue("");
|
||||||
|
|
||||||
|
channel->BasicPublish("", queue1, message1);
|
||||||
|
channel->BasicPublish("", queue2, message2);
|
||||||
|
channel->BasicPublish("", queue3, message3);
|
||||||
|
|
||||||
|
std::string consumer1 = channel->BasicConsume(queue1, "", true, false);
|
||||||
|
std::string consumer2 = channel->BasicConsume(queue2, "", true, false);
|
||||||
|
|
||||||
|
Envelope::ptr_t envelope1;
|
||||||
|
Envelope::ptr_t envelope2;
|
||||||
|
Envelope::ptr_t envelope3;
|
||||||
|
|
||||||
|
channel->BasicConsumeMessage(consumer1, envelope1);
|
||||||
|
channel->BasicAck(envelope1);
|
||||||
|
channel->BasicConsumeMessage(consumer2, envelope2);
|
||||||
|
channel->BasicAck(envelope2);
|
||||||
|
channel->BasicGet(envelope3, queue3);
|
||||||
|
channel->BasicAck(envelope3);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, basic_consume_1000messages) {
|
||||||
|
BasicMessage::ptr_t message1 = BasicMessage::Create("Message1");
|
||||||
|
|
||||||
|
std::string queue = channel->DeclareQueue("");
|
||||||
|
std::string consumer = channel->BasicConsume(queue, "");
|
||||||
|
|
||||||
|
Envelope::ptr_t msg;
|
||||||
|
for (int i = 0; i < 1000; ++i) {
|
||||||
|
message1->Timestamp(i);
|
||||||
|
channel->BasicPublish("", queue, message1, true);
|
||||||
|
channel->BasicConsumeMessage(consumer, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, basic_recover) {
|
||||||
|
BasicMessage::ptr_t message = BasicMessage::Create("Message1");
|
||||||
|
|
||||||
|
std::string queue = channel->DeclareQueue("");
|
||||||
|
std::string consumer = channel->BasicConsume(queue, "", true, false);
|
||||||
|
channel->BasicPublish("", queue, message);
|
||||||
|
|
||||||
|
Envelope::ptr_t message1;
|
||||||
|
Envelope::ptr_t message2;
|
||||||
|
|
||||||
|
EXPECT_TRUE(channel->BasicConsumeMessage(consumer, message1));
|
||||||
|
channel->BasicRecover(consumer);
|
||||||
|
EXPECT_TRUE(channel->BasicConsumeMessage(consumer, message2));
|
||||||
|
|
||||||
|
channel->DeleteQueue(queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, basic_recover_badconsumer) {
|
||||||
|
EXPECT_THROW(channel->BasicRecover("consumer_notexist"),
|
||||||
|
ConsumerTagNotFoundException);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, basic_qos) {
|
||||||
|
std::string queue = channel->DeclareQueue("");
|
||||||
|
std::string consumer = channel->BasicConsume(queue, "", true, false);
|
||||||
|
channel->BasicPublish("", queue, BasicMessage::Create("Message1"));
|
||||||
|
channel->BasicPublish("", queue, BasicMessage::Create("Message2"));
|
||||||
|
|
||||||
|
Envelope::ptr_t incoming;
|
||||||
|
EXPECT_TRUE(channel->BasicConsumeMessage(consumer, incoming, 100));
|
||||||
|
EXPECT_FALSE(channel->BasicConsumeMessage(consumer, incoming, 100));
|
||||||
|
|
||||||
|
channel->BasicQos(consumer, 2);
|
||||||
|
EXPECT_TRUE(channel->BasicConsumeMessage(consumer, incoming, 100));
|
||||||
|
|
||||||
|
channel->DeleteQueue(queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, basic_qos_badconsumer) {
|
||||||
|
EXPECT_THROW(channel->BasicQos("consumer_notexist", 1),
|
||||||
|
ConsumerTagNotFoundException);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, consumer_cancelled) {
|
||||||
|
std::string queue = channel->DeclareQueue("");
|
||||||
|
std::string consumer = channel->BasicConsume(queue, "", true, false);
|
||||||
|
channel->DeleteQueue(queue);
|
||||||
|
|
||||||
|
EXPECT_THROW(channel->BasicConsumeMessage(consumer),
|
||||||
|
ConsumerCancelledException);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, consumer_cancelled_one_message) {
|
||||||
|
std::string queue = channel->DeclareQueue("");
|
||||||
|
std::string consumer = channel->BasicConsume(queue, "", true, false);
|
||||||
|
|
||||||
|
channel->BasicPublish("", queue, BasicMessage::Create("Message"));
|
||||||
|
channel->BasicConsumeMessage(consumer);
|
||||||
|
|
||||||
|
channel->DeleteQueue(queue);
|
||||||
|
|
||||||
|
EXPECT_THROW(channel->BasicConsumeMessage(consumer),
|
||||||
|
ConsumerCancelledException);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, consume_multiple) {
|
||||||
|
std::string queue1 = channel->DeclareQueue("");
|
||||||
|
std::string queue2 = channel->DeclareQueue("");
|
||||||
|
|
||||||
|
std::string Body = "Message 1";
|
||||||
|
channel->BasicPublish("", queue1, BasicMessage::Create(Body));
|
||||||
|
|
||||||
|
channel->BasicConsume(queue1);
|
||||||
|
channel->BasicConsume(queue2);
|
||||||
|
|
||||||
|
Envelope::ptr_t env = channel->BasicConsumeMessage();
|
||||||
|
|
||||||
|
EXPECT_EQ(Body, env->Message()->Body());
|
||||||
|
}
|
||||||
164
testing/test_exchange.cpp
Normal file
164
testing/test_exchange.cpp
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <SimpleAmqpClient/SimpleAmqpClient.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "connected_test.h"
|
||||||
|
|
||||||
|
TEST_F(connected_test, declare_exchange_defaults) {
|
||||||
|
channel->DeclareExchange("declare_defaults");
|
||||||
|
channel->DeleteExchange("declare_defaults");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, declare_exchange_direct) {
|
||||||
|
channel->DeclareExchange("declare_direct", Channel::EXCHANGE_TYPE_DIRECT);
|
||||||
|
channel->DeleteExchange("declare_direct");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, declare_exchange_fanout) {
|
||||||
|
channel->DeclareExchange("declare_fanout", Channel::EXCHANGE_TYPE_FANOUT);
|
||||||
|
channel->DeleteExchange("declare_fanout");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, declare_exchange_topic) {
|
||||||
|
channel->DeclareExchange("declare_topic", Channel::EXCHANGE_TYPE_TOPIC);
|
||||||
|
channel->DeleteExchange("declare_topic");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, check_exchange_exists_succeeds) {
|
||||||
|
channel->DeclareExchange("declare_exists");
|
||||||
|
EXPECT_TRUE(channel->CheckExchangeExists("declare_exists"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, declare_exchange_passive_good) {
|
||||||
|
channel->DeclareExchange("declare_passive", Channel::EXCHANGE_TYPE_DIRECT);
|
||||||
|
channel->DeclareExchange("declare_passive", Channel::EXCHANGE_TYPE_DIRECT,
|
||||||
|
true);
|
||||||
|
|
||||||
|
channel->DeleteExchange("declare_passive");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, check_exchange_exists_fails) {
|
||||||
|
EXPECT_FALSE(channel->CheckExchangeExists("declare_notexist"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, declare_exchange_passive_notexist) {
|
||||||
|
EXPECT_THROW(channel->DeclareExchange("declare_passive_notexist",
|
||||||
|
Channel::EXCHANGE_TYPE_DIRECT, true),
|
||||||
|
ChannelException);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, declare_exchange_typemismatch) {
|
||||||
|
channel->DeclareExchange("declare_typemismatch",
|
||||||
|
Channel::EXCHANGE_TYPE_DIRECT);
|
||||||
|
EXPECT_THROW(channel->DeclareExchange("declare_typemismatch",
|
||||||
|
Channel::EXCHANGE_TYPE_FANOUT),
|
||||||
|
ChannelException);
|
||||||
|
|
||||||
|
channel->DeleteExchange("declare_typemismatch");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, declare_exchange_typemismatch2) {
|
||||||
|
channel->DeclareExchange("declare_typemismatch",
|
||||||
|
Channel::EXCHANGE_TYPE_DIRECT);
|
||||||
|
EXPECT_THROW(
|
||||||
|
channel->DeclareExchange("declare_typemismatch",
|
||||||
|
Channel::EXCHANGE_TYPE_DIRECT, false, true),
|
||||||
|
ChannelException);
|
||||||
|
|
||||||
|
channel->DeleteExchange("declare_typemismatch");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, declare_exchange_durable) {
|
||||||
|
channel->DeclareExchange("declare_durable", Channel::EXCHANGE_TYPE_DIRECT,
|
||||||
|
false, true);
|
||||||
|
|
||||||
|
channel->DeleteExchange("declare_durable");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, declare_exchange_autodelete) {
|
||||||
|
channel->DeclareExchange("declare_autodelete", Channel::EXCHANGE_TYPE_DIRECT,
|
||||||
|
false, false, true);
|
||||||
|
|
||||||
|
channel->DeleteExchange("declare_autodelete");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, delete_exchange) {
|
||||||
|
channel->DeclareExchange("delete_exchange");
|
||||||
|
channel->DeleteExchange("delete_exchange");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, delete_exhange_ifunused) {
|
||||||
|
channel->DeclareExchange("exchange_used", Channel::EXCHANGE_TYPE_DIRECT);
|
||||||
|
|
||||||
|
channel->DeleteExchange("exchange_used", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, delete_exhange_ifused) {
|
||||||
|
channel->DeclareExchange("exchange_used", Channel::EXCHANGE_TYPE_DIRECT);
|
||||||
|
std::string queue = channel->DeclareQueue("");
|
||||||
|
channel->BindQueue(queue, "exchange_used", "whatever");
|
||||||
|
|
||||||
|
EXPECT_THROW(channel->DeleteExchange("exchange_used", true),
|
||||||
|
ChannelException);
|
||||||
|
|
||||||
|
channel->DeleteQueue(queue);
|
||||||
|
channel->DeleteExchange("exchange_used");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, bind_exchange) {
|
||||||
|
channel->DeclareExchange("exchange_bind_dest");
|
||||||
|
channel->DeclareExchange("exchange_bind_src");
|
||||||
|
|
||||||
|
channel->BindExchange("exchange_bind_dest", "exchange_bind_src", "rk");
|
||||||
|
|
||||||
|
channel->DeleteExchange("exchange_bind_dest");
|
||||||
|
channel->DeleteExchange("exchange_bind_src");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, bind_exchange_badexchange) {
|
||||||
|
channel->DeclareExchange("exchange_bind_dest");
|
||||||
|
|
||||||
|
EXPECT_THROW(channel->BindExchange("exchange_bind_dest",
|
||||||
|
"exchange_bind_notexist", "rk"),
|
||||||
|
ChannelException);
|
||||||
|
|
||||||
|
channel->DeleteExchange("exchange_bind_dest");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, unbind_exchange) {
|
||||||
|
channel->DeclareExchange("exchange_bind_dest");
|
||||||
|
channel->DeclareExchange("exchange_bind_src");
|
||||||
|
|
||||||
|
channel->BindExchange("exchange_bind_dest", "exchange_bind_src", "rk");
|
||||||
|
channel->UnbindExchange("exchange_bind_dest", "exchange_bind_src", "rk");
|
||||||
|
|
||||||
|
channel->DeleteExchange("exchange_bind_dest");
|
||||||
|
channel->DeleteExchange("exchange_bind_src");
|
||||||
|
}
|
||||||
81
testing/test_get.cpp
Normal file
81
testing/test_get.cpp
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "connected_test.h"
|
||||||
|
|
||||||
|
using namespace AmqpClient;
|
||||||
|
|
||||||
|
TEST_F(connected_test, get_ok) {
|
||||||
|
BasicMessage::ptr_t message = BasicMessage::Create("Message Body");
|
||||||
|
std::string queue = channel->DeclareQueue("");
|
||||||
|
channel->BasicPublish("", queue, message, true);
|
||||||
|
|
||||||
|
Envelope::ptr_t new_message;
|
||||||
|
EXPECT_TRUE(channel->BasicGet(new_message, queue));
|
||||||
|
EXPECT_EQ(message->Body(), new_message->Message()->Body());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, get_empty) {
|
||||||
|
BasicMessage::ptr_t message = BasicMessage::Create("Message Body");
|
||||||
|
std::string queue = channel->DeclareQueue("");
|
||||||
|
|
||||||
|
Envelope::ptr_t new_message;
|
||||||
|
EXPECT_FALSE(channel->BasicGet(new_message, queue));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(test_get, get_big) {
|
||||||
|
// Smallest frame size allowed by AMQP
|
||||||
|
Channel::OpenOpts opts = connected_test::GetTestOpenOpts();
|
||||||
|
opts.frame_max = 4096;
|
||||||
|
Channel::ptr_t channel = Channel::Open(opts);
|
||||||
|
// Create a message with a body larger than a single frame
|
||||||
|
BasicMessage::ptr_t message = BasicMessage::Create(std::string(4099, 'a'));
|
||||||
|
std::string queue = channel->DeclareQueue("");
|
||||||
|
|
||||||
|
channel->BasicPublish("", queue, message);
|
||||||
|
Envelope::ptr_t new_message;
|
||||||
|
EXPECT_TRUE(channel->BasicGet(new_message, queue));
|
||||||
|
EXPECT_EQ(message->Body(), new_message->Message()->Body());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, bad_queue) {
|
||||||
|
Envelope::ptr_t new_message;
|
||||||
|
EXPECT_THROW(channel->BasicGet(new_message, "test_get_nonexistantqueue"),
|
||||||
|
ChannelException);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, ack_message) {
|
||||||
|
BasicMessage::ptr_t message = BasicMessage::Create("Message Body");
|
||||||
|
std::string queue = channel->DeclareQueue("");
|
||||||
|
channel->BasicPublish("", queue, message, true);
|
||||||
|
|
||||||
|
Envelope::ptr_t new_message;
|
||||||
|
EXPECT_TRUE(channel->BasicGet(new_message, queue, false));
|
||||||
|
channel->BasicAck(new_message);
|
||||||
|
EXPECT_FALSE(channel->BasicGet(new_message, queue, false));
|
||||||
|
}
|
||||||
134
testing/test_message.cpp
Normal file
134
testing/test_message.cpp
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <amqp.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <boost/array.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "connected_test.h"
|
||||||
|
|
||||||
|
using namespace AmqpClient;
|
||||||
|
|
||||||
|
TEST(basic_message, empty_message) {
|
||||||
|
BasicMessage::ptr_t empty_message = BasicMessage::Create();
|
||||||
|
|
||||||
|
EXPECT_EQ(std::string(), empty_message->Body());
|
||||||
|
|
||||||
|
// Allow the message to destruct
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(basic_message, empty_message_add_body) {
|
||||||
|
BasicMessage::ptr_t empty_message = BasicMessage::Create();
|
||||||
|
|
||||||
|
EXPECT_EQ(std::string(), empty_message->Body());
|
||||||
|
|
||||||
|
const std::string body("Message Body");
|
||||||
|
empty_message->Body(body);
|
||||||
|
|
||||||
|
EXPECT_EQ(body, empty_message->Body());
|
||||||
|
|
||||||
|
// Allow the message to destruct
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(basic_message, empty_message_add_body2) {
|
||||||
|
BasicMessage::ptr_t empty_message = BasicMessage::Create();
|
||||||
|
|
||||||
|
EXPECT_EQ(std::string(), empty_message->Body());
|
||||||
|
|
||||||
|
const std::string body("Message Body");
|
||||||
|
empty_message->Body(body);
|
||||||
|
|
||||||
|
EXPECT_EQ(body, empty_message->Body());
|
||||||
|
|
||||||
|
const std::string body2("Second body");
|
||||||
|
empty_message->Body(body2);
|
||||||
|
EXPECT_EQ(body2, empty_message->Body());
|
||||||
|
|
||||||
|
// Allow the message to destruct
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(basic_message, initial_message_replace) {
|
||||||
|
const std::string first_body("First message Body");
|
||||||
|
BasicMessage::ptr_t message = BasicMessage::Create(first_body);
|
||||||
|
|
||||||
|
EXPECT_EQ(first_body, message->Body());
|
||||||
|
|
||||||
|
const std::string second_body("Second message Body");
|
||||||
|
message->Body(second_body);
|
||||||
|
|
||||||
|
EXPECT_EQ(second_body, message->Body());
|
||||||
|
|
||||||
|
// Allow the message to destruct
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(basic_message, initial_message_replace2) {
|
||||||
|
const std::string first_body("First message body");
|
||||||
|
BasicMessage::ptr_t message = BasicMessage::Create(first_body);
|
||||||
|
EXPECT_EQ(first_body, message->Body());
|
||||||
|
|
||||||
|
const std::string second_body("second message body");
|
||||||
|
message->Body(second_body);
|
||||||
|
EXPECT_EQ(second_body, message->Body());
|
||||||
|
|
||||||
|
const std::string third_body("3rd Body");
|
||||||
|
message->Body(third_body);
|
||||||
|
EXPECT_EQ(third_body, message->Body());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(basic_message, embedded_nulls) {
|
||||||
|
const boost::array<char, 7> message_data = {
|
||||||
|
{'a', 'b', 'c', 0, '1', '2', '3'}};
|
||||||
|
const std::string body(message_data.data(), message_data.size());
|
||||||
|
BasicMessage::ptr_t message = BasicMessage::Create(body);
|
||||||
|
EXPECT_EQ(body, message->Body());
|
||||||
|
|
||||||
|
const boost::array<char, 7> message_data2 = {
|
||||||
|
{'1', '2', '3', 0, 'a', 'b', 'c'}};
|
||||||
|
const std::string body2(message_data2.data(), message_data2.size());
|
||||||
|
message->Body(body2);
|
||||||
|
EXPECT_EQ(body2, message->Body());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, replaced_received_body) {
|
||||||
|
const std::string queue = channel->DeclareQueue("");
|
||||||
|
const std::string consumer = channel->BasicConsume(queue);
|
||||||
|
|
||||||
|
const std::string body("First Message Body");
|
||||||
|
BasicMessage::ptr_t out_message = BasicMessage::Create(body);
|
||||||
|
channel->BasicPublish("", queue, out_message);
|
||||||
|
|
||||||
|
Envelope::ptr_t envelope = channel->BasicConsumeMessage(consumer);
|
||||||
|
BasicMessage::ptr_t in_message = envelope->Message();
|
||||||
|
EXPECT_EQ(out_message->Body(), in_message->Body());
|
||||||
|
|
||||||
|
const std::string body2("Second message body");
|
||||||
|
in_message->Body(body2);
|
||||||
|
EXPECT_EQ(body2, in_message->Body());
|
||||||
|
}
|
||||||
77
testing/test_nack.cpp
Normal file
77
testing/test_nack.cpp
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "connected_test.h"
|
||||||
|
|
||||||
|
using namespace AmqpClient;
|
||||||
|
|
||||||
|
TEST_F(connected_test, basic_nack_envelope) {
|
||||||
|
const BasicMessage::ptr_t message = BasicMessage::Create("Message Body");
|
||||||
|
std::string queue = channel->DeclareQueue("");
|
||||||
|
channel->BasicPublish("", queue, message);
|
||||||
|
|
||||||
|
std::string consumer = channel->BasicConsume(queue, "", true, false);
|
||||||
|
|
||||||
|
Envelope::ptr_t env = channel->BasicConsumeMessage(consumer);
|
||||||
|
|
||||||
|
channel->BasicReject(env, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, basic_nack_deliveryinfo) {
|
||||||
|
const BasicMessage::ptr_t message = BasicMessage::Create("Message Body");
|
||||||
|
std::string queue = channel->DeclareQueue("");
|
||||||
|
channel->BasicPublish("", queue, message);
|
||||||
|
|
||||||
|
std::string consumer = channel->BasicConsume(queue, "", true, false);
|
||||||
|
|
||||||
|
Envelope::DeliveryInfo info;
|
||||||
|
{
|
||||||
|
Envelope::ptr_t env = channel->BasicConsumeMessage(consumer);
|
||||||
|
info = env->GetDeliveryInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
channel->BasicReject(info, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, basic_nack_envelope_with_requeue) {
|
||||||
|
const BasicMessage::ptr_t message = BasicMessage::Create("Message Body");
|
||||||
|
std::string queue = channel->DeclareQueue("");
|
||||||
|
channel->BasicPublish("", queue, message);
|
||||||
|
|
||||||
|
std::string consumer = channel->BasicConsume(queue, "", true, false);
|
||||||
|
|
||||||
|
Envelope::ptr_t env = channel->BasicConsumeMessage(consumer);
|
||||||
|
|
||||||
|
channel->BasicReject(env, true);
|
||||||
|
|
||||||
|
Envelope::ptr_t env2 = channel->BasicConsumeMessage(consumer);
|
||||||
|
|
||||||
|
channel->BasicReject(env2, false);
|
||||||
|
}
|
||||||
88
testing/test_publish.cpp
Normal file
88
testing/test_publish.cpp
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "connected_test.h"
|
||||||
|
|
||||||
|
using namespace AmqpClient;
|
||||||
|
|
||||||
|
TEST_F(connected_test, publish_success) {
|
||||||
|
BasicMessage::ptr_t message = BasicMessage::Create("message body");
|
||||||
|
|
||||||
|
channel->BasicPublish("", "test_publish_rk", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(test_publish, publish_large_message) {
|
||||||
|
// Smallest frame size allowed by AMQP
|
||||||
|
Channel::OpenOpts opts = connected_test::GetTestOpenOpts();
|
||||||
|
opts.frame_max = 4096;
|
||||||
|
Channel::ptr_t channel = Channel::Open(opts);
|
||||||
|
// Create a message with a body larger than a single frame
|
||||||
|
BasicMessage::ptr_t message = BasicMessage::Create(std::string(4099, 'a'));
|
||||||
|
|
||||||
|
channel->BasicPublish("", "test_publish_rk", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, publish_badexchange) {
|
||||||
|
BasicMessage::ptr_t message = BasicMessage::Create("message body");
|
||||||
|
|
||||||
|
EXPECT_THROW(channel->BasicPublish("test_publish_notexist", "test_publish_rk",
|
||||||
|
message),
|
||||||
|
ChannelException);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, publish_recover_from_error) {
|
||||||
|
BasicMessage::ptr_t message = BasicMessage::Create("message body");
|
||||||
|
|
||||||
|
EXPECT_THROW(channel->BasicPublish("test_publish_notexist", "test_publish_rk",
|
||||||
|
message),
|
||||||
|
ChannelException);
|
||||||
|
channel->BasicPublish("", "test_publish_rk", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, publish_mandatory_fail) {
|
||||||
|
BasicMessage::ptr_t message = BasicMessage::Create("message body");
|
||||||
|
|
||||||
|
EXPECT_THROW(
|
||||||
|
channel->BasicPublish("", "test_publish_notexist", message, true),
|
||||||
|
MessageReturnedException);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, publish_mandatory_success) {
|
||||||
|
BasicMessage::ptr_t message = BasicMessage::Create("message body");
|
||||||
|
std::string queue = channel->DeclareQueue("");
|
||||||
|
|
||||||
|
channel->BasicPublish("", queue, message, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, publish_immediate_success) {
|
||||||
|
BasicMessage::ptr_t message = BasicMessage::Create("message body");
|
||||||
|
std::string queue = channel->DeclareQueue("");
|
||||||
|
std::string consumer = channel->BasicConsume(queue, "");
|
||||||
|
|
||||||
|
channel->BasicPublish("", queue, message, true);
|
||||||
|
}
|
||||||
247
testing/test_queue.cpp
Normal file
247
testing/test_queue.cpp
Normal file
@@ -0,0 +1,247 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "connected_test.h"
|
||||||
|
|
||||||
|
TEST_F(connected_test, queue_declare) {
|
||||||
|
std::string queue = channel->DeclareQueue("");
|
||||||
|
channel->DeleteQueue(queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, queue_declare_named) {
|
||||||
|
std::string queue = channel->DeclareQueue("declare_queue_test");
|
||||||
|
EXPECT_EQ("declare_queue_test", queue);
|
||||||
|
|
||||||
|
channel->DeleteQueue(queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, check_queue_exists_success) {
|
||||||
|
channel->DeclareQueue("declare_queue_passive");
|
||||||
|
EXPECT_TRUE(channel->CheckQueueExists("declare_queue_passive"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, queue_declare_passive) {
|
||||||
|
std::string queue = channel->DeclareQueue("declare_queue_passive");
|
||||||
|
channel->DeclareQueue("declare_queue_passive", true);
|
||||||
|
|
||||||
|
channel->DeleteQueue(queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, check_queue_exists_fail) {
|
||||||
|
EXPECT_FALSE(channel->CheckQueueExists("declare_queue_notexist"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, queue_declare_passive_fail) {
|
||||||
|
EXPECT_THROW(channel->DeclareQueue("declare_queue_notexist", true),
|
||||||
|
ChannelException);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, queue_declare_durable) {
|
||||||
|
std::string queue =
|
||||||
|
channel->DeclareQueue("declare_queue_durable", false, true, false);
|
||||||
|
|
||||||
|
channel->DeleteQueue(queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, queue_declare_notexclusive) {
|
||||||
|
std::string queue =
|
||||||
|
channel->DeclareQueue("declare_queue_notexclusive", false, false, false);
|
||||||
|
|
||||||
|
channel->DeleteQueue(queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, queue_declare_notautodelete) {
|
||||||
|
std::string queue = channel->DeclareQueue("declare_queue_notautodelete",
|
||||||
|
false, false, false, false);
|
||||||
|
|
||||||
|
channel->DeleteQueue(queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, queue_declare_counts) {
|
||||||
|
boost::uint32_t message_count = 123;
|
||||||
|
boost::uint32_t consumer_count = 123;
|
||||||
|
|
||||||
|
std::string queue = channel->DeclareQueueWithCounts(
|
||||||
|
"queue_declare_counts", message_count, consumer_count);
|
||||||
|
|
||||||
|
EXPECT_NE("", queue);
|
||||||
|
EXPECT_EQ(0, message_count);
|
||||||
|
EXPECT_EQ(0, consumer_count);
|
||||||
|
|
||||||
|
const std::string body("Test Message");
|
||||||
|
BasicMessage::ptr_t out_message = BasicMessage::Create(body);
|
||||||
|
channel->BasicPublish("", queue, out_message);
|
||||||
|
channel->BasicPublish("", queue, out_message);
|
||||||
|
channel->BasicPublish("", queue, out_message);
|
||||||
|
|
||||||
|
std::string queue2 = channel->DeclareQueueWithCounts(
|
||||||
|
"queue_declare_counts", message_count, consumer_count);
|
||||||
|
|
||||||
|
EXPECT_NE("", queue2);
|
||||||
|
EXPECT_EQ(3, message_count);
|
||||||
|
EXPECT_EQ(0, consumer_count);
|
||||||
|
|
||||||
|
channel->DeleteQueue(queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, queue_declare_counts_table) {
|
||||||
|
boost::uint32_t message_count = 123;
|
||||||
|
boost::uint32_t consumer_count = 123;
|
||||||
|
|
||||||
|
Table qTable;
|
||||||
|
|
||||||
|
qTable.insert(TableEntry(TableKey("IsATest"), TableValue(true)));
|
||||||
|
|
||||||
|
std::string queue = channel->DeclareQueueWithCounts(
|
||||||
|
"queue_declare_counts_table", message_count, consumer_count, false, false,
|
||||||
|
true, true, qTable);
|
||||||
|
|
||||||
|
EXPECT_NE("", queue);
|
||||||
|
EXPECT_EQ(0, message_count);
|
||||||
|
EXPECT_EQ(0, consumer_count);
|
||||||
|
|
||||||
|
const std::string body("Test Message");
|
||||||
|
BasicMessage::ptr_t out_message = BasicMessage::Create(body);
|
||||||
|
channel->BasicPublish("", queue, out_message);
|
||||||
|
channel->BasicPublish("", queue, out_message);
|
||||||
|
channel->BasicPublish("", queue, out_message);
|
||||||
|
|
||||||
|
std::string queue2 = channel->DeclareQueueWithCounts(
|
||||||
|
"queue_declare_counts_table", message_count, consumer_count, false, false,
|
||||||
|
true, true, qTable);
|
||||||
|
|
||||||
|
EXPECT_NE("", queue2);
|
||||||
|
EXPECT_EQ(3, message_count);
|
||||||
|
EXPECT_EQ(0, consumer_count);
|
||||||
|
|
||||||
|
channel->DeleteQueue(queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, queue_delete) {
|
||||||
|
std::string queue = channel->DeclareQueue("delete_queue");
|
||||||
|
channel->DeleteQueue(queue);
|
||||||
|
EXPECT_THROW(channel->DeclareQueue(queue, true), ChannelException);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, queue_delete_ifunused) {
|
||||||
|
std::string queue = channel->DeclareQueue("delete_queue_ifunused");
|
||||||
|
channel->DeleteQueue(queue, true);
|
||||||
|
EXPECT_THROW(channel->DeclareQueue(queue, true), ChannelException);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, queue_delete_ifused) {
|
||||||
|
std::string queue = channel->DeclareQueue("delete_queue_ifused");
|
||||||
|
channel->BasicConsume(queue);
|
||||||
|
EXPECT_THROW(channel->DeleteQueue(queue, true), ChannelException);
|
||||||
|
|
||||||
|
channel->DeleteQueue(queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, queue_delete_ifempty) {
|
||||||
|
std::string queue = channel->DeclareQueue("delete_queue_ifempty");
|
||||||
|
channel->DeleteQueue(queue, false, true);
|
||||||
|
|
||||||
|
EXPECT_THROW(channel->DeclareQueue(queue, true), ChannelException);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, queue_delete_ifnotempty) {
|
||||||
|
std::string queue = channel->DeclareQueue("delete_queue_ifnotempty");
|
||||||
|
BasicMessage::ptr_t message = BasicMessage::Create("Message body");
|
||||||
|
channel->BasicPublish("", queue, message, true);
|
||||||
|
|
||||||
|
EXPECT_THROW(channel->DeleteQueue(queue, false, true), ChannelException);
|
||||||
|
|
||||||
|
channel->DeleteQueue(queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, queue_bind) {
|
||||||
|
channel->DeclareExchange("queue_bind_exchange");
|
||||||
|
std::string queue = channel->DeclareQueue("queue_bind_queue");
|
||||||
|
|
||||||
|
channel->BindQueue(queue, "queue_bind_exchange", "rk");
|
||||||
|
|
||||||
|
channel->DeleteExchange("queue_bind_exchange");
|
||||||
|
channel->DeleteQueue(queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, queue_bind_badexchange) {
|
||||||
|
std::string queue = channel->DeclareQueue("queue_bind_badexchange");
|
||||||
|
|
||||||
|
EXPECT_THROW(channel->BindQueue(queue, "queue_bind_exchangenotexist", "rk"),
|
||||||
|
ChannelException);
|
||||||
|
|
||||||
|
channel->DeleteQueue(queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, queue_bind_badqueue) {
|
||||||
|
channel->DeclareExchange("queue_bind_badqueue");
|
||||||
|
|
||||||
|
EXPECT_THROW(channel->BindQueue("queue_bind_queuenotexist",
|
||||||
|
"queue_bind_badqueue", "rk"),
|
||||||
|
ChannelException);
|
||||||
|
|
||||||
|
channel->DeleteExchange("queue_bind_badqueue");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, queue_bind_nokey) {
|
||||||
|
channel->DeclareExchange("queue_bind_exchange");
|
||||||
|
std::string queue = channel->DeclareQueue("queue_bind_queue");
|
||||||
|
|
||||||
|
channel->BindQueue(queue, "queue_bind_exchange");
|
||||||
|
|
||||||
|
channel->DeleteExchange("queue_bind_exchange");
|
||||||
|
channel->DeleteQueue(queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, queue_unbind) {
|
||||||
|
channel->DeclareExchange("queue_unbind_exchange");
|
||||||
|
std::string queue = channel->DeclareQueue("queue_unbind_queue");
|
||||||
|
channel->BindQueue(queue, "queue_unbind_exchange", "rk");
|
||||||
|
|
||||||
|
channel->UnbindQueue(queue, "queue_unbind_exchange", "rk");
|
||||||
|
|
||||||
|
channel->DeleteExchange("queue_unbind_exchange");
|
||||||
|
channel->DeleteQueue(queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, queue_purge) {
|
||||||
|
std::string queue = channel->DeclareQueue("queue_purge");
|
||||||
|
BasicMessage::ptr_t message = BasicMessage::Create("Message Body");
|
||||||
|
channel->BasicPublish("", queue, message, true);
|
||||||
|
|
||||||
|
channel->PurgeQueue(queue);
|
||||||
|
Envelope::ptr_t envelope;
|
||||||
|
EXPECT_FALSE(channel->BasicGet(envelope, queue));
|
||||||
|
|
||||||
|
channel->DeleteQueue(queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, queue_purge_badqueue) {
|
||||||
|
EXPECT_THROW(channel->PurgeQueue("purge_queue_queuenotexist"),
|
||||||
|
ChannelException);
|
||||||
|
}
|
||||||
896
testing/test_table.cpp
Normal file
896
testing/test_table.cpp
Normal file
@@ -0,0 +1,896 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MIT
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010-2013 Alan Antonuk
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <boost/type_traits/remove_cv.hpp>
|
||||||
|
#include <boost/variant/get.hpp>
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
#include "connected_test.h"
|
||||||
|
|
||||||
|
using namespace AmqpClient;
|
||||||
|
|
||||||
|
TEST(table_value, void_value) {
|
||||||
|
TableValue value;
|
||||||
|
EXPECT_EQ(TableValue::VT_void, value.GetType());
|
||||||
|
|
||||||
|
EXPECT_THROW(value.GetBool(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTimestamp(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt64(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInteger(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetFloat(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetDouble(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetReal(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetString(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetArray(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTable(), boost::bad_get);
|
||||||
|
|
||||||
|
value.Set();
|
||||||
|
EXPECT_EQ(TableValue::VT_void, value.GetType());
|
||||||
|
|
||||||
|
EXPECT_THROW(value.GetBool(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTimestamp(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt64(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInteger(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetFloat(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetDouble(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetReal(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetString(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetArray(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTable(), boost::bad_get);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(table_value, bool_value) {
|
||||||
|
bool v1 = true;
|
||||||
|
bool v2 = false;
|
||||||
|
|
||||||
|
TableValue value(v1);
|
||||||
|
EXPECT_EQ(TableValue::VT_bool, value.GetType());
|
||||||
|
|
||||||
|
EXPECT_EQ(v1, value.GetBool());
|
||||||
|
EXPECT_THROW(value.GetUint8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTimestamp(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt64(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInteger(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetFloat(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetDouble(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetReal(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetString(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetArray(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTable(), boost::bad_get);
|
||||||
|
|
||||||
|
value.Set(v2);
|
||||||
|
EXPECT_EQ(TableValue::VT_bool, value.GetType());
|
||||||
|
|
||||||
|
EXPECT_EQ(v2, value.GetBool());
|
||||||
|
EXPECT_THROW(value.GetUint8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTimestamp(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt64(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInteger(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetFloat(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetDouble(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetReal(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetString(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetArray(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTable(), boost::bad_get);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(table_value, uint8_value) {
|
||||||
|
boost::uint8_t v1 = 1;
|
||||||
|
boost::uint8_t v2 = 2;
|
||||||
|
|
||||||
|
TableValue value(v1);
|
||||||
|
EXPECT_EQ(TableValue::VT_uint8, value.GetType());
|
||||||
|
EXPECT_EQ(v1, value.GetUint8());
|
||||||
|
EXPECT_EQ(v1, value.GetInteger());
|
||||||
|
|
||||||
|
EXPECT_THROW(value.GetBool(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTimestamp(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt64(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetFloat(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetDouble(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetReal(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetString(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetArray(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTable(), boost::bad_get);
|
||||||
|
|
||||||
|
value.Set(v2);
|
||||||
|
EXPECT_EQ(TableValue::VT_uint8, value.GetType());
|
||||||
|
EXPECT_EQ(v2, value.GetUint8());
|
||||||
|
EXPECT_EQ(v2, value.GetInteger());
|
||||||
|
|
||||||
|
EXPECT_THROW(value.GetBool(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTimestamp(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt64(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetFloat(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetDouble(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetReal(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetString(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetArray(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTable(), boost::bad_get);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(table_value, int8_value) {
|
||||||
|
boost::int8_t v1 = 1;
|
||||||
|
boost::int8_t v2 = 2;
|
||||||
|
|
||||||
|
TableValue value(v1);
|
||||||
|
EXPECT_EQ(TableValue::VT_int8, value.GetType());
|
||||||
|
EXPECT_EQ(v1, value.GetInt8());
|
||||||
|
EXPECT_EQ(v1, value.GetInteger());
|
||||||
|
|
||||||
|
EXPECT_THROW(value.GetBool(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTimestamp(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt64(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetFloat(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetDouble(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetReal(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetString(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetArray(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTable(), boost::bad_get);
|
||||||
|
|
||||||
|
value.Set(v2);
|
||||||
|
EXPECT_EQ(TableValue::VT_int8, value.GetType());
|
||||||
|
EXPECT_EQ(v2, value.GetInt8());
|
||||||
|
EXPECT_EQ(v2, value.GetInteger());
|
||||||
|
|
||||||
|
EXPECT_THROW(value.GetBool(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTimestamp(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt64(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetFloat(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetDouble(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetReal(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetString(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetArray(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTable(), boost::bad_get);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(table_value, uint16_value) {
|
||||||
|
boost::uint16_t v1 = 1;
|
||||||
|
boost::uint16_t v2 = 2;
|
||||||
|
|
||||||
|
TableValue value(v1);
|
||||||
|
EXPECT_EQ(TableValue::VT_uint16, value.GetType());
|
||||||
|
EXPECT_EQ(v1, value.GetUint16());
|
||||||
|
EXPECT_EQ(v1, value.GetInteger());
|
||||||
|
|
||||||
|
EXPECT_THROW(value.GetBool(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTimestamp(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt64(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetFloat(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetDouble(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetReal(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetString(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetArray(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTable(), boost::bad_get);
|
||||||
|
|
||||||
|
value.Set(v2);
|
||||||
|
EXPECT_EQ(TableValue::VT_uint16, value.GetType());
|
||||||
|
EXPECT_EQ(v2, value.GetUint16());
|
||||||
|
EXPECT_EQ(v2, value.GetInteger());
|
||||||
|
|
||||||
|
EXPECT_THROW(value.GetBool(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTimestamp(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt64(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetFloat(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetDouble(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetReal(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetString(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetArray(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTable(), boost::bad_get);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(table_value, int16_value) {
|
||||||
|
boost::int16_t v1 = 1;
|
||||||
|
boost::int16_t v2 = 2;
|
||||||
|
|
||||||
|
TableValue value(v1);
|
||||||
|
EXPECT_EQ(TableValue::VT_int16, value.GetType());
|
||||||
|
EXPECT_EQ(v1, value.GetInt16());
|
||||||
|
EXPECT_EQ(v1, value.GetInteger());
|
||||||
|
|
||||||
|
EXPECT_THROW(value.GetBool(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTimestamp(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt64(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetFloat(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetDouble(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetReal(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetString(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetArray(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTable(), boost::bad_get);
|
||||||
|
|
||||||
|
value.Set(v2);
|
||||||
|
EXPECT_EQ(TableValue::VT_int16, value.GetType());
|
||||||
|
EXPECT_EQ(v2, value.GetInt16());
|
||||||
|
EXPECT_EQ(v2, value.GetInteger());
|
||||||
|
|
||||||
|
EXPECT_THROW(value.GetBool(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTimestamp(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt64(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetFloat(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetDouble(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetReal(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetString(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetArray(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTable(), boost::bad_get);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(table_value, uint32_value) {
|
||||||
|
boost::uint32_t v1 = 1;
|
||||||
|
boost::uint32_t v2 = 2;
|
||||||
|
|
||||||
|
TableValue value(v1);
|
||||||
|
EXPECT_EQ(TableValue::VT_uint32, value.GetType());
|
||||||
|
EXPECT_EQ(v1, value.GetUint32());
|
||||||
|
EXPECT_EQ(v1, value.GetInteger());
|
||||||
|
|
||||||
|
EXPECT_THROW(value.GetBool(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTimestamp(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt64(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetFloat(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetDouble(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetReal(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetString(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetArray(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTable(), boost::bad_get);
|
||||||
|
|
||||||
|
value.Set(v2);
|
||||||
|
EXPECT_EQ(TableValue::VT_uint32, value.GetType());
|
||||||
|
EXPECT_EQ(v2, value.GetUint32());
|
||||||
|
EXPECT_EQ(v2, value.GetInteger());
|
||||||
|
|
||||||
|
EXPECT_THROW(value.GetBool(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTimestamp(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt64(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetFloat(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetDouble(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetReal(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetString(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetArray(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTable(), boost::bad_get);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(table_value, int32_value) {
|
||||||
|
boost::int32_t v1 = 1;
|
||||||
|
boost::int32_t v2 = 2;
|
||||||
|
|
||||||
|
TableValue value(v1);
|
||||||
|
EXPECT_EQ(TableValue::VT_int32, value.GetType());
|
||||||
|
EXPECT_EQ(v1, value.GetInt32());
|
||||||
|
EXPECT_EQ(v1, value.GetInteger());
|
||||||
|
|
||||||
|
EXPECT_THROW(value.GetBool(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTimestamp(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt64(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetFloat(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetDouble(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetReal(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetString(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetArray(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTable(), boost::bad_get);
|
||||||
|
|
||||||
|
value.Set(v2);
|
||||||
|
EXPECT_EQ(TableValue::VT_int32, value.GetType());
|
||||||
|
EXPECT_EQ(v2, value.GetInt32());
|
||||||
|
EXPECT_EQ(v2, value.GetInteger());
|
||||||
|
|
||||||
|
EXPECT_THROW(value.GetBool(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTimestamp(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt64(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetFloat(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetDouble(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetReal(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetString(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetArray(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTable(), boost::bad_get);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(table_value, timestamp_value) {
|
||||||
|
std::time_t v1 = 1;
|
||||||
|
std::time_t v2 = 2;
|
||||||
|
|
||||||
|
TableValue value = TableValue::Timestamp(v1);
|
||||||
|
EXPECT_EQ(TableValue::VT_timestamp, value.GetType());
|
||||||
|
EXPECT_EQ(v1, value.GetTimestamp());
|
||||||
|
|
||||||
|
EXPECT_THROW(value.GetBool(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt64(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInteger(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetFloat(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetDouble(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetReal(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetString(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetArray(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTable(), boost::bad_get);
|
||||||
|
|
||||||
|
value.SetTimestamp(v2);
|
||||||
|
EXPECT_EQ(TableValue::VT_timestamp, value.GetType());
|
||||||
|
EXPECT_EQ(v2, value.GetTimestamp());
|
||||||
|
|
||||||
|
EXPECT_THROW(value.GetBool(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt64(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInteger(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetFloat(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetDouble(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetReal(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetString(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetArray(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTable(), boost::bad_get);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(table_value, int64_value) {
|
||||||
|
boost::int64_t v1 = 1;
|
||||||
|
boost::int64_t v2 = 2;
|
||||||
|
|
||||||
|
TableValue value(v1);
|
||||||
|
EXPECT_EQ(TableValue::VT_int64, value.GetType());
|
||||||
|
EXPECT_EQ(v1, value.GetInt64());
|
||||||
|
EXPECT_EQ(v1, value.GetInteger());
|
||||||
|
|
||||||
|
EXPECT_THROW(value.GetBool(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTimestamp(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetFloat(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetDouble(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetReal(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetString(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetArray(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTable(), boost::bad_get);
|
||||||
|
|
||||||
|
value.Set(v2);
|
||||||
|
EXPECT_EQ(TableValue::VT_int64, value.GetType());
|
||||||
|
EXPECT_EQ(v2, value.GetInt64());
|
||||||
|
EXPECT_EQ(v2, value.GetInteger());
|
||||||
|
|
||||||
|
EXPECT_THROW(value.GetBool(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTimestamp(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetFloat(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetDouble(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetReal(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetString(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetArray(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTable(), boost::bad_get);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(table_value, float_value) {
|
||||||
|
float v1 = 1.;
|
||||||
|
float v2 = 2.;
|
||||||
|
|
||||||
|
TableValue value(v1);
|
||||||
|
EXPECT_EQ(TableValue::VT_float, value.GetType());
|
||||||
|
EXPECT_EQ(v1, value.GetFloat());
|
||||||
|
EXPECT_EQ(v1, value.GetReal());
|
||||||
|
|
||||||
|
EXPECT_THROW(value.GetBool(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTimestamp(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt64(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInteger(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetDouble(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetString(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetArray(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTable(), boost::bad_get);
|
||||||
|
|
||||||
|
value.Set(v2);
|
||||||
|
EXPECT_EQ(TableValue::VT_float, value.GetType());
|
||||||
|
EXPECT_EQ(v2, value.GetFloat());
|
||||||
|
EXPECT_EQ(v2, value.GetReal());
|
||||||
|
|
||||||
|
EXPECT_THROW(value.GetBool(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTimestamp(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt64(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInteger(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetDouble(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetString(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetArray(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTable(), boost::bad_get);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(table_value, double_value) {
|
||||||
|
double v1 = 1;
|
||||||
|
double v2 = 2;
|
||||||
|
|
||||||
|
TableValue value(v1);
|
||||||
|
EXPECT_EQ(TableValue::VT_double, value.GetType());
|
||||||
|
EXPECT_EQ(v1, value.GetDouble());
|
||||||
|
EXPECT_EQ(v1, value.GetReal());
|
||||||
|
|
||||||
|
EXPECT_THROW(value.GetBool(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTimestamp(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt64(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInteger(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetFloat(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetString(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetArray(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTable(), boost::bad_get);
|
||||||
|
|
||||||
|
value.Set(v2);
|
||||||
|
EXPECT_EQ(TableValue::VT_double, value.GetType());
|
||||||
|
EXPECT_EQ(v2, value.GetDouble());
|
||||||
|
EXPECT_EQ(v2, value.GetReal());
|
||||||
|
|
||||||
|
EXPECT_THROW(value.GetBool(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTimestamp(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt64(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInteger(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetFloat(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetString(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetArray(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTable(), boost::bad_get);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(table_value, string_value) {
|
||||||
|
std::string v1 = "1";
|
||||||
|
std::string v2 = "2";
|
||||||
|
|
||||||
|
TableValue value(v1);
|
||||||
|
EXPECT_EQ(TableValue::VT_string, value.GetType());
|
||||||
|
EXPECT_EQ(v1, value.GetString());
|
||||||
|
|
||||||
|
EXPECT_THROW(value.GetBool(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTimestamp(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt64(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInteger(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetFloat(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetDouble(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetReal(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetArray(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTable(), boost::bad_get);
|
||||||
|
|
||||||
|
value.Set(v2);
|
||||||
|
EXPECT_EQ(TableValue::VT_string, value.GetType());
|
||||||
|
EXPECT_EQ(v2, value.GetString());
|
||||||
|
|
||||||
|
EXPECT_THROW(value.GetBool(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTimestamp(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt64(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInteger(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetFloat(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetDouble(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetReal(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetArray(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTable(), boost::bad_get);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(table_value, array_value) {
|
||||||
|
Array v1;
|
||||||
|
v1.push_back(TableValue("first"));
|
||||||
|
|
||||||
|
Array v2;
|
||||||
|
v2.push_back(TableValue((int32_t)2));
|
||||||
|
|
||||||
|
TableValue value(v1);
|
||||||
|
EXPECT_EQ(TableValue::VT_array, value.GetType());
|
||||||
|
Array v1a = value.GetArray();
|
||||||
|
EXPECT_TRUE(v1.size() == v1a.size());
|
||||||
|
EXPECT_TRUE(std::equal(v1.begin(), v1.end(), v1a.begin()));
|
||||||
|
|
||||||
|
EXPECT_THROW(value.GetBool(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTimestamp(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt64(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInteger(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetFloat(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetDouble(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetReal(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetString(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTable(), boost::bad_get);
|
||||||
|
|
||||||
|
value.Set(v2);
|
||||||
|
EXPECT_EQ(TableValue::VT_array, value.GetType());
|
||||||
|
Array v2a = value.GetArray();
|
||||||
|
EXPECT_TRUE(v2.size() == v2a.size());
|
||||||
|
EXPECT_TRUE(std::equal(v2.begin(), v2.end(), v2a.begin()));
|
||||||
|
|
||||||
|
EXPECT_THROW(value.GetBool(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTimestamp(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt64(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInteger(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetFloat(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetDouble(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetReal(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetString(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTable(), boost::bad_get);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(table_value, table_value) {
|
||||||
|
Table v1;
|
||||||
|
v1.insert(TableEntry("one", 10));
|
||||||
|
|
||||||
|
Table v2;
|
||||||
|
v2.insert(TableEntry("two", 22.2));
|
||||||
|
|
||||||
|
TableValue value(v1);
|
||||||
|
EXPECT_EQ(TableValue::VT_table, value.GetType());
|
||||||
|
Table v1a = value.GetTable();
|
||||||
|
EXPECT_TRUE(v1.size() == v1a.size());
|
||||||
|
EXPECT_TRUE(std::equal(v1.begin(), v1.end(), v1a.begin()));
|
||||||
|
|
||||||
|
EXPECT_THROW(value.GetBool(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTimestamp(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt64(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInteger(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetFloat(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetDouble(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetReal(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetString(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetArray(), boost::bad_get);
|
||||||
|
|
||||||
|
value.Set(v2);
|
||||||
|
EXPECT_EQ(TableValue::VT_table, value.GetType());
|
||||||
|
Table v2a = value.GetTable();
|
||||||
|
EXPECT_TRUE(v2.size() == v2a.size());
|
||||||
|
EXPECT_TRUE(std::equal(v2.begin(), v2.end(), v2a.begin()));
|
||||||
|
|
||||||
|
EXPECT_THROW(value.GetBool(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt8(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt16(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetUint32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt32(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetTimestamp(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInt64(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetInteger(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetFloat(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetDouble(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetReal(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetString(), boost::bad_get);
|
||||||
|
EXPECT_THROW(value.GetArray(), boost::bad_get);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(table_value, equality) {
|
||||||
|
TableValue void_val1;
|
||||||
|
TableValue void_val2;
|
||||||
|
EXPECT_EQ(void_val1, void_val1);
|
||||||
|
EXPECT_EQ(void_val1, void_val2);
|
||||||
|
|
||||||
|
TableValue bool_val1(true);
|
||||||
|
TableValue bool_val2(bool_val1);
|
||||||
|
TableValue bool_val3(false);
|
||||||
|
TableValue bool_val4;
|
||||||
|
bool_val4.Set(bool_val3.GetBool());
|
||||||
|
EXPECT_EQ(bool_val1, bool_val1);
|
||||||
|
EXPECT_EQ(bool_val1, bool_val2);
|
||||||
|
EXPECT_NE(bool_val1, bool_val3);
|
||||||
|
EXPECT_NE(void_val1, bool_val1);
|
||||||
|
EXPECT_EQ(bool_val3, bool_val4);
|
||||||
|
|
||||||
|
TableValue int8_val1(int8_t(8));
|
||||||
|
TableValue int8_val2(int8_val1);
|
||||||
|
TableValue int8_val3(int8_t(9));
|
||||||
|
EXPECT_EQ(int8_val1, int8_val1);
|
||||||
|
EXPECT_EQ(int8_val1, int8_val2);
|
||||||
|
EXPECT_NE(int8_val1, int8_val3);
|
||||||
|
|
||||||
|
TableValue string_val1("one");
|
||||||
|
TableValue string_val2(std::string("one"));
|
||||||
|
std::string empty;
|
||||||
|
TableValue string_val3(empty);
|
||||||
|
EXPECT_EQ(string_val1, string_val1);
|
||||||
|
EXPECT_EQ(string_val1, string_val2);
|
||||||
|
EXPECT_NE(string_val1, string_val3);
|
||||||
|
|
||||||
|
std::vector<TableValue> vec_val1;
|
||||||
|
vec_val1.push_back(void_val1);
|
||||||
|
vec_val1.push_back(int8_val1);
|
||||||
|
std::vector<TableValue> vec_val2;
|
||||||
|
vec_val2.push_back(bool_val1);
|
||||||
|
vec_val2.push_back(void_val1);
|
||||||
|
TableValue array_val1(vec_val1);
|
||||||
|
TableValue array_val2(array_val1);
|
||||||
|
TableValue array_val3(vec_val2);
|
||||||
|
|
||||||
|
EXPECT_EQ(array_val1, array_val1);
|
||||||
|
EXPECT_EQ(array_val1, array_val2);
|
||||||
|
EXPECT_NE(array_val1, array_val3);
|
||||||
|
|
||||||
|
Table tbl1;
|
||||||
|
tbl1.insert(TableEntry("key1", int8_val1));
|
||||||
|
tbl1.insert(TableEntry("key2", "string"));
|
||||||
|
Table tbl2;
|
||||||
|
tbl2.insert(TableEntry("key1", void_val1));
|
||||||
|
tbl2.insert(TableEntry("array", array_val1));
|
||||||
|
|
||||||
|
TableValue table_val1(tbl1);
|
||||||
|
TableValue table_val2(tbl1);
|
||||||
|
TableValue table_val3(tbl2);
|
||||||
|
|
||||||
|
EXPECT_EQ(table_val1, table_val1);
|
||||||
|
EXPECT_EQ(table_val1, table_val2);
|
||||||
|
EXPECT_NE(table_val1, table_val3);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(table, convert_to_rabbitmq) {
|
||||||
|
Table table_in;
|
||||||
|
table_in.insert(TableEntry("void_key", TableValue()));
|
||||||
|
table_in.insert(TableEntry("bool_key", true));
|
||||||
|
table_in.insert(TableEntry("uint8_key", uint8_t(8)));
|
||||||
|
table_in.insert(TableEntry("int8_key", int8_t(8)));
|
||||||
|
table_in.insert(TableEntry("uint16_key", uint16_t(16)));
|
||||||
|
table_in.insert(TableEntry("int16_key", int16_t(16)));
|
||||||
|
table_in.insert(TableEntry("uint32_key", uint32_t(32)));
|
||||||
|
table_in.insert(TableEntry("int32_key", int32_t(32)));
|
||||||
|
table_in.insert(TableEntry("timestamp_key", TableValue::Timestamp(64)));
|
||||||
|
table_in.insert(TableEntry("int64_key", int64_t(64)));
|
||||||
|
table_in.insert(TableEntry("float_key", float(1.5)));
|
||||||
|
table_in.insert(TableEntry("double_key", double(2.25)));
|
||||||
|
table_in.insert(TableEntry("string_key", "A string!"));
|
||||||
|
|
||||||
|
std::vector<TableValue> array_in;
|
||||||
|
array_in.push_back(TableValue(false));
|
||||||
|
array_in.push_back(TableValue(int32_t(10)));
|
||||||
|
array_in.push_back(TableValue(std::string("Another string")));
|
||||||
|
|
||||||
|
table_in.insert(TableEntry("array_key", array_in));
|
||||||
|
|
||||||
|
Table table_inner;
|
||||||
|
table_inner.insert(TableEntry("inner_string", "An inner table"));
|
||||||
|
table_inner.insert(TableEntry("inner array", array_in));
|
||||||
|
|
||||||
|
table_in.insert(TableEntry("table_key", table_inner));
|
||||||
|
|
||||||
|
BasicMessage::ptr_t message = BasicMessage::Create();
|
||||||
|
message->HeaderTable(table_in);
|
||||||
|
|
||||||
|
EXPECT_TRUE(message->HeaderTableIsSet());
|
||||||
|
Table table_out = message->HeaderTable();
|
||||||
|
EXPECT_EQ(table_in.size(), table_out.size());
|
||||||
|
EXPECT_TRUE(std::equal(table_in.begin(), table_in.end(), table_out.begin()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(table, convert_to_rabbitmq_empty) {
|
||||||
|
Table table_in;
|
||||||
|
|
||||||
|
BasicMessage::ptr_t message = BasicMessage::Create();
|
||||||
|
message->HeaderTable(table_in);
|
||||||
|
|
||||||
|
Table table_out = message->HeaderTable();
|
||||||
|
EXPECT_EQ(0, table_out.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, basic_message_header_roundtrip) {
|
||||||
|
Table table_in;
|
||||||
|
table_in.insert(TableEntry("void_key", TableValue()));
|
||||||
|
table_in.insert(TableEntry("bool_key", true));
|
||||||
|
table_in.insert(TableEntry("uint8_key", uint8_t(8)));
|
||||||
|
table_in.insert(TableEntry("int8_key", int8_t(8)));
|
||||||
|
table_in.insert(TableEntry("uint16_key", uint16_t(16)));
|
||||||
|
table_in.insert(TableEntry("int16_key", int16_t(16)));
|
||||||
|
table_in.insert(TableEntry("uint32_key", uint32_t(32)));
|
||||||
|
table_in.insert(TableEntry("int32_key", int32_t(32)));
|
||||||
|
table_in.insert(TableEntry("timestamp_key", TableValue::Timestamp(64)));
|
||||||
|
table_in.insert(TableEntry("int64_key", int64_t(64)));
|
||||||
|
table_in.insert(TableEntry("float_key", float(1.5)));
|
||||||
|
table_in.insert(TableEntry("double_key", double(2.25)));
|
||||||
|
table_in.insert(TableEntry("string_key", "A string!"));
|
||||||
|
|
||||||
|
std::vector<TableValue> array_in;
|
||||||
|
array_in.push_back(TableValue(false));
|
||||||
|
array_in.push_back(TableValue(int32_t(10)));
|
||||||
|
array_in.push_back(TableValue(std::string("Another string")));
|
||||||
|
|
||||||
|
table_in.insert(TableEntry("array_key", array_in));
|
||||||
|
|
||||||
|
Table table_inner;
|
||||||
|
table_inner.insert(TableEntry("inner_string", "An inner table"));
|
||||||
|
table_inner.insert(TableEntry("inner array", array_in));
|
||||||
|
|
||||||
|
table_in.insert(TableEntry("table_key", table_inner));
|
||||||
|
|
||||||
|
std::string queue = channel->DeclareQueue("");
|
||||||
|
std::string tag = channel->BasicConsume(queue, "");
|
||||||
|
|
||||||
|
BasicMessage::ptr_t message_in = BasicMessage::Create("Body");
|
||||||
|
message_in->HeaderTable(table_in);
|
||||||
|
|
||||||
|
channel->BasicPublish("", queue, message_in);
|
||||||
|
|
||||||
|
Envelope::ptr_t envelope = channel->BasicConsumeMessage(tag);
|
||||||
|
BasicMessage::ptr_t message_out = envelope->Message();
|
||||||
|
Table table_out = message_out->HeaderTable();
|
||||||
|
|
||||||
|
EXPECT_EQ(table_in.size(), table_out.size());
|
||||||
|
EXPECT_TRUE(std::equal(table_in.begin(), table_in.end(), table_out.begin()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(connected_test, basic_message_empty_table_roundtrip) {
|
||||||
|
std::string queue = channel->DeclareQueue("");
|
||||||
|
std::string tag = channel->BasicConsume(queue, "");
|
||||||
|
|
||||||
|
Table table_in;
|
||||||
|
|
||||||
|
BasicMessage::ptr_t message_in = BasicMessage::Create("Body");
|
||||||
|
message_in->HeaderTable(table_in);
|
||||||
|
|
||||||
|
channel->BasicPublish("", queue, message_in);
|
||||||
|
|
||||||
|
Envelope::ptr_t envelope = channel->BasicConsumeMessage(tag);
|
||||||
|
BasicMessage::ptr_t message_out = envelope->Message();
|
||||||
|
Table table_out = message_out->HeaderTable();
|
||||||
|
|
||||||
|
EXPECT_EQ(table_in.size(), table_out.size());
|
||||||
|
EXPECT_TRUE(std::equal(table_in.begin(), table_in.end(), table_out.begin()));
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user