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