Re: RFC: new routing functionality for messenger

2013-03-28 Thread Darryl L. Pierce
On Thu, Mar 28, 2013 at 03:11:51PM -0400, Alan Conway wrote:
> I am starting to think we need a proton routing plug-in API so that
> different choices of routing rules, pattern matching, configuration
> files etc. can be implemented without baking one set of choices into
> messenger. Such a plugin API could be fairly simple and would allow
> choice and composition of functionality from different plug-ins.

+1 to that

-- 
Darryl L. Pierce, Sr. Software Engineer @ Red Hat, Inc.
Delivering value year after year.
Red Hat ranks #1 in value among software vendors.
http://www.redhat.com/promo/vendor/



pgp_Vx5mRbfTH.pgp
Description: PGP signature


Re: RFC: new routing functionality for messenger

2013-03-28 Thread Alan Conway

On 03/28/2013 09:11 AM, Ken Giusti wrote:

At first I was a bit skeptical whether this really belongs in the messenger 
API, but I've come to accept that it would have to be.  Internally, messenger 
does perform routing - mapping the 'to' address to the proper connection and 
link.  To me, this new API provides a level of control over that mapping 
process.

That said, the api needs a bit of fleshing out.

Assuming that we support multiple routes, then most obviously the api would 
need to provide the ability to query the route table for a given mapping.  I'd 
also like to see a means for walking the route table in match order.  And 
deletions - can't forget that.

And to be clear - the match precedent is determined by the order in which 
routes are added, correct?  That may be hard to manage if the route table is 
modified over time.  Perhaps a route should be given a priority?  Or maybe we 
give routes precedence based on their restrictiveness - matching more 
restrictive first?



I am starting to think we need a proton routing plug-in API so that different 
choices of routing rules, pattern matching, configuration files etc. can be 
implemented without baking one set of choices into messenger. Such a plugin API 
could be fairly simple and would allow choice and composition of functionality 
from different plug-ins.



- Original Message -

From: "Rafael Schloming" 
To: proton@qpid.apache.org
Sent: Saturday, March 23, 2013 12:43:07 PM
Subject: RFC: new routing functionality for messenger

Hi,

I've added a new API to messenger that gives the user some control
over the
internal routing behaviour of a messenger. Please check it out and
comment.
I've pasted the C API/doxygen below. This is currently only exposed
through
the python binding via the route method on the Messenger class.

--Rafael

/** Adds a routing rule to a Messenger's internal routing table.
  *
  * The route procedure may be used to influence how a messenger will
  * internally treat a given address or class of addresses. Every call
  * to the route procedure will result in messenger appending a
  routing
  * rule to its internal routing table.
  *
  * Whenever a message is presented to a messenger for delivery, it
  * will match the address of this message against the set of routing
  * rules in order. The first rule to match will be triggered, and
  * instead of routing based on the address presented in the message,
  * the messenger will route based on the address supplied in the
  rule.
  *
  * The pattern matching syntax supports two types of matches, a '%'
  * will match any character except a '/', and a '*' will match any
  * character including a '/'.
  *
  * A routing address is specified as a normal AMQP address, however
  it
  * may additionally use substitution variables from the pattern match
  * that triggered the rule.
  *
  * Any message sent to "foo" will be routed to "amqp://foo.com":
  *
  *   pn_messenger_route("foo", "amqp://foo.com");
  *
  * Any message sent to "foobar" will be routed to
  * "amqp://foo.com/bar":
  *
  *   pn_messenger_route("foobar", "amqp://foo.com/bar");
  *
  * Any message sent to bar/ will be routed to the corresponding
  * path within the amqp://bar.com domain:
  *
  *   pn_messenger_route("bar/*", "amqp://bar.com/$1");
  *
  * Route all messages over TLS:
  *
  *   pn_messenger_route("amqp:*", "amqps:$1")
  *
  * Supply credentials for foo.com:
  *
  *   pn_messenger_route("amqp://foo.com/*",
  "amqp://user:passw...@foo.com/$1
");
  *
  * Supply credentials for all domains:
  *
  *   pn_messenger_route("amqp://*", "amqp://user:password@$1");
  *
  * Route all addresses through a single proxy while preserving the
  * original destination:
  *
  *   pn_messenger_route("amqp://%/*",
  "amqp://user:password@proxy/$1/$2");
  *
  * Route any address through a single broker:
  *
  *   pn_messenger_route("*", "amqp://user:password@broker/$1");
  *
  * @param[in] messenger the Messenger
  * @param[in] pattern a glob pattern
  * @param[in] address an address indicating alternative routing
  *
  * @return an error code or zero on success
  * @see error.h
  *
  */
PN_EXTERN int pn_messenger_route(pn_messenger_t *messenger, const
char
*pattern,
  const char *address);





Re: RFC: new routing functionality for messenger

2013-03-28 Thread Rafael Schloming
On Thu, Mar 28, 2013 at 8:59 AM, Ken Giusti  wrote:

> Not to hijack this thread, but...
>
> Yes, absolutely - this is a Must Have as far as I'm concerned.
> Specifically:
>
> 1) The application should control whether Reply-to is set or not
> (currently always set by messenger)
> 2) The application should be able to get its local address (for reply-to)
> via messenger rather than require it to configured - the ${me} in the above.
>
> If no objections I'm gonna JIRA these...
>

Please feel free.

--Rafael


Re: RFC: new routing functionality for messenger

2013-03-28 Thread Ken Giusti
At first I was a bit skeptical whether this really belongs in the messenger 
API, but I've come to accept that it would have to be.  Internally, messenger 
does perform routing - mapping the 'to' address to the proper connection and 
link.  To me, this new API provides a level of control over that mapping 
process.

That said, the api needs a bit of fleshing out.

Assuming that we support multiple routes, then most obviously the api would 
need to provide the ability to query the route table for a given mapping.  I'd 
also like to see a means for walking the route table in match order.  And 
deletions - can't forget that.

And to be clear - the match precedent is determined by the order in which 
routes are added, correct?  That may be hard to manage if the route table is 
modified over time.  Perhaps a route should be given a priority?  Or maybe we 
give routes precedence based on their restrictiveness - matching more 
restrictive first?

-K

- Original Message -
> From: "Rafael Schloming" 
> To: proton@qpid.apache.org
> Sent: Saturday, March 23, 2013 12:43:07 PM
> Subject: RFC: new routing functionality for messenger
> 
> Hi,
> 
> I've added a new API to messenger that gives the user some control
> over the
> internal routing behaviour of a messenger. Please check it out and
> comment.
> I've pasted the C API/doxygen below. This is currently only exposed
> through
> the python binding via the route method on the Messenger class.
> 
> --Rafael
> 
> /** Adds a routing rule to a Messenger's internal routing table.
>  *
>  * The route procedure may be used to influence how a messenger will
>  * internally treat a given address or class of addresses. Every call
>  * to the route procedure will result in messenger appending a
>  routing
>  * rule to its internal routing table.
>  *
>  * Whenever a message is presented to a messenger for delivery, it
>  * will match the address of this message against the set of routing
>  * rules in order. The first rule to match will be triggered, and
>  * instead of routing based on the address presented in the message,
>  * the messenger will route based on the address supplied in the
>  rule.
>  *
>  * The pattern matching syntax supports two types of matches, a '%'
>  * will match any character except a '/', and a '*' will match any
>  * character including a '/'.
>  *
>  * A routing address is specified as a normal AMQP address, however
>  it
>  * may additionally use substitution variables from the pattern match
>  * that triggered the rule.
>  *
>  * Any message sent to "foo" will be routed to "amqp://foo.com":
>  *
>  *   pn_messenger_route("foo", "amqp://foo.com");
>  *
>  * Any message sent to "foobar" will be routed to
>  * "amqp://foo.com/bar":
>  *
>  *   pn_messenger_route("foobar", "amqp://foo.com/bar");
>  *
>  * Any message sent to bar/ will be routed to the corresponding
>  * path within the amqp://bar.com domain:
>  *
>  *   pn_messenger_route("bar/*", "amqp://bar.com/$1");
>  *
>  * Route all messages over TLS:
>  *
>  *   pn_messenger_route("amqp:*", "amqps:$1")
>  *
>  * Supply credentials for foo.com:
>  *
>  *   pn_messenger_route("amqp://foo.com/*",
>  "amqp://user:passw...@foo.com/$1
> ");
>  *
>  * Supply credentials for all domains:
>  *
>  *   pn_messenger_route("amqp://*", "amqp://user:password@$1");
>  *
>  * Route all addresses through a single proxy while preserving the
>  * original destination:
>  *
>  *   pn_messenger_route("amqp://%/*",
>  "amqp://user:password@proxy/$1/$2");
>  *
>  * Route any address through a single broker:
>  *
>  *   pn_messenger_route("*", "amqp://user:password@broker/$1");
>  *
>  * @param[in] messenger the Messenger
>  * @param[in] pattern a glob pattern
>  * @param[in] address an address indicating alternative routing
>  *
>  * @return an error code or zero on success
>  * @see error.h
>  *
>  */
> PN_EXTERN int pn_messenger_route(pn_messenger_t *messenger, const
> char
> *pattern,
>  const char *address);
> 

-- 
-K


Re: RFC: new routing functionality for messenger

2013-03-28 Thread Ken Giusti
Not to hijack this thread, but...

- Original Message -
> From: "Rafael Schloming" 
> To: proton@qpid.apache.org
> Sent: Tuesday, March 26, 2013 10:00:23 AM
> Subject: Re: RFC: new routing functionality for messenger
> 
> On Tue, Mar 26, 2013 at 7:19 AM, Bozo Dragojevic 
> wrote:
> 
> > On 3/23/13 5:43 PM, Rafael Schloming wrote:
> >
> >> Hi,
> >>
> >> I've added a new API to messenger that gives the user some control
> >> over
> >> the
> >> internal routing behaviour of a messenger. Please check it out and
> >> comment.
> >> I've pasted the C API/doxygen below. This is currently only
> >> exposed
> >> through
> >> the python binding via the route method on the Messenger class.
> >>
> >> --Rafael
> >>
> >> /** Adds a routing rule to a Messenger's internal routing table.
> >>   *
> >>   * The route procedure may be used to influence how a messenger
> >>   will
> >>   * internally treat a given address or class of addresses. Every
> >>   call
> >>   * to the route procedure will result in messenger appending a
> >>   routing
> >>   * rule to its internal routing table.
> >>   *
> >>   * Whenever a message is presented to a messenger for delivery,
> >>   it
> >>   * will match the address of this message against the set of
> >>   routing
> >>   * rules in order. The first rule to match will be triggered, and
> >>   * instead of routing based on the address presented in the
> >>   message,
> >>   * the messenger will route based on the address supplied in the
> >>   rule.
> >>   *
> >>
> >
> > Can you help me work through this use-case:
> >
> >
> > A 'dumb' client, sends a message, and expects a reply:
> >
> > // client.c
> > pn_message_set_address(msg, "amqp://localhost/bla");
> > pn_messenger_put(msgr, msg);
> > pn_messenger_receive(msgr,1);
> > msg = pn_messenger_get(msgr);
> >
> >
> >
> > The peer it connects to uses the new route functionality:
> >
> > // server.c
> > pn_messenger_subscribe(msgr, "~amqp://localhost/bla");
> >
> 
> I'm assuming you mean "amqp://~localhost/blah" above. ;-)
> 
> 
> >
> > 1) Are routes valid to use if there's a subscribe going on.
> >I assume yes.
> >
> > pn_messenger_route(msgr, "*", "amqp://broker/$1");
> >
> 
> It's certainly valid to use both at the same time.
> 
> 
> >
> > 2) How do they interact.
> >I assume they don't, routing is only applied to outgoing
> >messages.
> >
> 
> Actually routing should be applied equally to both, however now that
> I
> think about it I suspect you need to do the route before you do the
> subscribe in order for it to make a difference for the subscribe,
> although
> I expect that limitation to go away in the next round of changes.
> 
> 
> >
> > 3) Does the order of calls to route and subscribe matter.
> >According to 2) it does not.
> >
> 
> Actually the order does matter (see above). I expect eventually the
> implementation will evolve in such a way that the order does not
> matter,
> however even so you would effectively end up getting a resubscribe
> when the
> new route goes into place, e.g. the following sequence of events
> could
> occur:
> 
> subscribe("foo.com/bar")
> ...
> ... if you do a recv here, messages might arrive directly from
> foo.com
> ...
> route("foo.com/bar", "fooproxy.com/baz")
> ...
> ... now you get messages via the proxy
> 
> 
> >
> > pn_messenger_receive(msgr, 1);
> > msg = pn_messenger_get(msgr);
> >
> > /* echo */
> > char *sender = pn_message_get_reply_to(msg);
> > pn_message_set_address(msg, sender);
> > pn_messenger_put(msgr, msg);
> > pn_messenger_send(msgr);
> >
> >
> > 4) What would the pn_message_get_reply_to() return.
> >The value as set by the client's messenger would be
> > amqp://some-uuid-value
> >
> 
> This is a very good question. I don't recall exactly why messenger
> sets the
> reply_to automatically as it does, it may even be an unintentional
> side
> effect of a couple of different changes, but I've been thinking that
> it
> shouldn't actually do this automatically, i.e. that you should

Re: RFC: new routing functionality for messenger

2013-03-27 Thread Rafael Schloming
On Wed, Mar 27, 2013 at 8:55 AM, Ted Ross  wrote:

>
> On 03/25/2013 09:30 AM, Rafael Schloming wrote:
>
>> On Mon, Mar 25, 2013 at 8:36 AM, Ted Ross  wrote:
>>
>>  I question the value of having this as part of the API.  It seems to me
>>> that the Messenger routing table should be part of the configuration of a
>>> system (i.e. in a place like /etc/qpid/messenger/, or the Windows
>>> Registry,
>>> etc.).  Eventually, it might be desirable to have an address translation
>>> service that can be accessed remotely.  I guess I see this translation as
>>> being not the concern of the application, but more of the deployment of
>>> the
>>> application.
>>>
>>>
>>>  Initially I was actually going to add the functionality via some kind of
>> configuration file as you say. I have a similar conceptual view of the
>> functionality as you describe, i.e. it really should only be used as part
>> of the deployment/configuration of the messenger, not part of the
>> "application work" portion of the API. I ended up going this route for two
>> reasons (no pun intended). For starters it was a bit more expedient as I
>> didn't have to write some kind of file format parser, but the second, and
>> perhaps more important reason, is that I wasn't sure of the implications
>> of
>> adding dependencies onto files/file systems. I want messenger to be usable
>> from embedded devices that might not even have a file system, so I figured
>> it would be safer to offer as a pure API. I do think it would be
>> appropriate to layer some kind of system integration on top of this API
>> just as you describe.
>>
>> --Rafael
>>
>>
> I agree with your thinking on this.  But...
>
> This brings up the old question of what the purpose of Messenger is.  If
> it is to be an end-user API, then I think it's too much to ask the user to
> provide file parsing capability to load the routing/address-translation
> table.  Perhaps this should be a downstream-packaging issue, I'm not sure.
>  For example, Fedora, Ubuntu, Windows, etc. packages could be pre-loaded
> with route table loaders appropriate for their environments.


One thing we could do here is to provide some kind of
pn_messenger_configure(pn_messenger_t *m, const char *path). This could be
conditionally compiled and so would be unavailable if you're on some kind
of embedded system that couldn't support it. A key thing here would be that
it should only parse the file and call into otherwise public parts of the
messenger API, i.e. we would want to ensure that there isn't anything
special you could do through the config file that you couldn't also do
directly through the API.

This could be used for more than just the routing table. We could have a
section for the messenger name, and for all the ssl cert configuration as
well. We could even provide a build time option to configure some kind of
search path to load a default configuration. I would expect the downstream
packagers would likely build in the default location/search path that is
tailored to the distro.

--Rafael


Re: RFC: new routing functionality for messenger

2013-03-27 Thread Ted Ross


On 03/25/2013 09:30 AM, Rafael Schloming wrote:

On Mon, Mar 25, 2013 at 8:36 AM, Ted Ross  wrote:


I question the value of having this as part of the API.  It seems to me
that the Messenger routing table should be part of the configuration of a
system (i.e. in a place like /etc/qpid/messenger/, or the Windows Registry,
etc.).  Eventually, it might be desirable to have an address translation
service that can be accessed remotely.  I guess I see this translation as
being not the concern of the application, but more of the deployment of the
application.



Initially I was actually going to add the functionality via some kind of
configuration file as you say. I have a similar conceptual view of the
functionality as you describe, i.e. it really should only be used as part
of the deployment/configuration of the messenger, not part of the
"application work" portion of the API. I ended up going this route for two
reasons (no pun intended). For starters it was a bit more expedient as I
didn't have to write some kind of file format parser, but the second, and
perhaps more important reason, is that I wasn't sure of the implications of
adding dependencies onto files/file systems. I want messenger to be usable
from embedded devices that might not even have a file system, so I figured
it would be safer to offer as a pure API. I do think it would be
appropriate to layer some kind of system integration on top of this API
just as you describe.

--Rafael



I agree with your thinking on this.  But...

This brings up the old question of what the purpose of Messenger is.  If 
it is to be an end-user API, then I think it's too much to ask the user 
to provide file parsing capability to load the 
routing/address-translation table.  Perhaps this should be a 
downstream-packaging issue, I'm not sure.  For example, Fedora, Ubuntu, 
Windows, etc. packages could be pre-loaded with route table loaders 
appropriate for their environments.


-Ted



Re: RFC: new routing functionality for messenger

2013-03-26 Thread Rafael Schloming
On Tue, Mar 26, 2013 at 2:13 PM, Alan Conway  wrote:

> On 03/25/2013 09:30 AM, Rafael Schloming wrote:
>
>> On Mon, Mar 25, 2013 at 8:36 AM, Ted Ross  wrote:
>>
>>  I generally like this translation facility, though I'll need to think
>>> through some use cases to make sure there's sufficient capability in the
>>> matching and substitution.
>>>
>>>
>> I would definitely appreciate some more feedback on this area. I think
>> some
>> real world usage will help us out. I struggled with various options here.
>> I
>> didn't want to add a dependency onto a regular expression library without
>> at least some kind of fallback as I think this functionality is going to
>> end up being too useful to be optional.
>>
>> There are a number of public domain regular expression libraries out there
>> (e.g. t-rex) that are basically designed to be small enough and simple
>> enough to be sucked into a codebase wholesale for when you can't afford an
>> external dependency. I considered grabbing one of those, but I also wasn't
>> 100% sure that full on regex was the best/only option here. There is
>> something nice and simple about being able to say route("*", "my-uplink")
>> as opposed to writing a fullon regex.
>>
>> I can see possibly even wanting to support multiple syntax options
>> eventually, but for starters I decided to keep it simple. I wrote a very
>> small glob style matcher with substitution. It's roughly 100 lines of code
>> and should work on any platform. I'm entirely open to replacing this with
>> something a real regex library if we want or something else entirely, I
>> just wanted something simple/portable to start with so we could actually
>> play with the functionality and learn a bit more about what is
>> appropriate.
>>
>>
>>  I question the value of having this as part of the API.  It seems to me
>>> that the Messenger routing table should be part of the configuration of a
>>> system (i.e. in a place like /etc/qpid/messenger/, or the Windows
>>> Registry,
>>> etc.).  Eventually, it might be desirable to have an address translation
>>> service that can be accessed remotely.  I guess I see this translation as
>>> being not the concern of the application, but more of the deployment of
>>> the
>>> application.
>>>
>>
> I also don't think this belongs in the API. It can be easily be provided
> as a "translator" library on top of the public messenger API. In that case
> the argument over regexps vs. home-brew pattern matching is less an issue
> people, can write translators that use whatever patterns they like, and in
> whatever languages they want. I would favour keeping the messenger API as
> simple and focused as possible and provide additional services as layers on
> top. Even if we want a C implementation with multiple language bindings
> that can still be a separate library to the messenger.
>

I don't think you can provide equivalent functionality via translation. The
routing table is actually influencing what the messenger is doing
internally. A translation layer built on top of messenger would need to
modify the message address in order to achieve a similar effect, but then
the original destination of the message would be lost.

Thinking about a proxy use case might illustrate why it needs to be
builtin. Let's say we want to configure an app to route all of its messages
through a given proxy. The proxy might do some security checks, maybe log
some stuff, etc, but ultimately in the normal case it will forward the
message to wherever it would originally have been sent. If we're directing
everything to the proxy via a wrapper layer, then the original to address
won't actually appear in the message. This will leave the proxy no way to
know how to get the message to it's final destination (or to the next hop
towards it's final destination in an N step scenario).

--Rafael


Re: RFC: new routing functionality for messenger

2013-03-26 Thread Alan Conway

On 03/25/2013 09:30 AM, Rafael Schloming wrote:

On Mon, Mar 25, 2013 at 8:36 AM, Ted Ross  wrote:


I generally like this translation facility, though I'll need to think
through some use cases to make sure there's sufficient capability in the
matching and substitution.



I would definitely appreciate some more feedback on this area. I think some
real world usage will help us out. I struggled with various options here. I
didn't want to add a dependency onto a regular expression library without
at least some kind of fallback as I think this functionality is going to
end up being too useful to be optional.

There are a number of public domain regular expression libraries out there
(e.g. t-rex) that are basically designed to be small enough and simple
enough to be sucked into a codebase wholesale for when you can't afford an
external dependency. I considered grabbing one of those, but I also wasn't
100% sure that full on regex was the best/only option here. There is
something nice and simple about being able to say route("*", "my-uplink")
as opposed to writing a fullon regex.

I can see possibly even wanting to support multiple syntax options
eventually, but for starters I decided to keep it simple. I wrote a very
small glob style matcher with substitution. It's roughly 100 lines of code
and should work on any platform. I'm entirely open to replacing this with
something a real regex library if we want or something else entirely, I
just wanted something simple/portable to start with so we could actually
play with the functionality and learn a bit more about what is appropriate.



I question the value of having this as part of the API.  It seems to me
that the Messenger routing table should be part of the configuration of a
system (i.e. in a place like /etc/qpid/messenger/, or the Windows Registry,
etc.).  Eventually, it might be desirable to have an address translation
service that can be accessed remotely.  I guess I see this translation as
being not the concern of the application, but more of the deployment of the
application.


I also don't think this belongs in the API. It can be easily be provided as a 
"translator" library on top of the public messenger API. In that case the 
argument over regexps vs. home-brew pattern matching is less an issue people, 
can write translators that use whatever patterns they like, and in whatever 
languages they want. I would favour keeping the messenger API as simple and 
focused as possible and provide additional services as layers on top. Even if we 
want a C implementation with multiple language bindings that can still be a 
separate library to the messenger.


I also suspect it will be more fruitful to prototype this kind of thing in more 
productive languages like python or ruby before deciding if we want to bake 
something into a C implementation with bindings etc.


Cheers,
Alan.


Re: RFC: new routing functionality for messenger

2013-03-26 Thread Rafael Schloming
On Tue, Mar 26, 2013 at 7:19 AM, Bozo Dragojevic  wrote:

> On 3/23/13 5:43 PM, Rafael Schloming wrote:
>
>> Hi,
>>
>> I've added a new API to messenger that gives the user some control over
>> the
>> internal routing behaviour of a messenger. Please check it out and
>> comment.
>> I've pasted the C API/doxygen below. This is currently only exposed
>> through
>> the python binding via the route method on the Messenger class.
>>
>> --Rafael
>>
>> /** Adds a routing rule to a Messenger's internal routing table.
>>   *
>>   * The route procedure may be used to influence how a messenger will
>>   * internally treat a given address or class of addresses. Every call
>>   * to the route procedure will result in messenger appending a routing
>>   * rule to its internal routing table.
>>   *
>>   * Whenever a message is presented to a messenger for delivery, it
>>   * will match the address of this message against the set of routing
>>   * rules in order. The first rule to match will be triggered, and
>>   * instead of routing based on the address presented in the message,
>>   * the messenger will route based on the address supplied in the rule.
>>   *
>>
>
> Can you help me work through this use-case:
>
>
> A 'dumb' client, sends a message, and expects a reply:
>
> // client.c
> pn_message_set_address(msg, "amqp://localhost/bla");
> pn_messenger_put(msgr, msg);
> pn_messenger_receive(msgr,1);
> msg = pn_messenger_get(msgr);
>
>
>
> The peer it connects to uses the new route functionality:
>
> // server.c
> pn_messenger_subscribe(msgr, "~amqp://localhost/bla");
>

I'm assuming you mean "amqp://~localhost/blah" above. ;-)


>
> 1) Are routes valid to use if there's a subscribe going on.
>I assume yes.
>
> pn_messenger_route(msgr, "*", "amqp://broker/$1");
>

It's certainly valid to use both at the same time.


>
> 2) How do they interact.
>I assume they don't, routing is only applied to outgoing messages.
>

Actually routing should be applied equally to both, however now that I
think about it I suspect you need to do the route before you do the
subscribe in order for it to make a difference for the subscribe, although
I expect that limitation to go away in the next round of changes.


>
> 3) Does the order of calls to route and subscribe matter.
>According to 2) it does not.
>

Actually the order does matter (see above). I expect eventually the
implementation will evolve in such a way that the order does not matter,
however even so you would effectively end up getting a resubscribe when the
new route goes into place, e.g. the following sequence of events could
occur:

subscribe("foo.com/bar")
...
... if you do a recv here, messages might arrive directly from foo.com
...
route("foo.com/bar", "fooproxy.com/baz")
...
... now you get messages via the proxy


>
> pn_messenger_receive(msgr, 1);
> msg = pn_messenger_get(msgr);
>
> /* echo */
> char *sender = pn_message_get_reply_to(msg);
> pn_message_set_address(msg, sender);
> pn_messenger_put(msgr, msg);
> pn_messenger_send(msgr);
>
>
> 4) What would the pn_message_get_reply_to() return.
>The value as set by the client's messenger would be
> amqp://some-uuid-value
>

This is a very good question. I don't recall exactly why messenger sets the
reply_to automatically as it does, it may even be an unintentional side
effect of a couple of different changes, but I've been thinking that it
shouldn't actually do this automatically, i.e. that you should always set a
reply_to explicitly if that's what you want.

FWIW, it's not actually setting the reply_to value to some-random-uuid,
it's actually setting it to amqp://the-name-of-the-messenger. It just so
happens that the name of the messenger defaults to a UUID, but if you had
constructed your messenger as pn_messenger("bob") rather than
pn_messenger(NULL), then the reply_to would automatically get set to
amqp://bob.

I was also thinking that it would be convenient to have some way to
actually refer to the container name in an address, that way e.g.
explicitly setting the reply_to = "amqp://${me}" would give the same effect
that you currently get with the automatic setting, but would also be a bit
more flexible.


>
> 5) Would the route above apply or not to this particular outgoing reply
> message.
>

The rules always apply, the messenger impl doesn't really know the
difference between that and any other address.


>
> 6) If yes, how will 'broker' learn how to talk to the original client
>

Another very good question. Unfortunately the answer right now depends on
your broker as each broker assumes a private namespace, you would need to
construct a reply_to that is known to your broker, e.g. create a
reply-queue called "replies" on your broker and explicitly set your
reply-to to amqp://broker/replies.

One of the areas that we are working on within the OASIS TC is defining an
addressing standard such that this will be much more seamless, e.g. the
clients 

Re: RFC: new routing functionality for messenger

2013-03-26 Thread Bozo Dragojevic

On 3/23/13 5:43 PM, Rafael Schloming wrote:

Hi,

I've added a new API to messenger that gives the user some control over the
internal routing behaviour of a messenger. Please check it out and comment.
I've pasted the C API/doxygen below. This is currently only exposed through
the python binding via the route method on the Messenger class.

--Rafael

/** Adds a routing rule to a Messenger's internal routing table.
  *
  * The route procedure may be used to influence how a messenger will
  * internally treat a given address or class of addresses. Every call
  * to the route procedure will result in messenger appending a routing
  * rule to its internal routing table.
  *
  * Whenever a message is presented to a messenger for delivery, it
  * will match the address of this message against the set of routing
  * rules in order. The first rule to match will be triggered, and
  * instead of routing based on the address presented in the message,
  * the messenger will route based on the address supplied in the rule.
  *


Can you help me work through this use-case:


A 'dumb' client, sends a message, and expects a reply:

// client.c
pn_message_set_address(msg, "amqp://localhost/bla");
pn_messenger_put(msgr, msg);
pn_messenger_receive(msgr,1);
msg = pn_messenger_get(msgr);



The peer it connects to uses the new route functionality:

// server.c
pn_messenger_subscribe(msgr, "~amqp://localhost/bla");

1) Are routes valid to use if there's a subscribe going on.
   I assume yes.

pn_messenger_route(msgr, "*", "amqp://broker/$1");

2) How do they interact.
   I assume they don't, routing is only applied to outgoing messages.

3) Does the order of calls to route and subscribe matter.
   According to 2) it does not.

pn_messenger_receive(msgr, 1);
msg = pn_messenger_get(msgr);

/* echo */
char *sender = pn_message_get_reply_to(msg);
pn_message_set_address(msg, sender);
pn_messenger_put(msgr, msg);
pn_messenger_send(msgr);


4) What would the pn_message_get_reply_to() return.
   The value as set by the client's messenger would be 
amqp://some-uuid-value


5) Would the route above apply or not to this particular outgoing reply 
message.


6) If yes, how will 'broker' learn how to talk to the original client

7) If no, how will the server.c messenger know when to apply the routes 
and when not




Bozzo



Re: RFC: new routing functionality for messenger

2013-03-26 Thread Bozo Dragojevic

On 3/25/13 8:26 PM, Rafael Schloming wrote:

On Mon, Mar 25, 2013 at 3:06 PM, Bozo Dragojevic  wrote:


Rafael,

did you consider a variant where a user can supply a rewrite object?

pn_messenger_set_router(pn_**messenger_t *msgr, pn_router_t *router)

Proton library can then easily supply a one or more ready-made
implementations.


I did consider this, but it's difficult to expose an interface like that
through swig


I didn't want to suggest to go that far right now. It should be enough
to expose the default implementation as

pn_router_t *pn_router()

I agree it's difficult to expose a mechanism to define
a custom pn_router_t* in a scripting language. This is a separate
task and can be done later. It'd probably make sense to wait with
that until the interface between the router and the messenger firms up.


Bozzo



Re: RFC: new routing functionality for messenger

2013-03-25 Thread Rafael Schloming
On Mon, Mar 25, 2013 at 3:06 PM, Bozo Dragojevic  wrote:

> Rafael,
>
> did you consider a variant where a user can supply a rewrite object?
>
> pn_messenger_set_router(pn_**messenger_t *msgr, pn_router_t *router)
>
> Proton library can then easily supply a one or more ready-made
> implementations.
>

I did consider this, but it's difficult to expose an interface like that
through swig, and I wanted to start with something that would allow all the
basic scenarios to work consistently across all the different bindings. I
think if we find the need for something as flexible as you suggest above, I
would probably chain it together with a more basic mechanism like what is
there now, e.g. the router object would have access to rewrite both before
and/or after the basic translation rules are applied.

Some areas I can think of where such an interface might be interesting is
with dynamic routing tables, e.g. a larger AMQP network where next hop
information is propagated all the way to the endpoints, or perhaps with
centralized configuration management/discovery where the routing table is
queried dynamically when the network is joined. Right now though I am
thinking of those sorts of things as a distinct set of scenarios from
endpoint configured routing rules.

--Rafael


Re: RFC: new routing functionality for messenger

2013-03-25 Thread Bozo Dragojevic

Rafael,

did you consider a variant where a user can supply a rewrite object?

pn_messenger_set_router(pn_messenger_t *msgr, pn_router_t *router)

Proton library can then easily supply a one or more ready-made 
implementations.


Bozzo

On 3/23/13 5:43 PM, Rafael Schloming wrote:

Hi,

I've added a new API to messenger that gives the user some control over the
internal routing behaviour of a messenger. Please check it out and comment.
I've pasted the C API/doxygen below. This is currently only exposed through
the python binding via the route method on the Messenger class.

--Rafael

/** Adds a routing rule to a Messenger's internal routing table.
  *
  * The route procedure may be used to influence how a messenger will
  * internally treat a given address or class of addresses. Every call
  * to the route procedure will result in messenger appending a routing
  * rule to its internal routing table.
  *
  * Whenever a message is presented to a messenger for delivery, it
  * will match the address of this message against the set of routing
  * rules in order. The first rule to match will be triggered, and
  * instead of routing based on the address presented in the message,
  * the messenger will route based on the address supplied in the rule.
  *
  * The pattern matching syntax supports two types of matches, a '%'
  * will match any character except a '/', and a '*' will match any
  * character including a '/'.
  *
  * A routing address is specified as a normal AMQP address, however it
  * may additionally use substitution variables from the pattern match
  * that triggered the rule.
  *
  * Any message sent to "foo" will be routed to "amqp://foo.com":
  *
  *   pn_messenger_route("foo", "amqp://foo.com");
  *
  * Any message sent to "foobar" will be routed to
  * "amqp://foo.com/bar":
  *
  *   pn_messenger_route("foobar", "amqp://foo.com/bar");
  *
  * Any message sent to bar/  will be routed to the corresponding
  * path within the amqp://bar.com domain:
  *
  *   pn_messenger_route("bar/*", "amqp://bar.com/$1");
  *
  * Route all messages over TLS:
  *
  *   pn_messenger_route("amqp:*", "amqps:$1")
  *
  * Supply credentials for foo.com:
  *
  *   pn_messenger_route("amqp://foo.com/*", "amqp://user:passw...@foo.com/$1
");
  *
  * Supply credentials for all domains:
  *
  *   pn_messenger_route("amqp://*", "amqp://user:password@$1");
  *
  * Route all addresses through a single proxy while preserving the
  * original destination:
  *
  *   pn_messenger_route("amqp://%/*", "amqp://user:password@proxy/$1/$2");
  *
  * Route any address through a single broker:
  *
  *   pn_messenger_route("*", "amqp://user:password@broker/$1");
  *
  * @param[in] messenger the Messenger
  * @param[in] pattern a glob pattern
  * @param[in] address an address indicating alternative routing
  *
  * @return an error code or zero on success
  * @see error.h
  *
  */
PN_EXTERN int pn_messenger_route(pn_messenger_t *messenger, const char
*pattern,
  const char *address);





Re: RFC: new routing functionality for messenger

2013-03-25 Thread Rajith Attapattu
On Mon, Mar 25, 2013 at 11:42 AM, Rafael Schloming  wrote:
> On Mon, Mar 25, 2013 at 10:34 AM, Rajith Attapattu wrote:
>
>> For starters I would copy this email to the user list.
>> (In the future we should post things like this to a more wider
>> audience, especially if we are looking for feedback based on real
>> world use cases.)
>>
>
> I posted it where I intended it to go. I don't mind a broader audience
> looking at it, but at this stage I'm really looking for feedback from
> proton developers and people more keyed into messenger's distributed
> messaging model. This is for two reasons: (1) I don't want to push out
> stuff and have people start using it before it is sufficiently reviewed by
> other proton developers, and (2) a lot of the people on the users list
> (perhaps most of them) are quite firmly entrenched in the traditional hub
> and spoke broker model, and from their perspective the primary use for this
> functionality would simply be to route("*", "my-giant-hub-broker/$1") and
> thereby make messenger simulate your traditional hub and spoke client,
> however this functionality is about way more than that.
>
> I think after a round of discussion and documentation (not just API docs)
> it would probably be more digestable to a broader audience. Feel free to
> kick off wider discussion if you wish though, I've no objection, I'm just
> explaining my thinking at this stage.

Thanks for your explanation, and you do have a point about people
starting to use the feature a bit prematurely and perhaps in a
narrower scope than what we would have liked.
Unfortunately the same holds true if we publish it even after we deem
it's ready for general consumption.
Changing the mindset especially after years of being conditioned to a
particular approach is going to be difficult.
The challenge for Proton is to educate our users and the general
development community that we can do much more than the hub-spoke
model.

My desire to bring the discussion to a more wider audience was
motivated by recent comments/observations by Fraser and Gordon.
Within our user base, we do seem to have a few early adopters who
seems keen to be a bit more involved in the development process than a
regular user would.
Perhaps a more reasonable approach would be to copy dev@ instead of
user@ hoping the above crowd is on @dev.

>
>> I actually like the minimalistic approach you've taken here. It works
>> well in an embedded context.
>> Support for regex will be a welcome addition.
>> I don't think we should bother with a config file for proton. To me
>> it's neither here nor there. Let the application developer or the
>> deployment folks who use the proton based application worry about it.
>> As both you and Ted pointed out, a more sophisticated routing
>> capability is best achieved outside the scope of Proton.
>>
>
> I agree it's not the job of a library to provide system level
> integration/configuration, however we should do what we can to make it easy
> for system integrators to do so themselves and, to the extent that we can,
> encourage them to provide as consistent an experience as possible across
> systems, e.g. I considered plugging into system provided regex libraries
> for providing regular expression support, but that could result in slightly
> different styles of regex depending on which system you're on, so I decided
> against that option. (Not saying I don't want to provide regex support,
> just that if we do we should find a way that works the same regardless of
> where you are.)

Thats a fair point, I agree with you.

> Regarding your statement on sophisticated routing capabilities being kept
> outside of proton, I think it's worth pointing out that unless you're
> considering just the hub and spoke topology, routing isn't something that
> is contained to a single component or even a single class of component in
> your network. It's something that everything, including the endpoints in
> your network need to be aware of and cooperatively participate in so that
> you can achieve a given overall effect.

This is indeed what I meant, perhaps I should have elaborated a bit more.
As you said, for complicated networks, the routing aspect will be
de-centralized and achieved by the collaboration/cooperation of all
kinds of nodes/services within the network that may span
organizations.
Therefore it's impossible for us to provide a comprehensive solution
through proton, or other components (routers, bridges, brokers ..etc)
we offer through the larger QPid umbrella.
What we can provide is some simple basic building blocks/helper
utilities that will help the end users to compose more larger complex
routing strategies.

In that regard what you've offered seems quite good. Anything more
will be neither here nor there.

Rajith

> --Rafael


Re: RFC: new routing functionality for messenger

2013-03-25 Thread Rafael Schloming
On Mon, Mar 25, 2013 at 10:34 AM, Rajith Attapattu wrote:

> For starters I would copy this email to the user list.
> (In the future we should post things like this to a more wider
> audience, especially if we are looking for feedback based on real
> world use cases.)
>

I posted it where I intended it to go. I don't mind a broader audience
looking at it, but at this stage I'm really looking for feedback from
proton developers and people more keyed into messenger's distributed
messaging model. This is for two reasons: (1) I don't want to push out
stuff and have people start using it before it is sufficiently reviewed by
other proton developers, and (2) a lot of the people on the users list
(perhaps most of them) are quite firmly entrenched in the traditional hub
and spoke broker model, and from their perspective the primary use for this
functionality would simply be to route("*", "my-giant-hub-broker/$1") and
thereby make messenger simulate your traditional hub and spoke client,
however this functionality is about way more than that.

I think after a round of discussion and documentation (not just API docs)
it would probably be more digestable to a broader audience. Feel free to
kick off wider discussion if you wish though, I've no objection, I'm just
explaining my thinking at this stage.


> I actually like the minimalistic approach you've taken here. It works
> well in an embedded context.
> Support for regex will be a welcome addition.
> I don't think we should bother with a config file for proton. To me
> it's neither here nor there. Let the application developer or the
> deployment folks who use the proton based application worry about it.
> As both you and Ted pointed out, a more sophisticated routing
> capability is best achieved outside the scope of Proton.
>

I agree it's not the job of a library to provide system level
integration/configuration, however we should do what we can to make it easy
for system integrators to do so themselves and, to the extent that we can,
encourage them to provide as consistent an experience as possible across
systems, e.g. I considered plugging into system provided regex libraries
for providing regular expression support, but that could result in slightly
different styles of regex depending on which system you're on, so I decided
against that option. (Not saying I don't want to provide regex support,
just that if we do we should find a way that works the same regardless of
where you are.)

Regarding your statement on sophisticated routing capabilities being kept
outside of proton, I think it's worth pointing out that unless you're
considering just the hub and spoke topology, routing isn't something that
is contained to a single component or even a single class of component in
your network. It's something that everything, including the endpoints in
your network need to be aware of and cooperatively participate in so that
you can achieve a given overall effect.

--Rafael


Re: RFC: new routing functionality for messenger

2013-03-25 Thread Rajith Attapattu
For starters I would copy this email to the user list.
(In the future we should post things like this to a more wider
audience, especially if we are looking for feedback based on real
world use cases.)

I actually like the minimalistic approach you've taken here. It works
well in an embedded context.
Support for regex will be a welcome addition.
I don't think we should bother with a config file for proton. To me
it's neither here nor there. Let the application developer or the
deployment folks who use the proton based application worry about it.
As both you and Ted pointed out, a more sophisticated routing
capability is best achieved outside the scope of Proton.

Regards,

Rajith

On Mon, Mar 25, 2013 at 9:30 AM, Rafael Schloming  wrote:
> On Mon, Mar 25, 2013 at 8:36 AM, Ted Ross  wrote:
>
>> I generally like this translation facility, though I'll need to think
>> through some use cases to make sure there's sufficient capability in the
>> matching and substitution.
>>
>
> I would definitely appreciate some more feedback on this area. I think some
> real world usage will help us out. I struggled with various options here. I
> didn't want to add a dependency onto a regular expression library without
> at least some kind of fallback as I think this functionality is going to
> end up being too useful to be optional.
>
> There are a number of public domain regular expression libraries out there
> (e.g. t-rex) that are basically designed to be small enough and simple
> enough to be sucked into a codebase wholesale for when you can't afford an
> external dependency. I considered grabbing one of those, but I also wasn't
> 100% sure that full on regex was the best/only option here. There is
> something nice and simple about being able to say route("*", "my-uplink")
> as opposed to writing a fullon regex.
>
> I can see possibly even wanting to support multiple syntax options
> eventually, but for starters I decided to keep it simple. I wrote a very
> small glob style matcher with substitution. It's roughly 100 lines of code
> and should work on any platform. I'm entirely open to replacing this with
> something a real regex library if we want or something else entirely, I
> just wanted something simple/portable to start with so we could actually
> play with the functionality and learn a bit more about what is appropriate.
>
>
>> I question the value of having this as part of the API.  It seems to me
>> that the Messenger routing table should be part of the configuration of a
>> system (i.e. in a place like /etc/qpid/messenger/, or the Windows Registry,
>> etc.).  Eventually, it might be desirable to have an address translation
>> service that can be accessed remotely.  I guess I see this translation as
>> being not the concern of the application, but more of the deployment of the
>> application.
>>
>>
> Initially I was actually going to add the functionality via some kind of
> configuration file as you say. I have a similar conceptual view of the
> functionality as you describe, i.e. it really should only be used as part
> of the deployment/configuration of the messenger, not part of the
> "application work" portion of the API. I ended up going this route for two
> reasons (no pun intended). For starters it was a bit more expedient as I
> didn't have to write some kind of file format parser, but the second, and
> perhaps more important reason, is that I wasn't sure of the implications of
> adding dependencies onto files/file systems. I want messenger to be usable
> from embedded devices that might not even have a file system, so I figured
> it would be safer to offer as a pure API. I do think it would be
> appropriate to layer some kind of system integration on top of this API
> just as you describe.
>
> --Rafael


Re: RFC: new routing functionality for messenger

2013-03-25 Thread Rafael Schloming
On Mon, Mar 25, 2013 at 8:36 AM, Ted Ross  wrote:

> I generally like this translation facility, though I'll need to think
> through some use cases to make sure there's sufficient capability in the
> matching and substitution.
>

I would definitely appreciate some more feedback on this area. I think some
real world usage will help us out. I struggled with various options here. I
didn't want to add a dependency onto a regular expression library without
at least some kind of fallback as I think this functionality is going to
end up being too useful to be optional.

There are a number of public domain regular expression libraries out there
(e.g. t-rex) that are basically designed to be small enough and simple
enough to be sucked into a codebase wholesale for when you can't afford an
external dependency. I considered grabbing one of those, but I also wasn't
100% sure that full on regex was the best/only option here. There is
something nice and simple about being able to say route("*", "my-uplink")
as opposed to writing a fullon regex.

I can see possibly even wanting to support multiple syntax options
eventually, but for starters I decided to keep it simple. I wrote a very
small glob style matcher with substitution. It's roughly 100 lines of code
and should work on any platform. I'm entirely open to replacing this with
something a real regex library if we want or something else entirely, I
just wanted something simple/portable to start with so we could actually
play with the functionality and learn a bit more about what is appropriate.


> I question the value of having this as part of the API.  It seems to me
> that the Messenger routing table should be part of the configuration of a
> system (i.e. in a place like /etc/qpid/messenger/, or the Windows Registry,
> etc.).  Eventually, it might be desirable to have an address translation
> service that can be accessed remotely.  I guess I see this translation as
> being not the concern of the application, but more of the deployment of the
> application.
>
>
Initially I was actually going to add the functionality via some kind of
configuration file as you say. I have a similar conceptual view of the
functionality as you describe, i.e. it really should only be used as part
of the deployment/configuration of the messenger, not part of the
"application work" portion of the API. I ended up going this route for two
reasons (no pun intended). For starters it was a bit more expedient as I
didn't have to write some kind of file format parser, but the second, and
perhaps more important reason, is that I wasn't sure of the implications of
adding dependencies onto files/file systems. I want messenger to be usable
from embedded devices that might not even have a file system, so I figured
it would be safer to offer as a pure API. I do think it would be
appropriate to layer some kind of system integration on top of this API
just as you describe.

--Rafael


Re: RFC: new routing functionality for messenger

2013-03-25 Thread Ted Ross
I generally like this translation facility, though I'll need to think 
through some use cases to make sure there's sufficient capability in the 
matching and substitution.


I question the value of having this as part of the API.  It seems to me 
that the Messenger routing table should be part of the configuration of 
a system (i.e. in a place like /etc/qpid/messenger/, or the Windows 
Registry, etc.).  Eventually, it might be desirable to have an address 
translation service that can be accessed remotely.  I guess I see this 
translation as being not the concern of the application, but more of the 
deployment of the application.


-Ted

On 03/23/2013 12:43 PM, Rafael Schloming wrote:

Hi,

I've added a new API to messenger that gives the user some control over the
internal routing behaviour of a messenger. Please check it out and comment.
I've pasted the C API/doxygen below. This is currently only exposed through
the python binding via the route method on the Messenger class.

--Rafael

/** Adds a routing rule to a Messenger's internal routing table.
  *
  * The route procedure may be used to influence how a messenger will
  * internally treat a given address or class of addresses. Every call
  * to the route procedure will result in messenger appending a routing
  * rule to its internal routing table.
  *
  * Whenever a message is presented to a messenger for delivery, it
  * will match the address of this message against the set of routing
  * rules in order. The first rule to match will be triggered, and
  * instead of routing based on the address presented in the message,
  * the messenger will route based on the address supplied in the rule.
  *
  * The pattern matching syntax supports two types of matches, a '%'
  * will match any character except a '/', and a '*' will match any
  * character including a '/'.
  *
  * A routing address is specified as a normal AMQP address, however it
  * may additionally use substitution variables from the pattern match
  * that triggered the rule.
  *
  * Any message sent to "foo" will be routed to "amqp://foo.com":
  *
  *   pn_messenger_route("foo", "amqp://foo.com");
  *
  * Any message sent to "foobar" will be routed to
  * "amqp://foo.com/bar":
  *
  *   pn_messenger_route("foobar", "amqp://foo.com/bar");
  *
  * Any message sent to bar/ will be routed to the corresponding
  * path within the amqp://bar.com domain:
  *
  *   pn_messenger_route("bar/*", "amqp://bar.com/$1");
  *
  * Route all messages over TLS:
  *
  *   pn_messenger_route("amqp:*", "amqps:$1")
  *
  * Supply credentials for foo.com:
  *
  *   pn_messenger_route("amqp://foo.com/*", "amqp://user:passw...@foo.com/$1
");
  *
  * Supply credentials for all domains:
  *
  *   pn_messenger_route("amqp://*", "amqp://user:password@$1");
  *
  * Route all addresses through a single proxy while preserving the
  * original destination:
  *
  *   pn_messenger_route("amqp://%/*", "amqp://user:password@proxy/$1/$2");
  *
  * Route any address through a single broker:
  *
  *   pn_messenger_route("*", "amqp://user:password@broker/$1");
  *
  * @param[in] messenger the Messenger
  * @param[in] pattern a glob pattern
  * @param[in] address an address indicating alternative routing
  *
  * @return an error code or zero on success
  * @see error.h
  *
  */
PN_EXTERN int pn_messenger_route(pn_messenger_t *messenger, const char
*pattern,
  const char *address);





RFC: new routing functionality for messenger

2013-03-23 Thread Rafael Schloming
Hi,

I've added a new API to messenger that gives the user some control over the
internal routing behaviour of a messenger. Please check it out and comment.
I've pasted the C API/doxygen below. This is currently only exposed through
the python binding via the route method on the Messenger class.

--Rafael

/** Adds a routing rule to a Messenger's internal routing table.
 *
 * The route procedure may be used to influence how a messenger will
 * internally treat a given address or class of addresses. Every call
 * to the route procedure will result in messenger appending a routing
 * rule to its internal routing table.
 *
 * Whenever a message is presented to a messenger for delivery, it
 * will match the address of this message against the set of routing
 * rules in order. The first rule to match will be triggered, and
 * instead of routing based on the address presented in the message,
 * the messenger will route based on the address supplied in the rule.
 *
 * The pattern matching syntax supports two types of matches, a '%'
 * will match any character except a '/', and a '*' will match any
 * character including a '/'.
 *
 * A routing address is specified as a normal AMQP address, however it
 * may additionally use substitution variables from the pattern match
 * that triggered the rule.
 *
 * Any message sent to "foo" will be routed to "amqp://foo.com":
 *
 *   pn_messenger_route("foo", "amqp://foo.com");
 *
 * Any message sent to "foobar" will be routed to
 * "amqp://foo.com/bar":
 *
 *   pn_messenger_route("foobar", "amqp://foo.com/bar");
 *
 * Any message sent to bar/ will be routed to the corresponding
 * path within the amqp://bar.com domain:
 *
 *   pn_messenger_route("bar/*", "amqp://bar.com/$1");
 *
 * Route all messages over TLS:
 *
 *   pn_messenger_route("amqp:*", "amqps:$1")
 *
 * Supply credentials for foo.com:
 *
 *   pn_messenger_route("amqp://foo.com/*", "amqp://user:passw...@foo.com/$1
");
 *
 * Supply credentials for all domains:
 *
 *   pn_messenger_route("amqp://*", "amqp://user:password@$1");
 *
 * Route all addresses through a single proxy while preserving the
 * original destination:
 *
 *   pn_messenger_route("amqp://%/*", "amqp://user:password@proxy/$1/$2");
 *
 * Route any address through a single broker:
 *
 *   pn_messenger_route("*", "amqp://user:password@broker/$1");
 *
 * @param[in] messenger the Messenger
 * @param[in] pattern a glob pattern
 * @param[in] address an address indicating alternative routing
 *
 * @return an error code or zero on success
 * @see error.h
 *
 */
PN_EXTERN int pn_messenger_route(pn_messenger_t *messenger, const char
*pattern,
 const char *address);