qpid-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From acon...@apache.org
Subject [06/89] [abbrv] [partial] qpid-proton git commit: PROTON-1728: Reorganize the source tree
Date Tue, 03 Jul 2018 22:12:55 GMT
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/docs/mt.md
----------------------------------------------------------------------
diff --git a/cpp/docs/mt.md b/cpp/docs/mt.md
new file mode 100644
index 0000000..3be1bc2
--- /dev/null
+++ b/cpp/docs/mt.md
@@ -0,0 +1,124 @@
+# Multithreading {#mt_page}
+
+Full multithreading support is available with C++11 and later. Limited
+multithreading is possible with older versions of C++.  See the last
+section of this page for more information.
+
+`proton::container` handles multiple connections concurrently in a
+thread pool, created using `proton::container::run()`. As AMQP events
+occur on a connection the container calls `proton::messaging_handler`
+event callbacks.  The calls for each connection are *serialized* -
+callbacks for the same connection are never made concurrently.
+
+You assign a handler to a connection in `proton::container::connect()`
+or `proton::listen_handler::on_accept()` with
+`proton::connection_options::handler()`.  We recommend you create a
+separate handler for each connection.  That means the handler doesn't
+need locks or other synchronization to protect it against concurrent
+use by Proton threads.  If you use the handler concurrently from
+non-Proton threads then you will need synchronization.
+
+The examples @ref multithreaded_client.cpp and @ref
+multithreaded_client_flow_control.cpp illustrate these points.
+
+## Thread-safety rules
+
+`proton::container` is thread-safe *with C++11 or greater*.  An
+application thread can open (or listen for) new connections at any
+time. The container uses threads that call `proton::container::run()`
+to handle network IO and call user-defined `proton::messaging_handler`
+callbacks.
+
+`proton::container` ensures that calls to event callbacks for each
+connection instance are *serialized* (not called concurrently), but
+callbacks for different connections can be safely executed in
+parallel.
+
+`proton::connection` and related objects (`proton::session`,
+`proton::sender`, `proton::receiver`, `proton::delivery`) are *not*
+thread-safe and are subject to the following rules.
+
+1. They can only be used from a `proton::messaging_handler` event
+   callback called by Proton or a `proton::work_queue` function (more
+   below).
+
+2. You cannot use objects belonging to one connection from a callback
+   for another connection.  We recommend a single handler instance per
+   connection to avoid confusion.
+
+3. You can store Proton objects in member variables for use in a later
+   callback, provided you respect rule two.
+
+`proton::message` is a value type with the same threading constraints
+as a standard C++ built-in type.  It cannot be concurrently modified.
+
+## Work queues
+
+`proton::work_queue` provides a safe way to communicate between
+different connection handlers or between non-Proton threads and
+connection handlers.
+
+ * Each connection has an associated `proton::work_queue`.
+
+ * The work queue is thread-safe (C++11 or greater).  Any thread can
+   add *work*.
+
+ * *Work* is a `std::function`, and bound arguments will be
+   called like an event callback.
+
+When the work function is called by Proton, it will be serialized
+safely so that you can treat the work function like an event callback
+and safely access the handler and Proton objects stored on it.
+
+The examples @ref multithreaded_client.cpp and @ref
+multithreaded_client_flow_control.cpp show how you can send and
+receive messages from non-Proton threads using work queues.
+
+## The wake primitive
+
+`proton::connection::wake()` allows any thread to "wake up" a
+connection by generating an `on_connection_wake()` callback. This is
+the *only* thread-safe `proton::connection` function.
+
+This is a lightweight, low-level primitive for signaling between
+threads.
+
+ * It does not carry any code or data (unlike `proton::work_queue`).
+
+ * Multiple calls to `wake()` can be "coalesced" into a single
+   `on_connection_wake()`.
+
+ * Calls to `on_connection_wake()` can occur without any call to
+   `connection::wake()`.  Proton uses wake internally.
+
+The semantics of `wake()` are similar to
+`std::condition_variable::notify_one`.  There will be a wakeup, but
+there must be some shared application state to determine why the
+wakeup occurred and what, if anything, to do about it.
+
+Work queues are easier to use in many instances, but `wake()` may be
+useful if you already have your own external thread-safe queues and
+just need an efficient way to wake a connection to check them for
+data.
+
+## Using older versions of C++
+
+Before C++11 there was no standard support for threading in C++.  You
+can use Proton with threads but with the following limitations.
+
+ * The container will not create threads, it will only use the single
+   thread that calls `proton::container::run()`.
+
+ * None of the Proton library classes are thread-safe, including
+   `proton::container` and `proton::work_queue`.  You need an external
+   lock to use `proton::container` in multiple threads.
+
+The only exception is `proton::connection::wake()`, it *is*
+thread-safe even in older C++.
+
+You can implement your own `proton::container` using your own
+threading library, or ignore the container and embed the lower-level
+`proton::io::connection_driver` in an external poller. These
+approaches still use the same `proton::messaging_handler` callbacks,
+so you can reuse most of your application code.  Note that this is an
+advanced undertaking.  There are a few pointers in @ref io_page.

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/docs/overview.md
----------------------------------------------------------------------
diff --git a/cpp/docs/overview.md b/cpp/docs/overview.md
new file mode 100644
index 0000000..7a299b8
--- /dev/null
+++ b/cpp/docs/overview.md
@@ -0,0 +1,109 @@
+# Overview {#overview_page}
+
+Qpid Proton's concepts and capabilities closely match those of its
+wire protocol, AMQP.  See
+[the Qpid AMQP page](https://qpid.apache.org/amqp/index.html) and
+[the AMQP 1.0 spec](http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-overview-v1.0-os.html)
+for more information.
+
+## Key concepts
+
+A `proton::message` has a *body* (the main content), application
+properties where you can store additional data, and specific
+properties defined by AMQP.
+
+Messages are transferred over *links*. The sending end of a link is a
+`proton::sender`, and the receiving end is a `proton::receiver`.
+Links have a *source* and *target* address, as explained
+[below](#sources-and-targets).
+
+Links are grouped in a `proton::session`. Messages in the same session
+are sent sequentially, while those on different sessions can be
+interleaved. A large message being sent on one session does not block
+messages being sent on another session.
+
+Sessions belong to a `proton::connection`. If you don't need multiple
+sessions, a connection will create links directly using a default
+session.
+
+A `proton::delivery` represents the transfer of a message and allows
+the receiver to accept or reject it. The sender can use a
+`proton::tracker` to track the status of a sent message and find out
+if it was accepted.
+
+A delivery is *settled* when both ends are done with it.  Different
+settlement methods give different levels of reliability:
+*at-most-once*, *at-least-once*, and *exactly-once*. See
+[below](#delivery-guarantees).
+
+## The anatomy of a Proton application
+
+`proton::container` is the top-level object in a Proton application.
+A client uses `proton::container::connect()` to establish connections.
+A server uses `proton::container::listen()` to accept connections.
+
+Proton is an event-driven API. You implement a subclass of
+`proton::messaging_handler` and override functions to handle AMQP
+events, such as `on_container_open()` or `on_message()`. Each
+connection is associated with a handler for its events.
+`proton::container::run()` polls all connections and listeners and
+dispatches events to your handlers.
+
+A message body can be a string or byte sequence encoded any way you
+like. However, AMQP also provides standard, interoperable encodings
+for basic data types and structures such as maps and lists. You can
+use this encoding for your message bodies via `proton::value` and
+`proton::scalar`, which convert C++ types to their AMQP equivalents.
+
+## Sources and targets
+
+Every link has two addresses, *source* and *target*. The most common
+pattern for using these addresses is as follows.
+
+When a client creates a *receiver* link, it sets the *source*
+address. This means "I want to receive messages from this
+source". This is often referred to as "subscribing" to the
+source. When a client creates a *sender* link, it sets the *target*
+address. This means "I want to send to this target".
+
+In the case of a broker, the source or target usually refers to a
+queue or topic. In general they can refer to any AMQP-capable node.
+
+In the *request-response* pattern, a request message carries a
+*reply-to* address for the response message. This can be any AMQP
+address, but it is often useful to create a temporary address for the
+response message. The client creates a *receiver* with no source
+address and the *dynamic* flag set. The server generates a unique
+*source* address for the receiver, which is discarded when the link
+closes. The client uses this source address as the reply-to when it
+sends the request, so the response is delivered to the client's
+receiver.
+
+The @ref server_direct.cpp example shows how to implement a
+request-response server.
+
+## Delivery guarantees
+
+Proton offers three levels of message delivery guarantee:
+*at-most-once*, *at-least-once*, and *exactly-once*.
+
+For *at-most-once*, the sender settles the message as soon as it sends
+it. If the connection is lost before the message is received by the
+receiver, the message will not be delivered.
+
+For *at-least-once*, the receiver accepts and settles the message on
+receipt. If the connection is lost before the sender is informed of
+the settlement, then the delivery is considered in-doubt and should be
+retried. This will ensure it eventually gets delivered (provided of
+course the connection and link can be reestablished). It may mean that
+it is delivered multiple times, however.
+
+Finally, for *exactly-once*, the receiver accepts the message but
+doesn't settle it. The sender settles once it is aware that the
+receiver accepted it. In this way the receiver retains knowledge of an
+accepted message until it is sure the sender knows it has been
+accepted. If the connection is lost before settlement, the receiver
+informs the sender of all the unsettled deliveries it knows about, and
+from this the sender can deduce which need to be redelivered. The
+sender likewise informs the receiver which deliveries it knows about,
+from which the receiver can deduce which have already been settled.

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/docs/types.md
----------------------------------------------------------------------
diff --git a/cpp/docs/types.md b/cpp/docs/types.md
new file mode 100644
index 0000000..6c24d47
--- /dev/null
+++ b/cpp/docs/types.md
@@ -0,0 +1,86 @@
+# AMQP and C++ types {#types_page}
+
+An AMQP message body can hold binary data using any encoding you
+like. AMQP also defines its own encoding and types. The AMQP encoding
+is often used in message bodies because it is supported by AMQP
+libraries on many languages and platforms. You also need to use the
+AMQP types to set and examine message properties.
+
+## Scalar types
+
+Each type is identified by a proton::type_id.
+
+C++ type            | AMQP type_id         | Description
+--------------------|----------------------|-----------------------
+bool                | proton::BOOLEAN      | Boolean true or false
+uint8_t             | proton::UBYTE        | 8-bit unsigned byte
+int8_t              | proton::BYTE         | 8-bit signed byte
+uint16_t            | proton::USHORT       | 16-bit unsigned integer
+int16_t             | proton::SHORT        | 16-bit signed integer
+uint32_t            | proton::UINT         | 32-bit unsigned integer
+int32_t             | proton::INT          | 32-bit signed integer
+uint64_t            | proton::ULONG        | 64-bit unsigned integer
+int64_t             | proton::LONG         | 64-bit signed integer
+wchar_t             | proton::CHAR         | 32-bit unicode code point
+float               | proton::FLOAT        | 32-bit binary floating point
+double              | proton::DOUBLE       | 64-bit binary floating point
+proton::timestamp   | proton::TIMESTAMP    | 64-bit signed milliseconds since 00:00:00 (UTC), 1 January 1970.
+proton::decimal32   | proton::DECIMAL32    | 32-bit decimal floating point
+proton::decimal64   | proton::DECIMAL64    | 64-bit decimal floating point
+proton::decimal128  | proton::DECIMAL128   | 128-bit decimal floating point
+proton::uuid        | proton::UUID         | 128-bit universally-unique identifier
+std::string         | proton::STRING       | UTF-8 encoded Unicode string
+proton::symbol      | proton::SYMBOL       | 7-bit ASCII encoded string
+proton::binary      | proton::BINARY       | Variable-length binary data
+
+## Holder types
+
+`proton::message::body()` and other message-related data can contain
+different types of data at runtime. There are two "holder" types
+provided to hold runtime typed data:
+
+ - `proton::scalar` can hold a scalar value of any type.
+ - `proton::value` can hold any AMQP value, scalar or compound.
+
+You can set the value in a holder by assignment, and use the
+`proton::get()` and `proton::coerce()` templates to extract data in a
+type-safe way. Holders also provide functions to query the type of
+value they contain.
+
+## Compound types
+
+C++ type            | AMQP type_id         | Description
+--------------------|----------------------|-----------------------
+See below           | proton::ARRAY        | Sequence of values of the same type
+See below           | proton::LIST         | Sequence of values of mixed types
+See below           | proton::MAP          | Map of key-value pairs
+
+A `proton::value` containing a `proton::ARRAY` can convert to and from
+C++ sequences of the corresponding C++ type: `std::vector`,
+`std::deque`, `std::list`, and `std::forward_list`.
+
+`proton::LIST` converts to and from sequences of `proton::value` or
+`proton::scalar`, which can hold mixed types of data.
+
+`proton::MAP` converts to and from `std::map`, `std::unordered_map`,
+and sequences of `std::pair`.
+
+For example, you can decode a message body with any AMQP map as
+follows.
+
+    proton::message m = ...;
+    std::map<proton::value, proton::value> map;
+    proton::get(m.body(), map);
+
+You can encode a message body with a map of string keys and `uint64_t`
+values like this:
+
+    std::unordered_map<std::string, uint64_t> map;
+    map["foo"] = 123;
+    m.body() = map;
+
+## Include files
+
+`proton/types.hpp` includes all available type definitions and
+conversions. Alternatively, you can selectively include the `.hpp`
+files you want.

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/docs/user.doxygen.in
----------------------------------------------------------------------
diff --git a/cpp/docs/user.doxygen.in b/cpp/docs/user.doxygen.in
new file mode 100644
index 0000000..2b2eda6
--- /dev/null
+++ b/cpp/docs/user.doxygen.in
@@ -0,0 +1,83 @@
+##
+## Licensed to the Apache Software Foundation (ASF) under one
+## or more contributor license agreements.  See the NOTICE file
+## distributed with this work for additional information
+## regarding copyright ownership.  The ASF licenses this file
+## to you under the Apache License, Version 2.0 (the
+## "License"); you may not use this file except in compliance
+## with the License.  You may obtain a copy of the License at
+##
+##   http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing,
+## software distributed under the License is distributed on an
+## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+## KIND, either express or implied.  See the License for the
+## specific language governing permissions and limitations
+## under the License.
+##
+
+# Project options
+
+PROJECT_NAME            = "Qpid Proton C++"
+PROJECT_NUMBER          = @PN_VERSION_MAJOR@.@PN_VERSION_MINOR@.@PN_VERSION_POINT@
+OUTPUT_DIRECTORY        = .
+OUTPUT_LANGUAGE         = English
+BRIEF_MEMBER_DESC       = YES
+REPEAT_BRIEF            = YES
+ALWAYS_DETAILED_SEC     = NO
+INLINE_INHERITED_MEMB   = YES
+JAVADOC_AUTOBRIEF       = YES
+MULTILINE_CPP_IS_BRIEF  = NO
+INHERIT_DOCS            = YES
+BUILTIN_STL_SUPPORT     = YES
+INLINE_SIMPLE_STRUCTS   = YES
+HIDE_UNDOC_CLASSES      = YES
+HIDE_COMPOUND_REFERENCE = YES
+HIDE_SCOPE_NAMES        = YES
+MAX_INITIALIZER_LINES   = 0
+ALPHABETICAL_INDEX      = NO
+SORT_MEMBER_DOCS        = NO
+
+# Redefine protected as private and strip out the PN_CPP_EXTERN macro
+
+ENABLE_PREPROCESSING    = YES
+MACRO_EXPANSION         = YES
+EXPAND_ONLY_PREDEF      = YES
+PREDEFINED              = protected=private PN_CPP_DEPRECATED(x)= PN_CPP_EXTERN= PN_CPP_OVERRIDE= PN_CPP_HAS_CPP11=1 PN_CPP_HAS_SHARED_PTR=1 PN_CPP_HAS_UNIQUE_PTR=1 PN_CPP_HAS_LONG_LONG=1 PN_CPP_HAS_NULLPTR=1 PN_CPP_HAS_RVALUE_REFERENCES=1 PN_CPP_HAS_OVERRIDE=override PN_CPP_HAS_EXPLICIT_CONVERSIONS=1 PN_CPP_HAS_DEFAULTED_FUNCTIONS=1 PN_CPP_HAS_DELETED_FUNCTIONS=1 PN_CPP_HAS_STD_FUNCTION=1 PN_CPP_HAS_CHRONO=1 PN_CPP_SUPPORTS_THREADS=1
+EXCLUDE_SYMBOLS         = internal internal::*
+
+# Configuration options related to warning and progress messages
+
+QUIET                   = YES
+WARNINGS                = YES
+
+# Configuration options related to the input files
+
+INPUT                   = @CMAKE_SOURCE_DIR@/cpp/include \
+                          @CMAKE_SOURCE_DIR@/cpp/docs \
+                          @CMAKE_SOURCE_DIR@/cpp/examples
+FILE_PATTERNS           = *.hpp *.md *.dox
+EXCLUDE_PATTERNS        = @CMAKE_SOURCE_DIR@/cpp/examples/*.?pp \
+                          @CMAKE_SOURCE_DIR@/cpp/include/proton/internal/*.hpp
+FULL_PATH_NAMES         = YES
+RECURSIVE               = YES
+STRIP_FROM_PATH         = @CMAKE_SOURCE_DIR@/cpp/include
+EXAMPLE_PATH            = @CMAKE_SOURCE_DIR@/cpp/examples
+EXAMPLE_RECURSIVE       = YES
+
+# View and list options
+
+DISABLE_INDEX           = YES
+GENERATE_TREEVIEW       = YES
+GENERATE_TODOLIST       = NO
+GENERATE_TESTLIST       = NO
+GENERATE_BUGLIST        = NO
+GENERATE_DEPRECATEDLIST = NO
+
+# Configuration options related to the output format
+
+GENERATE_HTML           = YES
+HTML_OUTPUT             = html
+HTML_FILE_EXTENSION     = .html
+GENERATE_LATEX          = NO

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/examples/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/cpp/examples/CMakeLists.txt b/cpp/examples/CMakeLists.txt
new file mode 100644
index 0000000..a9bde0a
--- /dev/null
+++ b/cpp/examples/CMakeLists.txt
@@ -0,0 +1,138 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+cmake_minimum_required (VERSION 2.8.12)
+
+enable_language(CXX)
+
+set (ProtonCpp_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+find_package(ProtonCpp REQUIRED)
+set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
+find_package(Threads)
+
+include_directories(${ProtonCpp_INCLUDE_DIRS})
+link_libraries(${ProtonCpp_LIBRARIES})
+add_definitions(${ProtonCpp_DEFINITIONS})
+
+
+macro (has_cxx_features result)
+set(${result} OFF)
+if (DEFINED CMAKE_CXX_COMPILE_FEATURES)
+  set(${result} ON)
+  foreach(feature ${ARGN})
+    list(FIND CMAKE_CXX_COMPILE_FEATURES cxx_${feature} N)
+    if (N EQUAL -1)
+      set(${result} OFF)
+      break()
+    endif()
+  endforeach()
+endif()
+endmacro()
+
+set (BUILD_CPP_03 OFF CACHE BOOL "Compile as C++03 even when C++11 is available")
+# This effectively checks for cmake version 3.1 or later
+if (DEFINED CMAKE_CXX_COMPILE_FEATURES)
+  if (BUILD_CPP_03)
+    set(STD 98)
+  else ()
+    set(STD 11)
+    has_cxx_features(HAS_ENOUGH_CPP11 lambdas variadic_templates)
+    message(STATUS "Compiling C++11 examples: ${HAS_ENOUGH_CPP11}")
+  endif ()
+  set(CMAKE_CXX_STANDARD ${STD})
+  set(CMAKE_CXX_EXTENSIONS OFF)
+endif()
+
+# Single-threaded examples that work on C++03
+foreach(example
+    broker
+    helloworld
+    simple_connect
+    simple_recv
+    simple_send
+    reconnect_client
+    message_properties
+    scheduled_send_03
+    direct_recv
+    direct_send
+    client
+    server
+    server_direct
+    connection_options
+    queue_browser
+    colour_send
+    selected_recv
+    flow_control
+    ssl
+    ssl_client_cert
+    encode_decode)
+  add_executable(${example} ${example}.cpp)
+endforeach()
+
+if(HAS_ENOUGH_CPP11)
+  # Examples that require C++11
+  foreach(example
+      scheduled_send
+      service_bus)
+    add_executable(${example} ${example}.cpp)
+  endforeach()
+
+  # Examples that use threads directly
+  if (Threads_FOUND)
+    foreach(example
+        multithreaded_client
+        multithreaded_client_flow_control)
+      add_executable(${example} ${example}.cpp)
+      target_link_libraries(${example} ${CMAKE_THREAD_LIBS_INIT})
+    endforeach()
+  endif()
+endif()
+
+# Set result to a native search path - used by examples and binding tests.
+# args after result are directories or search paths.
+macro(set_search_path result)
+  set(${result} ${ARGN})
+  if (UNIX)
+    string(REPLACE ";" ":" ${result} "${${result}}") # native search path separators.
+  endif()
+  file(TO_NATIVE_PATH "${${result}}" ${result}) # native slash separators
+endmacro()
+
+# Add the tools directory for the 'proctest' module
+set_search_path(EXAMPLE_PYTHONPATH "${CMAKE_SOURCE_DIR}/tools/python" "$ENV{PYTHON_PATH}")
+set(EXAMPLE_ENV "PYTHONPATH=${EXAMPLE_PYTHONPATH}")
+
+# Add a test with the correct environment to find test executables and valgrind.
+macro(add_cpp_test name)
+  if(WIN32)
+    set(test_path "$<TARGET_FILE_DIR:broker>;$<TARGET_FILE_DIR:qpid-proton>;$<TARGET_FILE_DIR:qpid-proton-cpp>")
+  else(WIN32)
+    set(test_path "$<TARGET_FILE_DIR:broker>:$ENV{PATH}")
+  endif(WIN32)
+  add_test(
+    NAME ${name}
+    COMMAND ${PN_ENV_SCRIPT} ${EXAMPLE_ENV} "PATH=${test_path}" ${VALGRIND_ENV}
+            "HAS_CPP11=$<$<BOOL:${HAS_ENOUGH_CPP11}>:1>" -- ${ARGN}
+    )
+endmacro()
+
+add_cpp_test(cpp-example-container ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example_test.py -v ContainerExampleTest)
+
+if (NOT SSL_IMPL STREQUAL none)
+add_cpp_test(cpp-example-container-ssl ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example_test.py -v ContainerExampleSSLTest)
+endif()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/examples/ProtonCppConfig.cmake
----------------------------------------------------------------------
diff --git a/cpp/examples/ProtonCppConfig.cmake b/cpp/examples/ProtonCppConfig.cmake
new file mode 100644
index 0000000..e289ba4
--- /dev/null
+++ b/cpp/examples/ProtonCppConfig.cmake
@@ -0,0 +1,35 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# Note that this file is used *only* when building the examples within
+# the proton source tree not when the examples are installed separately
+# from it (for example in an OS distribution package).
+#
+# So if you find this file installed on your system something went wrong
+# with the packaging and/or package installation.
+#
+# For a packaged installation the equivalent file is created by the source
+# tree build and installed in the appropriate place for cmake on that system.
+
+set (ProtonCpp_VERSION       ${PN_VERSION})
+set (ProtonCpp_INCLUDE_DIRS  ${CMAKE_SOURCE_DIR}/c/include ${CMAKE_SOURCE_DIR}/cpp/include
+                             ${CMAKE_BINARY_DIR}/cpp)
+set (ProtonCpp_LIBRARIES     ${C_EXAMPLE_LINK_FLAGS} qpid-proton-cpp)
+set (ProtonCpp_DEFINITIONS   ${CXX_EXAMPLE_FLAGS})
+set (ProtonCpp_FOUND True)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/examples/README.dox
----------------------------------------------------------------------
diff --git a/cpp/examples/README.dox b/cpp/examples/README.dox
new file mode 100644
index 0000000..cb25e48
--- /dev/null
+++ b/cpp/examples/README.dox
@@ -0,0 +1,139 @@
+// C++ examples list (doxygen format)
+//
+// For a tutorial-style description of the examples see tutorial.dox.
+// To build the full HTML tutorial and documentation, in your build directory do:
+//
+//     make docs-cpp
+//
+// then open cpp/docs/html/tutorial.html in your browser.
+
+// DEVELOPER NOTE: If you add or modify examples, please add/update a short
+// description below and (if appropriate) extend/update tutorial.dox.
+
+/** @example helloworld.cpp
+
+Connects to a broker on 127.0.0.1:5672, establishes a subscription
+from the 'examples' node, and creates a sending link to the same
+node. Sends one message and receives it back.
+
+*/
+
+/** @example simple_send.cpp
+
+An example of sending a fixed number of messages and tracking their
+(asynchronous) acknowledgement. Messages are sent through the 'examples' node on
+an intermediary accessible on 127.0.0.1:5672.
+
+*/
+
+/** @example simple_recv.cpp
+
+Subscribes to the 'examples' node on an intermediary accessible
+on 127.0.0.1:5672. Simply prints out the body of received messages.
+
+*/
+
+/** @example message_properties.cpp
+
+Shows how to set and examine message properties.
+
+*/
+
+/** @example direct_send.cpp
+
+Accepts an incoming connection and then sends like `simple_send`.  You can
+connect directly to `direct_send` *without* a broker using @ref simple_recv.cpp.
+Make sure to stop the broker first or use a different port for `direct_send`.
+
+*/
+
+/** @example direct_recv.cpp
+
+Accepts an incoming connection and then receives like `simple_recv`.  You can
+connect directly to `direct_recv` *without* a broker using @ref simple_send.cpp.
+Make sure to stop the broker first or use a different port for `direct_recv`.
+
+*/
+
+/// @cond INTERNAL
+/** @example encode_decode.cpp
+
+Shows how C++ data types can be converted to and from AMQP types.
+
+*/
+/// @endcond
+
+/** @example client.cpp
+
+The client part of a request-response example. Sends requests and
+prints out responses. Requires an intermediary that supports the AMQP
+1.0 dynamic nodes on which the responses are received. The requests
+are sent through the 'examples' node.
+
+*/
+
+/** @example server.cpp
+
+The server part of a request-response example, that receives requests
+via the examples node, converts the body to uppercase and sends the
+result back to the indicated reply address.
+
+*/
+
+/** @example server_direct.cpp
+
+A variant of the server part of a request-response example that
+accepts incoming connections and does not need an intermediary. Much
+like the original server, it receives incoming requests, converts the
+body to uppercase and sends the result back to the indicated reply
+address. Can be used in conjunction with any of the client
+alternatives.
+
+*/
+
+/** @example broker.cpp
+
+A broker using the `proton::container`. You can use this to run other examples
+that require an intermediary, or you can use any AMQP 1.0 broker. This broker
+creates queues automatically when a client tries to send or subscribe.
+
+*/
+
+/** @example scheduled_send.cpp
+
+Shows how to use proton::container::schedule to schedule a timed callback.
+This version uses std::function and so requires C++11 or better. For a C++03 compatible
+approach see @ref scheduled_send_03.cpp.
+
+*/
+
+/** @example scheduled_send_03.cpp
+
+Shows how to use proton::container::schedule to schedule a timed callback in a
+C++03 compatible way. See @ref scheduled_send.cpp for a more convenient approach
+using std::function if you have C++11.
+
+*/
+
+/** @example service_bus.cpp
+
+A working example for accessing Service Bus session-enabled queues.
+Also provides some general notes on Service Bus usage.
+
+*/
+
+/** @example multithreaded_client.cpp
+
+A multithreaded sender and receiver.
+
+__Requires C++11__
+
+*/
+
+/** @example multithreaded_client_flow_control.cpp
+
+A multithreaded sender and receiver enhanced for flow control.
+
+__Requires C++11__
+
+*/

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/examples/broker.cpp
----------------------------------------------------------------------
diff --git a/cpp/examples/broker.cpp b/cpp/examples/broker.cpp
new file mode 100644
index 0000000..65384b3
--- /dev/null
+++ b/cpp/examples/broker.cpp
@@ -0,0 +1,454 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "options.hpp"
+
+#include <proton/connection.hpp>
+#include <proton/connection_options.hpp>
+#include <proton/container.hpp>
+#include <proton/delivery.hpp>
+#include <proton/error_condition.hpp>
+#include <proton/listen_handler.hpp>
+#include <proton/listener.hpp>
+#include <proton/message.hpp>
+#include <proton/messaging_handler.hpp>
+#include <proton/receiver_options.hpp>
+#include <proton/sender_options.hpp>
+#include <proton/source_options.hpp>
+#include <proton/target.hpp>
+#include <proton/target_options.hpp>
+#include <proton/tracker.hpp>
+#include <proton/transport.hpp>
+#include <proton/work_queue.hpp>
+
+#include <deque>
+#include <iostream>
+#include <map>
+#include <string>
+
+#if PN_CPP_HAS_STD_THREAD
+#include <thread>
+
+int hardware_concurrency() {return std::thread::hardware_concurrency();}
+#else
+int hardware_concurrency() {return 1;}
+#endif
+
+#include "fake_cpp11.hpp"
+
+// This is a simplified model for a message broker, that only allows for messages to go to a
+// single receiver.
+//
+// This broker is multithread safe and if compiled with C++11 with a multithreaded Proton
+// binding library will use as many threads as there are thread resources available (usually
+// cores)
+//
+// Queues are only created and never destroyed
+//
+// Broker Entities (that need to be individually serialised)
+// QueueManager - Creates new queues, finds queues
+// Queue        - Queues msgs, records subscribers, sends msgs to subscribers
+// Connection   - Receives Messages from network, sends messages to network.
+
+// Work
+// FindQueue(queueName, connection) - From a Connection to the QueueManager
+//     This will create the queue if it doesn't already exist and send a BoundQueue
+//     message back to the connection.
+// BoundQueue(queue) - From the QueueManager to a Connection
+//
+// QueueMsg(msg)        - From a Connection (receiver) to a Queue
+// Subscribe(sender)    - From a Connection (sender) to a Queue
+// Flow(sender, credit) - From a Connection (sender) to a Queue
+// Unsubscribe(sender)  - From a Connection (sender) to a Queue
+//
+// SendMsg(msg)   - From a Queue to a Connection (sender)
+// Unsubscribed() - From a Queue to a Connection (sender)
+
+
+// Simple debug output
+bool verbose;
+#define DOUT(x) do {if (verbose) {x};} while (false)
+
+class Queue;
+class Sender;
+
+typedef std::map<proton::sender, Sender*> senders;
+
+class Sender : public proton::messaging_handler {
+    friend class connection_handler;
+
+    proton::sender sender_;
+    senders& senders_;
+    proton::work_queue& work_queue_;
+    std::string queue_name_;
+    Queue* queue_;
+    int pending_credit_;
+
+    // Messaging handlers
+    void on_sendable(proton::sender &sender) OVERRIDE;
+    void on_sender_close(proton::sender &sender) OVERRIDE;
+
+public:
+    Sender(proton::sender s, senders& ss) :
+        sender_(s), senders_(ss), work_queue_(s.work_queue()), queue_(0), pending_credit_(0)
+    {}
+
+    bool add(proton::work f) {
+        return work_queue_.add(f);
+    }
+
+
+    void boundQueue(Queue* q, std::string qn);
+    void sendMsg(proton::message m) {
+        DOUT(std::cerr << "Sender:   " << this << " sending\n";);
+        sender_.send(m);
+    }
+    void unsubscribed() {
+        DOUT(std::cerr << "Sender:   " << this << " deleting\n";);
+        delete this;
+    }
+};
+
+// Queue - round robin subscriptions
+class Queue {
+    proton::work_queue work_queue_;
+    const std::string name_;
+    std::deque<proton::message> messages_;
+    typedef std::map<Sender*, int> subscriptions; // With credit
+    subscriptions subscriptions_;
+    subscriptions::iterator current_;
+
+    void tryToSend() {
+        DOUT(std::cerr << "Queue:    " << this << " tryToSend: " << subscriptions_.size(););
+        // Starting at current_, send messages to subscriptions with credit:
+        // After each send try to find another subscription; Wrap around;
+        // Finish when we run out of messages or credit.
+        size_t outOfCredit = 0;
+        while (!messages_.empty() && outOfCredit<subscriptions_.size()) {
+            // If we got the end (or haven't started yet) start at the beginning
+            if (current_==subscriptions_.end()) {
+                current_=subscriptions_.begin();
+            }
+            // If we have credit send the message
+            DOUT(std::cerr << "(" << current_->second << ") ";);
+            if (current_->second>0) {
+                DOUT(std::cerr << current_->first << " ";);
+                current_->first->add(make_work(&Sender::sendMsg, current_->first, messages_.front()));
+                messages_.pop_front();
+                --current_->second;
+                ++current_;
+            } else {
+                ++outOfCredit;
+            }
+        }
+        DOUT(std::cerr << "\n";);
+    }
+
+public:
+    Queue(proton::container& c, const std::string& n) :
+        work_queue_(c), name_(n), current_(subscriptions_.end())
+    {}
+
+    bool add(proton::work f) {
+        return work_queue_.add(f);
+    }
+
+    void queueMsg(proton::message m) {
+        DOUT(std::cerr << "Queue:    " << this << "(" << name_ << ") queueMsg\n";);
+        messages_.push_back(m);
+        tryToSend();
+    }
+    void flow(Sender* s, int c) {
+        DOUT(std::cerr << "Queue:    " << this << "(" << name_ << ") flow: " << c << " to " << s << "\n";);
+        subscriptions_[s] = c;
+        tryToSend();
+    }
+    void subscribe(Sender* s) {
+        DOUT(std::cerr << "Queue:    " << this << "(" << name_ << ") subscribe Sender: " << s << "\n";);
+        subscriptions_[s] = 0;
+    }
+    void unsubscribe(Sender* s) {
+        DOUT(std::cerr << "Queue:    " << this << "(" << name_ << ") unsubscribe Sender: " << s << "\n";);
+        // If we're about to erase the current subscription move on
+        if (current_ != subscriptions_.end() && current_->first==s) ++current_;
+        subscriptions_.erase(s);
+        s->add(make_work(&Sender::unsubscribed, s));
+    }
+};
+
+// We have credit to send a message.
+void Sender::on_sendable(proton::sender &sender) {
+    if (queue_) {
+        queue_->add(make_work(&Queue::flow, queue_, this, sender.credit()));
+    } else {
+        pending_credit_ = sender.credit();
+    }
+}
+
+void Sender::on_sender_close(proton::sender &sender) {
+    if (queue_) {
+        queue_->add(make_work(&Queue::unsubscribe, queue_, this));
+    } else {
+        // TODO: Is it possible to be closed before we get the queue allocated?
+        // If so, we should have a way to mark the sender deleted, so we can delete
+        // on queue binding
+    }
+    senders_.erase(sender);
+}
+
+void Sender::boundQueue(Queue* q, std::string qn) {
+    DOUT(std::cerr << "Sender:   " << this << " bound to Queue: " << q <<"(" << qn << ")\n";);
+    queue_ = q;
+    queue_name_ = qn;
+
+    q->add(make_work(&Queue::subscribe, q, this));
+    sender_.open(proton::sender_options()
+        .source((proton::source_options().address(queue_name_)))
+        .handler(*this));
+    if (pending_credit_>0) {
+        queue_->add(make_work(&Queue::flow, queue_, this, pending_credit_));
+    }
+    std::cout << "sending from " << queue_name_ << std::endl;
+}
+
+class Receiver : public proton::messaging_handler {
+    friend class connection_handler;
+
+    proton::receiver receiver_;
+    proton::work_queue& work_queue_;
+    Queue* queue_;
+    std::deque<proton::message> messages_;
+
+    // A message is received.
+    void on_message(proton::delivery &, proton::message &m) OVERRIDE {
+        messages_.push_back(m);
+
+        if (queue_) {
+            queueMsgs();
+        }
+    }
+
+    void queueMsgs() {
+        DOUT(std::cerr << "Receiver: " << this << " queueing " << messages_.size() << " msgs to: " << queue_ << "\n";);
+        while (!messages_.empty()) {
+            queue_->add(make_work(&Queue::queueMsg, queue_, messages_.front()));
+            messages_.pop_front();
+        }
+    }
+
+public:
+    Receiver(proton::receiver r) :
+        receiver_(r), work_queue_(r.work_queue()), queue_(0)
+    {}
+
+    bool add(proton::work f) {
+        return work_queue_.add(f);
+    }
+
+    void boundQueue(Queue* q, std::string qn) {
+        DOUT(std::cerr << "Receiver: " << this << " bound to Queue: " << q << "(" << qn << ")\n";);
+        queue_ = q;
+        receiver_.open(proton::receiver_options()
+            .source((proton::source_options().address(qn)))
+            .handler(*this));
+        std::cout << "receiving to " << qn << std::endl;
+
+        queueMsgs();
+    }
+};
+
+class QueueManager {
+    proton::container& container_;
+    proton::work_queue work_queue_;
+    typedef std::map<std::string, Queue*> queues;
+    queues queues_;
+    int next_id_; // Use to generate unique queue IDs.
+
+public:
+    QueueManager(proton::container& c) :
+        container_(c), work_queue_(c), next_id_(0)
+    {}
+
+    bool add(proton::work f) {
+        return work_queue_.add(f);
+    }
+
+    template <class T>
+    void findQueue(T& connection, std::string& qn) {
+        if (qn.empty()) {
+            // Dynamic queue creation
+            std::ostringstream os;
+            os << "_dynamic_" << next_id_++;
+            qn = os.str();
+        }
+        Queue* q = 0;
+        queues::iterator i = queues_.find(qn);
+        if (i==queues_.end()) {
+            q = new Queue(container_, qn);
+            queues_[qn] = q;
+        } else {
+            q = i->second;
+        }
+        connection.add(make_work(&T::boundQueue, &connection, q, qn));
+    }
+
+    void findQueueSender(Sender* s, std::string qn) {
+        findQueue(*s, qn);
+    }
+
+    void findQueueReceiver(Receiver* r, std::string qn) {
+        findQueue(*r, qn);
+    }
+};
+
+class connection_handler : public proton::messaging_handler {
+    QueueManager& queue_manager_;
+    senders senders_;
+
+public:
+    connection_handler(QueueManager& qm) :
+        queue_manager_(qm)
+    {}
+
+    void on_connection_open(proton::connection& c) OVERRIDE {
+        c.open();            // Accept the connection
+    }
+
+    // A sender sends messages from a queue to a subscriber.
+    void on_sender_open(proton::sender &sender) OVERRIDE {
+        std::string qn = sender.source().dynamic() ? "" : sender.source().address();
+        Sender* s = new Sender(sender, senders_);
+        senders_[sender] = s;
+        queue_manager_.add(make_work(&QueueManager::findQueueSender, &queue_manager_, s, qn));
+    }
+
+    // A receiver receives messages from a publisher to a queue.
+    void on_receiver_open(proton::receiver &receiver) OVERRIDE {
+        std::string qname = receiver.target().address();
+        if (qname == "shutdown") {
+            std::cout << "broker shutting down" << std::endl;
+            // Sending to the special "shutdown" queue stops the broker.
+            receiver.connection().container().stop(
+                proton::error_condition("shutdown", "stop broker"));
+        } else {
+            if (qname.empty()) {
+                DOUT(std::cerr << "ODD - trying to attach to a empty address\n";);
+            }
+            Receiver* r = new Receiver(receiver);
+            queue_manager_.add(make_work(&QueueManager::findQueueReceiver, &queue_manager_, r, qname));
+        }
+    }
+
+    void on_session_close(proton::session &session) OVERRIDE {
+        // Unsubscribe all senders that belong to session.
+        for (proton::sender_iterator i = session.senders().begin(); i != session.senders().end(); ++i) {
+            senders::iterator j = senders_.find(*i);
+            if (j == senders_.end()) continue;
+            Sender* s = j->second;
+            if (s->queue_) {
+                s->queue_->add(make_work(&Queue::unsubscribe, s->queue_, s));
+            }
+            senders_.erase(j);
+        }
+    }
+
+    void on_error(const proton::error_condition& e) OVERRIDE {
+        std::cerr << "error: " << e.what() << std::endl;
+    }
+
+    // The container calls on_transport_close() last.
+    void on_transport_close(proton::transport& t) OVERRIDE {
+        // Unsubscribe all senders.
+        for (proton::sender_iterator i = t.connection().senders().begin(); i != t.connection().senders().end(); ++i) {
+            senders::iterator j = senders_.find(*i);
+            if (j == senders_.end()) continue;
+            Sender* s = j->second;
+            if (s->queue_) {
+                s->queue_->add(make_work(&Queue::unsubscribe, s->queue_, s));
+            }
+        }
+        delete this;            // All done.
+    }
+};
+
+class broker {
+  public:
+    broker(const std::string addr) :
+        container_("broker"), queues_(container_), listener_(queues_)
+    {
+        container_.listen(addr, listener_);
+    }
+
+    void run() {
+#if PN_CPP_SUPPORTS_THREADS
+        int threads = hardware_concurrency();
+        std::cout << "starting " << threads << " listening threads\n";
+        std::cout.flush();
+        container_.run(threads);
+#else
+        std::cout << "no thread support - starting 1 listening thread\n";
+        std::cout.flush();
+        container_.run();
+#endif
+    }
+
+  private:
+    struct listener : public proton::listen_handler {
+        listener(QueueManager& c) : queues_(c) {}
+
+        proton::connection_options on_accept(proton::listener&) OVERRIDE{
+            return proton::connection_options().handler(*(new connection_handler(queues_)));
+        }
+
+        void on_open(proton::listener& l) OVERRIDE {
+            std::cout << "broker listening on " << l.port() << std::endl;
+        }
+
+        void on_error(proton::listener&, const std::string& s) OVERRIDE {
+            std::cerr << "listen error: " << s << std::endl;
+            throw std::runtime_error(s);
+        }
+        QueueManager& queues_;
+    };
+
+    proton::container container_;
+    QueueManager queues_;
+    listener listener_;
+};
+
+int main(int argc, char **argv) {
+    // Command line options
+    std::string address("0.0.0.0");
+    example::options opts(argc, argv);
+
+    opts.add_flag(verbose, 'v', "verbose", "verbose (debugging) output");
+    opts.add_value(address, 'a', "address", "listen on URL", "URL");
+
+    try {
+        verbose = false;
+        opts.parse();
+        broker(address).run();
+        return 0;
+    } catch (const example::bad_option& e) {
+        std::cout << opts << std::endl << e.what() << std::endl;
+    } catch (const std::exception& e) {
+        std::cerr << "broker shutdown: " << e.what() << std::endl;
+    }
+    return 1;
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/examples/client.cpp
----------------------------------------------------------------------
diff --git a/cpp/examples/client.cpp b/cpp/examples/client.cpp
new file mode 100644
index 0000000..a9d5dbe
--- /dev/null
+++ b/cpp/examples/client.cpp
@@ -0,0 +1,109 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "options.hpp"
+#include <proton/connection.hpp>
+#include <proton/container.hpp>
+#include <proton/delivery.hpp>
+#include <proton/message.hpp>
+#include <proton/messaging_handler.hpp>
+#include <proton/receiver_options.hpp>
+#include <proton/source_options.hpp>
+#include <proton/tracker.hpp>
+
+#include <iostream>
+#include <vector>
+
+#include "fake_cpp11.hpp"
+
+using proton::receiver_options;
+using proton::source_options;
+
+class client : public proton::messaging_handler {
+  private:
+    std::string url;
+    std::vector<std::string> requests;
+    proton::sender sender;
+    proton::receiver receiver;
+
+  public:
+    client(const std::string &u, const std::vector<std::string>& r) : url(u), requests(r) {}
+
+    void on_container_start(proton::container &c) OVERRIDE {
+        sender = c.open_sender(url);
+        // Create a receiver requesting a dynamically created queue
+        // for the message source.
+        receiver_options opts = receiver_options().source(source_options().dynamic(true));
+        receiver = sender.connection().open_receiver("", opts);
+    }
+
+    void send_request() {
+        proton::message req;
+        req.body(requests.front());
+        req.reply_to(receiver.source().address());
+        sender.send(req);
+    }
+
+    void on_receiver_open(proton::receiver &) OVERRIDE {
+        send_request();
+    }
+
+    void on_message(proton::delivery &d, proton::message &response) OVERRIDE {
+        if (requests.empty()) return; // Spurious extra message!
+
+        std::cout << requests.front() << " => " << response.body() << std::endl;
+        requests.erase(requests.begin());
+
+        if (!requests.empty()) {
+            send_request();
+        } else {
+            d.connection().close();
+        }
+    }
+};
+
+int main(int argc, char **argv) {
+    std::string url("127.0.0.1:5672/examples");
+    example::options opts(argc, argv);
+
+    opts.add_value(url, 'a', "address", "connect and send to URL", "URL");
+
+    try {
+        opts.parse();
+
+        std::vector<std::string> requests;
+        requests.push_back("Twas brillig, and the slithy toves");
+        requests.push_back("Did gire and gymble in the wabe.");
+        requests.push_back("All mimsy were the borogroves,");
+        requests.push_back("And the mome raths outgrabe.");
+
+        client c(url, requests);
+        proton::container(c).run();
+
+        return 0;
+    } catch (const example::bad_option& e) {
+        std::cout << opts << std::endl << e.what() << std::endl;
+    } catch (const std::exception& e) {
+        std::cerr << e.what() << std::endl;
+    }
+
+    return 1;
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/examples/colour_send.cpp
----------------------------------------------------------------------
diff --git a/cpp/examples/colour_send.cpp b/cpp/examples/colour_send.cpp
new file mode 100644
index 0000000..107b600
--- /dev/null
+++ b/cpp/examples/colour_send.cpp
@@ -0,0 +1,116 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "options.hpp"
+
+#include <proton/connection.hpp>
+#include <proton/connection_options.hpp>
+#include <proton/container.hpp>
+#include <proton/message.hpp>
+#include <proton/message_id.hpp>
+#include <proton/messaging_handler.hpp>
+#include <proton/tracker.hpp>
+#include <proton/types.hpp>
+
+#include <iostream>
+#include <sstream>
+#include <map>
+
+#include "fake_cpp11.hpp"
+
+class colour_send : public proton::messaging_handler {
+  private:
+    std::string url;
+    std::string user;
+    std::string password;
+    proton::sender sender;
+    int sent;
+    int confirmed;
+    int total;
+
+  public:
+    colour_send(const std::string &s, const std::string &u, const std::string &p, int c) :
+        url(s), user(u), password(p), sent(0), confirmed(0), total(c) {}
+
+    void on_container_start(proton::container &c) OVERRIDE {
+        proton::connection_options co;
+        if (!user.empty()) co.user(user);
+        if (!password.empty()) co.password(password);
+        sender = c.open_sender(url, co);
+    }
+
+    void on_sendable(proton::sender &s) OVERRIDE {
+        while (s.credit() && sent < total) {
+            proton::message msg;
+
+            std::string colour = sent % 2 ? "red" : "green";
+            msg.properties().put("colour", colour);
+            msg.id(sent + 1);
+            std::stringstream body;
+            body << colour << " " << (sent +1);
+            msg.body(body.str());
+
+            s.send(msg);
+            sent++;
+        }
+    }
+
+    void on_tracker_accept(proton::tracker &t) OVERRIDE {
+        confirmed++;
+
+        if (confirmed == total) {
+            std::cout << "all messages confirmed" << std::endl;
+            t.connection().close();
+        }
+    }
+
+    void on_transport_close(proton::transport &) OVERRIDE {
+        sent = confirmed;
+    }
+};
+
+int main(int argc, char **argv) {
+    std::string address("127.0.0.1:5672/examples");
+    std::string user;
+    std::string password;
+    int message_count = 100;
+    example::options opts(argc, argv);
+
+    opts.add_value(address, 'a', "address", "connect and send to URL", "URL");
+    opts.add_value(message_count, 'm', "messages", "send COUNT messages", "COUNT");
+    opts.add_value(user, 'u', "user", "authenticate as USER", "USER");
+    opts.add_value(password, 'p', "password", "authenticate with PASSWORD", "PASSWORD");
+
+    try {
+        opts.parse();
+
+        colour_send send(address, user, password, message_count);
+        proton::container(send).run();
+
+        return 0;
+    } catch (const example::bad_option& e) {
+        std::cout << opts << std::endl << e.what() << std::endl;
+    } catch (const std::exception& e) {
+        std::cerr << e.what() << std::endl;
+    }
+
+    return 1;
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/examples/connection_options.cpp
----------------------------------------------------------------------
diff --git a/cpp/examples/connection_options.cpp b/cpp/examples/connection_options.cpp
new file mode 100644
index 0000000..df26100
--- /dev/null
+++ b/cpp/examples/connection_options.cpp
@@ -0,0 +1,76 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include <proton/connection.hpp>
+#include <proton/connection_options.hpp>
+#include <proton/container.hpp>
+#include <proton/messaging_handler.hpp>
+#include <proton/transport.hpp>
+
+#include <iostream>
+
+using proton::connection_options;
+
+#include "fake_cpp11.hpp"
+
+class handler_2 : public proton::messaging_handler {
+    void on_connection_open(proton::connection &c) OVERRIDE {
+        std::cout << "connection events going to handler_2" << std::endl;
+        std::cout << "connection max_frame_size: " << c.max_frame_size() <<
+            ", idle timeout: " << c.idle_timeout() << std::endl;
+        c.close();
+    }
+};
+
+class main_handler : public proton::messaging_handler {
+  private:
+    std::string url;
+    handler_2 conn_handler;
+
+  public:
+    main_handler(const std::string& u) : url(u) {}
+
+    void on_container_start(proton::container &c) OVERRIDE {
+        // Connection options for this connection.  Merged with and overriding the container's
+        // client_connection_options() settings.
+        c.connect(url, connection_options().handler(conn_handler).max_frame_size(2468));
+    }
+
+    void on_connection_open(proton::connection &c) OVERRIDE {
+        std::cout << "unexpected connection event on main handler" << std::endl;
+        c.close();
+    }
+};
+
+int main(int argc, char **argv) {
+    try {
+        std::string url = argc > 1 ? argv[1] : "127.0.0.1:5672/examples";
+        main_handler handler(url);
+        proton::container container(handler);
+        // Global connection options for future connections on container.
+        container.client_connection_options(connection_options().max_frame_size(12345).idle_timeout(proton::duration(15000)));
+        container.run();
+        return 0;
+    } catch (const std::exception& e) {
+        std::cerr << e.what() << std::endl;
+    }
+    return 1;
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/examples/direct_recv.cpp
----------------------------------------------------------------------
diff --git a/cpp/examples/direct_recv.cpp b/cpp/examples/direct_recv.cpp
new file mode 100644
index 0000000..93ba06f
--- /dev/null
+++ b/cpp/examples/direct_recv.cpp
@@ -0,0 +1,101 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "options.hpp"
+
+#include <proton/connection.hpp>
+#include <proton/container.hpp>
+#include <proton/delivery.hpp>
+#include <proton/message.hpp>
+#include <proton/message_id.hpp>
+#include <proton/messaging_handler.hpp>
+#include <proton/link.hpp>
+#include <proton/listen_handler.hpp>
+#include <proton/listener.hpp>
+#include <proton/value.hpp>
+
+#include <iostream>
+#include <map>
+
+#include "fake_cpp11.hpp"
+
+class direct_recv : public proton::messaging_handler {
+  private:
+    class listener_ready_handler : public proton::listen_handler {
+        void on_open(proton::listener& l) OVERRIDE {
+            std::cout << "listening on " << l.port() << std::endl;
+        }
+    };
+
+    std::string url;
+    proton::listener listener;
+    listener_ready_handler listen_handler;
+    int expected;
+    int received;
+
+  public:
+    direct_recv(const std::string &s, int c) : url(s), expected(c), received(0) {}
+
+    void on_container_start(proton::container &c) OVERRIDE {
+        listener = c.listen(url, listen_handler);
+    }
+
+    void on_message(proton::delivery &d, proton::message &msg) OVERRIDE {
+        if (proton::coerce<int>(msg.id()) < received) {
+            return; // Ignore duplicate
+        }
+
+        if (expected == 0 || received < expected) {
+            std::cout << msg.body() << std::endl;
+            received++;
+        }
+
+        if (received == expected) {
+            d.receiver().close();
+            d.connection().close();
+            listener.stop();
+        }
+    }
+};
+
+int main(int argc, char **argv) {
+    std::string address("127.0.0.1:5672/examples");
+    int message_count = 100;
+    example::options opts(argc, argv);
+
+    opts.add_value(address, 'a', "address", "listen and receive on URL", "URL");
+    opts.add_value(message_count, 'm', "messages", "receive COUNT messages", "COUNT");
+
+    try {
+        opts.parse();
+
+        direct_recv recv(address, message_count);
+        proton::container(recv).run();
+
+        return 0;
+    } catch (const example::bad_option& e) {
+        std::cout << opts << std::endl << e.what() << std::endl;
+    } catch (const std::exception& e) {
+        std::cerr << e.what() << std::endl;
+    }
+
+    return 1;
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/examples/direct_send.cpp
----------------------------------------------------------------------
diff --git a/cpp/examples/direct_send.cpp b/cpp/examples/direct_send.cpp
new file mode 100644
index 0000000..79be34c
--- /dev/null
+++ b/cpp/examples/direct_send.cpp
@@ -0,0 +1,112 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "options.hpp"
+
+#include <proton/connection.hpp>
+#include <proton/container.hpp>
+#include <proton/listen_handler.hpp>
+#include <proton/listener.hpp>
+#include <proton/message.hpp>
+#include <proton/message_id.hpp>
+#include <proton/messaging_handler.hpp>
+#include <proton/value.hpp>
+#include <proton/tracker.hpp>
+#include <proton/types.hpp>
+
+#include <iostream>
+#include <map>
+
+#include "fake_cpp11.hpp"
+
+class simple_send : public proton::messaging_handler {
+  private:
+    class listener_ready_handler : public proton::listen_handler {
+        void on_open(proton::listener& l) OVERRIDE {
+            std::cout << "listening on " << l.port() << std::endl;
+        }
+    };
+
+    std::string url;
+    proton::listener listener;
+    listener_ready_handler listen_handler;
+    int sent;
+    int confirmed;
+    int total;
+
+  public:
+    simple_send(const std::string &s, int c) : url(s), sent(0), confirmed(0), total(c) {}
+
+    void on_container_start(proton::container &c) OVERRIDE {
+        listener = c.listen(url, listen_handler);
+    }
+
+    void on_sendable(proton::sender &sender) OVERRIDE {
+        while (sender.credit() && sent < total) {
+            proton::message msg;
+            std::map<std::string, int> m;
+            m["sequence"] = sent + 1;
+
+            msg.id(sent + 1);
+            msg.body(m);
+
+            sender.send(msg);
+            sent++;
+        }
+    }
+
+    void on_tracker_accept(proton::tracker &t) OVERRIDE {
+        confirmed++;
+
+        if (confirmed == total) {
+            std::cout << "all messages confirmed" << std::endl;
+            t.connection().close();
+            listener.stop();
+        }
+    }
+
+    void on_transport_close(proton::transport &) OVERRIDE {
+        sent = confirmed;
+    }
+};
+
+int main(int argc, char **argv) {
+    std::string address("127.0.0.1:5672/examples");
+    int message_count = 100;
+    example::options opts(argc, argv);
+
+    opts.add_value(address, 'a', "address", "listen and send on URL", "URL");
+    opts.add_value(message_count, 'm', "messages", "send COUNT messages", "COUNT");
+
+    try {
+        opts.parse();
+
+        simple_send send(address, message_count);
+        proton::container(send).run();
+        return 0;
+    } catch (const example::bad_option& e) {
+        std::cout << opts << std::endl << e.what() << std::endl;
+    } catch (const std::exception& e) {
+        std::cerr << e.what() << std::endl;
+    }
+
+    return 1;
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/examples/encode_decode.cpp
----------------------------------------------------------------------
diff --git a/cpp/examples/encode_decode.cpp b/cpp/examples/encode_decode.cpp
new file mode 100644
index 0000000..cd6169a
--- /dev/null
+++ b/cpp/examples/encode_decode.cpp
@@ -0,0 +1,251 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <proton/types.hpp>
+#include <proton/codec/encoder.hpp>
+#include <proton/codec/decoder.hpp>
+
+#include <algorithm>
+#include <iostream>
+#include <iterator>
+#include <sstream>
+
+// Examples of how to use the encoder and decoder to create and examine AMQP values.
+//
+
+// Print is defined at the end as an example of how to query and extract complex
+// values from a decoder in terms of their simple components.
+void print(proton::value&);
+
+// Some helper templates to print map and std::vector results.
+namespace std {
+template<class T, class U> ostream& operator<<(ostream& o, const std::pair<T,U>& p) {
+    return o << p.first << ":" << p.second;
+}
+template<class T> ostream& operator<<(ostream& o, const std::vector<T>& v) {
+    o << "[ ";
+    ostream_iterator<T> oi(o, " ");
+    copy(v.begin(), v.end(), oi);
+    return o << "]";
+}
+template<class T> ostream& operator<<(ostream& o, const std::list<T>& v) {
+    o << "[ ";
+    ostream_iterator<T> oi(o, " ");
+    copy(v.begin(), v.end(), oi);
+    return o << "]";
+}
+template<class K, class T> ostream& operator<<(ostream& o, const map<K, T>& m) {
+    o << "{ ";
+    ostream_iterator<std::pair<K,T> > oi(o, " ");
+    copy(m.begin(), m.end(), oi);
+    return o << "}";
+}
+}
+
+// Insert/extract native C++ containers with uniform type values.
+static void uniform_containers() {
+    std::cout << std::endl << "== Array, list and map of uniform type." << std::endl;
+    proton::value v;
+
+    std::vector<int> a;
+    a.push_back(1);
+    a.push_back(2);
+    a.push_back(3);
+    // By default a C++ container is encoded as an AMQP array.
+    v = a;
+    print(v);
+    std::list<int> a1;
+    proton::get(v, a1);
+    std::cout << a1 << std::endl;
+
+    // You can specify that a container should be encoded as an AMQP list instead.
+    v = proton::codec::encoder::list(a1);
+    print(v);
+    std::cout << proton::get<std::vector<int> >(v) << std::endl;
+
+    // C++ map types (types with key_type, mapped_type) convert to an AMQP map by default.
+    std::map<std::string, int> m;
+    m["one"] = 1;
+    m["two"] = 2;
+    v = m;
+    print(v);
+    std::cout << proton::get<std::map<std::string, int> >(v) << std::endl;
+
+    // A sequence of pairs encodes as an AMQP MAP, which lets you control the encoded order.
+    std::vector<std::pair<std::string, int> > pairs;
+    pairs.push_back(std::make_pair("z", 3));
+    pairs.push_back(std::make_pair("a", 4));
+    v = pairs;
+    print(v);
+
+    // You can also decode an AMQP map as a sequence of pairs to preserve encode order.
+    std::vector<std::pair<std::string, int> > pairs2;
+    proton::codec::decoder d(v);
+    d >> pairs2;
+    std::cout << pairs2 << std::endl;
+
+    // A vector of proton::value is normally encoded as a mixed-type AMQP LIST,
+    // but you can encoded it as an array provided all the values match the array type.
+    std::vector<proton::value> vv;
+    vv.push_back(proton::value("a"));
+    vv.push_back(proton::value("b"));
+    vv.push_back(proton::value("c"));
+    v = vv;
+    print(v);
+}
+
+// Containers with mixed types use value to represent arbitrary AMQP types.
+static void mixed_containers() {
+    std::cout << std::endl << "== List and map of mixed type values." << std::endl;
+    proton::value v;
+
+    std::vector<proton::value> l;
+    l.push_back(proton::value(42));
+    l.push_back(proton::value(std::string("foo")));
+    // By default, a sequence of proton::value is treated as an AMQP list.
+    v = l;
+    print(v);
+    std::vector<proton::value> l2 = proton::get<std::vector<proton::value> >(v);
+    std::cout << l2 << std::endl;
+
+    std::map<proton::value, proton::value> m;
+    m[proton::value("five")] = proton::value(5);
+    m[proton::value(4)] = proton::value("four"); v = m;
+    print(v);
+    typedef std::map<proton::value, proton::value> value_map;
+    value_map m2(proton::get<value_map>(v));
+    std::cout << m2 << std::endl;
+}
+
+// Insert using stream operators (see print_next for example of extracting with stream ops.)
+static void insert_stream_operators() {
+    std::cout << std::endl << "== Insert with stream operators." << std::endl;
+    proton::value v;
+
+    // Create an array of INT with values [1, 2, 3]
+    proton::codec::encoder e(v);
+    e << proton::codec::start::array(proton::INT)
+      << int32_t(1) << int32_t(2) << int32_t(3)
+      << proton::codec::finish();
+    print(v);
+
+    // Create a mixed-type list of the values [42, 0, "x"].
+    proton::codec::encoder e2(v);
+    e2 << proton::codec::start::list()
+       << int32_t(42) << false << proton::symbol("x")
+       << proton::codec::finish();
+    print(v);
+
+    // Create a map { "k1":42, "k2": false }
+    proton::codec::encoder e3(v);
+    e3 << proton::codec::start::map()
+       << "k1" << int32_t(42)
+       << proton::symbol("k2") << false
+       << proton::codec::finish();
+    print(v);
+}
+
+int main(int, char**) {
+    try {
+        uniform_containers();
+        mixed_containers();
+        insert_stream_operators();
+        return 0;
+    } catch (const std::exception& e) {
+        std::cerr << std::endl << "error: " << e.what() << std::endl;
+    }
+    return 1;
+}
+
+// print_next prints the next value from values by recursively descending into complex values.
+//
+// NOTE this is for example purposes only: There is a built in ostream operator<< for values.
+//
+//
+static void print_next(proton::codec::decoder& d) {
+    proton::type_id type = d.next_type();
+    proton::codec::start s;
+    switch (type) {
+      case proton::ARRAY: {
+          d >> s;
+          std::cout << "array<" << s.element;
+          if (s.is_described) {
+              std::cout  << ", descriptor=";
+              print_next(d);
+          }
+          std::cout << ">[";
+          for (size_t i = 0; i < s.size; ++i) {
+              if (i) std::cout << ", ";
+              print_next(d);
+          }
+          std::cout << "]";
+          d >> proton::codec::finish();
+          break;
+      }
+      case proton::LIST: {
+          d >> s;
+          std::cout << "list[";
+          for (size_t i = 0; i < s.size; ++i) {
+              if (i) std::cout << ", ";
+              print_next(d);
+          }
+          std::cout << "]";
+          d >> proton::codec::finish();
+          break;
+      }
+      case proton::MAP: {
+          d >> s;
+          std::cout << "map{";
+          for (size_t i = 0; i < s.size/2; ++i) {
+              if (i) std::cout << ", ";
+              print_next(d);
+              std::cout << ":";        // key:value
+              print_next(d);
+          }
+          std::cout << "}";
+          d >> proton::codec::finish();
+          break;
+      }
+      case proton::DESCRIBED: {
+          d >> s;
+          std::cout << "described(";
+          print_next(d);      // Descriptor
+          print_next(d);      // value
+          d >> proton::codec::finish();
+          break;
+      }
+      default:
+        // A simple type. We could continue the switch for all AMQP types but
+        // we will take a short cut and extract to another value and print that.
+        proton::value v2;
+        d >> v2;
+        std::cout << type << "(" << v2 << ")";
+    }
+}
+
+// Print a value, for example purposes. Normal code can use operator<<
+void print(proton::value& v) {
+    proton::codec::decoder d(v);
+    d.rewind();
+    while (d.more()) {
+        print_next(d);
+        if (d.more()) std::cout << ", ";
+    }
+    std::cout << std::endl;
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/examples/example_test.py
----------------------------------------------------------------------
diff --git a/cpp/examples/example_test.py b/cpp/examples/example_test.py
new file mode 100644
index 0000000..b9f0621
--- /dev/null
+++ b/cpp/examples/example_test.py
@@ -0,0 +1,266 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License
+#
+
+# This is a test script to run the examples and verify that they behave as expected.
+
+import unittest
+import os, sys, socket, time, re, inspect
+from proctest import *
+from random import randrange
+from subprocess import Popen, PIPE, STDOUT, call
+from copy import copy
+import platform
+from os.path import dirname as dirname
+from threading import Thread, Event
+from string import Template
+
+createdSASLDb = False
+
+def _cyrusSetup(conf_dir):
+  """Write out simple SASL config.tests
+  """
+  saslpasswd = os.getenv('SASLPASSWD')
+  if saslpasswd:
+    t = Template("""sasldb_path: ${db}
+mech_list: EXTERNAL DIGEST-MD5 SCRAM-SHA-1 CRAM-MD5 PLAIN ANONYMOUS
+""")
+    abs_conf_dir = os.path.abspath(conf_dir)
+    call(args=['rm','-rf',abs_conf_dir])
+    os.mkdir(abs_conf_dir)
+    db = os.path.join(abs_conf_dir,'proton.sasldb')
+    conf = os.path.join(abs_conf_dir,'proton-server.conf')
+    f = open(conf, 'w')
+    f.write(t.substitute(db=db))
+    f.close()
+
+    cmd_template = Template("echo password | ${saslpasswd} -c -p -f ${db} -u proton user")
+    cmd = cmd_template.substitute(db=db, saslpasswd=saslpasswd)
+    call(args=cmd, shell=True)
+
+    os.environ['PN_SASL_CONFIG_PATH'] = abs_conf_dir
+    global createdSASLDb
+    createdSASLDb = True
+
+# Globally initialize Cyrus SASL configuration
+_cyrusSetup('sasl-conf')
+
+def wait_listening(proc):
+    m = proc.wait_re(".*listening on ([0-9]+)$")
+    return m.group(1), m.group(0)+"\n" # Return (port, line)
+
+class BrokerTestCase(ProcTestCase):
+    """
+    ExampleTest that starts a broker in setUpClass and kills it in tearDownClass.
+    Subclasses must set `broker_exe` class variable with the name of the broker executable.
+    """
+    @classmethod
+    def setUpClass(cls):
+        cls.broker = None       # In case Proc throws, create the attribute.
+        cls.broker = Proc([cls.broker_exe, "-a", "//:0"])
+        cls.port, line = wait_listening(cls.broker)
+        cls.addr = "//:%s/example" % cls.port
+
+    @classmethod
+    def tearDownClass(cls):
+        if cls.broker:
+            cls.broker.kill()
+
+    def tearDown(self):
+        b = type(self).broker
+        if b and b.poll() !=  None: # Broker crashed
+            type(self).setUpClass() # Start another for the next test.
+            raise ProcError(b, "broker crash")
+        super(BrokerTestCase, self).tearDown()
+
+
+CLIENT_EXPECT="""Twas brillig, and the slithy toves => TWAS BRILLIG, AND THE SLITHY TOVES
+Did gire and gymble in the wabe. => DID GIRE AND GYMBLE IN THE WABE.
+All mimsy were the borogroves, => ALL MIMSY WERE THE BOROGROVES,
+And the mome raths outgrabe. => AND THE MOME RATHS OUTGRABE.
+"""
+
+def recv_expect():
+    return "".join(['{"sequence"=%s}\n' % (i+1) for i in range(100)])
+
+class ContainerExampleTest(BrokerTestCase):
+    """Run the container examples, verify they behave as expected."""
+
+    broker_exe = "broker"
+
+    def test_helloworld(self):
+        self.assertMultiLineEqual('Hello World!\n', self.proc(["helloworld", self.addr]).wait_exit())
+
+    def test_simple_send_recv(self):
+        self.assertMultiLineEqual("all messages confirmed\n", self.proc(["simple_send", "-a", self.addr]).wait_exit())
+        self.assertMultiLineEqual(recv_expect(), self.proc(["simple_recv", "-a", self.addr]).wait_exit())
+
+    def test_simple_recv_send(self):
+        # Start receiver first, then run sender"""
+        recv = self.proc(["simple_recv", "-a", self.addr])
+        self.assertMultiLineEqual("all messages confirmed\n", self.proc(["simple_send", "-a", self.addr]).wait_exit())
+        self.assertMultiLineEqual(recv_expect(), recv.wait_exit())
+
+
+    def test_simple_send_direct_recv(self):
+        recv = self.proc(["direct_recv", "-a", "//:0"])
+        port, line = wait_listening(recv)
+        addr = "//:%s/examples" % port
+        self.assertMultiLineEqual("all messages confirmed\n",
+                                  self.proc(["simple_send", "-a", addr]).wait_exit())
+        self.assertMultiLineEqual(line+recv_expect(), recv.wait_exit())
+
+    def test_simple_recv_direct_send(self):
+        send = self.proc(["direct_send", "-a", "//:0"])
+        port, line = wait_listening(send)
+        addr = "//:%s/examples" % port
+        self.assertMultiLineEqual(recv_expect(), self.proc(["simple_recv", "-a", addr]).wait_exit())
+        self.assertMultiLineEqual(line+"all messages confirmed\n", send.wait_exit())
+
+    def test_request_response(self):
+        server = self.proc(["server", self.addr, "example"]) # self.addr has the connection info
+        server.wait_re("connected")
+        self.assertMultiLineEqual(CLIENT_EXPECT,
+                         self.proc(["client", "-a", self.addr]).wait_exit())
+
+    def test_request_response_direct(self):
+        server = self.proc(["server_direct", "-a", "//:0"])
+        port, line = wait_listening(server);
+        addr = "//:%s/examples" % port
+        self.assertMultiLineEqual(CLIENT_EXPECT, self.proc(["client", "-a", addr]).wait_exit())
+
+    def test_flow_control(self):
+        want="""success: Example 1: simple credit
+success: Example 2: basic drain
+success: Example 3: drain without credit
+success: Example 4: high/low watermark
+"""
+        self.assertMultiLineEqual(want, self.proc(["flow_control", "--quiet"]).wait_exit())
+
+    def test_encode_decode(self):
+        want="""
+== Array, list and map of uniform type.
+array<int>[int(1), int(2), int(3)]
+[ 1 2 3 ]
+list[int(1), int(2), int(3)]
+[ 1 2 3 ]
+map{string(one):int(1), string(two):int(2)}
+{ one:1 two:2 }
+map{string(z):int(3), string(a):int(4)}
+[ z:3 a:4 ]
+list[string(a), string(b), string(c)]
+
+== List and map of mixed type values.
+list[int(42), string(foo)]
+[ 42 foo ]
+map{int(4):string(four), string(five):int(5)}
+{ 4:four five:5 }
+
+== Insert with stream operators.
+array<int>[int(1), int(2), int(3)]
+list[int(42), boolean(0), symbol(x)]
+map{string(k1):int(42), symbol(k2):boolean(0)}
+"""
+        self.maxDiff = None
+        self.assertMultiLineEqual(want, self.proc(["encode_decode"]).wait_exit())
+
+    def test_scheduled_send_03(self):
+        # Output should be a bunch of "send" lines but can't guarantee exactly how many.
+        out = self.proc(["scheduled_send_03", "-a", self.addr+"scheduled_send", "-t", "0.1", "-i", "0.001"]).wait_exit().split()
+        self.assertTrue(len(out) > 0);
+        self.assertEqual(["send"]*len(out), out)
+
+    @unittest.skipUnless(os.getenv('HAS_CPP11'), "not a  C++11 build")
+    def test_scheduled_send(self):
+        out = self.proc(["scheduled_send", "-a", self.addr+"scheduled_send", "-t", "0.1", "-i", "0.001"]).wait_exit().split()
+        self.assertTrue(len(out) > 0);
+        self.assertEqual(["send"]*len(out), out)
+
+    def test_message_properties(self):
+        expect="""using put/get: short=123 string=foo symbol=sym
+using coerce: short(as long)=123
+props[short]=123
+props[string]=foo
+props[symbol]=sym
+short=42 string=bar
+expected conversion_error: "unexpected type, want: uint got: int"
+expected conversion_error: "unexpected type, want: uint got: string"
+"""
+        self.assertMultiLineEqual(expect, self.proc(["message_properties"]).wait_exit())
+
+    @unittest.skipUnless(os.getenv('HAS_CPP11'), "not a  C++11 build")
+    def test_multithreaded_client(self):
+        got = self.proc(["multithreaded_client", self.addr, "examples", "10"], helgrind=True).wait_exit()
+        self.maxDiff = None
+        self.assertRegexpMatches(got, "10 messages sent and received");
+
+#    @unittest.skipUnless(os.getenv('HAS_CPP11'), "not a  C++11 build")
+    @unittest.skip("Test is unstable, will enable when fixed")
+    def test_multithreaded_client_flow_control(self):
+        got = self.proc(["multithreaded_client_flow_control", self.addr, "examples", "10", "2"], helgrind=True).wait_exit()
+        self.maxDiff = None
+        self.assertRegexpMatches(got, "20 messages sent and received");
+
+class ContainerExampleSSLTest(BrokerTestCase):
+    """Run the SSL container examples, verify they behave as expected."""
+
+    broker_exe = "broker"
+    valgrind = False            # Disable for all tests, including inherited
+
+    def setUp(self):
+        super(ContainerExampleSSLTest, self).setUp()
+
+    def tearDown(self):
+        super(ContainerExampleSSLTest, self).tearDown()
+
+    def ssl_certs_dir(self):
+        """Absolute path to the test SSL certificates"""
+        return os.path.join(dirname(sys.argv[0]), "ssl-certs")
+
+    def test_ssl(self):
+        # SSL without SASL, VERIFY_PEER_NAME
+        # Disable valgrind when using OpenSSL
+        out = self.proc(["ssl", "-c", self.ssl_certs_dir()]).wait_exit()
+        expect = "Server certificate identity CN=test_server\nHello World!"
+        self.assertIn(expect, out)
+
+    def test_ssl_no_name(self):
+        # VERIFY_PEER
+        # Disable valgrind when using OpenSSL
+        out = self.proc(["ssl", "-c", self.ssl_certs_dir(), "-v", "noname"], valgrind=False).wait_exit()
+        expect = "Outgoing client connection connected via SSL.  Server certificate identity CN=test_server\nHello World!"
+        self.assertIn(expect, out)
+
+    def test_ssl_bad_name(self):
+        # VERIFY_PEER
+        out = self.proc(["ssl", "-c", self.ssl_certs_dir(), "-v", "fail"]).wait_exit()
+        expect = "Expected failure of connection with wrong peer name"
+        self.assertIn(expect, out)
+
+    def test_ssl_client_cert(self):
+        # SSL with SASL EXTERNAL
+        expect="""Inbound client certificate identity CN=test_client
+Outgoing client connection connected via SSL.  Server certificate identity CN=test_server
+Hello World!
+"""
+        # Disable valgrind when using OpenSSL
+        out = self.proc(["ssl_client_cert", self.ssl_certs_dir()]).wait_exit()
+        self.assertIn(expect, out)
+
+if __name__ == "__main__":
+    unittest.main()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/examples/fake_cpp11.hpp
----------------------------------------------------------------------
diff --git a/cpp/examples/fake_cpp11.hpp b/cpp/examples/fake_cpp11.hpp
new file mode 100644
index 0000000..03daa3b
--- /dev/null
+++ b/cpp/examples/fake_cpp11.hpp
@@ -0,0 +1,34 @@
+#ifndef FAKE_CPP11_HPP
+#define FAKE_CPP11_HPP
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/// These definitions allow us to use some new C++11 features in previous compilers
+///
+/// It is strongly recommended not to copy this - just use C++11/C++14 instead!
+
+#if __cplusplus < 201103L
+#define OVERRIDE
+#else
+#define OVERRIDE override
+#endif
+
+
+#endif // FAKE_CPP11_HPP


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


Mime
View raw message