WAMP for C++ 11 on POCO
C++ Python CMake
Pull request Compare This branch is 25 commits ahead, 243 commits behind crossbario:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
autobahn
doc
examples
examples_poco/crossbar_authenticate
test
.gitignore
LICENSE
README.md
SConstruct
autobahncpp.sublime.project

README.md

WAMP_POCO

WAMP_POCO is a fork of AutobahnCpp that is using POCO instead of Boost. JSON is used for serialization and the transport is WebSocket (optionally via SSL). Errors are raised by std::future exceptions. Authentication with "ticket" and "wampcra" methods is implemented.

Dependencies

  • Modern C++ compiler (MSVC 2013 and GCC 4.7 tested)
  • POCO Libraries (1.5.3+ for WAMP-CRA support)
  • openssl (required by POCO's Net_SSL module)

Example code

Notable changes to AutobahnCpp:

  • Using std::future instead of boost::future. The missing "then" continuation functionality is implemented in util/Continuation.h. future.then([]{ ... }); can be rewritten to util::then(future, []{ ... });
  • Using Poco::Dynamic instead of boost any libraries. See documentation for usage

For a complete compilable example see the directory examples_poco.

The examples in this repository are not updated for this fork. The changes would be trivial as demonstrated in the following.

Calling a remote Procedure

auto c1 = util::then(session.call("com.mathservice.add2", {23, 777}),
   [&](std::future<any> f) {
        cout << "Got call result " << f.get().convert<uint64_t>() << endl;
    });

Registering a remoted Procedure

auto r1 = util::then(session.provide("com.myapp.cpp.square",
   [](const anyvec& args, const anymap& kwargs) {
      cout << "Procedure is invoked .." << endl;
      uint64_t x = args[0].convert<uint64_t>();
      return x * x;
   }),

   [](future<registration> reg) {
      cout << "Registered with ID " << reg.get().id << endl;
   });

Publishing an Event

session.publish("com.myapp.topic2", {23, true, string("hello")});

Publishing an Event (acknowledged)

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

auto p1 = util::then(session.publish("com.myapp.topic2", {23, true, string("hello")}, opts),

   [](future<publication> pub) {
      cout << "Published with ID " << pub.get().id << endl;
   });

Subscribing to a Topic

auto s1 = util::then(session.subscribe("com.myapp.topic1",
   [](const anyvec& args, const anymap& kwargs) {
      cout << "Got event: " << args[0].convert<uint64_t>() << endl;
   }),

   [](future<subscription> sub) {
      cout << "Subscribed with ID " << sub.get().id << endl;
   });

Below is the original README

Autobahn|Cpp

Autobahn|Cpp is a subproject of Autobahn which implements the Web Application Messaging Protocol (WAMP) in C++ supporting the following application roles

  • Caller
  • Callee
  • Publisher
  • Subscriber

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", {23, 777})
.then(
   [&](future<any> f) {
        cout << "Got call result " << any_cast<uint64_t> (f.get()) << endl;
    });

Registering a remoted Procedure

auto r1 = session.provide("com.myapp.cpp.square",
   [](const anyvec& args, const anymap& kwargs) {
      cout << "Procedure is invoked .." << endl;
      uint64_t x = any_cast<uint64_t> (args[0]);
      return x * x;
   })
.then(
   [](future<registration> reg) {
      cout << "Registered with ID " << reg.get().id << endl;
   });

Publishing an Event

session.publish("com.myapp.topic2", {23, true, string("hello")});

Publishing an Event (acknowledged)

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

auto p1 = session.publish("com.myapp.topic2", {23, true, string("hello")}, opts)
.then(
   [](future<publication> pub) {
      cout << "Published with ID " << pub.get().id << endl;
   });

Subscribing to a Topic

auto s1 = session.subscribe("com.myapp.topic1",
   [](const anyvec& args, const anymap& kwargs) {
      cout << "Got event: " << any_cast<uint64_t>(args[0]) << endl;
   })
.then(
   [](future<subscription> sub) {
      cout << "Subscribed with ID " << sub.get().id << 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.

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 2015 (see C++ Standardisation Roadmap)
  • Support for when_all and when_any as described in above proposal depends on Boost 1.56 (upcoming release as of 31/03/2014) 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:

sudo apt-get install libbz2-dev libssl-dev ruby libtool autoconf scons

clang

Install clang and libc++:

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

Boost

To build Boost 1.55 (current release) from sources, get source code package for the latest Boost release from here and

cd $HOME
tar xvjf Downloads/boost_1_55_0.tar.bz2
cd boost_1_55_0/
./bootstrap.sh
./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 with GCC instead of clang:

./b2 toolset=gcc -j 4

To build Boost trunk (needed for when_all, when_any)

cd $HOME
git clone --recursive git@github.com:boostorg/boost.git
cd boost/
./bootstrap.sh
./b2 toolset=clang cxxflags="-stdlib=libc++" linkflags="-stdlib=libc++" -j 4

MsgPack-C

Get MsgPack-C and build with clang:

cd $HOME
git clone https://github.com/msgpack/msgpack-c.git
cd msgpack-c
./bootstrap
CXX=`which clang++` CC=`which clang` CXXFLAGS="-std=c++11 -stdlib=libc++" \
   LDFLAGS="-stdlib=libc++" ./configure --prefix=$HOME/msgpack_clang
make
make install

To build with GCC instead of clang:

./configure --prefix=$HOME/msgpack_gcc

Autobahn|Cpp

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

cd $HOME
git clone git@github.com:tavendo/AutobahnCpp.git
cd AutobahnCpp

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

Examples

The Autobahn|Cpp repository contains a number of examples that demonstrate all 4 basic patterns of using WAMP:

Building the Examples

For building the examples, add the following to your ~/.profile:

## Use clang
##
export CC='clang'
export CXX='clang++'

## Libaries (clang based)
##
export BOOST_ROOT=${HOME}/boost_trunk_clang
export LD_LIBRARY_PATH=${BOOST_ROOT}/stage/lib:${LD_LIBRARY_PATH}

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

For building with GCC, use the following

## Use GNU
##
export CC='gcc'
export CXX='g++'

## Libraries (GCC based)
##
export BOOST_ROOT=${HOME}/boost_trunk_gcc
export LD_LIBRARY_PATH=${BOOST_ROOT}/stage/lib:${LD_LIBRARY_PATH}

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

Now build all examples:

cd autobahn/examples
scons -j 4

The examples will get built in autobahn/build/examples.

Running the Examples

The examples include a Autobahn|Python based WAMP router and example backend.

To run this, you need Python and pip already installed.

Then, to install Autobahn|Python

pip install autobahn[twisted]

Start the example router in a first terminal

cd autobahn/examples
python server.py

Then start one of the built C++ examples in a second terminal

cd autobahn
./build/examples/call1

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 Cheetsheet

  • [] 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