.. 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.

Basic Usage and Examples
========================

Standalone and Interior Modes
-----------------------------

The router can operate stand-alone or as a node in a network of routers.
The mode is configured in the *router* section of the configuration
file. In stand-alone mode, the router does not attempt to collaborate
with any other routers and only routes messages among directly connected
endpoints.

If your router is running in stand-alone mode, *qdstat -a* will look
like the following:

::

    $ qdstat -a
    Router Addresses
      class   address          phase  in-proc  local  remote  in  out  thru  to-proc  from-proc
      ===========================================================================================
      local   $management             Y        0      0       0   0    0     0        0
      mobile  $management      0      Y        0      0       1   0    0     1        0
      local   temp.4Q3i01lWbs                  1      0       0   0    0     0        0

Note that there are two known addresses. *$management* is the address of
the router's embedded management agent. *temp.4Q3i01lWbs* is the temporary
reply-to address of the *qdstat* client making requests to the agent.

If you change the mode to interior and restart the processs, the same
command will yield additional addresses which are used for
inter-router communication:

::

    $ qdstat -a
    Router Addresses
      class   address          phase  in-proc  local  remote  in  out  thru  to-proc  from-proc
      ===========================================================================================
      local   $management             Y        0      0       0   0    0     0        0
      mobile  $management      0      Y        0      0       1   0    0     1        0
      local   qdhello                 Y        0      0       0   0    0     0        3
      local   qdrouter                Y        0      0       0   0    0     0        1
      local   qdrouter.ma             Y        0      0       0   0    0     0        0
      local   temp.2ot2AWsnYz                  1      0       0   0    0     0        0

Mobile Subscribers
------------------

The term "mobile subscriber" simply refers to the fact that a client may
connect to the router and subscribe to an address to receive messages
sent to that address. No matter where in the network the subscriber
attaches, the messages will be routed to the appropriate destination.

To illustrate a subscription on a stand-alone router, you can use the
examples that are provided with Qpid Proton. Using the *simple_recv.py* example
receiver:

::

    $ python ./simple_recv.py -a 127.0.0.1/my-address

This command creates a receiving link subscribed to the specified
address. To verify the subscription:

::

    $ qdstat -a
    Router Addresses
      class   address          phase  in-proc  local  remote  in  out  thru  to-proc  from-proc
      ===========================================================================================
      local   $management             Y        0      0       0   0    0     0        0
      mobile  $management      0      Y        0      0       1   0    0     1        0
      mobile  my-address       0               1      0       0   0    0     0        0
      local   temp.JAgKj1+iB8                  1      0       0   0    0     0        0


You can then, in a separate command window, run a sender to produce
messages to that address:

::

    $ python ./simple_send.py -a 127.0.0.1/my-address

Dynamic Reply-To
----------------

Dynamic reply-to can be used to obtain a reply-to address that routes
back to a client's receiving link regardless of how many hops it has to
take to get there. To illustrate this feature, see below a simple
program (written in C++ against the qpid::messaging API) that queries
the management agent of the attached router for a list of other known
routers' management addresses.

::

    #include <qpid/messaging/Address.h>
    #include <qpid/messaging/Connection.h>
    #include <qpid/messaging/Message.h>
    #include <qpid/messaging/Receiver.h>
    #include <qpid/messaging/Sender.h>
    #include <qpid/messaging/Session.h>

    using namespace qpid::messaging;
    using namespace qpid::types;

    using std::stringstream;
    using std::string;

    int main() {
        const char* url = "amqp:tcp:127.0.0.1:5672";
        std::string connectionOptions = "{protocol:amqp1.0}";

        Connection connection(url, connectionOptions);
        connection.open();
        Session session = connection.createSession();
        Sender sender = session.createSender("mgmt");

        // create reply receiver and get the reply-to address
        Receiver receiver = session.createReceiver("#");
        Address responseAddress = receiver.getAddress();

        Message request;
        request.setReplyTo(responseAddress);
        request.setProperty("x-amqp-to", "amqp:/_local/$management");
        request.setProperty("operation", "DISCOVER-MGMT-NODES");
        request.setProperty("type", "org.amqp.management");
        request.setProperty("name, "self");

        sender.send(request);
        Message response = receiver.fetch();
        Variant content(response.getContentObject());
        std::cout << "Response: " << content << std::endl << std::endl;

        connection.close();
    }

The equivalent program written in Python against the Proton Messenger
API:

::

    from proton import Messenger, Message

    def main():
        host = "0.0.0.0:5672"

        messenger = Messenger()
        messenger.start()
        messenger.route("amqp:/*", "amqp://%s/$1" % host)
        reply_subscription = messenger.subscribe("amqp:/#")
        reply_address = reply_subscription.address

        request  = Message()
        response = Message()

        request.address = "amqp:/_local/$management"
        request.reply_to = reply_address
        request.properties = {u'operation' : u'DISCOVER-MGMT-NODES',
                              u'type'      : u'org.amqp.management',
                              u'name'      : u'self'}

        messenger.put(request)
        messenger.send()
        messenger.recv()
        messenger.get(response)

        print "Response: %r" % response.body

        messenger.stop()

    main()

