You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by jr...@apache.org on 2018/04/05 19:33:39 UTC

[04/51] [partial] qpid-proton git commit: PROTON-1728: Reorganize the source tree

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/examples/simple_send.cpp
----------------------------------------------------------------------
diff --git a/cpp/examples/simple_send.cpp b/cpp/examples/simple_send.cpp
new file mode 100644
index 0000000..a4c2272
--- /dev/null
+++ b/cpp/examples/simple_send.cpp
@@ -0,0 +1,113 @@
+/*
+ *
+ * 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 <map>
+
+#include "fake_cpp11.hpp"
+
+class simple_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:
+    simple_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::map<std::string, int> m;
+            m["sequence"] = sent + 1;
+
+            msg.id(sent + 1);
+            msg.body(m);
+
+            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();
+
+        simple_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/ssl-certs/README.txt
----------------------------------------------------------------------
diff --git a/cpp/examples/ssl-certs/README.txt b/cpp/examples/ssl-certs/README.txt
new file mode 100644
index 0000000..9a8a4f9
--- /dev/null
+++ b/cpp/examples/ssl-certs/README.txt
@@ -0,0 +1,24 @@
+This directory contains basic self signed test certificates for use by
+proton examples.
+
+The ".pem" files are in the format expected by proton implementations
+using OpenSSL.  The ".p12" file are for Windows implementations using
+SChannel.
+
+The commands used to generate the certificates follow.
+
+
+make_pn_cert()
+{
+  name=$1
+  subject=$2
+  passwd=$3
+  # create the pem files
+  openssl req -newkey rsa:2048 -keyout $name-private-key.pem -out $name-certificate.pem -subj $subject -passout pass:$passwd -x509 -days 3650
+  # create the p12 files
+  openssl pkcs12 -export -out $name-full.p12 -passin pass:$passwd -passout pass:$passwd -inkey $name-private-key.pem -in $name-certificate.pem -name $name
+  openssl pkcs12 -export -out $name-certificate.p12 -in $name-certificate.pem -name $name -nokeys -passout pass:
+}
+
+make_pn_cert tserver /CN=test_server/OU=proton_test tserverpw
+make_pn_cert tclient /CN=test_client/OU=proton_test tclientpw

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/examples/ssl-certs/tclient-certificate.p12
----------------------------------------------------------------------
diff --git a/cpp/examples/ssl-certs/tclient-certificate.p12 b/cpp/examples/ssl-certs/tclient-certificate.p12
new file mode 100644
index 0000000..4d0e000
Binary files /dev/null and b/cpp/examples/ssl-certs/tclient-certificate.p12 differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/examples/ssl-certs/tclient-certificate.pem
----------------------------------------------------------------------
diff --git a/cpp/examples/ssl-certs/tclient-certificate.pem b/cpp/examples/ssl-certs/tclient-certificate.pem
new file mode 100644
index 0000000..8088e2e
--- /dev/null
+++ b/cpp/examples/ssl-certs/tclient-certificate.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDKzCCAhOgAwIBAgIJAIV7frIjftgcMA0GCSqGSIb3DQEBCwUAMCwxFDASBgNV
+BAMMC3Rlc3RfY2xpZW50MRQwEgYDVQQLDAtwcm90b25fdGVzdDAeFw0xNTExMjcx
+ODEwMzlaFw0yNTExMjQxODEwMzlaMCwxFDASBgNVBAMMC3Rlc3RfY2xpZW50MRQw
+EgYDVQQLDAtwcm90b25fdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAPCIS4qUdOtQplUxZ6WW0LXcvosqFP6qOiCARLSEWpR3B8bq213rzefwwfcM
+4TtMr88bP+huLKmlyMfwpl8yB88eXkscPgaAce2zk24urWkFXKSQ6GPitWBLGqBa
+V+W0wJ4mfW7MwefVslWfGXI381QEUlBHjkFG30AtzMMTRj2GK2JqUlRXZPljGyB7
+WcXwxcoS+HkKV7FtHWSkLAzyXwQ9vsCUEYdWTUaGXfCUNRSRV7h1LIANbu03NxV0
+XdEl7WXcr7tuTw3axeUGhRFVhLegrxKLuZTTno4aAJnEr8uaDzjxvXnv3Ne2igvy
+gRfZgOMx+XrZEob9OpAoRghQt4cCAwEAAaNQME4wHQYDVR0OBBYEFE4vbyiM0RjG
+TLMLLGGhMZE/5x1GMB8GA1UdIwQYMBaAFE4vbyiM0RjGTLMLLGGhMZE/5x1GMAwG
+A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAErr/rvLS9Ig0UCMwh1J1lA9
+/gvXf93iIK/SjrFIAqYRmfZxg4husfoes8t2hFUeuqoH05TuSOoXG8p8DpgTSGmF
+jAFe+T90vJZTm0oqZkkkI/hdzjGQoHURRp9/O2Z/lm39KSKGVAN5pUWCUDi/G5iS
+P9LZPJN6a5syXMrR6x62IPxAXowlpXkRghKClF3zPOaOBTzT1V27EkI8IEgC+p45
+246EooLnw8ibB+ucNc3KHNzpgKGVd/622+I+Q5eg9AT9PLFttP+R2ECsrVDDPYuA
+p0qaSnwgeozj/d6K3FOgKKEKbzBmpWgkv0jdcVk18aPMHypI/RDtZ/+3ET2Ksi8=
+-----END CERTIFICATE-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/examples/ssl-certs/tclient-full.p12
----------------------------------------------------------------------
diff --git a/cpp/examples/ssl-certs/tclient-full.p12 b/cpp/examples/ssl-certs/tclient-full.p12
new file mode 100644
index 0000000..ad2d7d3
Binary files /dev/null and b/cpp/examples/ssl-certs/tclient-full.p12 differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/examples/ssl-certs/tclient-private-key.pem
----------------------------------------------------------------------
diff --git a/cpp/examples/ssl-certs/tclient-private-key.pem b/cpp/examples/ssl-certs/tclient-private-key.pem
new file mode 100644
index 0000000..e5c114d
--- /dev/null
+++ b/cpp/examples/ssl-certs/tclient-private-key.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQICy6ghWp45z4CAggA
+MBQGCCqGSIb3DQMHBAiVdDoo4NIghQSCBMixGm1bm/omMxsaKnIPO7zm5dyLexJ+
+yTFpmh2KV7kQqmpzCyIOdoG6K8YqFnie2XdFWm3S8faRHoMq54bDmyEWIxfQPq5f
+I1iYFbIZkbnhUvK53RActsEUMf0locS4xylU7VQK3XTAwp0TVip3Lp3ehEMEdcXL
+iUWibGsoTPKcY9MIWGXZAJXsEXoeHt6k2hHo1G4E0/Bi6mLW1LY/cxZCjHTGD6qI
+Kt54SCCDvinqVa+rixw6yX9F14EA6bhALami8e+Ccd3lqHOyYlXcBaSS1ezCg6ig
+oNK97mC+gEGy1KlkZDKWXclFoOCBXRBe4DByre6Rlq3yeI9L42bvAuSBSmf5QT5g
+73Yl8vjEAKR65awBT09dPuKu7t+Fb6vkwF8/t+uyj9IuL+42UuXhMLK3ohf+6DbU
+8/zB4y3GXI80QmWM0+Wx4n6khFhPFLHt2q0Sn6V9PG1vtHyiq50oSCoyrPQLaecp
+hefnMCFBYTcT3JUwmoVGGy0boIAwL7T4aGsMt7QhwOx5tU35tKFxyY7m4fX14AKo
+2EIy+TPQwCGkGf3Puy/Pc9VA8IAxB5+WwSrjk+NeCv88eIX7gy43k4rCr+OmD9FF
+wknr3xoP3KYhNXjdZ4Ep/1UHSK+JAtzzbNLQjDcqN+gQPg/yUX6ih0j5K3Wvh9bK
+E/DvzbpJroUZPgzR+8z5O68CfsD+OIdpHBFTKqAFmzvUuqpADpr998LdCjD+lW+V
+xZZgZa8KEblwgiH3fdGbYl46Ho1zrZisf439DbqyybAuBIQB4NSZcL/MAgVGO17k
+QDpVElWZWYrFm4CFTcvS2HvIzRmbefF5m5oJedsN7Q6WQCp+3gnwYx1xIOknd7pW
+N4AHNnqjscSj9yACj/EiBVKAKNnC5H7ZGZTsaAjMETZyjLXfI2AZ3Fviz4zFR+oz
+NkAfFB6WUpRpl7H02FzrzYT7XkkLcXd6H6g+mv2iDa9uKWk/PS2QlqnJt8/dHEHD
+JKTG331yDK5GHlKAVGF3nP5BwFGgTQMuSoeiOervMXPUwDpQ8OaYkuaRej0cZLgT
+kAF9sUjqdsoYNcXDFHALp6y5g8qYkfrxrlIbKs82zIsmB5I+dtZbUaD3a0zAUrmW
+5Xm3Pc9dVP0EXKwfHz6zqPReEw2yYLisB5IoHd4M2wa3GzHBdra1ij4QTmvd3o7e
+buGFoX8KJQAcig0zpbYkoDP2gPhIh9rY4unVPQNX1Q8/wRsiJAZZsYvZY+A+SmuZ
+bwSwk+8ZJRsFzdYYYhQeRytD5cDAIQiClcI5Yj4T9dWQV/gf0N/wIBDNTMp0jJAy
+1l7PuXTfGZodNJWZH0oqsrNoWbn/k67NildvvofIKX+h09Nxszr670Pvj0qoHd5/
+CWq30lnxoJBUgbikFOz6ZuuHi/ZiCXL+haH+v8hJKN5ptRKnyYJQHchRB/IOGRoT
+5lmWxo8a7K+yXhp0VBDHJfw3685ms0xQX8Xj4X3MEuN64zd0fB1JmhtP12ydK85J
+ABawNKlRQPw5weckwtCviXQX+vX25S/xu3xA6IuqlHyqL/1t3DICzuxeOyT2mZxD
+tKQxEgNihPvu32vn9m74qA3adEaxuWPRkPZuTeITHOkMTZolvqYX/5olBsSgYwka
+7/g=
+-----END ENCRYPTED PRIVATE KEY-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/examples/ssl-certs/tserver-certificate.p12
----------------------------------------------------------------------
diff --git a/cpp/examples/ssl-certs/tserver-certificate.p12 b/cpp/examples/ssl-certs/tserver-certificate.p12
new file mode 100644
index 0000000..f38b67d
Binary files /dev/null and b/cpp/examples/ssl-certs/tserver-certificate.p12 differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/examples/ssl-certs/tserver-certificate.pem
----------------------------------------------------------------------
diff --git a/cpp/examples/ssl-certs/tserver-certificate.pem b/cpp/examples/ssl-certs/tserver-certificate.pem
new file mode 100644
index 0000000..86231f3
--- /dev/null
+++ b/cpp/examples/ssl-certs/tserver-certificate.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDKzCCAhOgAwIBAgIJAPnYOOQCJ3kDMA0GCSqGSIb3DQEBCwUAMCwxFDASBgNV
+BAMMC3Rlc3Rfc2VydmVyMRQwEgYDVQQLDAtwcm90b25fdGVzdDAeFw0xNTExMjcx
+ODEwMzlaFw0yNTExMjQxODEwMzlaMCwxFDASBgNVBAMMC3Rlc3Rfc2VydmVyMRQw
+EgYDVQQLDAtwcm90b25fdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAKJNB78lgw4KtXDAvXocTLud6mbn6zgfB6ETIF+kcrukOH9DnPxjLBBM4Lig
+sp1+kmeudFK5/X8riDrvIW52b/rlEBLgLB+oDtI74m6OTbBs9L+FUFYOuxApetQF
+qoJy2vf9pWfy4uku24vCpeo7eVLi6ypu4lXE3LR+Km3FruHI1NKonHBMhwXSOWqF
+pYM6/4IZJ4fbV0+eU0Jrx+05s6XHg5vone2BVJKxeSIBje+zWnNnh8+qG0Z70Jgp
+aMetME5KGnLNgD1okpH0vb3lwjvuqkkx4WswGVZGbLLkSqqBpXPyM9fCFVy5aKSL
+DBq7IABQtO67O2nBzK3OyigHrUUCAwEAAaNQME4wHQYDVR0OBBYEFGV1PY0FCFbJ
+gpcDVKI6JGiRTt3kMB8GA1UdIwQYMBaAFGV1PY0FCFbJgpcDVKI6JGiRTt3kMAwG
+A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAIx1TOTGWnnbpan4bse7wuvH
+GYSNDJhoTVS+X1TC63xukJD1JBAsCNTqg/ZV6lN3XEl7vvOXfGoCiyXM6a9XOKUo
+gSDtMrIr+wTh6Ss1yRO8QcCJmxH5JDXNu1ojtwsjFW/vneI4IL9kwpDsSlMQEX/E
+EkkQwtAx/Cvfe7pecZL4qSeykJOUMTts9H8fCAZqEiRZBA3ugJxqF8jwLP3DoFVQ
+6QZzKDY6CSPqfMnVb5i0MAIYVDpau+e3N9dgQpZD22F/zbua0OVbfAPdiRMnYxML
+FT4sxLnh+5YVqwpVWbEKp4onHe2Fq6YIvAxUYAJ3SBA2C8O2RAVKWxf1jko3jYI=
+-----END CERTIFICATE-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/examples/ssl-certs/tserver-full.p12
----------------------------------------------------------------------
diff --git a/cpp/examples/ssl-certs/tserver-full.p12 b/cpp/examples/ssl-certs/tserver-full.p12
new file mode 100644
index 0000000..d4a0e40
Binary files /dev/null and b/cpp/examples/ssl-certs/tserver-full.p12 differ

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/examples/ssl-certs/tserver-private-key.pem
----------------------------------------------------------------------
diff --git a/cpp/examples/ssl-certs/tserver-private-key.pem b/cpp/examples/ssl-certs/tserver-private-key.pem
new file mode 100644
index 0000000..91dcf0e
--- /dev/null
+++ b/cpp/examples/ssl-certs/tserver-private-key.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQI1cT0c2J3GcQCAggA
+MBQGCCqGSIb3DQMHBAi1hxSX2LJ+EgSCBMheHJ0iXr5A36Natjk/LcAEeKUMT9s+
+sMzoQceCWe8qMlQluWksr9iDdZ4JRIE8cpK8dbmx4dLY/SShUzdlhJHCSa4zZBHq
+8cZ/jGUF/RF1rqdgjK589eUq+uOl3/gXKzG/SxBqayy6PSn12kX3qnvmlkXCmtwU
+lg+iBm5wRcJ0MyVHaJkyA8sW8gr186C/VAau6Yu0crQXN7NRo9snrd4ewuYMIEhZ
+hgaG9XsYQWB1bPhAaKj80CZGxsQbJyTwcbKKkB3IY4WXx8mmhuiNl+vKT3HBJ9Ju
+YB6tgIjs8CJ4X2P4aU3yNJwG1QldgHSqmFGQ19bcZAw3s3kzwjdzRf4H2V16XOBd
+zQ5AEs/ffVMzMIAfkb1gYwgunZ2CVwwDJ2mi1RcgkX+Og2aFQc+fxXcVOnDcGLxV
+6fuCuZ2lsXfoiIyRh9kj3L75N12GtVUvgBdnMuOc1wPw6XnGQtDwt0acJpdexLMG
+k0j57r/gcgzTcmF3qNM+y9L/HLssgrJkvVJw2Np5gmtIyfDocsDUWUbClS4dTpYf
+oTngUTU+vWtHBuaUnb+f5/WJaRS/S7mmR8usbVG3i9WnEr/vlPJpbJFSjW2S6u/H
+7cFxKUmmBZsSuEv/EKt9a+Sh62kprOChm4myqfCI1/gvNKfUZC6m0Vp8zf+2LgAq
+2RgbMuqysMjWUtV4kDRZT7oCYckUDwsCHdbLES3nmVrtBk2ShMKHBpDp8/GoRuiV
+jdV7/EjKM/M1kXtFYYe3z7Mxv++lKYIJ7bNwVrQ8nrhce/VwHw6D5emWXNCJXhKZ
+FW7EM2ZOZ9eaKOlCsIi8sbjV6Yie9IY6HJKKmi3CpO0Tv5kLBdHkru8vGCSFm3O1
+n7wz7Ys5FBSlZ19X0NwQSCQX1Q4w+tido6i1SCRX0qJEdTNGuGwVXMHCf4/1zyHV
+hj8vnxh8fzo79LFrwlTTgwLg1Mr8sEUFFDJ/raJ1AhFXi8n24trtNR8EHxRW8wtD
+CLCKaqkEqfBiFXK/Yq3RrefCayPHiD+DaNsI8BwefMGpED3vD8YYCjAzXNPh/CSF
+sc1i1jWMzbJhzOoFSPNXhlfusbUFMFQ/6olatmH47SY6HBBOL3DDP5uQ0jw8P454
+QBjlMOpEZmZxO6TcEtJwu0vzgog4rQ5g3NWy6SIpjWehNwTynLt7yM3R5WTI6cZs
+0GTv/rqo2/SUoNsFmnGIUwj/DrBe4XOAq1nS2ZlEctxKhBsKH0hMFp6D1rXOzrgl
+bwcq+oistoB0TLcThShyNgSqzW1znQ1n5SVUk9b5rRhSttJxn3yOMewH0i3v8bPo
+HOhP5kaGjblPsCYyhlL/SNVF0OXEGTwLNey7FQdWFOwVwTRRXe7k+uGZ2d5hg+Jn
+It/trDZ1RDYbVmB7/Qy73c16J4mvhOUJ2de5ZciFBjkidbiiUKLj9xnjK9k9Sauo
+MKhNnDMAEU5VDQM3xNe5BRdX8dFLwfF5H64sU3nROF83aUnDgvfFEowYPnCuPYfm
+m4aQHfoBSg4j3v1OeOwktcl+Q2TjxPHfWhbWeRBfxOTqQ/suYhnQChuFSK/qyo9K
+ccgotqghhunRsWMoZT25H7AZM6yKb1sMz/0oyMRIKeGqoYh+ULM5XLY0xNYd4/xU
+WtQ=
+-----END ENCRYPTED PRIVATE KEY-----

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/examples/ssl.cpp
----------------------------------------------------------------------
diff --git a/cpp/examples/ssl.cpp b/cpp/examples/ssl.cpp
new file mode 100644
index 0000000..cd5e48e
--- /dev/null
+++ b/cpp/examples/ssl.cpp
@@ -0,0 +1,230 @@
+/*
+ *
+ * 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_options.hpp>
+#include <proton/connection.hpp>
+#include <proton/container.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/ssl.hpp>
+#include <proton/tracker.hpp>
+#include <proton/transport.hpp>
+
+#include <iostream>
+
+#include "fake_cpp11.hpp"
+
+using proton::connection_options;
+using proton::ssl_client_options;
+using proton::ssl_server_options;
+using proton::ssl_certificate;
+
+// Helper functions defined below.
+bool using_OpenSSL();
+std::string platform_CA(const std::string &base_name);
+ssl_certificate platform_certificate(const std::string &base_name, const std::string &passwd);
+std::string find_CN(const std::string &);
+
+namespace {
+    const std::string verify_full("full");  // Normal verification
+    const std::string verify_noname("noname"); // Skip matching host name against the certificate
+    const std::string verify_fail("fail");  // Force name mismatch failure
+    std::string verify(verify_full);  // Default for example
+    std::string cert_directory;
+}
+
+
+struct server_handler : public proton::messaging_handler {
+    proton::listener listener;
+
+    void on_connection_open(proton::connection &c) OVERRIDE {
+        std::cout << "Inbound server connection connected via SSL.  Protocol: " <<
+            c.transport().ssl().protocol() << std::endl;
+        listener.stop();  // Just expecting the one connection.
+
+        // Go and do default inbound open stuff too
+        messaging_handler::on_connection_open(c);
+    }
+
+    void on_transport_error(proton::transport &t) OVERRIDE {
+        listener.stop();
+    }
+
+    void on_message(proton::delivery &, proton::message &m) OVERRIDE {
+        std::cout << m.body() << std::endl;
+    }
+};
+
+
+class hello_world_direct : public proton::messaging_handler {
+  private:
+    class listener_open_handler : public proton::listen_handler {
+        void on_open(proton::listener& l) OVERRIDE {
+            std::ostringstream url;
+            url << "//:" << l.port() << "/example"; // Connect to the actual port
+            l.container().open_sender(url.str());
+        }
+    };
+
+    listener_open_handler listen_handler;
+    server_handler s_handler;
+
+  public:
+    void on_container_start(proton::container &c) OVERRIDE {
+        // Configure listener.  Details vary by platform.
+        ssl_certificate server_cert = platform_certificate("tserver", "tserverpw");
+        ssl_server_options ssl_srv(server_cert);
+        connection_options server_opts;
+        server_opts.ssl_server_options(ssl_srv).handler(s_handler);
+        c.server_connection_options(server_opts);
+
+        // Configure client with a Certificate Authority database
+        // populated with the server's self signed certificate.
+        connection_options client_opts;
+        if (verify == verify_full) {
+            ssl_client_options ssl_cli(platform_CA("tserver"));
+            client_opts.ssl_client_options(ssl_cli);
+            // The next line is optional in normal use.  Since the
+            // example uses IP addresses in the connection string, use
+            // the virtual_host option to set the server host name
+            // used for certificate verification:
+            client_opts.virtual_host("test_server");
+        } else if (verify == verify_noname) {
+            // Downgrade the verification from VERIFY_PEER_NAME to VERIFY_PEER.
+            ssl_client_options ssl_cli(platform_CA("tserver"), proton::ssl::VERIFY_PEER);
+            client_opts.ssl_client_options(ssl_cli);
+        } else if (verify == verify_fail) {
+            ssl_client_options ssl_cli(platform_CA("tserver"));
+            client_opts.ssl_client_options(ssl_cli);
+            client_opts.virtual_host("wrong_name_for_server"); // Pick any name that doesn't match.
+        } else throw std::logic_error("bad verify mode: " + verify);
+
+        c.client_connection_options(client_opts);
+        s_handler.listener = c.listen("//:0", listen_handler); // Listen on port 0 for a dynamic port
+    }
+
+    void on_connection_open(proton::connection &c) OVERRIDE {
+        std::string subject = c.transport().ssl().remote_subject();
+        std::cout << "Outgoing client connection connected via SSL.  Server certificate identity " <<
+            find_CN(subject) << std::endl;
+    }
+
+    void on_transport_error(proton::transport &t) OVERRIDE {
+        std::string err = t.error().what();
+        if (verify == verify_fail && err.find("certificate") != std::string::npos) {
+            std::cout << "Expected failure of connection with wrong peer name: " << err
+                      << std::endl;
+        } else {
+            std::cout << "Unexpected transport error: " << err << std::endl;
+        }
+    }
+
+    void on_sendable(proton::sender &s) OVERRIDE {
+        proton::message m;
+        m.body("Hello World!");
+        s.send(m);
+        s.close();
+    }
+
+    void on_tracker_accept(proton::tracker &t) OVERRIDE {
+        // All done.
+        t.connection().close();
+    }
+};
+
+int main(int argc, char **argv) {
+    example::options opts(argc, argv);
+    opts.add_value(cert_directory, 'c', "cert_directory",
+                   "directory containing SSL certificates and private key information", "CERTDIR");
+    opts.add_value(verify, 'v', "verify", "verify type: \"minimum\", \"full\", \"fail\"", "VERIFY");
+
+    try {
+        opts.parse();
+
+        size_t sz = cert_directory.size();
+        if (sz && cert_directory[sz -1] != '/')
+            cert_directory.append("/");
+        else cert_directory = "ssl-certs/";
+
+        if (verify != verify_noname && verify != verify_full && verify != verify_fail)
+            throw std::runtime_error("bad verify argument: " + verify);
+
+        hello_world_direct hwd;
+        proton::container(hwd).run();
+        return 0;
+    } catch (const std::exception& e) {
+        std::cerr << e.what() << std::endl;
+    }
+    return 1;
+}
+
+
+bool using_OpenSSL() {
+    // Current defaults.
+#if defined(WIN32)
+    return false;
+#else
+    return true;
+#endif
+}
+
+ssl_certificate platform_certificate(const std::string &base_name, const std::string &passwd) {
+    if (using_OpenSSL()) {
+        // The first argument will be the name of the file containing the public certificate, the
+        // second argument will be the name of the file containing the private key.
+        return ssl_certificate(cert_directory + base_name + "-certificate.pem",
+                               cert_directory + base_name + "-private-key.pem", passwd);
+    }
+    else {
+        // Windows SChannel
+        // The first argument will be the database or store that contains one or more complete certificates
+        // (public and private data).  The second will be an optional name of the certificate in the store
+        // (not used in this example with one certificate per store).
+        return ssl_certificate(cert_directory + base_name + "-full.p12", "", passwd);
+    }
+}
+
+std::string platform_CA(const std::string &base_name) {
+    if (using_OpenSSL()) {
+        // In this simple example with self-signed certificates, the peer's certificate is the CA database.
+        return cert_directory + base_name + "-certificate.pem";
+    }
+    else {
+        // Windows SChannel.  Use a pkcs#12 file with just the peer's public certificate information.
+        return cert_directory + base_name + "-certificate.p12";
+    }
+}
+
+std::string find_CN(const std::string &subject) {
+    // The subject string is returned with different whitespace and component ordering between platforms.
+    // Here we just return the common name by searching for "CN=...." in the subject, knowing that
+    // the test certificates do not contain any escaped characters.
+    size_t pos = subject.find("CN=");
+    if (pos == std::string::npos) throw std::runtime_error("No common name in certificate subject");
+    std::string cn = subject.substr(pos);
+    pos = cn.find(',');
+    return pos == std::string::npos ? cn : cn.substr(0, pos);
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/examples/ssl_client_cert.cpp
----------------------------------------------------------------------
diff --git a/cpp/examples/ssl_client_cert.cpp b/cpp/examples/ssl_client_cert.cpp
new file mode 100644
index 0000000..4656ca2
--- /dev/null
+++ b/cpp/examples/ssl_client_cert.cpp
@@ -0,0 +1,203 @@
+/*
+ *
+ * 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/listen_handler.hpp>
+#include <proton/listener.hpp>
+#include <proton/message.hpp>
+#include <proton/messaging_handler.hpp>
+#include <proton/sasl.hpp>
+#include <proton/ssl.hpp>
+#include <proton/tracker.hpp>
+#include <proton/transport.hpp>
+
+#include <iostream>
+#include <sstream>
+
+#include "fake_cpp11.hpp"
+
+using proton::connection_options;
+using proton::ssl_client_options;
+using proton::ssl_server_options;
+using proton::ssl_certificate;
+using proton::sasl;
+
+// Helper functions defined below.
+bool using_OpenSSL();
+std::string platform_CA(const std::string &base_name);
+ssl_certificate platform_certificate(const std::string &base_name, const std::string &passwd);
+static std::string cert_directory;
+static std::string find_CN(const std::string &);
+
+
+struct server_handler : public proton::messaging_handler {
+    proton::listener listener;
+
+    void on_connection_open(proton::connection &c) OVERRIDE {
+        std::cout << "Inbound server connection connected via SSL.  Protocol: " <<
+            c.transport().ssl().protocol() << std::endl;
+        if (c.transport().sasl().outcome() == sasl::OK) {
+            std::string subject = c.transport().ssl().remote_subject();
+            std::cout << "Inbound client certificate identity " << find_CN(subject) << std::endl;
+        }
+        else {
+            std::cout << "Inbound client authentication failed" <<std::endl;
+            c.close();
+        }
+        listener.stop();
+
+        // Go and do default inbound open stuff too
+        messaging_handler::on_connection_open(c);
+    }
+
+    void on_message(proton::delivery &, proton::message &m) OVERRIDE {
+        std::cout << m.body() << std::endl;
+    }
+};
+
+
+class hello_world_direct : public proton::messaging_handler {
+  private:
+    class listener_open_handler : public proton::listen_handler {
+        void on_open(proton::listener& l) OVERRIDE {
+            std::ostringstream url;
+            url << "//:" << l.port() << "/example"; // Connect to the actual port
+            l.container().open_sender(url.str());
+        }
+    };
+
+    listener_open_handler listen_handler;
+    server_handler s_handler;
+
+  public:
+
+    void on_container_start(proton::container &c) OVERRIDE {
+        // Configure listener.  Details vary by platform.
+        ssl_certificate server_cert = platform_certificate("tserver", "tserverpw");
+        std::string client_CA = platform_CA("tclient");
+        // Specify an SSL domain with CA's for client certificate verification.
+        ssl_server_options srv_ssl(server_cert, client_CA);
+        connection_options server_opts;
+        server_opts.ssl_server_options(srv_ssl).handler(s_handler);
+        server_opts.sasl_allowed_mechs("EXTERNAL");
+        c.server_connection_options(server_opts);
+
+        // Configure client.
+        ssl_certificate client_cert = platform_certificate("tclient", "tclientpw");
+        std::string server_CA = platform_CA("tserver");
+        // Since the test certificate's credentials are unlikely to match this host's name, downgrade the verification
+        // from VERIFY_PEER_NAME to VERIFY_PEER.
+        ssl_client_options ssl_cli(client_cert, server_CA, proton::ssl::VERIFY_PEER);
+        connection_options client_opts;
+        client_opts.ssl_client_options(ssl_cli).sasl_allowed_mechs("EXTERNAL");
+        c.client_connection_options(client_opts);
+
+        s_handler.listener = c.listen("//:0", listen_handler);
+    }
+
+    void on_connection_open(proton::connection &c) OVERRIDE {
+        std::string subject = c.transport().ssl().remote_subject();
+        std::cout << "Outgoing client connection connected via SSL.  Server certificate identity " <<
+            find_CN(subject) << std::endl;
+    }
+
+    void on_sendable(proton::sender &s) OVERRIDE {
+        proton::message m;
+        m.body("Hello World!");
+        s.send(m);
+        s.close();
+    }
+
+    void on_tracker_accept(proton::tracker &t) OVERRIDE {
+        // All done.
+        t.connection().close();
+    }
+};
+
+int main(int argc, char **argv) {
+    try {
+        // Location of certificates and private key information:
+        if (argc > 1) {
+            cert_directory = argv[1];
+            size_t sz = cert_directory.size();
+            if (sz && cert_directory[sz -1] != '/')
+                cert_directory.append("/");
+        } else {
+            cert_directory = "ssl-certs/";
+        }
+        hello_world_direct hwd;
+        proton::container(hwd).run();
+        return 0;
+    } catch (const std::exception& e) {
+        std::cerr << e.what() << std::endl;
+    }
+    return 1;
+}
+
+
+bool using_OpenSSL() {
+    // Current defaults.
+#if defined(WIN32)
+    return false;
+#else
+    return true;
+#endif
+}
+
+ssl_certificate platform_certificate(const std::string &base_name, const std::string &passwd) {
+    if (using_OpenSSL()) {
+        // The first argument will be the name of the file containing the public certificate, the
+        // second argument will be the name of the file containing the private key.
+        return ssl_certificate(cert_directory + base_name + "-certificate.pem",
+                               cert_directory + base_name + "-private-key.pem", passwd);
+    }
+    else {
+        // Windows SChannel
+        // The first argument will be the database or store that contains one or more complete certificates
+        // (public and private data).  The second will be an optional name of the certificate in the store
+        // (not used in this example with one certificate per store).
+        return ssl_certificate(cert_directory + base_name + "-full.p12", "", passwd);
+    }
+}
+
+std::string platform_CA(const std::string &base_name) {
+    if (using_OpenSSL()) {
+        // In this simple example with self-signed certificates, the peer's certificate is the CA database.
+        return cert_directory + base_name + "-certificate.pem";
+    }
+    else {
+        // Windows SChannel.  Use a pkcs#12 file with just the peer's public certificate information.
+        return cert_directory + base_name + "-certificate.p12";
+    }
+}
+
+std::string find_CN(const std::string &subject) {
+    // The subject string is returned with different whitespace and component ordering between platforms.
+    // Here we just return the common name by searching for "CN=...." in the subject, knowing that
+    // the test certificates do not contain any escaped characters.
+    size_t pos = subject.find("CN=");
+    if (pos == std::string::npos) throw std::runtime_error("No common name in certificate subject");
+    std::string cn = subject.substr(pos);
+    pos = cn.find(',');
+    return pos == std::string::npos ? cn : cn.substr(0, pos);
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/examples/tutorial.dox
----------------------------------------------------------------------
diff --git a/cpp/examples/tutorial.dox b/cpp/examples/tutorial.dox
new file mode 100644
index 0000000..fdab808
--- /dev/null
+++ b/cpp/examples/tutorial.dox
@@ -0,0 +1,371 @@
+// -*-markdown-*-
+// NOTE: doxygen can include markdown pages directly but there seems to be a bug
+// that shows messed-up line numbers in \skip \until code extracts. This file
+// is markdown wrapped in a doxygen comment - which works. The file is best viewed/edited
+// as markdown.
+
+/**
+
+@page tutorial_page Tutorial
+
+This is a brief guide to to the fundamentals of building messaging
+applications using Qpid Proton C++.
+
+Proton provides an "event-driven" programming model, where you
+implement a subclass of `proton::messaging_handler` and override
+functions that react to various AMQP events (connections opening and
+closing, messages being delivered, and so on).
+
+The examples below show how to implement handlers for clients and
+servers and how to run them using the `proton::container`, a portable,
+easy-to-use way to build single-threaded clients or servers.
+
+Some of the examples require an AMQP *broker* that can receive, store,
+and send messages. @ref broker.cpp defines a simple example broker. If
+run without arguments, it listens on `0.0.0.0:5672`, the standard AMQP
+port on all network interfaces. To use a different port or network
+interface, use the `-a` option.
+
+    broker -a <host>:<port>
+
+Instead of the example broker, you can use any AMQP 1.0-compliant
+broker. You must configure your broker to have a queue (or topic)
+named "examples".
+
+The `helloworld` examples take an optional URL argument. The other
+examples take an option `-a URL`. A URL looks like this:
+
+    HOST:PORT/ADDRESS
+
+It usually defaults to `127.0.0.1:5672/examples`, but you can change
+this if your broker is on a different host or port, or you want to use
+a different queue or topic name (the ADDRESS part of the URL).
+
+Hello World!
+------------
+
+\dontinclude helloworld.cpp
+
+Tradition dictates that we start with Hello World! This example sends
+a message to a broker and then receives the same message back. In a
+realistic system the sender and receiver would normally be in
+different processes. The complete example is @ref helloworld.cpp
+
+We will include the following classes. `proton::container` runs an
+event loop which dispatches events to a
+`proton::messaging_handler`. This allows a *reactive* style of
+programming which is well suited to messaging
+applications. `proton::connection` and `proton::delivery` are AMQP
+entities used in the handler functions.  `proton::url` is a simple
+parser for the URL format mentioned above.
+
+\skip proton/connection
+\until proton/url
+
+We will define a class `hello_world` which is a subclass of
+`proton::messaging_handler` and overrides functions to handle the
+events of interest in sending and receiving a message.
+
+\skip class hello_world
+\until {}
+
+`proton::messaging_handler::on_container_start()` is called when the
+event loop first starts. We handle that by establishing a connection
+and creating a sender and a receiver.
+
+\skip on_container_start
+\until }
+\until }
+
+`proton::messaging_handler::on_sendable()` is called when the message
+can be transferred over the associated sender link to the remote
+peer. We create a `proton::message`, set the message body to `"Hello
+World!"`, and send the message. Then we close the sender, since we
+only want to send one message. Closing the sender will prevent further
+calls to `proton::messaging_handler::on_sendable()`.
+
+\skip on_sendable
+\until }
+
+`proton::messaging_handler::on_message()` is called when a message is
+received. We just print the body of the message and close the
+connection, as we only want one message.
+
+\skip on_message
+\until }
+
+The message body is a `proton::value`.  See @ref types_page for more
+on how to extract the message body as type-safe C++ values.
+
+Our `main` function creates an instance of the `hello_world` handler
+and a `proton::container` using that handler. Calling
+`proton::container::run()` sets things in motion and returns when we
+close the connection. It may throw an exception, which will be a
+subclass of `proton::error`. That in turn is a subclass of
+`std::exception`.
+
+\skip main
+\until }
+\until }
+\until }
+
+Asynchronous send and receive
+-----------------------------
+
+Of course, these `Hello World!` examples are very artificial,
+communicating as they do over a network connection but with the same
+process. A more realistic example involves communication between
+separate processes, which could indeed be running on completely
+separate machines.
+
+Let's separate the sender from the receiver, and transfer more than a
+single message between them.
+
+We'll start with a simple sender, @ref simple_send.cpp.
+
+\dontinclude simple_send.cpp
+
+As with the previous example, we define the application logic in a
+class that handles events. Because we are transferring more than one
+message, we need to keep track of how many we have sent. We'll use a
+`sent` member variable for that.  The `total` member variable will
+hold the number of messages we want to send.
+
+\skip class simple_send
+\until total
+
+As before, we use the
+`proton::messaging_handler::on_container_start()` event to establish
+our sender link over which we will transfer messages.
+
+\skip on_container_start
+\until }
+
+AMQP defines a credit-based flow-control mechanism. Flow control
+allows the receiver to control how many messages it is prepared to
+receive at a given time and thus prevents any component being
+overwhelmed by the number of messages it is sent.
+
+In the `proton::messaging_handler::on_sendable()` callback, we check
+that our sender has credit before sending messages. We also check that
+we haven't already sent the required number of messages.
+
+\skip on_sendable
+\until }
+\until }
+
+The `proton::sender::send()` call above is asynchronous. When it
+returns, the message has not yet actually been transferred across the
+network to the receiver. By handling the
+`proton::messaging_handler::on_tracker_accept()` event, we can get
+notified when the receiver has received and accepted the message. In
+our example we use this event to track the confirmation of the
+messages we have sent. We only close the connection and exit when the
+receiver has received all the messages we wanted to send.
+
+\skip on_tracker_accept
+\until }
+\until }
+
+If we are disconnected after a message is sent and before it has been
+confirmed by the receiver, it is said to be "in doubt". We don't know
+whether or not it was received. In this example, we will handle that
+by resending any in-doubt messages. This is known as an
+"at-least-once" guarantee, since each message should eventually be
+received at least once, though a given message may be received more
+than once (i.e., duplicates are possible). In the
+`proton::messaging_handler::on_transport_close()` callback, we reset
+the sent count to reflect only those that have been confirmed. The
+library will automatically try to reconnect for us, and when our
+sender is sendable again, we can restart from the point we know the
+receiver got to.
+
+\skip on_transport_close
+\until }
+
+\dontinclude simple_recv.cpp
+
+Now let's look at the corresponding receiver, @ref simple_recv.cpp.
+
+This time we'll use an `expected` member variable for for the number
+of messages we expect and a `received` variable to count how many we
+have received so far.
+
+\skip class simple_recv
+\until received
+
+We handle `proton::messaging_handler::on_container_start()` by
+creating our receiver, much like we did for the sender.
+
+\skip on_container_start
+\until }
+
+We also handle the `proton::messaging_handler::on_message()` event for
+received messages and print the message out as in the `Hello World!`
+examples.  However, we add some logic to allow the receiver to wait
+for a given number of messages and then close the connection and
+exit. We also add some logic to check for and ignore duplicates, using
+a simple sequential ID scheme.
+
+\skip on_message
+\until }
+
+Direct send and receive
+-----------------------
+
+Sending between these two examples requires an intermediary broker
+since neither accepts incoming connections. AMQP allows us to send
+messages directly between two processes. In that case, one or other of
+the processes needs to accept incoming connections. Let's create a
+modified version of the receiving example that does this with @ref
+direct_recv.cpp.
+
+\dontinclude direct_recv.cpp
+
+There are only two differences here. Instead of initiating a link (and
+implicitly a connection), we listen for incoming connections.
+
+\skip on_container_start
+\until }
+
+When we have received all the expected messages, we then stop
+listening for incoming connections by calling
+`proton::listener::stop()`
+
+\skip on_message
+\until }
+\until }
+\until }
+\until }
+
+You can use the @ref simple_send.cpp example to send to this receiver
+directly. (Note: you will need to stop any broker that is listening on
+the 5672 port, or else change the port used by specifying a different
+address to each example via the `-a` command-line switch).
+
+We can also modify the sender to allow the original receiver to
+connect to it, in @ref direct_send.cpp. Again, that requires just two
+modifications:
+
+\dontinclude direct_send.cpp
+
+As with the modified receiver, instead of initiating establishment of a
+link, we listen for incoming connections.
+
+\skip on_container_start
+\until }
+
+When we have received confirmation of all the messages we sent, we call
+`container::listener::stop()` to exit.
+
+\skip on_tracker_accept
+\until }
+\until }
+
+To try this modified sender, run the original @ref simple_recv.cpp
+against it.
+
+The symmetry in the underlying AMQP wire protocol that enables this is
+quite unique and elegant, and in reflecting this the Proton API
+provides a flexible toolkit for implementing all sorts of interesting
+intermediaries.
+
+Request and response
+--------------------
+
+A common pattern is to send a request message and expect a response
+message in return. AMQP has special support for this pattern. Let's
+have a look at a simple example. We'll start with @ref server.cpp, the
+program that will process the request and send the response. Note that
+we are still using a broker in this example.
+
+Our server will provide a very simple service: it will respond with
+the body of the request converted to uppercase.
+
+\dontinclude server.cpp
+\skip class server
+\until };
+
+The code here is not too different from the simple receiver example.
+However, when we receive a request in
+`proton::messaging_handler::on_message`, we look at the
+`proton::message::reply_to` address and create a sender with that
+address for the response. We'll cache the senders in case we get
+further requests with the same `reply_to`.
+
+Now let's create a simple @ref client.cpp to test this service out.
+
+\dontinclude client.cpp
+
+Our client takes a list of strings to send as requests.
+
+\skipline client(
+
+Since we will be sending and receiving, we create a sender and a
+receiver in `proton::messaging_handler::on_container_start`.  Our
+receiver has a blank address and sets the `dynamic` flag to true,
+which means we expect the remote end (the broker or server) to assign
+a unique address for us.
+
+\skip on_container_start
+\until }
+
+Now we need a function to send the next request from our list of
+requests. We set the `reply_to` address to be the dynamically assigned
+address of our receiver.
+
+\skip send_request
+\until }
+
+We need to use the address assigned by the broker as the `reply_to`
+address of our requests, so we can't send them until our receiver has
+been set up. To do that, we add an
+`proton::messaging_handler::on_receiver_open()` method to our handler
+class and use that as the trigger to send our first request.
+
+\skip on_receiver_open
+\until }
+
+When we receive a reply, we send the next request.
+
+\skip on_message
+\until }
+\until }
+\until }
+
+Direct request and response
+---------------------------
+
+We can avoid the intermediary process by writing a server that accepts
+connections directly, @ref server_direct.cpp. It involves the
+following changes to our original server:
+
+\dontinclude server_direct.cpp
+
+Our server must generate unique `reply-to` addresses for links from
+the client that request a dynamic address (previously this was done by
+the broker).  We use a simple counter.
+
+\skip generate_address
+\until }
+
+Next we need to handle incoming requests for links with dynamic
+addresses from the client.  We give the link a unique address and
+record it in our `senders` map.
+
+\skip on_sender_open
+\until }
+
+Note that we are interested in *sender* links above because we are
+implementing the server. A *receiver* link created on the client
+corresponds to a *sender* link on the server.
+
+Finally when we receive a message we look up its `reply_to` in our
+senders map and send the reply.
+
+\skip on_message
+\until }
+\until }
+\until }
+
+*/

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/include/proton/annotation_key.hpp
----------------------------------------------------------------------
diff --git a/cpp/include/proton/annotation_key.hpp b/cpp/include/proton/annotation_key.hpp
new file mode 100644
index 0000000..f9cc129
--- /dev/null
+++ b/cpp/include/proton/annotation_key.hpp
@@ -0,0 +1,87 @@
+#ifndef PROTON_ANNOTATION_KEY_HPP
+#define PROTON_ANNOTATION_KEY_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.
+ *
+ */
+
+#include "./scalar_base.hpp"
+#include "./symbol.hpp"
+
+#include <proton/type_compat.h>
+
+/// @file
+/// @copybrief proton::annotation_key
+
+namespace proton {
+
+/// A key for use with AMQP annotation maps.
+///
+/// An annotation_key can contain either a uint64_t or a proton::symbol.
+class annotation_key : public scalar_base {
+  public:
+    /// An empty annotation key.
+    annotation_key() {}
+
+    /// Construct from any type that can be assigned.
+    template <class T> annotation_key(const T& x) { *this = x; }
+
+    /// @name Assign from a uint64_t or symbol.
+    /// @{
+    annotation_key& operator=(uint64_t x) { put_(x); return *this; }
+    annotation_key& operator=(const symbol& x) { put_(x); return *this; }
+    /// @}
+
+    /// @name Extra conversions for strings, treated as codec::SYMBOL.
+    /// @{
+    annotation_key& operator=(const std::string& x) { put_(symbol(x)); return *this; }
+    annotation_key& operator=(const char *x) { put_(symbol(x)); return *this; }
+    /// @}
+
+    /// @cond INTERNAL
+  friend class message;
+  friend class codec::decoder;
+    /// @endcond
+};
+
+/// @cond INTERNAL
+/// Primary template for get<T>(message_id), specialized for legal types.
+template <class T> T get(const annotation_key& x);
+/// @endcond
+
+/// Get the uint64_t value or throw conversion_error.
+///
+/// @relatedalso annotation_key
+template<> inline uint64_t get<uint64_t>(const annotation_key& x) { return internal::get<uint64_t>(x); }
+
+/// Get the @ref symbol value or throw conversion_error.
+///
+/// @relatedalso annotation_key
+template<> inline symbol get<symbol>(const annotation_key& x) { return internal::get<symbol>(x); }
+
+/// Get the @ref binary value or throw conversion_error.
+///
+/// @copydoc scalar::coerce
+/// @relatedalso annotation_key
+template<class T> T coerce(const annotation_key& x) { return internal::coerce<T>(x); }
+
+} // proton
+
+#endif // PROTON_ANNOTATION_KEY_HPP

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/include/proton/binary.hpp
----------------------------------------------------------------------
diff --git a/cpp/include/proton/binary.hpp b/cpp/include/proton/binary.hpp
new file mode 100644
index 0000000..e2a8ebc
--- /dev/null
+++ b/cpp/include/proton/binary.hpp
@@ -0,0 +1,63 @@
+#ifndef PROTON_BINARY_HPP
+#define PROTON_BINARY_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.
+ *
+ */
+
+#include "./internal/export.hpp"
+#include "./types_fwd.hpp"
+
+#include <proton/type_compat.h>
+
+#include <iosfwd>
+#include <string>
+#include <vector>
+
+/// @file
+/// @copybrief proton::binary
+
+namespace proton {
+
+/// Arbitrary binary data.
+class binary : public std::vector<uint8_t> {
+  public:
+    /// @name Constructors
+    /// @{
+    explicit binary() : std::vector<value_type>() {}
+    explicit binary(size_t n) : std::vector<value_type>(n) {}
+    explicit binary(size_t n, value_type x) : std::vector<value_type>(n, x) {}
+    explicit binary(const std::string& s) : std::vector<value_type>(s.begin(), s.end()) {}
+    template <class Iter> binary(Iter first, Iter last) : std::vector<value_type>(first, last) {}
+    /// @}
+
+    /// Convert to std::string
+    operator std::string() const { return std::string(begin(), end()); }
+
+    /// Assignment
+    binary& operator=(const std::string& x) { assign(x.begin(), x.end()); return *this; }
+};
+
+/// Print a binary value
+PN_CPP_EXTERN std::ostream& operator<<(std::ostream&, const binary&);
+
+} // proton
+
+#endif // PROTON_BINARY_HPP

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/include/proton/byte_array.hpp
----------------------------------------------------------------------
diff --git a/cpp/include/proton/byte_array.hpp b/cpp/include/proton/byte_array.hpp
new file mode 100644
index 0000000..2f32b3b
--- /dev/null
+++ b/cpp/include/proton/byte_array.hpp
@@ -0,0 +1,102 @@
+#ifndef PROTON_BYTE_ARRAY_HPP
+#define PROTON_BYTE_ARRAY_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.
+ */
+
+#include "./internal/export.hpp"
+#include "./internal/comparable.hpp"
+#include "./types_fwd.hpp"
+
+#include <proton/type_compat.h>
+
+#include <algorithm>
+#include <iterator>
+
+/// @file
+/// @copybrief proton::byte_array
+
+namespace proton {
+
+namespace internal {
+PN_CPP_EXTERN void print_hex(std::ostream& o, const uint8_t* p, size_t n);
+}
+
+/// Arbitrary fixed-size data.
+///    
+/// Used to represent fixed-sized data types that don't have a natural
+/// C++ representation as an array of bytes.
+template <size_t N> class byte_array : private internal::comparable<byte_array<N> > {
+  public:
+    /// @name Sequence container typedefs
+    /// @{
+    typedef uint8_t                                   value_type;
+    typedef value_type*			              pointer;
+    typedef const value_type*                         const_pointer;
+    typedef value_type&                   	      reference;
+    typedef const value_type&             	      const_reference;
+    typedef value_type*          		      iterator;
+    typedef const value_type*			      const_iterator;
+    typedef std::size_t                    	      size_type;
+    typedef std::ptrdiff_t                   	      difference_type;
+    typedef std::reverse_iterator<iterator>	      reverse_iterator;
+    typedef std::reverse_iterator<const_iterator>     const_reverse_iterator;
+    /// @}
+
+    /// Zero-initialized byte array
+    byte_array() { std::fill(bytes_, bytes_+N, '\0'); }
+
+    /// Size of the array
+    static size_t size() { return N; }
+
+    /// @name Array operators
+    /// @{
+    value_type* begin() { return bytes_; }
+    value_type* end() { return bytes_+N; }
+    value_type& operator[](size_t i) { return bytes_[i]; }
+
+    const value_type* begin() const { return bytes_; }
+    const value_type* end() const { return bytes_+N; }
+    const value_type& operator[](size_t i) const { return bytes_[i]; }
+    /// @}
+
+    /// @name Comparison operators
+    /// @{
+  friend bool operator==(const byte_array& x, const byte_array& y) {
+      return std::equal(x.begin(), x.end(), y.begin());
+  }
+
+  friend bool operator<(const byte_array& x, const byte_array& y) {
+      return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
+  }
+    /// @}
+
+    /// Print byte array in hex
+  friend std::ostream& operator<<(std::ostream& o, const byte_array& b) {
+      internal::print_hex(o, b.begin(), b.size());
+      return o;
+  }
+
+  private:
+    value_type bytes_[N];
+};
+
+} // proton
+
+#endif // PROTON_BYTE_ARRAY_HPP

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/include/proton/codec/common.hpp
----------------------------------------------------------------------
diff --git a/cpp/include/proton/codec/common.hpp b/cpp/include/proton/codec/common.hpp
new file mode 100644
index 0000000..7bd1e5c
--- /dev/null
+++ b/cpp/include/proton/codec/common.hpp
@@ -0,0 +1,62 @@
+#ifndef PROTON_CODEC_COMMON_HPP
+#define PROTON_CODEC_COMMON_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.
+ *
+ */
+
+#include "../type_id.hpp"
+
+/// @file
+/// **Unsettled API** - Shared codec functions.
+
+namespace proton {
+namespace codec {
+
+/// **Unsettled API** - Start encoding a complex type.
+struct start {
+    /// @cond INTERNAL
+    /// XXX Document
+    start(type_id type_=NULL_TYPE, type_id element_=NULL_TYPE,
+          bool described_=false, size_t size_=0) :
+        type(type_), element(element_), is_described(described_), size(size_) {}
+
+    type_id type;            ///< The container type: ARRAY, LIST, MAP or DESCRIBED.
+    type_id element;         ///< the element type for array only.
+    bool is_described;       ///< true if first value is a descriptor.
+    size_t size;             ///< the element count excluding the descriptor (if any)
+    /// @endcond
+
+    /// @cond INTERNAL
+    /// XXX Document
+    static start array(type_id element, bool described=false) { return start(ARRAY, element, described); }
+    static start list() { return start(LIST); }
+    static start map() { return start(MAP); }
+    static start described() { return start(DESCRIBED, NULL_TYPE, true); }
+    /// @endcond
+};
+
+/// **Unsettled API** - Finish inserting or extracting a complex type.
+struct finish {};
+
+} // codec
+} // proton
+
+#endif // PROTON_CODEC_COMMON_HPP

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/include/proton/codec/decoder.hpp
----------------------------------------------------------------------
diff --git a/cpp/include/proton/codec/decoder.hpp b/cpp/include/proton/codec/decoder.hpp
new file mode 100644
index 0000000..5f587ff
--- /dev/null
+++ b/cpp/include/proton/codec/decoder.hpp
@@ -0,0 +1,217 @@
+#ifndef PROTON_CODEC_DECODER_HPP
+#define PROTON_CODEC_DECODER_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.
+ *
+ */
+
+#include "../internal/data.hpp"
+#include "../internal/type_traits.hpp"
+#include "../types_fwd.hpp"
+#include "./common.hpp"
+
+#include <proton/type_compat.h>
+
+#include <utility>
+
+/// @file
+/// @copybrief proton::codec::decoder
+
+namespace proton {
+
+class annotation_key;
+class message_id;
+class scalar;
+class value;
+
+namespace internal {
+class value_base;
+}
+
+namespace codec {
+
+/// **Unsettled API** - A stream-like decoder from AMQP bytes to C++
+/// values.
+///
+/// For internal use only.
+///
+/// @see @ref types_page for the recommended ways to manage AMQP data
+class decoder : public internal::data {
+  public:
+    /// Wrap a Proton C data object.  The exact flag if set means
+    /// decode only when there is an exact match between the AMQP and
+    /// C++ type. If not set then perform automatic conversions.
+    explicit decoder(const data& d, bool exact=false) : data(d), exact_(exact) {}
+
+    /// Attach decoder to a proton::value. The decoder is rewound to
+    /// the start of the data.
+    PN_CPP_EXTERN explicit decoder(const internal::value_base&, bool exact=false);
+
+    /// Decode AMQP data from a buffer and add it to the end of the
+    /// decoders stream.
+    PN_CPP_EXTERN void decode(const char* buffer, size_t size);
+
+    /// Decode AMQP data from a std::string and add it to the end of
+    /// the decoders stream.
+    PN_CPP_EXTERN void decode(const std::string&);
+
+    /// Return true if there are more value to extract at the current level.
+    PN_CPP_EXTERN bool more();
+
+    /// Get the type of the next value that will be read by
+    /// operator>>.
+    ///
+    /// @throw conversion_error if no more values. @see
+    /// decoder::more().
+    PN_CPP_EXTERN type_id next_type();
+
+    /// @name Extract built-in types
+    ///
+    /// @throw conversion_error if the decoder is empty or has an
+    /// incompatible type.
+    ///
+    /// @{
+    PN_CPP_EXTERN decoder& operator>>(bool&);
+    PN_CPP_EXTERN decoder& operator>>(uint8_t&);
+    PN_CPP_EXTERN decoder& operator>>(int8_t&);
+    PN_CPP_EXTERN decoder& operator>>(uint16_t&);
+    PN_CPP_EXTERN decoder& operator>>(int16_t&);
+    PN_CPP_EXTERN decoder& operator>>(uint32_t&);
+    PN_CPP_EXTERN decoder& operator>>(int32_t&);
+    PN_CPP_EXTERN decoder& operator>>(wchar_t&);
+    PN_CPP_EXTERN decoder& operator>>(uint64_t&);
+    PN_CPP_EXTERN decoder& operator>>(int64_t&);
+    PN_CPP_EXTERN decoder& operator>>(timestamp&);
+    PN_CPP_EXTERN decoder& operator>>(float&);
+    PN_CPP_EXTERN decoder& operator>>(double&);
+    PN_CPP_EXTERN decoder& operator>>(decimal32&);
+    PN_CPP_EXTERN decoder& operator>>(decimal64&);
+    PN_CPP_EXTERN decoder& operator>>(decimal128&);
+    PN_CPP_EXTERN decoder& operator>>(uuid&);
+    PN_CPP_EXTERN decoder& operator>>(std::string&);
+    PN_CPP_EXTERN decoder& operator>>(symbol&);
+    PN_CPP_EXTERN decoder& operator>>(binary&);
+    PN_CPP_EXTERN decoder& operator>>(message_id&);
+    PN_CPP_EXTERN decoder& operator>>(annotation_key&);
+    PN_CPP_EXTERN decoder& operator>>(scalar&);
+    PN_CPP_EXTERN decoder& operator>>(internal::value_base&);
+    PN_CPP_EXTERN decoder& operator>>(null&);
+    ///@}
+
+    /// Start decoding a container type, such as an ARRAY, LIST or
+    /// MAP.  This "enters" the container, more() will return false at
+    /// the end of the container.  Call finish() to "exit" the
+    /// container and move on to the next value.
+    PN_CPP_EXTERN decoder& operator>>(start&);
+
+    /// Finish decoding a container type, and move on to the next
+    /// value in the stream.
+    PN_CPP_EXTERN decoder& operator>>(const finish&);
+
+    /// @cond INTERNAL
+    template <class T> struct sequence_ref { T& ref; sequence_ref(T& r) : ref(r) {} };
+    template <class T> struct associative_ref { T& ref; associative_ref(T& r) : ref(r) {} };
+    template <class T> struct pair_sequence_ref { T& ref;  pair_sequence_ref(T& r) : ref(r) {} };
+
+    template <class T> static sequence_ref<T> sequence(T& x) { return sequence_ref<T>(x); }
+    template <class T> static associative_ref<T> associative(T& x) { return associative_ref<T>(x); }
+    template <class T> static pair_sequence_ref<T> pair_sequence(T& x) { return pair_sequence_ref<T>(x); }
+    /// @endcond
+
+    /// Extract any AMQP sequence (ARRAY, LIST or MAP) to a C++
+    /// sequence container of T if the elements types are convertible
+    /// to T. A MAP is extracted as `[key1, value1, key2, value2...]`.
+    template <class T> decoder& operator>>(sequence_ref<T> r)  {
+        start s;
+        *this >> s;
+        if (s.is_described) next();
+        r.ref.resize(s.size);
+        for (typename T::iterator i = r.ref.begin(); i != r.ref.end(); ++i)
+            *this >> *i;
+        return *this;
+    }
+
+    /// Extract an AMQP MAP to a C++ associative container
+    template <class T> decoder& operator>>(associative_ref<T> r)  {
+        using namespace internal;
+        start s;
+        *this >> s;
+        assert_type_equal(MAP, s.type);
+        r.ref.clear();
+        for (size_t i = 0; i < s.size/2; ++i) {
+            typename remove_const<typename T::key_type>::type k;
+            typename remove_const<typename T::mapped_type>::type v;
+            *this >> k >> v;
+            r.ref[k] = v;
+        }
+        return *this;
+    }
+
+    /// Extract an AMQP MAP to a C++ push_back sequence of pairs
+    /// preserving encoded order.
+    template <class T> decoder& operator>>(pair_sequence_ref<T> r)  {
+        using namespace internal;
+        start s;
+        *this >> s;
+        assert_type_equal(MAP, s.type);
+        r.ref.clear();
+        for (size_t i = 0; i < s.size/2; ++i) {
+            typedef typename T::value_type value_type;
+            typename remove_const<typename value_type::first_type>::type k;
+            typename remove_const<typename value_type::second_type>::type v;
+            *this >> k >> v;
+            r.ref.push_back(value_type(k, v));
+        }
+        return *this;
+    }
+
+  private:
+    type_id pre_get();
+    template <class T, class U> decoder& extract(T& x, U (*get)(pn_data_t*));
+    bool exact_;
+
+  friend class message;
+};
+
+/// @cond INTERNAL
+/// XXX Document this
+template<class T> T get(decoder& d) {
+    assert_type_equal(internal::type_id_of<T>::value, d.next_type());
+    T x;
+    d >> x;
+    return x;
+}
+/// @endcond
+
+/// operator>> for integer types that are not covered by the standard
+/// overrides.
+template <class T> typename internal::enable_if<internal::is_unknown_integer<T>::value, decoder&>::type
+operator>>(decoder& d, T& i)  {
+    using namespace internal;
+    typename integer_type<sizeof(T), is_signed<T>::value>::type v;
+    d >> v;                     // Extract as a known integer type
+    i = v;                      // C++ conversion to the target type.
+    return d;
+}
+
+} // codec
+} // proton
+
+#endif // PROTON_CODEC_DECODER_HPP

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/include/proton/codec/deque.hpp
----------------------------------------------------------------------
diff --git a/cpp/include/proton/codec/deque.hpp b/cpp/include/proton/codec/deque.hpp
new file mode 100644
index 0000000..bdac2e7
--- /dev/null
+++ b/cpp/include/proton/codec/deque.hpp
@@ -0,0 +1,63 @@
+#ifndef PROTON_CODEC_DEQUE_HPP
+#define PROTON_CODEC_DEQUE_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.
+ */
+
+/// @file
+/// **Unsettled API** - Enable conversions between `proton::value` and `std::deque`.
+
+#include "./encoder.hpp"
+#include "./decoder.hpp"
+
+#include <deque>
+#include <utility>
+
+namespace proton {
+namespace codec {
+
+/// std::deque<T> for most T is encoded as an amqp::ARRAY (same type elements)
+template <class T, class A>
+encoder& operator<<(encoder& e, const std::deque<T, A>& x) {
+    return e << encoder::array(x, internal::type_id_of<T>::value);
+}
+
+/// std::deque<value> encodes as codec::list_type (mixed type elements)
+template <class A>
+encoder& operator<<(encoder& e, const std::deque<value, A>& x) { return e << encoder::list(x); }
+
+/// std::deque<scalar> encodes as codec::list_type (mixed type elements)
+template <class A>
+encoder& operator<<(encoder& e, const std::deque<scalar, A>& x) { return e << encoder::list(x); }
+
+/// std::deque<std::pair<k,t> > encodes as codec::map_type.
+/// Map entries are encoded in order they appear in the list.
+template <class A, class K, class T>
+encoder& operator<<(encoder& e, const std::deque<std::pair<K,T>, A>& x) { return e << encoder::map(x); }
+
+/// Decode to std::deque<T> from an amqp::LIST or amqp::ARRAY.
+template <class T, class A> decoder& operator>>(decoder& d, std::deque<T, A>& x) { return d >> decoder::sequence(x); }
+
+/// Decode to std::deque<std::pair<K, T> from an amqp::MAP.
+template <class A, class K, class T> decoder& operator>>(decoder& d, std::deque<std::pair<K, T> , A>& x) { return d >> decoder::pair_sequence(x); }
+
+} // codec
+} // proton
+
+#endif // PROTON_CODEC_DEQUE_HPP

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/include/proton/codec/encoder.hpp
----------------------------------------------------------------------
diff --git a/cpp/include/proton/codec/encoder.hpp b/cpp/include/proton/codec/encoder.hpp
new file mode 100644
index 0000000..961695e
--- /dev/null
+++ b/cpp/include/proton/codec/encoder.hpp
@@ -0,0 +1,221 @@
+#ifndef PROTON_CODEC_ENCODER_HPP
+#define PROTON_CODEC_ENCODER_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.
+ *
+ */
+
+#include "../internal/data.hpp"
+#include "../internal/type_traits.hpp"
+#include "../types_fwd.hpp"
+#include "./common.hpp"
+
+#include <proton/type_compat.h>
+
+/// @file
+/// @copybrief proton::codec::encoder
+
+namespace proton {
+class scalar_base;
+
+namespace internal{
+class value_base;
+}
+
+namespace codec {
+
+/// **Unsettled API** - A stream-like encoder from C++ values to AMQP
+/// bytes.
+///
+/// For internal use only.
+///
+/// @see @ref types_page for the recommended ways to manage AMQP data
+class encoder : public internal::data {
+  public:
+    /// Wrap Proton-C data object.
+    explicit encoder(const data& d) : data(d) {}
+
+    /// Encoder into v. Clears any current value in v.
+    PN_CPP_EXTERN explicit encoder(internal::value_base& v);
+
+    /// Encode the current values into buffer and update size to reflect the
+    /// number of bytes encoded.
+    ///
+    /// Clears the encoder.
+    ///
+    /// @return if buffer == 0 or size is too small, then return false
+    /// and size to the required size.  Otherwise, return true and set
+    /// size to the number of bytes encoded.
+    PN_CPP_EXTERN bool encode(char* buffer, size_t& size);
+
+    /// Encode the current values into a std::string and resize the
+    /// string if necessary. Clears the encoder.
+    PN_CPP_EXTERN void encode(std::string&);
+
+    /// Encode the current values into a std::string. Clears the
+    /// encoder.
+    PN_CPP_EXTERN std::string encode();
+
+    /// @name Insert built-in types
+    /// @{
+    PN_CPP_EXTERN encoder& operator<<(bool);
+    PN_CPP_EXTERN encoder& operator<<(uint8_t);
+    PN_CPP_EXTERN encoder& operator<<(int8_t);
+    PN_CPP_EXTERN encoder& operator<<(uint16_t);
+    PN_CPP_EXTERN encoder& operator<<(int16_t);
+    PN_CPP_EXTERN encoder& operator<<(uint32_t);
+    PN_CPP_EXTERN encoder& operator<<(int32_t);
+    PN_CPP_EXTERN encoder& operator<<(wchar_t);
+    PN_CPP_EXTERN encoder& operator<<(uint64_t);
+    PN_CPP_EXTERN encoder& operator<<(int64_t);
+    PN_CPP_EXTERN encoder& operator<<(timestamp);
+    PN_CPP_EXTERN encoder& operator<<(float);
+    PN_CPP_EXTERN encoder& operator<<(double);
+    PN_CPP_EXTERN encoder& operator<<(decimal32);
+    PN_CPP_EXTERN encoder& operator<<(decimal64);
+    PN_CPP_EXTERN encoder& operator<<(decimal128);
+    PN_CPP_EXTERN encoder& operator<<(const uuid&);
+    PN_CPP_EXTERN encoder& operator<<(const std::string&);
+    PN_CPP_EXTERN encoder& operator<<(const symbol&);
+    PN_CPP_EXTERN encoder& operator<<(const binary&);
+    PN_CPP_EXTERN encoder& operator<<(const scalar_base&);
+    PN_CPP_EXTERN encoder& operator<<(const null&);
+#if PN_CPP_HAS_NULLPTR
+    PN_CPP_EXTERN encoder& operator<<(decltype(nullptr));
+#endif
+    /// @}
+
+    /// Insert a proton::value.
+    ///
+    /// @internal NOTE insert value_base, not value to avoid recursive
+    /// implicit conversions.
+    PN_CPP_EXTERN encoder& operator<<(const internal::value_base&);
+
+    /// Start a complex type
+    PN_CPP_EXTERN encoder& operator<<(const start&);
+
+    /// Finish a complex type
+    PN_CPP_EXTERN encoder& operator<<(const finish&);
+
+    /// @cond INTERNAL
+
+    // Undefined template to  prevent pointers being implicitly converted to bool.
+    template <class T> void* operator<<(const T*);
+
+    template <class T> struct list_cref { T& ref; list_cref(T& r) : ref(r) {} };
+    template <class T> struct map_cref { T& ref;  map_cref(T& r) : ref(r) {} };
+
+    template <class T> struct array_cref {
+        start array_start;
+        T& ref;
+        array_cref(T& r, type_id el, bool described) : array_start(ARRAY, el, described), ref(r) {}
+    };
+
+    template <class T> static list_cref<T> list(T& x) { return list_cref<T>(x); }
+    template <class T> static map_cref<T> map(T& x) { return map_cref<T>(x); }
+    template <class T> static array_cref<T> array(T& x, type_id element, bool described=false) {
+        return array_cref<T>(x, element, described);
+    }
+
+    template <class T> encoder& operator<<(const map_cref<T>& x) {
+        internal::state_guard sg(*this);
+        *this << start::map();
+        for (typename T::const_iterator i = x.ref.begin(); i != x.ref.end(); ++i)
+            *this << i->first << i->second;
+        *this << finish();
+        return *this;
+    }
+
+    template <class T> encoder& operator<<(const list_cref<T>& x) {
+        internal::state_guard sg(*this);
+        *this << start::list();
+        for (typename T::const_iterator i = x.ref.begin(); i != x.ref.end(); ++i)
+            *this << *i;
+        *this << finish();
+        return *this;
+    }
+
+    template <class T> encoder& operator<<(const array_cref<T>& x) {
+        internal::state_guard sg(*this);
+        *this << x.array_start;
+        for (typename T::const_iterator i = x.ref.begin(); i != x.ref.end(); ++i)
+            *this << *i;
+        *this << finish();
+        return *this;
+    }
+    /// @endcond
+
+  private:
+    template<class T, class U> encoder& insert(const T& x, int (*put)(pn_data_t*, U));
+    void check(long result);
+};
+
+/// Treat char* as string
+inline encoder& operator<<(encoder& e, const char* s) { return e << std::string(s); }
+
+/// operator << for integer types that are not covered by the standard overrides.
+template <class T> typename internal::enable_if<internal::is_unknown_integer<T>::value, encoder&>::type
+operator<<(encoder& e, T i)  {
+    using namespace internal;
+    return e << static_cast<typename integer_type<sizeof(T), is_signed<T>::value>::type>(i);
+}
+
+/// @cond INTERNAL
+
+namespace is_encodable_impl {   // Protect the world from fallback operator<<
+
+using namespace internal;
+
+sfinae::no operator<<(encoder const&, const sfinae::any_t &); // Fallback
+
+template<typename T> struct is_encodable : public sfinae {
+    static yes test(encoder&);
+    static no test(...);         // Failed test, no match.
+    static encoder* e;
+    static const T* t;
+    static bool const value = sizeof(test(*e << *t)) == sizeof(yes);
+};
+
+// Avoid recursion
+template <> struct is_encodable<value> : public true_type {};
+
+} // is_encodable_impl
+
+using is_encodable_impl::is_encodable;
+
+// Metafunction to test if a class looks like an encodable map from K to T.
+template <class M, class K, class T, class Enable = void>
+struct is_encodable_map : public internal::false_type {};
+
+template <class M, class K, class T> struct is_encodable_map<
+    M, K, T, typename internal::enable_if<
+                 internal::is_same<K, typename M::key_type>::value &&
+                 internal::is_same<T, typename M::mapped_type>::value &&
+                 is_encodable<M>::value
+                 >::type
+    > : public internal::true_type {};
+
+
+/// @endcond
+
+} // codec
+} // proton
+
+#endif /// PROTON_CODEC_ENCODER_HPP

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/include/proton/codec/forward_list.hpp
----------------------------------------------------------------------
diff --git a/cpp/include/proton/codec/forward_list.hpp b/cpp/include/proton/codec/forward_list.hpp
new file mode 100644
index 0000000..a7e46e1
--- /dev/null
+++ b/cpp/include/proton/codec/forward_list.hpp
@@ -0,0 +1,63 @@
+#ifndef PROTON_CODEC_FORWARD_LIST_HPP
+#define PROTON_CODEC_FORWARD_LIST_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.
+ */
+
+/// @file
+/// **Unsettled API** - Enable conversions between `proton::value` and `std::forward_list`.
+
+#include "./encoder.hpp"
+#include "./decoder.hpp"
+
+#include <forward_list>
+#include <utility>
+
+namespace proton {
+namespace codec {
+
+/// std::forward_list<T> for most T is encoded as an AMQP array.
+template <class T, class A>
+encoder& operator<<(encoder& e, const std::forward_list<T, A>& x) {
+    return e << encoder::array(x, internal::type_id_of<T>::value);
+}
+
+/// Specialize for std::forward_list<value>, encode as AMQP forward_list (variable type)
+template <class A>
+encoder& operator<<(encoder& e, const std::forward_list<value, A>& x) { return e << encoder::list(x); }
+
+/// Specialize for std::forward_list<scalar>, encode as AMQP list (variable type)
+template <class A>
+encoder& operator<<(encoder& e, const std::forward_list<scalar, A>& x) { return e << encoder::list(x); }
+
+/// Specialize for std::forward_list<std::pair<k,t> >, encode as AMQP map.
+/// Allows control over the order of encoding map entries.
+template <class A, class K, class T>
+encoder& operator<<(encoder& e, const std::forward_list<std::pair<K,T>, A>& x) { return e << encoder::map(x); }
+
+/// Decode to std::forward_list<T> from an amqp::LIST or amqp::ARRAY.
+template <class T, class A> decoder& operator>>(decoder& d, std::forward_list<T, A>& x) { return d >> decoder::sequence(x); }
+
+/// Decode to std::forward_list<std::pair<K, T> from an amqp::MAP.
+template <class A, class K, class T> decoder& operator>>(decoder& d, std::forward_list<std::pair<K, T> , A>& x) { return d >> decoder::pair_sequence(x); }
+
+} // codec
+} // proton
+
+#endif // PROTON_CODEC_FORWARD_LIST_HPP

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/include/proton/codec/list.hpp
----------------------------------------------------------------------
diff --git a/cpp/include/proton/codec/list.hpp b/cpp/include/proton/codec/list.hpp
new file mode 100644
index 0000000..7c96f45
--- /dev/null
+++ b/cpp/include/proton/codec/list.hpp
@@ -0,0 +1,65 @@
+#ifndef PROTON_CODEC_LIST_HPP
+#define PROTON_CODEC_LIST_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.
+ *
+ */
+
+/// @file
+/// **Unsettled API** - Enable conversions between `proton::value` and `std::list`.
+
+#include "./encoder.hpp"
+#include "./decoder.hpp"
+
+#include <list>
+#include <utility>
+
+namespace proton {
+namespace codec {
+
+/// std::list<T> for most T is encoded as an AMQP array.
+template <class T, class A>
+encoder& operator<<(encoder& e, const std::list<T, A>& x) {
+    return e << encoder::array(x, internal::type_id_of<T>::value);
+}
+
+/// Specialize for std::list<value>, encode as AMQP list (variable type)
+template <class A>
+encoder& operator<<(encoder& e, const std::list<value, A>& x) { return e << encoder::list(x); }
+
+/// Specialize for std::list<scalar>, encode as AMQP list (variable type)
+template <class A>
+encoder& operator<<(encoder& e, const std::list<scalar, A>& x) { return e << encoder::list(x); }
+
+/// Specialize for std::list<std::pair<k,t> >, encode as AMQP map.
+/// Allows control over the order of encoding map entries.
+template <class A, class K, class T>
+encoder& operator<<(encoder& e, const std::list<std::pair<K,T>, A>& x) { return e << encoder::map(x); }
+
+/// Decode to std::list<T> from an amqp::LIST or amqp::ARRAY.
+template <class T, class A> decoder& operator>>(decoder& d, std::list<T, A>& x) { return d >> decoder::sequence(x); }
+
+/// Decode to std::list<std::pair<K, T> from an amqp::MAP.
+template <class A, class K, class T> decoder& operator>>(decoder& d, std::list<std::pair<K, T> , A>& x) { return d >> decoder::pair_sequence(x); }
+
+} // codec
+} // proton
+
+#endif // PROTON_CODEC_LIST_HPP

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/include/proton/codec/map.hpp
----------------------------------------------------------------------
diff --git a/cpp/include/proton/codec/map.hpp b/cpp/include/proton/codec/map.hpp
new file mode 100644
index 0000000..9f17b98
--- /dev/null
+++ b/cpp/include/proton/codec/map.hpp
@@ -0,0 +1,47 @@
+#ifndef PROTON_CODEC_MAP_HPP
+#define PROTON_CODEC_MAP_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.
+ *
+ */
+
+/// @file
+/// **Unsettled API** - Enable conversions between `proton::value` and `std::map`.
+
+#include "./encoder.hpp"
+#include "./decoder.hpp"
+
+#include <map>
+
+namespace proton {
+namespace codec {
+
+/// Encode std::map<K, T> as amqp::MAP.
+template <class K, class T, class C, class A>
+encoder& operator<<(encoder& e, const std::map<K, T, C, A>& m) { return e << encoder::map(m); }
+
+/// Decode to std::map<K, T> from amqp::MAP.
+template <class K, class T, class C, class A>
+decoder& operator>>(decoder& d, std::map<K, T, C, A>& m) { return d >> decoder::associative(m); }
+
+} // codec
+} // proton
+
+#endif // PROTON_CODEC_MAP_HPP

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/include/proton/codec/unordered_map.hpp
----------------------------------------------------------------------
diff --git a/cpp/include/proton/codec/unordered_map.hpp b/cpp/include/proton/codec/unordered_map.hpp
new file mode 100644
index 0000000..57a3b87
--- /dev/null
+++ b/cpp/include/proton/codec/unordered_map.hpp
@@ -0,0 +1,47 @@
+#ifndef PROTON_CODEC_UNORDERED_MAP_HPP
+#define PROTON_CODEC_UNORDERED_MAP_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.
+ *
+ */
+
+/// @file
+/// **Unsettled API** - Enable conversions between `proton::value` and `std::unordered_map`.
+
+#include "./encoder.hpp"
+#include "./decoder.hpp"
+
+#include <unordered_map>
+
+namespace proton {
+namespace codec {
+
+/// Encode std::unordered_map<K, T> as amqp::UNORDERED_MAP.
+template <class K, class T, class C, class A>
+encoder& operator<<(encoder& e, const std::unordered_map<K, T, C, A>& m) { return e << encoder::map(m); }
+
+/// Decode to std::unordered_map<K, T> from amqp::UNORDERED_MAP.
+template <class K, class T, class C, class A>
+decoder& operator>>(decoder& d, std::unordered_map<K, T, C, A>& m) { return d >> decoder::associative(m); }
+
+} // codec
+} // proton
+
+#endif // PROTON_CODEC_UNORDERED_MAP_HPP

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/cpp/include/proton/codec/vector.hpp
----------------------------------------------------------------------
diff --git a/cpp/include/proton/codec/vector.hpp b/cpp/include/proton/codec/vector.hpp
new file mode 100644
index 0000000..4dee919
--- /dev/null
+++ b/cpp/include/proton/codec/vector.hpp
@@ -0,0 +1,61 @@
+#ifndef PROTON_CODEC_VECTOR_HPP
+#define PROTON_CODEC_VECTOR_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.
+ *
+ */
+
+/// @file
+/// **Unsettled API** - Enable conversions between `proton::value` and `std::vector`.
+
+#include "./encoder.hpp"
+#include "./decoder.hpp"
+
+#include <vector>
+#include <utility>
+
+namespace proton {
+namespace codec {
+
+/// Encode std::vector<T> as amqp::ARRAY (same type elements)
+template <class T, class A> encoder& operator<<(encoder& e, const std::vector<T, A>& x) {
+    return e << encoder::array(x, internal::type_id_of<T>::value);
+}
+
+/// Encode std::vector<value> encode as amqp::LIST (mixed type elements)
+template <class A> encoder& operator<<(encoder& e, const std::vector<value, A>& x) { return e << encoder::list(x); }
+
+/// Encode std::vector<scalar> as amqp::LIST (mixed type elements)
+template <class A> encoder& operator<<(encoder& e, const std::vector<scalar, A>& x) { return e << encoder::list(x); }
+
+/// Encode std::deque<std::pair<k,t> > as amqp::MAP, preserves order of entries.
+template <class A, class K, class T>
+encoder& operator<<(encoder& e, const std::vector<std::pair<K,T>, A>& x) { return e << encoder::map(x); }
+
+/// Decode to std::vector<T> from an amqp::LIST or amqp::ARRAY.
+template <class T, class A> decoder& operator>>(decoder& d, std::vector<T, A>& x) { return d >> decoder::sequence(x); }
+
+/// Decode to std::vector<std::pair<K, T> from an amqp::MAP.
+template <class A, class K, class T> decoder& operator>>(decoder& d, std::vector<std::pair<K, T> , A>& x) { return d >> decoder::pair_sequence(x); }
+
+} // codec
+} // proton
+
+#endif // PROTON_CODEC_VECTOR_HPP


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