Giter Site home page Giter Site logo

simpleamqpclient's Introduction

SimpleAmqpClient

SimpleAmqpClient is an easy-to-use C++ wrapper around the rabbitmq-c C library. It derives inspiration from the 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 or newer (uses chrono, system internally in addition to other header based libraries such as sharedptr and noncopyable)
  • rabbitmq-c you'll need version 0.8.0 or better.
  • cmake 3.5+ what is needed for the build system
  • 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 should be built as shared library.

Let boost_chrono and boost_system be in same directory C:\boost, 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);

simpleamqpclient's People

Contributors

0xflotus avatar alanxz avatar artemartey avatar ashokanand1 avatar ceefour avatar dergunov avatar hith3sh avatar infactum avatar jwald avatar kblaschke avatar kinnou02 avatar luca3m avatar lyuzinmaxim avatar miguelbarro avatar p487morgan avatar rajish avatar s3rvac avatar sharpyfox avatar slepasteur avatar stonemaster avatar ulidtko avatar vthiery avatar whoan avatar zephyrus3 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

simpleamqpclient's Issues

undefined reference to

Hi, I'am trying to connect with rabbitmq using this library and I struggle with linker error. Someone can explain me what is wrong.
I receive this error:

In function `boost::detail::sp_if_not_array<AmqpClient::Channel>::type boost::make_shared<AmqpClient::Channel, std::string, int, std::string, std::string, std::string, int>(std::string const&, int const&, std::string const&, std::string const&, std::string const&, int const&)':
makefile:48: polecenia dla obiektu 'cuda-client' nie powiodły się
/usr/include/boost/smart_ptr/make_shared_object.hpp:891: undefined reference to `AmqpClient::Channel::Channel(std::string const&, int, std::string const&, std::string const&, std::string const&, int)'

I have the newest version of boost library

memory pilling up in publish

while(true){    
try{
        BasicMessage::ptr_t bm = BasicMessage::Create();
        bm->Body(message);
        m_channel->BasicPublish(exchangename, routingkey,bm,true, true);
        return true;
    }catch(MessageReturnedException& e){
        std::cout << e.what() << std::endl;
        return false;
    }
}

when setting "mandatory" bit true,and publishing msg that not routed,program will catch and print exception and memory is piliing up.i think it may be a bug when exception caught.

Can it support connect heartbeat?

I use RabbitMQ in a unreliable network. So, the clients may lose connection with the server sometimes.
I think the "heartbeat" defined in amqp_login could help me.
Could I just modify the #define BROKER_HEARTBEAT in Channel.cpp?
Or I need to modify more source files?

Enable Message Requeue feature for BasicConsumeMessage

Hi ,

I am looking for an option to set message requeue, after consuming the message. For my case wanted the message to be present in queue, even after consumed by the consumer.

If this featire is already existing, i am very sorry, couldnt find it, could anyone please help me the option/ param to be used while calling channel->BasicConsumeMessage()

Thanks,

enable_testing flag

Hi Alan,

Thanks again for your work on this simpleamqpclient. I'm about to suggest a Homebrew formula to the Homebrew team.

I had a compilation problem when using clang (4.1 in C++11 mode = the default now on osx).

The embedded gtest needs tr1/tuple, and clang does not ship it (of course, it's in c++11 mode only now). Although gtest should be optional it is on by default : I had to edit the CMakeList.txt to find that ENABLE_TESTING flag to make this option off.

Could you please state the -DENABLE_TESTING=OFF case in the Readme.md please?

Cheers

receive no-delay msg from publisher

i encounter a problem that when i received one msg,i have to proceed a long time ,so when i received the next msg,i got a delay msg published by the publisher that i don't need.
i need the no-delay msg so if the msg published too fast, some of them should be abandoned.
can anybody give me some advice?
i try the immediate flag,but it do not work,beacuse i think when my program is running, there is a consumer connected to the exchange.

while(true)
{
std::string msg;
std::string rk;
if(!this->waitforMessage(msg ,rk)){
continue;
}
sleep(2000);
}
thanks.

Windows build seems broken for ChannelImpl.cpp

The file ChannelImpl.cpp doesn't compile under MSVC on Windows, it needs a definition for the timeval struct. I got this to build by adding the following to ChannelImpl.cpp

#ifdef _WIN32
# define NOMINMAX
# ifndef WIN32_LEAN_AND_MEAN
#  define WIN32_LEAN_AND_MEAN
# endif
# include <Winsock2.h>
#endif

consumer listens to multiple queues

Hi,
i was wondering if it is possible to use a single consumer to listen to multiple queues?
This is possible in the java API through multiple calls of basicConsume. Is there something similar in SimpleAmqpClient?

thanks

clarification: Our data model requires a single worker to produce the messages and multiple consumers which handle possibly the same topic or different topics. In any case only one consumer should get the message.

Error README compile command

The compile command from readme look as

mkdir simpleamqpclient-build
cd simpleamqpclient-build 
cmake ../SimpleAmqpClient

And It must look as

mkdir simpleamqpclient-build
cd simpleamqpclient-build 
cmake ..

Building with Visual Studio 2010

I am trying to use the library on Windows (Windows 7 Professional) with Visual Studio 2010 and Boost 1.52 (current at the time of writing). And I get linking error for Boost.Chrono.

My procedure is following.

  1. I am making a git clone into MinGW root folder. Thus I get C:\MinGW\SimpleAmqpClient.git.
  2. Then I make a sibling directory for CMake: C:\MinGW\SimpleAmqpClient.git-bin.
  3. There from command line I call cmake "../SimpleAmqpClient.git"
    • This fails because of missing references to Boost and rabbitmq-c.
  4. Then again from command line I call cmake -DBOOST_LIBRARYDIR="C:\Library\boost\boost_1_52_0\stage\Win32\lib" -DBOOST_INCLUDEDIR="C:\Library\boost\boost_1_52_0" -DRabbitmqc_INCLUDE_DIR="C:\Library\rabbitmq-c\Release\include" -DRabbitmqc_LIBRARY="C:\Library\rabbitmq-c\Release\lib\rabbitmq.1.lib" "../SimpleAmqpClient.git"
    • For some reason specifying those values in first call to cmake fails with an error of some file missing. Apparently it it not willing to create then but the first call does create the file even thou the call fails.
  5. This succeeds. Now I open the SimpleAmqpClient.sln file with Visual Studio IDE.
  6. And there building the Win32.Debug configuration fails (on project SimpleAmqpClient). It fails with following message: LINK : fatal error LNK1104: cannot open file 'libboost_chrono-vc100-mt-gd-1_52.lib'.
    • There are also few Doxygen messages - just so that you know. (My Doxygen is 1.8.2.)

I played around with the project. Removing the dependency (generated by cmake) on Boost.Chrono from Additional Dependencies doesn't solve the issue. Because it is not this reference that fails.

The one that fails is automatic linking of Boost.Chrono itself. Note that it tries to link to libboost_chrono-vc100-mt-gd-1_52.lib (which is missing) rather than to boost_chrono-vc100-mt-gd-1_52.lib (which is there).

The lib prefix is used because preprocessor defines are set so. To skip the prefix the project would have to define (_DLL or _RTLDLL) and BOOST_DYN_LINK while apparently it doesn't. Not to mention that auto-linking would likely fail anyway since the project does not specify Additional Library Directories even thou I provide them to cmake.

Any help?

And by the way. How should I set things up so that SimpleAmqpClient in Debug builds with rabbitmq-c Debug while in Release it builds with rabbitmq-c Release? My rabbitmq-c is laid out so that in root directory I have subdirectories Debug and Release which contain complete installations of the library (bin, include and lib) for the given configuration.

Listening to messages with given routing key

I need code that would connect to RabbitMQ with specified connection data and exchange. Then it would create a temporary (for program lifetime only) queue and listen for messages with specified routing key. This is what alanxz/rabbitmq-c does in examples/amqp_listen.c.

How to achieve that with this library? I wasn't able to do it myself and none of the examples seems to illustrate this.

When I just run the code similar to the one given in README.md (by which I mean AmqpClient::Channel::Create, DeclareQueue, BasicConsume, BasicConsumeMessage) it never exits BasicConsumeMessage even after publishing messages (using RabbitMQ Management web page, which claims the message has been routed).

Since the above procedure does not use at any point routing key I tried adding BindQueue between DeclareQueue and BasicConsume with my routing key. After that change BasicConsumeMessage fails with bad_alloc (in SimpleAmqpClient code) after I publish a message.

"undefined reference" error while linking against static SimpleAmqpClient 2.3

When linking application against static SimpleAmqpClient 2.3 built on top of rabbitmq-c 0.4.0 (both with or without SSL support) linker throws these error messages:

/usr/local/lib/libSimpleAmqpClient.a(Channel.cpp.o):Channel.cpp:function AmqpClient::Channel::Channel(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&): error: undefined reference to 'amqp_ssl_socket_new'
/usr/local/lib/libSimpleAmqpClient.a(Channel.cpp.o):Channel.cpp:function AmqpClient::Channel::Channel(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&): error: undefined reference to 'amqp_ssl_socket_set_cacert'
/usr/local/lib/libSimpleAmqpClient.a(Channel.cpp.o):Channel.cpp:function AmqpClient::Channel::Channel(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&): error: undefined reference to 'amqp_ssl_socket_set_key'
collect2: ld returned 1 exit status

Looks like there is some bug. We use

gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)

Is it possible to build SimpleAmqpClient without SSL support? If not it would be nice to have it as a build option.

Annotating message with timestamp

I am trying to annotate the message with timestamp during publishing, and later use that to find out the time when I am consuming and processing the message. I see that BasicMessage has methods to set and get Timestamp.

However, in the implementation, the get method seems to check for ReplyToIsSet... which was not set in my case, so it always returns 0. Why is the check for "ReplyToIsSet" needed? Any examples on how to use ReplyTo? Any other way to get the timestamp or diff between time of message publishing and time of message consumption?

Build failure on Linux

Hi there.
Up until revision ec09fa3 the library was correctly built on my Linux environment below:

[root@machine build]# gcc --version
gcc (GCC) 4.3.2
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

[root@machine build]# uname -a
Linux machine 2.6.29.1-server-4mnb #1 SMP Mon Apr 20 17:17:54 EDT 2009 x86_64 Intel(R) Xeon(R) CPU E5530 @ 2.40GHz GNU/Linux

I've now tried to build revision 5480846 and compilation fails with the following output:

[root@machine build]# cmake ..
-- The C compiler identification is GNU
-- The CXX compiler identification is GNU
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Boost version: 1.48.0
-- Found the following Boost libraries:
-- chrono
-- system
-- Found Rabbitmqc
-- Looking for strerror_s
-- Looking for strerror_s - not found
-- Looking for strerror_r
-- Looking for strerror_r - found
-- Looking for winsock2.h
-- Looking for winsock2.h - not found
-- Looking for sys/socket.h
-- Looking for sys/socket.h - found
-- Could NOT find GTest (missing: GTEST_LIBRARY GTEST_INCLUDE_DIR GTEST_MAIN_LIBRARY) (Required is at least version "1.5.0")
-- Could NOT find Doxygen (missing: DOXYGEN_EXECUTABLE)
-- Configuring done
-- Generating done
-- Build files have been written to: /root/libs/alanxz-SimpleAmqpClient-5480846/build
[root@machinebuild]# cd ../build
[root@machine build]# make
Scanning dependencies of target SimpleAmqpClient
[ 14%] Building CXX object CMakeFiles/SimpleAmqpClient.dir/src/AmqpException.cpp.o
In file included from /root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:38:
/usr/local/include/amqp.h:57: error: ‘uint32_t’ does not name a type
/usr/local/include/amqp.h:58: error: ‘uint32_t’ does not name a type
/usr/local/include/amqp.h:59: error: ‘uint16_t’ does not name a type
/usr/local/include/amqp.h:62: error: ‘size_t’ does not name a type
/usr/local/include/amqp.h:67: error: ‘uint8_t’ does not name a type
/usr/local/include/amqp.h:68: error: ‘uint32_t’ does not name a type
/usr/local/include/amqp.h:121: error: ‘uint8_t’ does not name a type
/usr/local/include/amqp.h:124: error: ‘int8_t’ does not name a type
/usr/local/include/amqp.h:125: error: ‘uint8_t’ does not name a type
/usr/local/include/amqp.h:126: error: ‘int16_t’ does not name a type
/usr/local/include/amqp.h:127: error: ‘uint16_t’ does not name a type
/usr/local/include/amqp.h:128: error: ‘int32_t’ does not name a type
/usr/local/include/amqp.h:129: error: ‘uint32_t’ does not name a type
/usr/local/include/amqp.h:130: error: ‘int64_t’ does not name a type
/usr/local/include/amqp.h:131: error: ‘uint64_t’ does not name a type
/usr/local/include/amqp.h:173: error: ‘size_t’ does not name a type
/usr/local/include/amqp.h:180: error: ‘size_t’ does not name a type
/usr/local/include/amqp.h:184: error: ‘amqp_method_number_t’ does not name a type
/usr/local/include/amqp.h:189: error: ‘uint8_t’ does not name a type
/usr/local/include/amqp.h:190: error: ‘amqp_channel_t’ does not name a type
/usr/local/include/amqp.h:194: error: ‘uint16_t’ does not name a type
/usr/local/include/amqp.h:195: error: ‘uint64_t’ does not name a type
/usr/local/include/amqp.h:201: error: ‘uint8_t’ does not name a type
/usr/local/include/amqp.h:202: error: ‘uint8_t’ does not name a type
/usr/local/include/amqp.h:203: error: ‘uint8_t’ does not name a type
/usr/local/include/amqp.h:204: error: ‘uint8_t’ does not name a type
/usr/local/include/amqp.h:242: error: ‘size_t’ has not been declared
/usr/local/include/amqp.h:246: error: ‘size_t’ has not been declared
/usr/local/include/amqp.h:248: error: ‘size_t’ has not been declared
/usr/local/include/amqp.h:252: error: ‘size_t’ was not declared in this scope
/usr/local/include/amqp.h:295: error: ‘amqp_channel_t’ has not been declared
/usr/local/include/amqp.h:296: error: ‘amqp_method_number_t’ has not been declared
/usr/local/include/amqp.h:300: error: ‘amqp_channel_t’ has not been declared
/usr/local/include/amqp.h:301: error: ‘amqp_method_number_t’ has not been declared
/usr/local/include/amqp.h:305: error: ‘amqp_channel_t’ has not been declared
/usr/local/include/amqp.h:306: error: ‘amqp_method_number_t’ has not been declared
/usr/local/include/amqp.h:307: error: ‘amqp_method_number_t’ has not been declared
/usr/local/include/amqp.h:311: error: ‘amqp_channel_t’ has not been declared
/usr/local/include/amqp.h:312: error: ‘amqp_method_number_t’ has not been declared
/usr/local/include/amqp.h:313: error: ‘amqp_method_number_t’ has not been declared
/usr/local/include/amqp.h:341: error: ‘amqp_channel_t’ has not been declared
/usr/local/include/amqp.h:351: error: ‘amqp_channel_t’ has not been declared
/usr/local/include/amqp.h:358: error: ‘amqp_channel_t’ has not been declared
/usr/local/include/amqp.h:359: error: ‘uint64_t’ has not been declared
/usr/local/include/amqp.h:363: error: ‘amqp_channel_t’ has not been declared
/usr/local/include/amqp.h:368: error: ‘amqp_channel_t’ has not been declared
/usr/local/include/amqp.h:369: error: ‘uint64_t’ has not been declared
/usr/local/include/amqp.h:393: error: ‘size_t’ has not been declared
/usr/local/include/amqp.h:397: error: ‘size_t’ has not been declared
In file included from /root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:39:
/usr/local/include/amqp_framing.h:43: error: ‘amqp_method_number_t’ was not declared in this scope
/usr/local/include/amqp_framing.h:44: error: ‘amqp_method_number_t’ was not declared in this scope
/usr/local/include/amqp_framing.h:45: error: ‘amqp_method_number_t’ was not declared in this scope
/usr/local/include/amqp_framing.h:46: error: expected primary-expression before ‘’ token
/usr/local/include/amqp_framing.h:46: error: ‘pool’ was not declared in this scope
/usr/local/include/amqp_framing.h:47: error: expected primary-expression before ‘encoded’
/usr/local/include/amqp_framing.h:48: error: expected primary-expression before ‘void’
/usr/local/include/amqp_framing.h:48: error: initializer expression list treated as compound expression
/usr/local/include/amqp_framing.h:49: error: ‘uint16_t’ was not declared in this scope
/usr/local/include/amqp_framing.h:50: error: expected primary-expression before ‘
’ token
/usr/local/include/amqp_framing.h:50: error: ‘pool’ was not declared in this scope
/usr/local/include/amqp_framing.h:51: error: expected primary-expression before ‘encoded’
/usr/local/include/amqp_framing.h:52: error: expected primary-expression before ‘void’
/usr/local/include/amqp_framing.h:52: error: initializer expression list treated as compound expression
/usr/local/include/amqp_framing.h:53: error: ‘amqp_method_number_t’ was not declared in this scope
/usr/local/include/amqp_framing.h:54: error: expected primary-expression before ‘void’
/usr/local/include/amqp_framing.h:55: error: expected primary-expression before ‘encoded’
/usr/local/include/amqp_framing.h:55: error: initializer expression list treated as compound expression
/usr/local/include/amqp_framing.h:56: error: ‘uint16_t’ was not declared in this scope
/usr/local/include/amqp_framing.h:57: error: expected primary-expression before ‘void’
/usr/local/include/amqp_framing.h:58: error: expected primary-expression before ‘encoded’
/usr/local/include/amqp_framing.h:58: error: initializer expression list treated as compound expression
/usr/local/include/amqp_framing.h:64: error: ‘uint8_t’ does not name a type
/usr/local/include/amqp_framing.h:65: error: ‘uint8_t’ does not name a type
/usr/local/include/amqp_framing.h:91: error: ‘uint16_t’ does not name a type
/usr/local/include/amqp_framing.h:92: error: ‘uint32_t’ does not name a type
/usr/local/include/amqp_framing.h:93: error: ‘uint16_t’ does not name a type
/usr/local/include/amqp_framing.h:98: error: ‘uint16_t’ does not name a type
/usr/local/include/amqp_framing.h:99: error: ‘uint32_t’ does not name a type
/usr/local/include/amqp_framing.h:100: error: ‘uint16_t’ does not name a type
/usr/local/include/amqp_framing.h:117: error: ‘uint16_t’ does not name a type
/usr/local/include/amqp_framing.h:119: error: ‘uint16_t’ does not name a type
/usr/local/include/amqp_framing.h:120: error: ‘uint16_t’ does not name a type
/usr/local/include/amqp_framing.h:150: error: ‘uint16_t’ does not name a type
/usr/local/include/amqp_framing.h:152: error: ‘uint16_t’ does not name a type
/usr/local/include/amqp_framing.h:153: error: ‘uint16_t’ does not name a type
/usr/local/include/amqp_framing.h:173: error: ‘uint16_t’ does not name a type
/usr/local/include/amqp_framing.h:178: error: ‘uint16_t’ does not name a type
/usr/local/include/amqp_framing.h:196: error: ‘uint16_t’ does not name a type
/usr/local/include/amqp_framing.h:209: error: ‘uint16_t’ does not name a type
/usr/local/include/amqp_framing.h:224: error: ‘uint16_t’ does not name a type
/usr/local/include/amqp_framing.h:239: error: ‘uint16_t’ does not name a type
/usr/local/include/amqp_framing.h:252: error: ‘uint32_t’ does not name a type
/usr/local/include/amqp_framing.h:253: error: ‘uint32_t’ does not name a type
/usr/local/include/amqp_framing.h:258: error: ‘uint16_t’ does not name a type
/usr/local/include/amqp_framing.h:273: error: ‘uint16_t’ does not name a type
/usr/local/include/amqp_framing.h:280: error: ‘uint32_t’ does not name a type
/usr/local/include/amqp_framing.h:285: error: ‘uint16_t’ does not name a type
/usr/local/include/amqp_framing.h:294: error: ‘uint32_t’ does not name a type
/usr/local/include/amqp_framing.h:299: error: ‘uint16_t’ does not name a type
/usr/local/include/amqp_framing.h:313: error: ‘uint32_t’ does not name a type
/usr/local/include/amqp_framing.h:314: error: ‘uint16_t’ does not name a type
/usr/local/include/amqp_framing.h:325: error: ‘uint16_t’ does not name a type
/usr/local/include/amqp_framing.h:353: error: ‘uint16_t’ does not name a type
/usr/local/include/amqp_framing.h:362: error: ‘uint16_t’ does not name a type
/usr/local/include/amqp_framing.h:371: error: ‘uint64_t’ does not name a type
/usr/local/include/amqp_framing.h:379: error: ‘uint16_t’ does not name a type
/usr/local/include/amqp_framing.h:386: error: ‘uint64_t’ does not name a type
/usr/local/include/amqp_framing.h:390: error: ‘uint32_t’ does not name a type
/usr/local/include/amqp_framing.h:400: error: ‘uint64_t’ does not name a type
/usr/local/include/amqp_framing.h:406: error: ‘uint64_t’ does not name a type
/usr/local/include/amqp_framing.h:427: error: ‘uint64_t’ does not name a type
/usr/local/include/amqp_framing.h:475: error: ‘amqp_flags_t’ does not name a type
/usr/local/include/amqp_framing.h:481: error: ‘amqp_flags_t’ does not name a type
/usr/local/include/amqp_framing.h:487: error: ‘amqp_flags_t’ does not name a type
/usr/local/include/amqp_framing.h:493: error: ‘amqp_flags_t’ does not name a type
/usr/local/include/amqp_framing.h:499: error: ‘amqp_flags_t’ does not name a type
/usr/local/include/amqp_framing.h:519: error: ‘amqp_flags_t’ does not name a type
/usr/local/include/amqp_framing.h:523: error: ‘uint8_t’ does not name a type
/usr/local/include/amqp_framing.h:524: error: ‘uint8_t’ does not name a type
/usr/local/include/amqp_framing.h:529: error: ‘uint64_t’ does not name a type
/usr/local/include/amqp_framing.h:538: error: ‘amqp_flags_t’ does not name a type
/usr/local/include/amqp_framing.h:544: error: ‘amqp_flags_t’ does not name a type
/usr/local/include/amqp_framing.h:550: error: ‘amqp_channel_t’ has not been declared
/usr/local/include/amqp_framing.h:551: error: ‘amqp_channel_t’ has not been declared
/usr/local/include/amqp_framing.h:552: error: ‘amqp_channel_t’ has not been declared
/usr/local/include/amqp_framing.h:553: error: ‘amqp_channel_t’ has not been declared
/usr/local/include/amqp_framing.h:554: error: ‘amqp_channel_t’ has not been declared
/usr/local/include/amqp_framing.h:555: error: ‘amqp_channel_t’ has not been declared
/usr/local/include/amqp_framing.h:556: error: ‘amqp_channel_t’ has not been declared
/usr/local/include/amqp_framing.h:557: error: ‘amqp_channel_t’ has not been declared
/usr/local/include/amqp_framing.h:558: error: ‘amqp_channel_t’ has not been declared
/usr/local/include/amqp_framing.h:559: error: ‘amqp_channel_t’ has not been declared
/usr/local/include/amqp_framing.h:560: error: ‘amqp_channel_t’ has not been declared
/usr/local/include/amqp_framing.h:561: error: ‘amqp_channel_t’ has not been declared
/usr/local/include/amqp_framing.h:561: error: ‘uint32_t’ has not been declared
/usr/local/include/amqp_framing.h:561: error: ‘uint16_t’ has not been declared
/usr/local/include/amqp_framing.h:562: error: ‘amqp_channel_t’ has not been declared
/usr/local/include/amqp_framing.h:563: error: ‘amqp_channel_t’ has not been declared
/usr/local/include/amqp_framing.h:564: error: ‘amqp_channel_t’ has not been declared
/usr/local/include/amqp_framing.h:565: error: ‘amqp_channel_t’ has not been declared
/usr/local/include/amqp_framing.h:566: error: ‘amqp_channel_t’ has not been declared
/usr/local/include/amqp_framing.h:567: error: ‘amqp_channel_t’ has not been declared
/usr/local/include/amqp_framing.h:568: error: ‘amqp_channel_t’ has not been declared
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp: In static member function ‘static void AmqpClient::AmqpException::Throw(const amqp_rpc_reply_t&)’:
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:73: error: ‘const struct amqp_method_t’ has no member named ‘id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:75: error: ‘amqp_method_number_t’ was not declared in this scope
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:75: error: expected )' before numeric constant /root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:76: error: expected:' before ‘;’ token
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:78: error: ‘amqp_method_number_t’ cannot appear in a constant-expression
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:78: error: expected )' before numeric constant /root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:79: error: expected:' before ‘;’ token
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:82: error: ‘const struct amqp_method_t’ has no member named ‘id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp: In static member function ‘static void AmqpClient::AmqpException::Throw(const amqp_channel_close_t&)’:
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:88: error: ‘const struct amqp_channel_close_t_’ has no member named ‘reply_code’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:91: error: ‘const struct amqp_bytes_t’ has no member named ‘len’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:91: error: ‘const struct amqp_channel_close_t_’ has no member named ‘class_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:91: error: ‘const struct amqp_channel_close_t_’ has no member named ‘method_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:93: error: ‘const struct amqp_bytes_t’ has no member named ‘len’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:93: error: ‘const struct amqp_channel_close_t_’ has no member named ‘class_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:93: error: ‘const struct amqp_channel_close_t_’ has no member named ‘method_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:95: error: ‘const struct amqp_bytes_t’ has no member named ‘len’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:95: error: ‘const struct amqp_channel_close_t_’ has no member named ‘class_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:95: error: ‘const struct amqp_channel_close_t_’ has no member named ‘method_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:97: error: ‘const struct amqp_bytes_t’ has no member named ‘len’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:97: error: ‘const struct amqp_channel_close_t_’ has no member named ‘class_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:97: error: ‘const struct amqp_channel_close_t_’ has no member named ‘method_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:99: error: ‘const struct amqp_bytes_t’ has no member named ‘len’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:99: error: ‘const struct amqp_channel_close_t_’ has no member named ‘class_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:99: error: ‘const struct amqp_channel_close_t_’ has no member named ‘method_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:101: error: ‘const struct amqp_bytes_t’ has no member named ‘len’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:101: error: ‘const struct amqp_channel_close_t_’ has no member named ‘class_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:101: error: ‘const struct amqp_channel_close_t_’ has no member named ‘method_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:103: error: ‘const struct amqp_bytes_t’ has no member named ‘len’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:103: error: ‘const struct amqp_channel_close_t_’ has no member named ‘class_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:103: error: ‘const struct amqp_channel_close_t_’ has no member named ‘method_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:105: error: ‘const struct amqp_channel_close_t_’ has no member named ‘reply_code’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp: In static member function ‘static void AmqpClient::AmqpException::Throw(const amqp_connection_close_t&)’:
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:111: error: ‘const struct amqp_connection_close_t_’ has no member named ‘reply_code’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:114: error: ‘const struct amqp_bytes_t’ has no member named ‘len’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:114: error: ‘const struct amqp_connection_close_t_’ has no member named ‘class_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:114: error: ‘const struct amqp_connection_close_t_’ has no member named ‘method_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:116: error: ‘const struct amqp_bytes_t’ has no member named ‘len’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:116: error: ‘const struct amqp_connection_close_t_’ has no member named ‘class_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:116: error: ‘const struct amqp_connection_close_t_’ has no member named ‘method_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:118: error: ‘const struct amqp_bytes_t’ has no member named ‘len’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:118: error: ‘const struct amqp_connection_close_t_’ has no member named ‘class_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:118: error: ‘const struct amqp_connection_close_t_’ has no member named ‘method_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:120: error: ‘const struct amqp_bytes_t’ has no member named ‘len’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:120: error: ‘const struct amqp_connection_close_t_’ has no member named ‘class_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:120: error: ‘const struct amqp_connection_close_t_’ has no member named ‘method_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:122: error: ‘const struct amqp_bytes_t’ has no member named ‘len’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:122: error: ‘const struct amqp_connection_close_t_’ has no member named ‘class_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:122: error: ‘const struct amqp_connection_close_t_’ has no member named ‘method_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:124: error: ‘const struct amqp_bytes_t’ has no member named ‘len’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:124: error: ‘const struct amqp_connection_close_t_’ has no member named ‘class_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:124: error: ‘const struct amqp_connection_close_t_’ has no member named ‘method_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:126: error: ‘const struct amqp_bytes_t’ has no member named ‘len’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:126: error: ‘const struct amqp_connection_close_t_’ has no member named ‘class_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:126: error: ‘const struct amqp_connection_close_t_’ has no member named ‘method_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:128: error: ‘const struct amqp_bytes_t’ has no member named ‘len’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:128: error: ‘const struct amqp_connection_close_t_’ has no member named ‘class_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:128: error: ‘const struct amqp_connection_close_t_’ has no member named ‘method_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:130: error: ‘const struct amqp_bytes_t’ has no member named ‘len’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:130: error: ‘const struct amqp_connection_close_t_’ has no member named ‘class_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:130: error: ‘const struct amqp_connection_close_t_’ has no member named ‘method_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:132: error: ‘const struct amqp_bytes_t’ has no member named ‘len’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:132: error: ‘const struct amqp_connection_close_t_’ has no member named ‘class_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:132: error: ‘const struct amqp_connection_close_t_’ has no member named ‘method_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:134: error: ‘const struct amqp_bytes_t’ has no member named ‘len’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:134: error: ‘const struct amqp_connection_close_t_’ has no member named ‘class_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:134: error: ‘const struct amqp_connection_close_t_’ has no member named ‘method_id’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:136: error: ‘const struct amqp_connection_close_t_’ has no member named ‘reply_code’
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp: In constructor ‘AmqpClient::AmqpException::AmqpException(const std::string&, uint16_t, uint16_t)’:
/root/libs/alanxz-SimpleAmqpClient-5480846/src/AmqpException.cpp:141: error: ‘amqp_method_name’ cannot be used as a function
make[2]: *** [CMakeFiles/SimpleAmqpClient.dir/src/AmqpException.cpp.o] Error 1
make[1]: *** [CMakeFiles/SimpleAmqpClient.dir/all] Error 2
make: *** [all] Error 2

Connection closed issue

We are using the latest version of the SimpleAmqpClient and we ran into problems when the connection of a consumer to the RabbitMQ server is (force) closed on the peer end.

Scenario

We start a consumer and have it consume messages by calling 'Channel::BasicConsumeMessage'. When there are no messages, the function just waits. If we now force close the connection on the RabbitMQ server, the exception ConnectionForcedException is thrown. This exception class has AmqpException as its very base class. However, during the construction of AmqpException another error (0xC0000005 access violation) occurs, because the function 'amqp_method_name' returns a NULL pointer. See the constructor of AmqpException below:

AmqpException::AmqpException(const std::string& reply_text, boost::uint16_t class_id, boost::uint16_t method_id) throw() :
std::runtime_error(std::string(amqp_method_name((class_id << 16) | method_id)).append(" caused: ").append(reply_text)),
m_reply_text(reply_text),
m_class_id(class_id),
m_method_id(method_id)
{}

The value for 'reply_text' is: "connection exception: CONNECTION_FORCED - Closed via management plugin".
The value for both 'class_id' and 'method_id' is 0.

Memory leaks when Channel() constructor throws

There are memory leaks when the constructor Channel throws an exception:

  • The m_impl->m_connection won't be reset because the object has not been successfully created. So ~Channel() won't ever be called. Maybe m_connection should be wrapped in a thin wrapper which just handles freeing the connetion.
  • If an error occurs and amp_error_string is called, the memory which is reserved within that function never gets freed.

SSL support?

I was wondering if it supports SSL. I guess rabbitmq-c supports SSL currently, though I havent tried it.

32-bit build?

Is it possible to build a 32-bit version of this library on MacOSX? I succeeded in getting everything built only to realize the 64-bit only lib won't work with my 32-bit OpenFrameworks app.

Fix examples

Fix the examples in the examples/ directory to work with the v2.0 interface.

Memory in publish not freed when exchange doesn't exist anymore

I found an issue where memory that is used to publish a message to an exchange (which does not exist anymore) is piling up, until you destroy the channel. I don't know if this is by design and expected behaviour.

Steps to reproduce:

  1. Create an instance of AmqpClient::Detail::Channel and have it declare an exchange
  2. Start publishing messages to the exchange using AmqpClient::Detail::Channel::BasicPublish
  3. At a random point in time, delete the exchange (for example through the console)

After the exchange is deleted, the method AmqpClient::Detail::Channel::BasicPublish throws an exception whenever it is called. As such calling code knows that something went wrong. However this exception is not handled in the method itself. Therefor, the cleanup code in the method is never called (although I am not really sure what this code does). So if one just blindly ignores the exception and keep publishing messages, you can bring your system down because it eventually runs out of memory. The exception is thrown in this statement:

m_impl->GetMethodOnChannel(channel, response, PUBLISH_ACK);

Let me post the code of the implementation, that makes it easier to explain I guess (I marked the line with '>>>>>>>>>').

void Channel::BasicPublish(const std::string& exchange_name,
                           const std::string& routing_key,
                           const BasicMessage::ptr_t message,
                           bool mandatory,
                           bool immediate)
{
  m_impl->CheckIsConnected();
  amqp_channel_t channel = m_impl->GetChannel();

  m_impl->CheckForError(amqp_basic_publish(m_impl->m_connection, channel,
                       amqp_cstring_bytes(exchange_name.c_str()),
                       amqp_cstring_bytes(routing_key.c_str()),
                       mandatory,
                       immediate,
                       message->getAmqpProperties(),
                       message->getAmqpBody()));

  // If we've done things correctly we can get one of 4 things back from the broker
  // - basic.ack - our channel is in confirm mode, messsage was 'dealt with' by the broker
  // - basic.return then basic.ack - the message wasn't delievered, but was dealt with
  // - channel.close - probably tried to publish to a non-existant exchange, in any case error!
  // - connection.clsoe - something really bad happened
  const boost::array<boost::uint32_t, 2> PUBLISH_ACK = { { AMQP_BASIC_ACK_METHOD, AMQP_BASIC_RETURN_METHOD } };
  amqp_frame_t response;

>>>>>>>>>  m_impl->GetMethodOnChannel(channel, response, PUBLISH_ACK);

  if (AMQP_BASIC_RETURN_METHOD == response.payload.method.id)
  {
    MessageReturnedException message_returned = 
      m_impl->CreateMessageReturnedException(*(reinterpret_cast<amqp_basic_return_t*>(response.payload.method.decoded)), channel);

    const boost::array<boost::uint32_t, 1> BASIC_ACK = { { AMQP_BASIC_ACK_METHOD } };
    m_impl->GetMethodOnChannel(channel, response, BASIC_ACK);
    m_impl->ReturnChannel(channel);
    m_impl->MaybeReleaseBuffers();
    throw message_returned;
  }

  m_impl->ReturnChannel(channel);
  m_impl->MaybeReleaseBuffers();
}

Memory leaks when "void BasicMessage::Body(const std::string& body)" called many times

void BasicMessage::Body(const std::string& body)
{
amqp_bytes_t body_bytes;
body_bytes.bytes = const_cast<char*>(body.data());
body_bytes.len = body.length();
m_impl->m_body = amqp_bytes_malloc_dup(body_bytes);
}
when function body(const std::string& body) is called first time ,the program malloc some space for body,and when basicmessage is destroyed ,program will free this space.and that's ok.
but if body() called many times before basicmessage destroyed, as the program will free the space malloced by the last time body called. so memory leaks happens because the space malloced before the last time body called can not be free.

Make OpenSSL support optional / dependent on rabbitmq-c

Currently, SimpleAmqpClient implicitly requires a rabbitmq-c library compiled with SSL support. In environments where the complexity of SSL support is not a requirement, developers are currently forced to link both libraries against OpenSSL. While some people may argue this is not much of an overhead and OpenSSL is readily available on many platforms, it'd still be cleaner to keep SimpleAmqpClient in line with rabbitmq-c and have optional SSL support.

I would contribute the required changes, but before this, like to discuss the best way to implement it. My suggestion is:

  • In CMakeLists.txt, check for the availability of amqp_ssl_socket.h. If the file exists, provide the user with an option to enable of disable SSL support, and default it to "ON".
  • Split up the AmqpClient::Channel class, and move the SSL-specific create() function and the associated constructor into a derived class, e.g. SecureChannel.
  • If SSL support is ON, add the SecureChannel implementation and header files to the build.

Library SIGSEGV's when connecting to qpid broker.

When library tries to connect to qpid broker, it fails with error:

Expected 0x000A000A method frame on channel 0, got frame type 65
Aborted (core dumped)

In my opinion, when it receives bad frame type, it should throw an exception [like when there's no broker, it throws std::runtime_error].

Program demonstrating this behavior [assuming qpid on default port]:
http://bcdev.net/data/minimal_connect.cpp

Tested on CentOS 6.2 with gcc 4.4.6.

I need support!!!

I am new in rabbitMQ and using SimpleAmqpClient to work with it. I have one connection on write and one on read, each in own thread. Also I am using acking to support a sort of transactions. But it works too slow for me. I've only 2 msg/s on pushing and I don't know how increase it. I think, I can add new threads and channels, but is there other way?

Support for C++11

Add support for using SimpleAmqpClient when the C++ compiler is in -std=c++11 or -std=c++0x mode.

publish msg in no confirm mode

i use this interface to publish some msg and considering the efficiency i do not want to use confirm mode.so i think when i create a channel, i can specify the mode of channel.but your library code make the channel in confirm mode directly.
so i change the code and when i publish msg i can specify the mode of channel.
i think this feature should be updated.

Getting queue size

Is there any API available on channel (or it can be supported later) to get the current queue size .. I know that Rabbitmq monitoring API has option to get queue size, but just wondering if there is an API available from channel (Channel.cpp).. My usecase is that I just want to know the workload remaining to be consumed : I know I can go through all messages one-by-one and then determine the queue size. But, is there an alternate simple way?

Building with rabbitmq-c git fails

using alanxz/rabbitmq-c@4eaf771 and 44b8b4e (currently the latest available) SimpleAmqpClient fails compiling.

It builds correctly with the release 2.2 (as the bug was introduced in 44b8b4e).

The problem is in creating a SSL Channel :

/home/tristram/SimpleAmqpClient/src/Channel.cpp: In constructor ‘AmqpClient::Channel::Channel(const string&, int, const string&, const string&, const string&, int, const string&, const string&, const string&)’:
/home/tristram/SimpleAmqpClient/src/Channel.cpp:134:49: error: too few arguments to function ‘amqp_socket_t* > amqp_ssl_socket_new(amqp_connection_state_t)’
amqp_socket_t* socket = amqp_ssl_socket_new();

https://github.com/alanxz/SimpleAmqpClient/blob/master/src/Channel.cpp#L134

https://github.com/alanxz/rabbitmq-c/blob/master/librabbitmq/amqp_openssl.c#L358

cstdint

Alan,

With clang c++11, I had to manually add #include <boost/cstdint.hpp> in all cpp files from the src folder.

I added it just before #include <amqp.h>, else clang complains about size_t, uint16_t, etc undefined.
But then other errors appear:

In file included from /Users/romain/Documents/github/SimpleAmqpClient/src/Channel.cpp:30:
In file included from /usr/local/include/boost/cstdint.hpp:36:
In file included from /usr/local/include/boost/config.hpp:40:
In file included from /usr/local/include/boost/config/select_stdlib_config.hpp:37:
In file included from /usr/local/include/boost/config/no_tr1/utility.hpp:21:
/usr/bin/../lib/c++/v1/utility:218:9: error: field has incomplete type 'AmqpClient::TableValue'
    _T2 second;
        ^
/usr/bin/../lib/c++/v1/__tree:602:16: note: in instantiation of template class 'std::__1::pair<std::__1::basic_string<char>,
      AmqpClient::TableValue>' requested here
    value_type __value_;
               ^

Could you please update this? Thanks!
Romain

amqp_simple_wait_frame hangs

Hi,

I have a problem with a call to amqp_simple_wait_frame in BasicPublish():

  • RabbitMQ messages are sent through a thread pool which internally sends messages to the rabbitmq server using your C++ wrapper. Sometimes it happens that the application doesn't quit because the thread pool hangs in a call to Channel::BasicPublish. This actually runs down to the code line CheckForError(amqp_simple_wait_frame(m_connection, &frame)); in ChannelImpl::GetNextFrameFromBroker.
  • The stack trace looks like this:
    #0 0x0000000000f7fb0c in recv ()
    #1 0x0000000000ea7e59 in wait_frame_inner ()
    #2 0x0000000000ea7f64 in amqp_simple_wait_frame ()
    #3 0x0000000000de2fc4 in AmqpClient::Detail::ChannelImpl::GetNextFrameFromBroker (this=0x1323d6d0, frame=..., timeout=...) at SimpleAmqpClient/ChannelImpl.cpp:344
    #4 0x0000000000de3392 in AmqpClient::Detail::ChannelImpl::GetNextFrameFromBrokerOnChannel (this=0x1323d6d0, channel=2, frame_out=..., timeout=...)
    at /SimpleAmqpClient/ChannelImpl.cpp:358
    #5 0x0000000000ddf086 in GetMethodOnChannel > (timeout=..., expected_responses=..., frame=..., channel=, this=)
    at /SimpleAmqpClient/ChannelImpl.h:106
    #6 GetMethodOnChannel > (timeout=..., expected_responses=..., frame=..., channel=, this=0x1323d6d0)
    at /SimpleAmqpClient/Channel.cpp:287
    #7 AmqpClient::Channel::BasicPublish (this=0xc6ae2a0, exchange_name=..., routing_key=..., message=..., mandatory=, immediate=)
    at /SimpleAmqpClient/Channel.cpp:311
  • It seems as if the connection died (which might be possible because the network in my case sometimes has some latency) and the recv call never returns actually blocking the thread pool and thus stopping the application from quitting.

I'm actually quite clueless right now so maybe you have an idea what might be causing this problems. If you need any more debug information just tell me.

Cheers,
André

Build system under cygwin

When building under cygwin with MinGW installed both sys/types.h and WinSock2.h are available to the compiler. We need to be a bit smarter about how we detect which socket library to use.

  • For native Win32 - we need to use WinSock2
  • For cygwin based executables we need to use posix sockets

Improve exception contract

Right now std::runtime_exception is sometimes thrown in a public interfaces. It would better for error handling purposes if this specialized a bit better to allow programatic handling of various error conditions.

Places of note:

  • Channel::Channel - when login fails
  • Channel::BasicAck
  • ChannelImpl errors dealing with various channel conditions
  • others?

Build SimpleAmqpClient with Microsoft Studio 2012, window 7 32 bit

I need to compile SimpleAmqpClient on my Window 7 32bit machine.

What I have done is :

  1. cmake rabbitmq-c by using below commands
    -- mkdir build && cd build
    -- cmake .. -DENABLE_SSL_SUPPORT=OFF -DDBUILD_STATIC_LIBS=ON
  2. open rabbitmq-c.sln file with MS 2012 and build
  3. cmake SimpleAmqpClient by using below commands
    -- mkdir SimpleAmqpClient-build && cd SimpleAmqpClient-build
    -- cmake -DBOOST_ROOT="F:\SourceCode\boost\1.5.5\boost_1_55_0" -DBOOST_LIBRARYDIR="F:\SourceCode\boost\1.5.5\boost_1_55_0\stage\lib" -DBOOST_INCLUDEDIR="F:\SourceCode\boost\1.5.5\boost_1_55_0" -DRabbitmqc_INCLUDE_DIR="F:\SourceCode\Rabbit\rabbitmq-c\librabbitmq" -DRabbitmqc_LIBRARY="F:\SourceCode\Rabbit\rabbitmq-c-master\build\librabbitmq\Debug\rabbitmq.1.lib" -DBUILD_STATIC_LIBS=ON -DENABLE_SSL_SUPPORT=OFF -DBoost_USE_STATIC_LIBS=ON -DDOXYFILE_LATEX=OFF "../SimpleAmqpClient"
  4. open SimpleAmqpClient.sln file with MS 2012 and build
    Error appear when I try to the solution. below are the error messages.

2> Generating Code...
2> Creating library F:/SourceCode/Rabbit/simpleamqpclient-build/Debug/SimpleAmqpClient.2.lib and object F:/SourceCode/Rabbit/simpleamqpclient-build/Debug/SimpleAmqpClient.2.exp
2>Channel.obj : error LNK2019: unresolved external symbol _amqp_ssl_socket_new referenced in function __catch$??0Channel@AmqpClient@@QAE@ABV?$basic_string@DU?$char_traits@D@std@@v?$allocator@D@2@@std@@H000H@Z$0
2>Channel.obj : error LNK2019: unresolved external symbol _amqp_ssl_socket_set_cacert referenced in function __catch$??0Channel@AmqpClient@@QAE@ABV?$basic_string@DU?$char_traits@D@std@@v?$allocator@D@2@@std@@H000H@Z$0
2>Channel.obj : error LNK2019: unresolved external symbol _amqp_ssl_socket_set_key referenced in function __catch$??0Channel@AmqpClient@@QAE@ABV?$basic_string@DU?$char_traits@D@std@@v?$allocator@D@2@@std@@H000H@Z$0
2>F:\SourceCode\Rabbit\simpleamqpclient-build\Debug\SimpleAmqpClient.2.dll : fatal error LNK1120: 3 unresolved externals

anyone know how to resolve this error ? thanks in advance !

Asynchronous API support

I was wondering if there is plan to have asynchronous calls for different simpleamqpclient APIs.

Small bug in docs

Hi
Instead of
"In a sibiling directory to where you extracted the source code: mkdir simpleamqpclient-build cd simpleamqpclient-build cmake ../SimpleAmqpClient"
it should be
"In a sibiling directory to where you extracted the source code: mkdir simpleamqpclient-build cd simpleamqpclient-build cmake .."
( at least for win32 :-)

consumer doesn't get message, sent before instantiation

I am evaluating a SimpleAmqpClient based cosumer example program (found from a previous issue).
The problem is that when I first send the message and then run the consumer, the consumer is not receiving anything. However, if I have the consumer running, then a new message sent to the exchange appears in the consumer.

following is the actual code:

#include <SimpleAmqpClient/SimpleAmqpClient.h>

#include <iostream>
#include <fstream>

using namespace AmqpClient;

class ConnectionData{
public:
    std::string host;
    int port;
    std::string user;
    std::string password;
    std::string vHost;
    std::string routingKey;
    std::string exchange;

}theConnectionData;

void main()
{

    theConnectionData.host = "127.0.0.1";
    theConnectionData.port = 5672;
    theConnectionData.user = "guest";
    theConnectionData.password = "guest";
    theConnectionData.vHost = "/";
    theConnectionData.routingKey = "";
    theConnectionData.exchange = "indexer";


  std::ofstream file( "Log.txt" );
  file << "Listener" << std::endl;
  file << "\t" << "host: " << theConnectionData.host << std::endl;
  file << "\t" << "port: " << theConnectionData.port << std::endl;
  file << "\t" << "user: " << theConnectionData.user << std::endl;
  file << "\t" << "password: " << theConnectionData.password << std::endl;
  file << "\t" << "vHost: " << theConnectionData.vHost << std::endl;
  file << "\t" << "routingKey: " << theConnectionData.routingKey << std::endl;
  file.flush();

  try
  {
   file << "AmqpClient::Channel::Create" << std::endl;
   file.flush();
   AmqpClient::Channel::ptr_t channelPtr = AmqpClient::Channel::Create();// theConnectionData.host, theConnectionData.port, theConnectionData.user, theConnectionData.password, theConnectionData.vHost);

    file << "DeclareQueue" << std::endl;
    file.flush();
    std::string queueName = channelPtr->DeclareQueue("");
    file << "\t" << "queue: " << queueName << std::endl;
    file.flush();

    file << "BindQueue" << std::endl;
    file.flush();
    channelPtr->BindQueue(queueName, theConnectionData.exchange, theConnectionData.routingKey );

    file << "BasicConsume" << std::endl;
    file.flush();
    std::string consumer_tag  =   channelPtr->BasicConsume( queueName, "" );
    file << "\t" << "tag: " << consumer_tag << std::endl;
    file.flush();

    /**
    **Fair dispatch**
    You might have noticed that the dispatching still doesn't work exactly as we want. For example in a situation with two workers, when all odd messages are heavy and even messages are light, one worker will be constantly busy and the other one will do hardly any work. Well, RabbitMQ doesn't know anything about that and will still dispatch messages evenly.
    This happens because RabbitMQ just dispatches a message when the message enters the queue. It doesn't look at the number of unacknowledged messages for a consumer. It just blindly dispatches every n-th message to the n-th consumer.
    In order to defeat that we can use the basicQos method with the prefetchCount = 1 setting. This tells RabbitMQ not to give more than one message to a worker at a time. Or, in other words, don't dispatch a new message to a worker until it has processed and acknowledged the previous one. Instead, it will dispatch it to the next worker that is not still busy.
    int prefetchCount = 1;
    channel.basicQos(prefetchCount);
*/
    //int prefetchCount = 1;
    //channelPtr->BasicQos(consumer_tag,prefetchCount);

    file << "BasicConsumeMessage" << std::endl;
    file.flush();
    AmqpClient::Envelope::ptr_t envelopePtr =  channelPtr->BasicConsumeMessage( consumer_tag );
    file << "\t" << "body: " << envelopePtr->Message()->Body() << std::endl;
    file.flush();

    file << "BasicCancel" << std::endl;
    file.flush();
    channelPtr->BasicCancel( consumer_tag );
  }
  catch ( AmqpClient::AmqpException const& exception )
  {
    file << "Exception: " << typeid( exception ).name() << std::endl;
    file << "\t" << "what: " << exception.what() << std::endl;
    file << "\t" << "is_soft_error: " << exception.is_soft_error() << std::endl;
    file << "\t" << "reply_code: " << exception.reply_code() << std::endl;
    file << "\t" << "class_id: " << exception.class_id() << std::endl;
    file << "\t" << "method_id: " << exception.method_id() << std::endl;
    file << "\t" << "reply_text: " << exception.reply_text() << std::endl;
  }
  catch ( std::exception const& exception )
  {
    file << "Exception: " << typeid( exception ).name() << std::endl;
    file << "\t" << "what: " << exception.what() << std::endl;
  }
  catch ( ... )
  {
    file << "Exception: ..." << std::endl;
  }
}

Memory leak when QoS > 1

Hello,

When using prefetch count higher than 1, I experience memory leak.
Am I missing something or is this a bug?
The code below allocates memory and never releases it, and eventually system crashes.

#include <SimpleAmqpClient.h>
#include <iostream>

using namespace AmqpClient;
using namespace std;

int main()
{
    // queue name
    string queue = "test-queue";
    // connect
    Channel::ptr_t channel = Channel::Create("localhost",5672,"guest","guest","rafal-test",131072);
    // declare queue
    channel->DeclareQueue(queue,false,true,false,false);
    // create message
    BasicMessage::ptr_t message = BasicMessage::Create("The message.");
    // publish it couple of times so we can use some prefetch
    for (int i=0; i<10; i++)
        channel->BasicPublish("", queue, message, false, false);
    // create consumer, QoS = 10
    std::string consumer = channel->BasicConsume(queue,"ConsumerTag1",false,false,false,10);
    // keep looping
    for (int i=0; true; i++)
    {
        // delay every 1000 iterations to slow things down a bit
        if (i%1000 == 0)sleep(1);
        // consume message
        Envelope::ptr_t envelope = channel->BasicConsumeMessage(consumer);
        // show counter
        cout << i << " Received message with body: " << envelope->Message()->Body() << std::endl;
        // publish back to the queue
        channel->BasicPublish("", queue, envelope->Message(), false, false);
        // ack consumed message
        channel->BasicAck(envelope->GetDeliveryInfo());
    }
}

Channel::BasicConsumeMessage timeout not ms

As described in the headerfile for the Channel class, the overloaded function 'BasicConsumeMessage' accepts a timeout parameter. The timeout must be specified in ms (milliseconds), but this turns out not to be correct. The value is treated as having the unit 'seconds', thus the actual timeout value calculated in 'BasicConsumeMessage' is factor 1000 times higher.

Extra Channel::BasicAck() method with just a delivery tag or message key

Hello,

We use pretty big message bodies (sometimes many megabytes big) that hold JSON encoded data. The first thing that we do when we consume a message from the queue, is parse the JSON to get the data we need. From that moment on, we no longer use or need the envelope, message and message body.

However, all the time we still have to keep this full envelope object with all its data in main memory, because we need to pass the full envelope object to the Channel::BasicAck() method (which is done much later). This is a waste of resources.

My feature request is this: can we have an additional BasicAck() method that does not require a full envelope parameter, but only a small object that holds just enough information to do the ack? The entire envelope object can then be deallocated after is is read, and we just have to keep this small MessageID, DeliveryTag, AckKey object (or any other appropriate name that you give to it) in memory.

Thanks!

Doesn't build under VS2008

Library doesn't compile under VS2008 because its missing typedefs for uint#_t 's.

Looks like I'm using boost/cstdint.h incorrectly as all of the typedefs are in the boost:: namespace.

Workaround (untested) for the moment is to include msinttypes before including any SimpleAmqpClient header.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.