WAMP in C++ for Boost/Asio
C++ CMake
Latest commit f8a6de2 Dec 29, 2016 @oberstet oberstet committed on GitHub Merge pull request #147 from agrecascino/master
Fix verbose logging when using websocket.

README.md

Autobahn|Cpp

This documentation is quite outdated (and also woefully incomplete). When in doubt ask on the mailing list or read the code!

Autobahn|Cpp is a subproject of Autobahn which provides a C++ WAMP implementation that is able to talk WAMP over stdio pipes.

  • Caller
  • Callee
  • Publisher
  • Subscriber

Autobahn|Cpp is open-source, licensed under the Boost Software License.

The API and implementation make use of modern C++ 11 and new asynchronous idioms using (upcoming) features of the standard C++ library, in particular Futures, Continuations and Lambdas.

Continuations are one way of managing control flow in an asynchronous program. Other styles include: asynchronous Callbacks, Coroutines (yield or await), Actors (Erlang/OTP, Scala/Akka or Rust) and Transactional memory.

Autobahn|Cpp supports running WAMP (rawsocket-msgpack) over TCP(-TLS), Unix domain sockets or pipes (stdio). The library is "header-only", light-weight (< 2k code lines) and depends on the following:

For getting help, questions or feedback, get in touch on the mailing list, Twitter or IRC #autobahn (Freenode).

Show me some code!

Here is how programming with C++ and Autobahn|Cpp looks like.

Calling a remote Procedure

auto c1 = session.call("com.mathservice.add2", std::make_tuple(23, 777))
    .then([&](boost::future<wamp_call_result> result) {
        std::cout << "Got call result " << result.get().argument<uint64_t>(0) << std::endl;
    });

Registering a remoted Procedure

auto r1 = session.provide("com.myapp.cpp.square",
    [](autobahn::wamp_invocation invocation) {
        std::cout << "Procedure is invoked .." << endl;
        uint64_t x = invocation->argument<uint64_t>(0);
        return x * x;
    })
    .then([](boost::future<autobahn::wamp_registration> reg) {
        std::cout << "Registered with ID " << reg.get().id() << std::endl;
    });

Publishing an Event

session.publish("com.myapp.topic2", std::make_tuple(23, true, std::string("hello")));

Publishing an Event (acknowledged)

auto opts = PublishOptions();
opts.acknowledge = True;

session.publish("com.myapp.topic2", std::make_tuple(23, true, std::string("hello")), opts)
    .then([](boost::future<autobahn::wamp_publication> pub) {
        std::cout << "Published with ID " << pub.get().id() << std::endl;
    });

Subscribing to a Topic

auto s1 = session.subscribe("com.myapp.topic1",
    [](const autobahn::wamp_event& event) {
        std::cout << "Got event: " << event.argument<uint64_t>(0) << std::endl;
    })
    .then([](boost::future<autobahn::wamp_subscription> sub) {
        std::cout << "Subscribed with ID " << sub.get().id() << std::endl;
    });

Here is JavaScript running in Chrome call into C++ running on command line. Both are connected via a WAMP router, in this case Autobahn|Python based.

Examples

The Autobahn|Cpp repository contains a number of examples that demonstrate all 4 basic patterns of using WAMP. There are also examples for WAMP-CRA and Unix domain sockets.

Building

Notes

  • The library code is written in standard C++ 11. Target toolchains currently include clang and gcc. Support for MSVC is tracked on this issue.
  • While C++ 11 includes std::future in the standard library, this lacks continuations. boost::future.then allows attaching continuations to futures as outlined in the proposal here. This feature will come to standard C++, but probably not before 2017 (see C++ Standardisation Roadmap)
  • Support for when_all and when_any as described in above proposal depends on Boost 1.56 or higher.
  • The library and example programs were tested and developed with clang 3.4, libc++ and Boost trunk/1.56 on an Ubuntu 13.10 x86-64 bit system. It also works with gcc 4.8, libstdc++ and Boost trunk/1.56. Your mileage with other versions of the former may vary, but we accept PRs;)

Build tools

Install some libs and build tools (these are for Ubuntu):

sudo apt-get install -y libbz2-dev libssl-dev cmake

Clang

If you want to work with Clang (rather than GCC), install clang and libc++ (these are for Ubuntu):

sudo apt-get install -y clang libc++1 libc++-dev

Then make Clang available:

oberstet@corei7ub1310:~$ sudo update-alternatives --config c++
[sudo] password for oberstet:
Es gibt 3 Auswahlmöglichkeiten für die Alternative c++ (welche /usr/bin/c++ bereitstellen).

  Auswahl      Pfad                     Priorität Status
------------------------------------------------------------
* 0            /usr/bin/g++              20        Auto-Modus
  1            /usr/bin/clang++          10        manueller Modus
  2            /usr/bin/clang++-libc++   5         manueller Modus
  3            /usr/bin/g++              20        manueller Modus

Drücken Sie die Eingabetaste, um die aktuelle Wahl[*] beizubehalten,
oder geben Sie die Auswahlnummer ein: 1
update-alternatives: /usr/bin/clang++ wird verwendet, um /usr/bin/c++ (c++) im manueller Modus bereitzustellen

Boost

Most of the time, your distro's Boost libraries will be outdated (unless you're using Arch or Homebrew). Don't waste time with those: to build the latest Boost 1.60 (current release as of 2016/01) from sources

cd ~
wget http://downloads.sourceforge.net/project/boost/boost/1.60.0/boost_1_60_0.tar.bz2
tar xvjf boost_1_60_0.tar.bz2
cd boost_1_60_0
./bootstrap.sh --with-toolset=clang
./b2 toolset=clang cxxflags="-stdlib=libc++" linkflags="-stdlib=libc++" -j 4

Note: The -j 4 option will allow use of 4 cores for building.

To build using GCC instead of Clang:

./bootstrap.sh --with-toolset=gcc
./b2 toolset=gcc -j 4

Then add the following to your ~/.profile:

export BOOST_ROOT=${HOME}/boost_1_60_0
export LD_LIBRARY_PATH=${BOOST_ROOT}/stage/lib:${LD_LIBRARY_PATH}

MsgPack-C

Get MsgPack-C and install:

cd ~
git clone https://github.com/msgpack/msgpack-c.git
cd msgpack-c
git checkout cpp-1.4.0
export CC=/usr/bin/clang
export CXX=/usr/bin/clang++
export CXXFLAGS="$CXXFLAGS -std=c++11"
./bootstrap
./configure --prefix=$HOME/msgpack_clang
make install

On FreeBSD, you need to pkg install autotools and invoke gmake instead of make.

Then add the following to your ~/.profile:

export MSGPACK_ROOT=${HOME}/msgpack_clang
export LD_LIBRARY_PATH=${MSGPACK_ROOT}/lib:${LD_LIBRARY_PATH}

Autobahn|Cpp

To get Autobahn|Cpp library and examples, clone the repo

cd $HOME
git clone https://github.com/crossbario/autobahn-cpp.git
cd autobahn

The library is "header-only", means there isn't anything to compile or build. Just include the relevant headers.

Documentation

Click here for the Autobahn|Cpp reference documentation.

Get in touch

Get in touch on IRC #autobahn on chat.freenode.net, follow us on Twitter or join the mailing list.

Resources

Closures Cheatsheet

  • [] Capture nothing (or, a scorched earth strategy?)
  • [&] Capture any referenced variable by reference
  • [=] Capture any referenced variable by making a copy
  • [=, &foo] Capture any referenced variable by making a copy, but capture variable foo by reference
  • [bar] Capture bar by making a copy; don't copy anything else
  • [this] Capture the this pointer of the enclosing class