PROTON-1109: Improve C++ binding documentation - Update the overview and tutorial; this is Alan's work - Add lots of new API documentation - Correct broken links - Hide elements of the API that are not yet settled - Configure doxygen for less cluttered output - Clean up the header files (all one style) - Adjust the formatting of some of the examples
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/72b5f953 Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/72b5f953 Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/72b5f953 Branch: refs/heads/master Commit: 72b5f95323cd316011b0aa6dce27a51ebffd85e9 Parents: 6e3d6ec Author: Justin Ross <[email protected]> Authored: Mon Jan 25 21:16:10 2016 -0800 Committer: Justin Ross <[email protected]> Committed: Mon Jan 25 21:16:10 2016 -0800 ---------------------------------------------------------------------- examples/cpp/README.hpp | 129 +++++++-- examples/cpp/broker.cpp | 7 +- examples/cpp/broker.hpp | 70 +++-- examples/cpp/client.cpp | 10 +- examples/cpp/direct_recv.cpp | 16 +- examples/cpp/direct_send.cpp | 17 +- examples/cpp/engine/helloworld.cpp | 4 +- examples/cpp/helloworld.cpp | 4 +- examples/cpp/helloworld_direct.cpp | 7 +- examples/cpp/queue_browser.cpp | 8 +- examples/cpp/selected_recv.cpp | 4 +- examples/cpp/server.cpp | 17 +- examples/cpp/server_direct.cpp | 15 +- examples/cpp/simple_recv.cpp | 18 +- examples/cpp/simple_send.cpp | 16 +- proton-c/CMakeLists.txt | 1 + proton-c/bindings/cpp/docs/mainpage.md | 234 ++++++++------- proton-c/bindings/cpp/docs/tutorial.hpp | 72 +++-- proton-c/bindings/cpp/docs/user.doxygen.in | 58 ++-- .../bindings/cpp/include/proton/acceptor.hpp | 21 +- .../cpp/include/proton/annotation_key.hpp | 38 ++- .../bindings/cpp/include/proton/condition.hpp | 26 +- proton-c/bindings/cpp/include/proton/config.hpp | 21 +- .../bindings/cpp/include/proton/connection.hpp | 88 +++--- .../cpp/include/proton/connection_engine.hpp | 85 +++--- .../cpp/include/proton/connection_options.hpp | 101 +++++-- .../bindings/cpp/include/proton/container.hpp | 98 ++++--- proton-c/bindings/cpp/include/proton/data.hpp | 13 +- .../bindings/cpp/include/proton/decoder.hpp | 6 +- .../bindings/cpp/include/proton/delivery.hpp | 101 +++---- .../bindings/cpp/include/proton/duration.hpp | 19 +- .../bindings/cpp/include/proton/encoder.hpp | 12 +- .../bindings/cpp/include/proton/endpoint.hpp | 55 ++-- proton-c/bindings/cpp/include/proton/error.hpp | 54 +++- proton-c/bindings/cpp/include/proton/event.hpp | 40 ++- proton-c/bindings/cpp/include/proton/export.hpp | 6 +- .../bindings/cpp/include/proton/handler.hpp | 82 ++++-- proton-c/bindings/cpp/include/proton/io.hpp | 52 ++-- proton-c/bindings/cpp/include/proton/link.hpp | 87 ++++-- .../cpp/include/proton/link_options.hpp | 137 +++++---- .../bindings/cpp/include/proton/message.hpp | 283 ++++++++++--------- .../bindings/cpp/include/proton/message_id.hpp | 41 ++- proton-c/bindings/cpp/include/proton/object.hpp | 25 +- .../cpp/include/proton/pn_unique_ptr.hpp | 24 +- .../bindings/cpp/include/proton/reactor.hpp | 7 + .../bindings/cpp/include/proton/receiver.hpp | 10 +- .../cpp/include/proton/reconnect_timer.hpp | 8 +- proton-c/bindings/cpp/include/proton/sasl.hpp | 35 ++- proton-c/bindings/cpp/include/proton/scalar.hpp | 82 ++++-- proton-c/bindings/cpp/include/proton/sender.hpp | 20 +- .../bindings/cpp/include/proton/session.hpp | 69 +++-- proton-c/bindings/cpp/include/proton/ssl.hpp | 106 +++++-- proton-c/bindings/cpp/include/proton/task.hpp | 12 +- .../bindings/cpp/include/proton/terminus.hpp | 69 +++-- .../bindings/cpp/include/proton/transport.hpp | 27 +- .../bindings/cpp/include/proton/type_traits.hpp | 20 +- proton-c/bindings/cpp/include/proton/types.hpp | 126 +++++---- proton-c/bindings/cpp/include/proton/url.hpp | 136 +++++---- proton-c/bindings/cpp/include/proton/value.hpp | 91 +++--- proton-c/include/proton/ssl.h | 8 +- 60 files changed, 1974 insertions(+), 1074 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/72b5f953/examples/cpp/README.hpp ---------------------------------------------------------------------- diff --git a/examples/cpp/README.hpp b/examples/cpp/README.hpp index de65d6e..c03982b 100644 --- a/examples/cpp/README.hpp +++ b/examples/cpp/README.hpp @@ -1,35 +1,34 @@ // Examples overview. // // For a better overview, see the tutorial in the generated documentation. +// // In your build directory do: +// // make docs-cpp -// then open proton-c/bindings/cpp/docs/html/tutorial.html in your browser. // +// then open proton-c/bindings/cpp/docs/html/tutorial.html in your browser. // DEVELOPER NOTE: if you are adding or modifying examples you should keep this // file and ../proton-c/bindings/cpp/docs/tutorial.hpp up to date. -/** \example helloworld.cpp +/** @example helloworld.cpp -Basic example that connects to an intermediary on 127.0.0.1:5672, -establishes a subscription from the 'examples' nodeu on that -intermediary, then creates a sending link to the same node and sends -one message. On receving the message back via the subcription, the -connection is closed. +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 helloworld_direct.cpp +/** @example helloworld_direct.cpp -A variant of the basic helloworld example, that does not use an -intermediary, but listens for incoming connections itself. It -establishes a connection to itself with a link over which a single -message is sent. This demonstrates the ease with which a simple daemon -can be built using the API. +Variation of helloworld that does not use a broker, but listens for +incoming connections itself. It establishes a connection to itself +with a link over which a single message is sent. This demonstrates the +ease with which a simple daemon an be built using the API. */ -/** \example simple_send.cpp +/** @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 @@ -37,14 +36,14 @@ an intermediary accessible on 127.0.0.1:5672. */ -/** \example simple_recv.cpp +/** @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 direct_send.cpp +/** @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. @@ -52,7 +51,7 @@ Make sure to stop the broker first or use a different port for `direct_send`. */ -/** \example direct_recv.cpp +/** @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. @@ -60,13 +59,16 @@ Make sure to stop the broker first or use a different port for `direct_recv`. */ -/** \example encode_decode.cpp +/// @cond INTERNAL +/// XXX change namespaces +/** @example encode_decode.cpp Shows how C++ data types can be converted to and from AMQP types. */ +/// @endcond -/** \example client.cpp +/** @example client.cpp The client part of a request-response example. Sends requests and prints out responses. Requires an intermediary that supports the AMQP @@ -75,7 +77,7 @@ are sent through the 'examples' node. */ -/** \example server.cpp +/** @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 @@ -83,9 +85,9 @@ result back to the indicated reply address. */ -/** \example server_direct.cpp +/** @example server_direct.cpp -A variant of the server part of a request-response example, that +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 @@ -94,23 +96,98 @@ alternatives. */ -/** \example broker.hpp +/** @example broker.hpp Common logic for a simple "mini broker" that creates creates queues automatically when a client tries to send or subscribe. This file contains the `queue` class that queues messages and the `broker_handler` class that manages queues and links and transfers messages to/from clients. -There are several broker programs all using the same logic but illustrating -different ways to run a server application. +Examples \ref broker.cpp and \ref engine/broker.cpp use this same +broker logic but show different ways to run it in a server application. + +*/ + +/** @example broker.cpp + +A simple, single-threaded broker using the `proton::container`. You can use this +to run other examples that reqiure an intermediary, or you can use any AMQP 1.0 +broker. This broker creates queues automatically when a client tries to send or +subscribe. + +Uses the broker logic from \ref broker.hpp, the same logic as the +`proton::connection_engine` broker example \ref engine/broker.cpp. + +*/ + +//////////////// connection_engine examples. + +/** \example engine/helloworld.cpp + +`proton::connection_engine` example to send a "Hello World" message to +itself. Compare with the corresponding `proton::container` example \ref +helloworld.cpp. + +*/ + +/** \example engine/simple_send.cpp + +`proton::connection_engine` 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 broker.cpp +/** \example engine/simple_recv.cpp + +`proton::connection_engine` example that subscribes to the 'examples' node and prints + the body of received messages. + +*/ + +/** \example engine/direct_send.cpp + +`proton::connection_engine` example 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 engine/direct_recv.cpp + +`proton::connection_engine` example 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`. + +*/ + +/** \example engine/client.cpp + +`proton::connection_engine` client for 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 engine/server.cpp + +`proton::connection_engine` server for 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 engine/broker.cpp A simple, single-threaded broker using the `proton::container`. You can use this to run other examples that reqiure an intermediary, or you can use any AMQP 1.0 broker. This broker creates queues automatically when a client tries to send or subscribe. +Uses the broker logic from \ref broker.hpp, the same logic as the +proton::container` broker example \ref broker.cpp. + */ http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/72b5f953/examples/cpp/broker.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/broker.cpp b/examples/cpp/broker.cpp index 097a612..48efa93 100644 --- a/examples/cpp/broker.cpp +++ b/examples/cpp/broker.cpp @@ -39,7 +39,6 @@ class broker { proton::handler& handler() { return handler_; } private: - class my_handler : public broker_handler { public: my_handler(const proton::url& u, queues& qs) : broker_handler(qs), url_(u) {} @@ -59,19 +58,23 @@ class broker { }; int main(int argc, char **argv) { - // Command line options proton::url url("0.0.0.0"); options opts(argc, argv); + opts.add_value(url, 'a', "address", "listen on URL", "URL"); + try { opts.parse(); + broker b(url); proton::container(b.handler()).run(); + return 0; } catch (const 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/72b5f953/examples/cpp/broker.hpp ---------------------------------------------------------------------- diff --git a/examples/cpp/broker.hpp b/examples/cpp/broker.hpp index 1c13ae4..c7fd0df 100644 --- a/examples/cpp/broker.hpp +++ b/examples/cpp/broker.hpp @@ -1,5 +1,6 @@ #ifndef BROKER_HPP #define BROKER_HPP + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -19,13 +20,12 @@ * under the License. */ -/**@file - * - * Common code used by different broker examples. - * - * The examples add functionality as needed, this helps to make it easier to see - * the important differences between the examples. - */ +/// @file +/// +/// Common code used by different broker examples. +/// +/// The examples add functionality as needed, this helps to make it +/// easier to see the important differences between the examples. #include "proton/event.hpp" #include "proton/message.hpp" @@ -39,7 +39,7 @@ #include <list> #include <sstream> -/** A simple implementation of a queue. */ +/// A simple implementation of a queue. class queue { public: queue(const std::string &name, bool dynamic = false) : name_(name), dynamic_(dynamic) {} @@ -66,26 +66,34 @@ class queue { } bool deliver_to(proton::sender *s) { - // deliver to single sender if supplied, else all consumers + // Deliver to single sender if supplied, else all consumers int count = s ? 1 : consumers_.size(); + if (!count) return false; + bool result = false; sender_list::iterator it = consumers_.begin(); - if (!s && count) - s = &*it; + if (!s && count) { + s = &*it; + } + while (messages_.size()) { if (s->credit()) { const proton::message& m = messages_.front(); + s->send(m); messages_.pop_front(); result = true; } - if (--count) + + if (--count) { it++; - else + } else { return result; + } } + return false; } @@ -99,17 +107,21 @@ class queue { sender_list consumers_; }; -/** A collection of queues and queue factory, used by a broker */ +/// A collection of queues and queue factory, used by a broker. class queues { public: queues() : next_id_(0) {} // Get or create a queue. virtual queue &get(const std::string &address = std::string()) { - if (address.empty()) + if (address.empty()) { throw std::runtime_error("empty queue name"); + } + queue*& q = queues_[address]; + if (!q) q = new queue(address); + return *q; } @@ -118,6 +130,7 @@ class queues { std::ostringstream os; os << "q" << next_id_++; queue *q = queues_[os.str()] = new queue(os.str(), true); + return *q; } @@ -130,7 +143,7 @@ class queues { protected: typedef std::map<std::string, queue *> queue_map; queue_map queues_; - uint64_t next_id_; // Use to generate unique queue IDs. + uint64_t next_id_; // Use to generate unique queue IDs. }; @@ -141,15 +154,17 @@ class broker_handler : public proton::handler { void on_link_open(proton::event &e) { proton::link lnk = e.link(); + if (!!lnk.sender()) { proton::terminus remote_source(lnk.remote_source()); queue &q = remote_source.dynamic() ? queues_.dynamic() : queues_.get(remote_source.address()); lnk.local_source().address(q.name()); + q.subscribe(lnk.sender()); std::cout << "broker outgoing link from " << q.name() << std::endl; - } - else { // Receiver + } else { + // Receiver std::string address = lnk.remote_target().address(); if (!address.empty()) { lnk.local_target().address(address); @@ -158,16 +173,20 @@ class broker_handler : public proton::handler { } } - void unsubscribe (proton::sender lnk) { + void unsubscribe(proton::sender lnk) { std::string address = lnk.local_source().address(); - if (queues_.get(address).unsubscribe(lnk)) + + if (queues_.get(address).unsubscribe(lnk)) { queues_.erase(address); + } } void on_link_close(proton::event &e) { proton::link lnk = e.link(); - if (!!lnk.sender()) + + if (!!lnk.sender()) { unsubscribe(lnk.sender()); + } } void on_connection_close(proton::event &e) { @@ -179,10 +198,12 @@ class broker_handler : public proton::handler { } void remove_stale_consumers(proton::connection connection) { - proton::link_range r = connection.find_links(proton::endpoint::REMOTE_ACTIVE); + proton::link_range r = connection.find_links(proton::endpoint::REMOTE_ACTIVE); + for (proton::link_iterator l = r.begin(); l != r.end(); ++l) { - if (!!l->sender()) + if (!!l->sender()) { unsubscribe(l->sender()); + } } } @@ -190,11 +211,13 @@ class broker_handler : public proton::handler { proton::link lnk = e.link(); std::string address = lnk.local_source().address(); proton::sender s = lnk.sender(); + queues_.get(address).dispatch(&s); } void on_message(proton::event &e) { std::string address = e.link().local_target().address(); + queues_.get(address).publish(e.message(), e.link().receiver()); } @@ -202,5 +225,4 @@ class broker_handler : public proton::handler { queues& queues_; }; - #endif // BROKER_HPP http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/72b5f953/examples/cpp/client.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/client.cpp b/examples/cpp/client.cpp index 60eb13b..43ccb3c 100644 --- a/examples/cpp/client.cpp +++ b/examples/cpp/client.cpp @@ -48,19 +48,24 @@ class client : public proton::handler { proton::message req; req.body(requests.front()); req.reply_to(receiver.remote_source().address()); + sender.send(req); } void on_link_open(proton::event &e) { - if (e.link() == receiver) + if (e.link() == receiver) { send_request(); + } } void on_message(proton::event &e) { if (requests.empty()) return; // Spurious extra message! + proton::message& response = e.message(); + std::cout << requests.front() << " => " << response.body() << std::endl; requests.erase(requests.begin()); + if (!requests.empty()) { send_request(); } else { @@ -70,9 +75,9 @@ class client : public proton::handler { }; int main(int argc, char **argv) { - // Command line options proton::url url("127.0.0.1:5672/examples"); options opts(argc, argv); + opts.add_value(url, 'a', "address", "connect and send to URL", "URL"); try { @@ -93,5 +98,6 @@ int main(int argc, char **argv) { } catch (const std::exception& e) { std::cerr << e.what() << std::endl; } + return 1; } http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/72b5f953/examples/cpp/direct_recv.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/direct_recv.cpp b/examples/cpp/direct_recv.cpp index 56fa1e2..ffb2f03 100644 --- a/examples/cpp/direct_recv.cpp +++ b/examples/cpp/direct_recv.cpp @@ -49,37 +49,45 @@ class direct_recv : public proton::handler { void on_message(proton::event &e) { proton::message& msg = e.message(); - if (msg.id().get<uint64_t>() < received) - return; // ignore duplicate + + if (msg.id().get<uint64_t>() < received) { + return; // Ignore duplicate + } + if (expected == 0 || received < expected) { std::cout << msg.body() << std::endl; received++; } + if (received == expected) { e.receiver().close(); e.connection().close(); + if (!!acceptor) acceptor.close(); } } }; int main(int argc, char **argv) { - // Command line options std::string address("127.0.0.1:5672/examples"); int message_count = 100; 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 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/72b5f953/examples/cpp/direct_send.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/direct_send.cpp b/examples/cpp/direct_send.cpp index d171175..edd7102 100644 --- a/examples/cpp/direct_send.cpp +++ b/examples/cpp/direct_send.cpp @@ -38,8 +38,8 @@ class simple_send : public proton::handler { int confirmed; int total; proton::acceptor acceptor; - public: + public: simple_send(const std::string &s, int c) : url(s), sent(0), confirmed(0), total(c) {} void on_start(proton::event &e) { @@ -49,12 +49,15 @@ class simple_send : public proton::handler { void on_sendable(proton::event &e) { proton::sender sender = e.sender(); + while (sender.credit() && sent < total) { proton::message msg; - msg.id(sent + 1); std::map<std::string, int> m; - m["sequence"] = sent+1; + m["sequence"] = sent + 1; + + msg.id(sent + 1); msg.body(m); + sender.send(msg); sent++; } @@ -62,8 +65,10 @@ class simple_send : public proton::handler { void on_delivery_accept(proton::event &e) { confirmed++; + if (confirmed == total) { std::cout << "all messages confirmed" << std::endl; + e.connection().close(); acceptor.close(); } @@ -75,21 +80,25 @@ class simple_send : public proton::handler { }; int main(int argc, char **argv) { - // Command line options std::string address("127.0.0.1:5672/examples"); int message_count = 100; 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 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/72b5f953/examples/cpp/engine/helloworld.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/engine/helloworld.cpp b/examples/cpp/engine/helloworld.cpp index 72be78e..4440e4d 100644 --- a/examples/cpp/engine/helloworld.cpp +++ b/examples/cpp/engine/helloworld.cpp @@ -31,7 +31,6 @@ class hello_world : public proton::handler { std::string address_; public: - hello_world(const std::string& address) : address_(address) {} void on_start(proton::event &e) { @@ -55,11 +54,14 @@ class hello_world : public proton::handler { int main(int argc, char **argv) { try { proton::url url(argc > 1 ? argv[1] : "127.0.0.1:5672/examples"); + hello_world hw(url.path()); proton::io::socket_engine(url, hw).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/72b5f953/examples/cpp/helloworld.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/helloworld.cpp b/examples/cpp/helloworld.cpp index b8f8b61..a969f27 100644 --- a/examples/cpp/helloworld.cpp +++ b/examples/cpp/helloworld.cpp @@ -31,7 +31,6 @@ class hello_world : public proton::handler { proton::url url; public: - hello_world(const proton::url& u) : url(u) {} void on_start(proton::event &e) { @@ -55,11 +54,14 @@ class hello_world : public proton::handler { int main(int argc, char **argv) { try { std::string url = argc > 1 ? argv[1] : "127.0.0.1:5672/examples"; + hello_world hw(url); proton::container(hw).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/72b5f953/examples/cpp/helloworld_direct.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/helloworld_direct.cpp b/examples/cpp/helloworld_direct.cpp index 8b4af5b..05ae8a2 100644 --- a/examples/cpp/helloworld_direct.cpp +++ b/examples/cpp/helloworld_direct.cpp @@ -30,8 +30,8 @@ class hello_world_direct : public proton::handler { private: proton::url url; proton::acceptor acceptor; - public: + public: hello_world_direct(const proton::url& u) : url(u) {} void on_start(proton::event &e) { @@ -60,14 +60,17 @@ class hello_world_direct : public proton::handler { int main(int argc, char **argv) { try { - // Pick an "unusual" port since we are going to be talking to ourselves, not a broker. + // Pick an "unusual" port since we are going to be talking to + // ourselves, not a broker. std::string url = argc > 1 ? argv[1] : "127.0.0.1:8888/examples"; hello_world_direct hwd(url); proton::container(hwd).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/72b5f953/examples/cpp/queue_browser.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/queue_browser.cpp b/examples/cpp/queue_browser.cpp index 015e6ad..02c0b30 100644 --- a/examples/cpp/queue_browser.cpp +++ b/examples/cpp/queue_browser.cpp @@ -32,7 +32,6 @@ class browser : public proton::handler { proton::url url; public: - browser(const proton::url& u) : url(u) {} void on_start(proton::event &e) { @@ -42,19 +41,24 @@ class browser : public proton::handler { void on_message(proton::event &e) { std::cout << e.message().body() << std::endl; - if (e.receiver().queued() == 0 && e.receiver().drained() > 0) + + if (e.receiver().queued() == 0 && e.receiver().drained() > 0) { e.connection().close(); + } } }; int main(int argc, char **argv) { try { std::string url = argc > 1 ? argv[1] : "127.0.0.1:5672/examples"; + browser b(url); proton::container(b).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/72b5f953/examples/cpp/selected_recv.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/selected_recv.cpp b/examples/cpp/selected_recv.cpp index ad010c0..a07d9a5 100644 --- a/examples/cpp/selected_recv.cpp +++ b/examples/cpp/selected_recv.cpp @@ -32,7 +32,6 @@ class selected_recv : public proton::handler { proton::url url; public: - selected_recv(const proton::url& u) : url(u) {} void on_start(proton::event &e) { @@ -48,11 +47,14 @@ class selected_recv : public proton::handler { int main(int argc, char **argv) { try { std::string url = argc > 1 ? argv[1] : "127.0.0.1:5672/examples"; + selected_recv recv(url); proton::container(recv).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/72b5f953/examples/cpp/server.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/server.cpp b/examples/cpp/server.cpp index 7711f0e..d913ee1 100644 --- a/examples/cpp/server.cpp +++ b/examples/cpp/server.cpp @@ -40,49 +40,60 @@ class server : public proton::handler { sender_map senders; public: - server(const std::string &u) : url(u) {} void on_start(proton::event &e) { connection = e.container().connect(url); connection.open_receiver(url.path()); + std::cout << "server connected to " << url << std::endl; } std::string to_upper(const std::string &s) { std::string uc(s); size_t l = uc.size(); + for (size_t i=0; i<l; i++) uc[i] = std::toupper(uc[i]); + return uc; } void on_message(proton::event &e) { std::cout << "Received " << e.message().body() << std::endl; + std::string reply_to = e.message().reply_to(); proton::message reply; + reply.address(reply_to); reply.body(to_upper(e.message().body().get<std::string>())); reply.correlation_id(e.message().correlation_id()); - if (!senders[reply_to]) + + if (!senders[reply_to]) { senders[reply_to] = connection.open_sender(reply_to); + } + senders[reply_to].send(reply); } }; int main(int argc, char **argv) { - // Command line options std::string address("amqp://0.0.0.0:5672/examples"); options opts(argc, argv); + opts.add_value(address, 'a', "address", "listen on URL", "URL"); + try { opts.parse(); + server srv(address); proton::container(srv).run(); + return 0; } catch (const 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/72b5f953/examples/cpp/server_direct.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/server_direct.cpp b/examples/cpp/server_direct.cpp index abc49c0..9d3b79c 100644 --- a/examples/cpp/server_direct.cpp +++ b/examples/cpp/server_direct.cpp @@ -41,7 +41,6 @@ class server : public proton::handler { int address_counter; public: - server(const std::string &u) : url(u), address_counter(0) {} void on_start(proton::event &e) { @@ -52,18 +51,22 @@ class server : public proton::handler { std::string to_upper(const std::string &s) { std::string uc(s); size_t l = uc.size(); + for (size_t i=0; i<l; i++) uc[i] = std::toupper(uc[i]); + return uc; } std::string generate_address() { std::ostringstream addr; addr << "server" << address_counter++; + return addr.str(); } void on_link_open(proton::event& e) { proton::link link = e.link(); + if (!!link.sender() && link.remote_source().dynamic()) { link.local_source().address(generate_address()); senders[link.local_source().address()] = link.sender(); @@ -72,35 +75,43 @@ class server : public proton::handler { void on_message(proton::event &e) { std::cout << "Received " << e.message().body() << std::endl; + std::string reply_to = e.message().reply_to(); sender_map::iterator it = senders.find(reply_to); + if (it == senders.end()) { std::cout << "No link for reply_to: " << reply_to << std::endl; } else { proton::sender sender = it->second; proton::message reply; + reply.address(reply_to); reply.body(to_upper(e.message().body().get<std::string>())); reply.correlation_id(e.message().correlation_id()); + sender.send(reply); } } }; int main(int argc, char **argv) { - // Command line options std::string address("amqp://127.0.0.1:5672/examples"); options opts(argc, argv); + opts.add_value(address, 'a', "address", "listen on URL", "URL"); + try { opts.parse(); + server srv(address); proton::container(srv).run(); + return 0; } catch (const 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/72b5f953/examples/cpp/simple_recv.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/simple_recv.cpp b/examples/cpp/simple_recv.cpp index c3df477..22d603e 100644 --- a/examples/cpp/simple_recv.cpp +++ b/examples/cpp/simple_recv.cpp @@ -31,16 +31,14 @@ #include <iostream> #include <map> - - class simple_recv : public proton::handler { private: proton::url url; proton::receiver receiver; uint64_t expected; uint64_t received; - public: + public: simple_recv(const std::string &s, int c) : url(s), expected(c), received(0) {} void on_start(proton::event &e) { @@ -50,11 +48,15 @@ class simple_recv : public proton::handler { void on_message(proton::event &e) { proton::message& msg = e.message(); - if (msg.id().get<uint64_t>() < received) - return; // ignore duplicate + + if (msg.id().get<uint64_t>() < received) { + return; // Ignore duplicate + } + if (expected == 0 || received < expected) { std::cout << msg.body() << std::endl; received++; + if (received == expected) { e.receiver().close(); e.connection().close(); @@ -64,22 +66,26 @@ class simple_recv : public proton::handler { }; int main(int argc, char **argv) { - // Command line options std::string address("127.0.0.1:5672/examples"); + int message_count = 100; options opts(argc, argv); + opts.add_value(address, 'a', "address", "connect to and receive from URL", "URL"); opts.add_value(message_count, 'm', "messages", "receive COUNT messages", "COUNT"); try { opts.parse(); + simple_recv recv(address, message_count); proton::container(recv).run(); + return 0; } catch (const 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/72b5f953/examples/cpp/simple_send.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/simple_send.cpp b/examples/cpp/simple_send.cpp index cfec153..8598fe0 100644 --- a/examples/cpp/simple_send.cpp +++ b/examples/cpp/simple_send.cpp @@ -37,8 +37,8 @@ class simple_send : public proton::handler { int sent; int confirmed; int total; - public: + public: simple_send(const std::string &s, int c) : url(s), sent(0), confirmed(0), total(c) {} void on_start(proton::event &e) { @@ -47,12 +47,15 @@ class simple_send : public proton::handler { void on_sendable(proton::event &e) { proton::sender sender = e.sender(); + while (sender.credit() && sent < total) { proton::message msg; - msg.id(sent + 1); std::map<std::string, int> m; - m["sequence"] = sent+1; + m["sequence"] = sent + 1; + + msg.id(sent + 1); msg.body(m); + sender.send(msg); sent++; } @@ -60,6 +63,7 @@ class simple_send : public proton::handler { void on_delivery_accept(proton::event &e) { confirmed++; + if (confirmed == total) { std::cout << "all messages confirmed" << std::endl; e.connection().close(); @@ -72,21 +76,25 @@ class simple_send : public proton::handler { }; int main(int argc, char **argv) { - // Command line options std::string address("127.0.0.1:5672/examples"); int message_count = 100; 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"); + try { opts.parse(); + simple_send send(address, message_count); proton::container(send).run(); + return 0; } catch (const 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/72b5f953/proton-c/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/proton-c/CMakeLists.txt b/proton-c/CMakeLists.txt index 9d97348..c3f9294 100644 --- a/proton-c/CMakeLists.txt +++ b/proton-c/CMakeLists.txt @@ -43,6 +43,7 @@ else() set (OPTIONAL_ARG OPTIONAL) add_custom_target(docs) endif() +add_custom_target(doc DEPENDS docs) # Set the default SSL/TLS implementation find_package(OpenSSL) http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/72b5f953/proton-c/bindings/cpp/docs/mainpage.md ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/docs/mainpage.md b/proton-c/bindings/cpp/docs/mainpage.md index 3f7e35c..f20d957 100644 --- a/proton-c/bindings/cpp/docs/mainpage.md +++ b/proton-c/bindings/cpp/docs/mainpage.md @@ -1,112 +1,136 @@ -Introduction {#mainpage} -============ +# Introduction {#mainpage} -This is the C++ API for the proton AMQP protocol engine. It allows you to write -client and server applications that send and receive AMQP messages. +This is the C++ API for the Proton AMQP protocol engine. It allows you +to write client and server applications that send and receive AMQP +messages. The best way to start is with the \ref tutorial "tutorial". -An overview of the model ------------------------- - -Messages are transferred between connected peers over 'links'. At the sending -peer the link is called a sender. At the receiving peer it is called a -receiver. Messages are sent by senders and received by receivers. Links may have -named 'source' and 'target' addresses (see "sources and targets" below.) - -Links are established over sessions. Sessions are established over -connections. Connections are (generally) established between two uniquely -identified containers. Though a connection can have multiple sessions, often -this is not needed. The container API allows you to ignore sessions unless you -actually require them. - -The sending of a message over a link is called a delivery. The message -is the content sent, including all meta-data such as headers and -annotations. The delivery is the protocol exchange associated with the -transfer of that content. - -To indicate that a delivery is complete, either the sender or the -receiver 'settles' it. When the other side learns that it has been -settled, they will no longer communicate about that delivery. The -receiver can also indicate whether they accept or reject the -message. - -Three different delivery levels or 'guarantees' can be achieved: at-most-once, -at-least-once or exactly-once. See below for details. - -### 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 just the response message. - -The most common approach is for the client to create a *receiver* for the -response with the *dynamic* flag set. This asks the server to generate a unique -*source* address automatically and discard it when the link closes. The client -uses this "dynamic" source address as the reply-to when it sends the request, -and the response is delivered to the client's dynamic receiver. - -In the case of a broker a dynamic address usually corresponds to a temporary -queue but any AMQP request-response server can use this technique. The \ref -server_direct.cpp example illustrates how to implement a queueless -request-response server. - -Commonly used classes ---------------------- - -A brief summary of some of the key classes follows. - -The `proton::container` class is the main entry point into the API, allowing -connections and links to be established. Applications are structured as one or -more event handlers. - -The easiest way to implement a handler is to define a subclass of -`proton::messaging_handler` and over-ride the event handling member functions -that interest you. - -To send messages, call `proton::container::create_sender()` to create a -`proton::sender` and then call `proton::sender::send()`. This is typically done -when the sender is *sendable*, a condition indicated by the -`proton::messaging_handler::on_sendable()` event, to avoid execessive build up -of messages. - -To receive messages, call `proton::container::create_receiver()` to create a -`proton::receiver`. When messages are recieved the -`proton::messaging_handler::on_message()` event handler function will be called. - -Other key classes: - -- proton::message represents an AMQP message, which has a body, headers and other properties. -- proton::connection represents a connection to a remote AMQP endpoint. -- proton::delivery holds the delivery status of a message. -- proton::event carries details of an event. - -The library provides intuitive default conversions between AMQP and C++ types -for message data q, but also allows detailed examination and construction of -complex AMQP types. For details on converting between AMQP and C++ data types -see the \ref encode_decode.cpp example and classes `proton::encoder`, -`proton::decoder` and `proton::value`. - -`proton::connection_engine` provides fewer facilities that `proton::container` -but makes fewer (no) assumptions about application threading and IO. It may be -easier to integrate with an existing IO framework, for multi-threaded -applications or for non-socket IO. See the \ref select_broker.cpp example. The -main application and AMQP logic is implemented the same way using the `connection_engine` or -the container. - -Delivery Guarantees -------------------- +## An overview of the AMQP model + +Messages are transferred between connected peers over *links*. The +sending end of a link is a `proton::sender`, and the receiving end is +a `proton::receiver`. Links have named 'source' and 'target' +addresses. See "Sources and Targets" below for more information. + +Links are grouped in a `proton::session`. Messages for links in the +same session are sent sequentially. Messages on different sessions +can be interleaved, so a large message being sent on one session does +not block messages being sent on other sessions. + +Sessions are created over a `proton::connection`, which represents the +network connection. You can create links directly on a connection +using its default session if you don't need multiple sessions. + +`proton::message` represents the message: the body (content), headers, +annotations, and so on. A `proton::delivery` represents the act of +transferring a message over a link. The receiver acknowledges the +delivery by accepting or rejecting it. The 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 "Delivery Guarantees" below for details. + +## 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 just +the response message. + +The most common approach is for the client to create a *receiver* for +the response with the *dynamic* flag set. This asks the server to +generate a unique *source* address automatically and discard it when +the link closes. The client uses this "dynamic" source address as the +reply-to when it sends the request, and the response is delivered to +the client's dynamic receiver. + +In the case of a broker, a dynamic address usually corresponds to a +temporary queue, but any AMQP request-response server can use this +technique. The \ref server_direct.cpp example illustrates how to +implement a queueless request-response server. + +## Anatomy of a Proton application + +To send AMQP commands, call methods on classes like +`proton::connection`, `proton::sender`, `proton::receiver`, or +`proton::delivery`. To handle incoming commands, implement the +`proton::handler` interface. The handler receives calls like +`on_message` (a message is received), `on_link_open` (a link is +opened), and `on_sendable` (a link is ready to send messages). + +Messages are represented by `proton::message`. AMQP defines a type +encoding that you can use for interoperability, but you can also use +any encoding you wish and pass binary data as the +`proton::message::body`. `proton::value` and `proton::scalar` provide +conversion between AMQP and C++ data types. + +<!-- See the example \ref encode_decode.cpp. --> + +There are two alternative ways to manage handlers and AMQP objects, +the `proton::container` and the `proton::connection_engine`. You can +code your application so that it can be run with either. Say you find +the `proton::container` easier to get started but later need more +flexibility. You can switch to the `proton::connection_engine` with +little or no change to your handlers. + +### %proton::container + +`proton::container` is a *reactor* framework that manages multiple +connections and dispatches events to handlers. You implement +`proton::handler` with your logic to react to events, and register it +with the container. The container lets you open multiple connections +and links, receive incoming connections and links, and send, receive, +and acknowledge messages. + +The reactor handles IO for multiple connections using sockets and +`poll`. It dispatches events to your handlers in a single thread, +where you call `proton::container::run`. The container is not +thread-safe: once it is running you can only operate on Proton objects +from your handler methods. + +### %proton::connection_engine + +`proton::connection_engine` dispatches events for a *single +connection*. The subclass `proton::io::socket_engine` does +socket-based IO. An application with a single connection is just like +using `proton::container` except you attach your handler to a +`proton::io::socket_engine` instead. You can compare examples, such as +\ref helloworld.cpp and \ref engine/helloworld.cpp. + +Now consider multiple connections. `proton::container` is easy to use +but restricted to a single thread. `proton::connection_engine` is not +thread-safe either, but *each engine is independent*. You can process +different connections in different threads, or use a thread pool to +process a dynamic set of connections. + +The engine does not provide built-in polling and listening like the +`proton::container`, but you can drive engines using any polling or +threading strategy and any IO library (for example, epoll, kqueue, +solaris completion ports, IOCP proactor, boost::asio, libevent, etc.) +This can be important for optimizing performance or supporting diverse +platforms. The example \ref engine/broker.cpp shows a broker using +sockets and poll, but you can see how the code could be adapted. + +`proton::connection_engine` also does not dictate the IO mechanism, +but it is an abstract class. `proton::socket_engine` provides +ready-made socket-based IO, but you can write your own subclass with +any IO code. Just override the `io_read`, `io_write` and `io_close` +methods. For example, the proton test suite implements an in-memory +connection using `std::deque` for test purposes. + +## Delivery guarantees 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 http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/72b5f953/proton-c/bindings/cpp/docs/tutorial.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/docs/tutorial.hpp b/proton-c/bindings/cpp/docs/tutorial.hpp index 81ca7c9..dcfbe05 100644 --- a/proton-c/bindings/cpp/docs/tutorial.hpp +++ b/proton-c/bindings/cpp/docs/tutorial.hpp @@ -3,7 +3,7 @@ // that shows messed-up line numbers in \skip \until code extracts so this file // is markdown wrapped in a C++ comment - which works. -/*! \page tutorial Tutorial +/**\page tutorial Tutorial This is a brief tutorial that will walk you through the fundamentals of building messaging applications in incremental steps. There are further examples, in @@ -28,6 +28,10 @@ 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). URL details are at `proton::url` +The first part of the tutorial uses the `proton::container`, later we will +show some of the same examples implemented using the `proton::connection_engine`. +Most of the code is the same for either approach. + Hello World! ------------ @@ -39,14 +43,14 @@ receiving. 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* +which dispatches events to a `proton::handler`. This allows a *reactive* style of programming which is well suited to messaging applications. `proton::url` is a simple parser for the URL format mentioned above. \skip proton/container \until proton/url We will define a class `hello_world` which is a subclass of -`proton::messaging_handler` and over-rides functions to handle the events +`proton::handler` and over-rides functions to handle the events of interest in sending and receiving a message. \skip class hello_world @@ -121,18 +125,18 @@ as before. However we also handle two new events. We now close the connection from the senders side once the message has been accepted. The acceptance of the message is an indication of successful transfer to the -peer. We are notified of that event through the `on_accepted()` +peer. We are notified of that event through the `on_delivery_accept()` callback. -\skip on_accepted +\skip on_delivery_accept \until } Then, once the connection has been closed, of which we are -notified through the `on_closed()` callback, we stop accepting incoming +notified through the `on_connection_close()` callback, we stop accepting incoming connections at which point there is no work to be done and the event loop exits, and the run() method will return. -\skip on_closed +\skip on_connection_close \until } So now we have our example working without a broker involved! @@ -193,7 +197,7 @@ 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_accepted +\skip on_delivery_accept \until } \until } @@ -209,7 +213,7 @@ 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_disconnected +\skip on_disconnect \until } \dontinclude simple_recv.cpp @@ -283,7 +287,7 @@ link, we listen for incoming connections. When we have received confirmation of all the messages we sent, we can close the acceptor in order to exit. -\skip on_accepted +\skip on_delivery_accept \until } \until } @@ -340,11 +344,11 @@ reply_to address to be the dynamically assigned address of our receiver. 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 `on_link_opened()` method to our handler class, and if the link +that, we add an `on_link_open()` method to our handler class, and if the link associated with event is the receiver, we use that as the trigger to send our first request. -\skip on_link_opened +\skip on_link_open \until } When we receive a reply, we send the next request. @@ -374,7 +378,7 @@ 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_link_opening +\skip on_link_open \until } Note we are interested in *sender* links above because we are implementing the @@ -388,21 +392,37 @@ Finally when we receive a message we look up its `reply_to` in our senders map a \until } \until } -/* TODO selector and browser +Connection Engine +----------------- + +The `proton::connection_engine` is an alternative to the container. For simple +applications with a single connection, its use is about the same as the the +`proton::container`, but it allows more flexibility for multi-threaded +applications or applications with unusual IO requirements. + +\dontinclude engine/helloworld.cpp + +We'll look at the \ref engine/helloworld.cpp example step-by-step to see how it differs +from the container \ref helloworld.cpp version. -Many brokers offer the ability to consume messages based on a 'selector' -that defines which messages are of interest based on particular values -of the headers. The following example shows how that can be achieved: +First we include the `proton::io::socket_engine` class, which is a `proton::connection_engine` +that uses socket IO. -\todo TODO selected_recv.cpp +\skipline proton/io.hpp -When creating the receiver, we specify a Selector object as an option. -The options argument can take a single object or a list. Another option -that is sometimes of interest when using a broker is the ability to -'browse' the messages on a queue, rather than consuming them. This is -done in AMQP by specifying a distribution mode of 'copy' (instead of -'move' which is the expected default for queues). An example of that is -shown next: +Our `hello_world` class differs only in the `on_start()` method. Instead of +calling `container.connect()`, we simply call `proton::connection::open` to open the +engine's' connection: + +\skip on_start +\until } + +Our `main` function only differs in that it creates and runs a `socket_engine` +instead of a `container`. + +\skip main +\until } +\until } +\until } -\todo TODO queue_browser.cpp */ http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/72b5f953/proton-c/bindings/cpp/docs/user.doxygen.in ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/docs/user.doxygen.in b/proton-c/bindings/cpp/docs/user.doxygen.in index fa4a9f2..e76337a 100644 --- a/proton-c/bindings/cpp/docs/user.doxygen.in +++ b/proton-c/bindings/cpp/docs/user.doxygen.in @@ -1,4 +1,4 @@ -# +## ## 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 @@ -19,31 +19,38 @@ # Project options -PROJECT_NAME = proton-cpp -PROJECT_NUMBER = @PN_VERSION_MAJOR@.@PN_VERSION_MINOR@ -PROJECT_BRIEF = "Proton C++ API" -OUTPUT_DIRECTORY = . -OUTPUT_LANGUAGE = English -BRIEF_MEMBER_DESC = YES -REPEAT_BRIEF = YES -INLINE_INHERITED_MEMB = YES -JAVADOC_AUTOBRIEF = YES -MULTILINE_CPP_IS_BRIEF = NO -INHERIT_DOCS = YES -BUILTIN_STL_SUPPORT = YES -INLINE_SIMPLE_STRUCTS = YES +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 +INLINE_INHERITED_MEMB = YES +JAVADOC_AUTOBRIEF = YES +MULTILINE_CPP_IS_BRIEF = NO +INHERIT_DOCS = YES +BUILTIN_STL_SUPPORT = YES +INLINE_SIMPLE_STRUCTS = YES +EXTRACT_LOCAL_CLASSES = NO +HIDE_UNDOC_CLASSES = YES +HIDE_COMPOUND_REFERENCE = YES +HIDE_SCOPE_NAMES = YES +MAX_INITIALIZER_LINES = 0 +ALPHABETICAL_INDEX = NO -# Build related configuration options +# Redefine protected as private and strip out the PN_CPP_EXTERN macro -EXTRACT_ALL = YES -INTERNAL_DOCS = NO +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = YES +EXPAND_ONLY_PREDEF = YES +PREDEFINED = protected=private PN_CPP_EXTERN= -# configuration options related to warning and progress messages +# Configuration options related to warning and progress messages QUIET = YES WARNINGS = YES -# configuration options related to the input files +# Configuration options related to the input files INPUT = @CMAKE_SOURCE_DIR@/proton-c/bindings/cpp/include @CMAKE_SOURCE_DIR@/proton-c/bindings/cpp/docs @CMAKE_SOURCE_DIR@/examples/cpp/README.hpp FILE_PATTERNS = *.hpp *.md @@ -53,17 +60,14 @@ EXAMPLE_RECURSIVE = YES # View and list options -GENERATE_TREEVIEW = YES -GENERATE_TODOLIST = NO -GENERATE_TESTLIST = NO -GENERATE_BUGLIST = NO -GENERATE_DEPRECATEDLIST= YES - +GENERATE_TODOLIST = NO +GENERATE_TESTLIST = NO +GENERATE_BUGLIST = NO +GENERATE_DEPRECATEDLIST = YES -# configuration options related to the HTML output +# 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/72b5f953/proton-c/bindings/cpp/include/proton/acceptor.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/acceptor.hpp b/proton-c/bindings/cpp/include/proton/acceptor.hpp index 4edcc11..ebca8ba 100644 --- a/proton-c/bindings/cpp/include/proton/acceptor.hpp +++ b/proton-c/bindings/cpp/include/proton/acceptor.hpp @@ -30,23 +30,28 @@ struct pn_connection_t; namespace proton { -/** acceptor accepts connections. @see container::listen */ +/// A context for accepting inbound connections. +/// +/// @see container::listen class acceptor : public object<pn_acceptor_t> { public: + /// @cond INTERNAL + /// XXX important to expose? acceptor(pn_acceptor_t* a=0) : object<pn_acceptor_t>(a) {} + /// @endcond - /** close the acceptor */ + /// Close the acceptor. PN_CPP_EXTERN void close(); - /** Return the current set of connection options applied to inbound connectons by the acceptor. - * - * Note that changes made to the connection options only affect connections accepted after this - * call returns. - */ + /// Return the current set of connection options applied to + /// inbound connectons by the acceptor. + /// + /// Note that changes made to the connection options only affect + /// connections accepted after this call returns. PN_CPP_EXTERN class connection_options &connection_options(); }; } -#endif /*!PROTON_CPP_ACCEPTOR_H*/ +#endif // PROTON_CPP_ACCEPTOR_H http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/72b5f953/proton-c/bindings/cpp/include/proton/annotation_key.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/annotation_key.hpp b/proton-c/bindings/cpp/include/proton/annotation_key.hpp index edd63b1..69138ca 100644 --- a/proton-c/bindings/cpp/include/proton/annotation_key.hpp +++ b/proton-c/bindings/cpp/include/proton/annotation_key.hpp @@ -1,5 +1,6 @@ #ifndef ANNOTATION_KEY_HPP #define ANNOTATION_KEY_HPP + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -23,36 +24,53 @@ #include "proton/scalar.hpp" namespace proton { + class encoder; class decoder; -/** An annotation_key can contain one of the following types: uint64_t or amqp_symbol. */ +/// A key for use with AMQP annotation maps. +/// +/// An annotation_key can contain either a uint64_t or a +/// proton::amqp::amqp_symbol. class annotation_key : public restricted_scalar { public: + /// Create an empty key. annotation_key() { scalar_ = uint64_t(0); } - ///@name Assign a C++ value, deduce the AMQP type() - ///@{ + /// @name Assignment operators + /// + /// Assign a C++ value, deducing the AMQP type(). + /// + /// @{ annotation_key& operator=(uint64_t x) { scalar_ = x; return *this; } annotation_key& operator=(const amqp_symbol& x) { scalar_ = x; return *this; } - /// std::string is encoded as amqp_symbol + /// `std::string` is encoded as proton::amqp::amqp_symbol. annotation_key& operator=(const std::string& x) { scalar_ = amqp_symbol(x); return *this; } - /// char* is encoded as amqp_symbol + /// `char*` is encoded as proton::amqp::amqp_symbol. annotation_key& operator=(const char *x) { scalar_ = amqp_symbol(x); return *this; } - ///@} + /// @} - /// Converting constructor from any type that we can assign from. + /// A constructor that converts from any type that we can assign + /// from. template <class T> annotation_key(T x) { *this = x; } + /// @name Get methods + /// + /// @{ void get(uint64_t& x) const { scalar_.get(x); } void get(amqp_symbol& x) const { scalar_.get(x); } + /// @} + /// Return the value as type T. template<class T> T get() const { T x; get(x); return x; } - friend PN_CPP_EXTERN encoder operator<<(encoder, const annotation_key&); - friend PN_CPP_EXTERN decoder operator>>(decoder, annotation_key&); - friend class message; + /// @cond INTERNAL + friend PN_CPP_EXTERN encoder operator<<(encoder, const annotation_key&); + friend PN_CPP_EXTERN decoder operator>>(decoder, annotation_key&); + friend class message; + /// @endcond }; } + #endif // ANNOTATION_KEY_HPP http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/72b5f953/proton-c/bindings/cpp/include/proton/condition.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/condition.hpp b/proton-c/bindings/cpp/include/proton/condition.hpp index 46d6e75..426e374 100644 --- a/proton-c/bindings/cpp/include/proton/condition.hpp +++ b/proton-c/bindings/cpp/include/proton/condition.hpp @@ -21,6 +21,7 @@ * under the License. * */ + #include "proton/export.hpp" #include "proton/value.hpp" @@ -30,22 +31,29 @@ struct pn_condition_t; namespace proton { -/** condition allows access to error or other special circumstance information */ -class condition -{ +/// Describes an endpoint error state. +class condition { public: + /// @cond INTERNAL condition(pn_condition_t* c) : condition_(c) {} + /// @endcond - /** Assert no condition set */ + /// @cond INTERNAL + /// XXX want to discuss + /// Assert no condition set. bool operator!() const; - /** Condition name */ + /// @endcond + + /// Condition name. std::string name() const; - /** Descriptive string for condition */ + + /// Descriptive string for condition. std::string description() const; - /** Extra information for condition n*/ + + /// Extra information for condition n*/ value info() const; - /** Simple printable string for condition */ + /// Simple printable string for condition. std::string str() const; private: @@ -54,4 +62,4 @@ class condition } -#endif /*!PROTON_CPP_CONDITION_H*/ +#endif // PROTON_CPP_CONDITION_H http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/72b5f953/proton-c/bindings/cpp/include/proton/config.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/config.hpp b/proton-c/bindings/cpp/include/proton/config.hpp index 4d3dff9..dea4c9e 100644 --- a/proton-c/bindings/cpp/include/proton/config.hpp +++ b/proton-c/bindings/cpp/include/proton/config.hpp @@ -1,5 +1,6 @@ #ifndef CONFIG_HPP #define CONFIG_HPP + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -19,13 +20,17 @@ * under the License. */ -/**@file - * - * Configuration macros, can be set via -D compiler options or in code. - * - * On a C++11 compliant compiler, all C++11 features are enabled by default. - * Otherwise they can be enabled or disabled separately with -D on the compile line. - */ +/// @cond INTERNAL +/// XXX discuss + +/// @file +/// +/// Configuration macros. They can be set via -D compiler options or +/// in code. +/// +/// On a C++11 compliant compiler, all C++11 features are enabled by +/// default. Otherwise they can be enabled or disabled separately +/// with -D on the compile line. #ifndef PN_HAS_CPP11 #if (defined(__cplusplus) && __cplusplus >= 201100) @@ -48,3 +53,5 @@ #endif #endif // CONFIG_HPP + +/// @endcond http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/72b5f953/proton-c/bindings/cpp/include/proton/connection.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/connection.hpp b/proton-c/bindings/cpp/include/proton/connection.hpp index ec86bd7..410f7f6 100644 --- a/proton-c/bindings/cpp/include/proton/connection.hpp +++ b/proton-c/bindings/cpp/include/proton/connection.hpp @@ -21,6 +21,7 @@ * under the License. * */ + #include "proton/export.hpp" #include "proton/endpoint.hpp" #include "proton/link.hpp" @@ -37,20 +38,23 @@ namespace proton { class handler; class engine; -/** connection to a remote AMQP peer. */ -class connection : public object<pn_connection_t>, public endpoint -{ +/// A connection to a remote AMQP peer. +class connection : public object<pn_connection_t>, public endpoint { public: + /// @cond INTERNAL connection(pn_connection_t* c=0) : object<pn_connection_t>(c) {} + /// @endcond - /* Endpoint behaviours */ - + /// Get the state of this connection. PN_CPP_EXTERN endpoint::state state() const; + PN_CPP_EXTERN condition local_condition() const; PN_CPP_EXTERN condition remote_condition() const; - /// Get the container, throw an exception if this connection is not managed - /// by a container. + /// Get the container. + /// + /// @throw proton::error if this connection is not managed by a + /// container PN_CPP_EXTERN class container &container() const; /// Get the transport for the connection. @@ -59,59 +63,77 @@ class connection : public object<pn_connection_t>, public endpoint /// Return the AMQP host name for the connection. PN_CPP_EXTERN std::string host() const; + /// @cond INTERNAL + /// XXX this should be a connection option, right? /// Set the AMQP host name for the connection PN_CPP_EXTERN void host(const std::string& h); + /// @endcond - /// Return the container-ID for the connection. + /// Return the container ID for the connection. PN_CPP_EXTERN std::string container_id() const; - /** Initiate local open, not complete till messaging_handler::on_connection_opened() - * or proton_handler::on_connection_remote_open() - */ + /// @cond INTERNAL + /// XXX connection options + /// Initiate local open. The operation is not complete till + /// handler::on_connection_open(). PN_CPP_EXTERN void open(); + /// @endcond - /** Initiate local close, not complete till messaging_handler::on_connection_closed() - * or proton_handler::on_connection_remote_close() - */ + /// Initiate local close. The operation is not complete till + /// handler::on_connection_close(). PN_CPP_EXTERN void close(); - /** Release link and session resources of this connection - */ + /// @cond INTERNAL + /// XXX undiscussed + /// Release link and session resources of this connection. PN_CPP_EXTERN void release(); + /// @endcond - /** Create a new session */ + /// Open a new session. PN_CPP_EXTERN session open_session(); - /** Default session is created on first call and re-used for the lifetime of the connection */ + /// Get the default session. A default session is created on the + /// first call and reused for the lifetime of the connection. PN_CPP_EXTERN session default_session(); - /** Create a sender on default_session() with target=addr and link options=opts */ - PN_CPP_EXTERN sender open_sender(const std::string &addr, const link_options &opts = link_options()); + /// Open a sender for `addr` on default_session(). + PN_CPP_EXTERN sender open_sender(const std::string &addr, + const link_options &opts = link_options()); - /** Create a receiver on default_session() with target=addr and optional link options opts */ - PN_CPP_EXTERN receiver open_receiver(const std::string &addr, const link_options &opts = link_options()); + /// Open a receiver for `addr` on default_session(). + PN_CPP_EXTERN receiver open_receiver(const std::string &addr, + const link_options &opts = link_options()); - /** Return links on this connection matching the state mask. */ + /// Return links on this connection matching the state mask. PN_CPP_EXTERN link_range find_links(endpoint::state mask) const; - /** Return sessions on this connection matching the state mask. */ + /// Return sessions on this connection matching the state mask. PN_CPP_EXTERN session_range find_sessions(endpoint::state mask) const; - /// True if the connection is fully closed, i.e. local and remote ends are closed. - bool closed() const { return (state()&LOCAL_CLOSED) && (state()&REMOTE_CLOSED); } + /// @cond INTERNAL + /// + /// XXX not yet discussed, why this convenience but not others? + /// opened? should this not be on endpoint? + /// + /// True if the connection is fully closed, i.e. local and remote + /// ends are closed. + bool closed() const { return (state() & LOCAL_CLOSED) && (state() & REMOTE_CLOSED); } + /// @endcond private: PN_CPP_EXTERN void user(const std::string &); PN_CPP_EXTERN void password(const std::string &); - friend class connection_context; - friend class connection_engine; - friend class connection_options; - friend class connector; - friend class transport; - friend class container_impl; + /// @cond INTERNAL + friend class connection_context; + friend class connection_engine; + friend class connection_options; + friend class connector; + friend class transport; + friend class container_impl; + /// @endcond }; } -#endif /*!PROTON_CPP_CONNECTION_H*/ +#endif // PROTON_CPP_CONNECTION_H http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/72b5f953/proton-c/bindings/cpp/include/proton/connection_engine.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/connection_engine.hpp b/proton-c/bindings/cpp/include/proton/connection_engine.hpp index 83839e8..4565f33 100644 --- a/proton-c/bindings/cpp/include/proton/connection_engine.hpp +++ b/proton-c/bindings/cpp/include/proton/connection_engine.hpp @@ -1,5 +1,6 @@ #ifndef CONNECTION_ENGINE_HPP #define CONNECTION_ENGINE_HPP + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -33,41 +34,40 @@ namespace proton { class connection_engine_context; - class handler; class connection; // TODO aconway 2016-01-23: doc contrast with container. -/** - * A connection_engine manages a single AMQP connection. It is useful for - * integrating AMQP into an existing IO framework. - * - * The engine provides a simple "bytes-in/bytes-out" interface. Incoming AMQP - * bytes from any kind of data connection are fed into the engine and processed - * to dispatch events to a proton::handler. The resulting AMQP output data is - * available from the engine and can sent back over the connection. - * - * The engine does no IO of its own. It assumes a two-way flow of bytes over - * some externally-managed "connection". The "connection" could be a socket - * managed by select, poll, epoll or some other mechanism, or it could be - * something else such as an RDMA connection, a shared-memory buffer or a Unix - * pipe. - * - * The application is coded the same way for engine or container: you implement - * proton::handler. Handlers attached to an engine will receive transport, - * connection, session, link and message events. They will not receive reactor, - * selectable or timer events, the engine assumes those are managed externally. - * - * THREAD SAFETY: A single engine instance cannot be called concurrently, but - * different engine instances can be processed concurrently in separate threads. - */ +/// An interface for connection-oriented IO integration. A +/// connection_engine manages a single AMQP connection. It is useful +/// for integrating AMQP into an existing IO framework. +/// +/// The engine provides a simple "bytes-in/bytes-out" interface. Incoming AMQP +/// bytes from any kind of data connection are fed into the engine and processed +/// to dispatch events to a proton::handler. The resulting AMQP output data is +/// available from the engine and can sent back over the connection. +/// +/// The engine does no IO of its own. It assumes a two-way flow of bytes over +/// some externally-managed "connection". The "connection" could be a socket +/// managed by select, poll, epoll or some other mechanism, or it could be +/// something else such as an RDMA connection, a shared-memory buffer or a Unix +/// pipe. +/// +/// The application is coded the same way for engine or container: you implement +/// proton::handler. Handlers attached to an engine will receive transport, +/// connection, session, link and message events. They will not receive reactor, +/// selectable or timer events, the engine assumes those are managed externally. +/// +/// THREAD SAFETY: A single engine instance cannot be called concurrently, but +/// different engine instances can be processed concurrently in separate threads. class connection_engine { public: // FIXME aconway 2016-01-23: DOC class container { public: - /// Create a container with id, default to random UUID if id == "". + /// Create a container with id. Default to random UUID if id + /// == "". PN_CPP_EXTERN container(const std::string &id = ""); /// Return the container-id @@ -90,7 +90,7 @@ class connection_engine { connection_options options_; }; - /** Create a connection engine that dispatches to handler. */ + /// Create a connection engine that dispatches to handler. PN_CPP_EXTERN connection_engine(handler&, const connection_options& = no_opts); PN_CPP_EXTERN virtual ~connection_engine(); @@ -117,29 +117,33 @@ class connection_engine { /// @return true if process should be called again, i.e. !closed() PN_CPP_EXTERN bool process(int io_flags=READ|WRITE); - /// Non-throwing version of process. - /// Use closed() and error_str() to check the status of the engine. + /// Non-throwing version of process. Use closed() and error_str() + /// to check the status of the engine. PN_CPP_EXTERN bool process_nothrow(int io_flags=READ|WRITE); - /** - * True if the engine is closed, meaning there are no further - * events to process and close_io has been called. - * Call error_str() to get an error description. - */ + /// True if the engine is closed, meaning there are no further + /// events to process and close_io has been called. Call + /// error_str() to get an error description. PN_CPP_EXTERN bool closed() const; - /** If the engine was closed by an error, return a pointer */ + /// If the engine was closed by an error, return a pointer. PN_CPP_EXTERN std::string error_str() const; - /** Get the AMQP connection associated with this connection_engine. */ + /// Get the AMQP connection associated with this connection_engine. PN_CPP_EXTERN class connection connection() const; - /** Get the transport object connection associated with this connection_engine. */ + /// Get the transport associated with this connection_engine. PN_CPP_EXTERN class transport transport() const; - /** Disconnect the engine. Calls io::close and dispatches final events to - * the handler. Neither the handler nor the io will be used after this call. - */ + /// Disconnect the engine. + /// + /// @internal + /// + /// XXX calls io::close? + /// + /// Calls io::close and dispatches final events to the + /// handler. Neither the handler nor the io will be used after + /// this call. PN_CPP_EXTERN void disconnect(); protected: @@ -166,7 +170,6 @@ class connection_engine { PN_CPP_EXTERN static const connection_options no_opts; private: - connection_engine(const connection_engine&); connection_engine& operator=(const connection_engine&); @@ -178,6 +181,6 @@ class connection_engine { connection_engine_context* ctx_; }; - } + #endif // CONNECTION_ENGINE_HPP http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/72b5f953/proton-c/bindings/cpp/include/proton/connection_options.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/connection_options.hpp b/proton-c/bindings/cpp/include/proton/connection_options.hpp index e72ac13..cea1900 100644 --- a/proton-c/bindings/cpp/include/proton/connection_options.hpp +++ b/proton-c/bindings/cpp/include/proton/connection_options.hpp @@ -21,6 +21,7 @@ * under the License. * */ + #include "proton/config.hpp" #include "proton/export.hpp" #include "proton/pn_unique_ptr.hpp" @@ -35,50 +36,102 @@ namespace proton { class proton_handler; class connection; -/** Options for creating a connection. - * - * Options can be "chained" like this: - * - * c = container.connect(url, connection_options().handler(h).max_frame_size(1234)); - * - * You can also create an options object with common settings and use it as a base - * for different connections that have mostly the same settings: - * - * connection_options opts; - * opts.idle_timeout(1000).max_frame_size(10000); - * c1 = container.connect(url1, opts.handler(h1)); - * c2 = container.connect(url2, opts.handler(h2)); - * - * Normal value semantics, copy or assign creates a separate copy of the options. - */ +/// Options for creating a connection. +/// +/// Options can be "chained" like this: +/// +/// @code +/// c = container.connect(url, connection_options().handler(h).max_frame_size(1234)); +/// @endcode +/// +/// You can also create an options object with common settings and use +/// it as a base for different connections that have mostly the same +/// settings: +/// +/// @code +/// connection_options opts; +/// opts.idle_timeout(1000).max_frame_size(10000); +/// c1 = container.connect(url1, opts.handler(h1)); +/// c2 = container.connect(url2, opts.handler(h2)); +/// @endcode +/// +/// Normal value semantics: copy or assign creates a separate copy of +/// the options. class connection_options { public: + /// Create an empty set of options. PN_CPP_EXTERN connection_options(); + + /// Copy options. PN_CPP_EXTERN connection_options(const connection_options&); + PN_CPP_EXTERN ~connection_options(); + + /// Copy options. PN_CPP_EXTERN connection_options& operator=(const connection_options&); /// Override with options from other. PN_CPP_EXTERN void override(const connection_options& other); - // TODO: Document options - + /// Set a handler for the connection. PN_CPP_EXTERN connection_options& handler(class handler *); + + /// Set the maximum frame size. PN_CPP_EXTERN connection_options& max_frame_size(uint32_t max); + + /// Set the maximum channels. PN_CPP_EXTERN connection_options& max_channels(uint16_t max); + + /// Set the idle timeout. PN_CPP_EXTERN connection_options& idle_timeout(duration); + + /// @cond INTERNAL + /// XXX remove PN_CPP_EXTERN connection_options& heartbeat(duration); + /// @endcond + + /// Set the container ID. PN_CPP_EXTERN connection_options& container_id(const std::string &id); + + /// @cond INTERNAL + + /// XXX more discussion PN_CPP_EXTERN connection_options& link_prefix(const std::string &id); + + /// XXX settle questions about reconnect_timer PN_CPP_EXTERN connection_options& reconnect(const reconnect_timer &); + + /// @endcond + + /// Set SSL client options. PN_CPP_EXTERN connection_options& ssl_client_options(const class ssl_client_options &); + + /// Set SSL server options. PN_CPP_EXTERN connection_options& ssl_server_options(const class ssl_server_options &); + + /// @cond INTERNAL + + /// XXX remove PN_CPP_EXTERN connection_options& peer_hostname(const std::string &name); + + /// XXX ssl_ prefix PN_CPP_EXTERN connection_options& resume_id(const std::string &id); + + /// @endcond + + /// Enable or disable SASL. PN_CPP_EXTERN connection_options& sasl_enabled(bool); + + /// @cond INTERNAL + /// XXX sasl_ prefix PN_CPP_EXTERN connection_options& allow_insecure_mechs(bool); PN_CPP_EXTERN connection_options& allowed_mechs(const std::string &); + /// @endcond + + /// Set the SASL configuration name. PN_CPP_EXTERN connection_options& sasl_config_name(const std::string &); + + /// Set the SASL configuration path. PN_CPP_EXTERN connection_options& sasl_config_path(const std::string &); private: @@ -91,11 +144,13 @@ class connection_options { class impl; pn_unique_ptr<impl> impl_; - friend class container_impl; - friend class connector; - friend class connection_engine; + /// @cond INTERNAL + friend class container_impl; + friend class connector; + friend class connection_engine; + /// @endcond }; -} // namespace +} -#endif /*!PROTON_CPP_CONNECTION_OPTIONS_H*/ +#endif // PROTON_CPP_CONNECTION_OPTIONS_H --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
