samples: net: NATS protocol sample
NATS is a publisher/subscriber protocol implemented on top of TCP. It
is specified in [1], and this is a sample implementation for Zephyr
using the new IP stack. The API is loosely based off of [2].
With this sample, it's possible to subscribe/unsubscribe to a given
subject, and be notified of changes asynchronously. In order to
conserve resources, the implementation does not keep its own track of
subscribed subjects; that must be performed by the application itself,
so it ignore unknown/undesired subjects.
TLS is not supported yet, although basic auth is. The client will
indicate if it supports username/password if a certain callback is set
in the struct nats. This callback will then be called, and the user
must copy the username/password to the supplied user/pass buffers.
Content might be also published for a given subject.
The sample application lets one observe the subject "led0", and turn it
"on", "off", or "toggle" its value. Changing the value will, if
supported, act on a status LED on the development board. The new
status will be published.
Also worth noting is that most of the networking and GPIO boilerplate
has been shamelessly copied from the IRC bot example. (Curiously, both
protocols are similar.)
[1] http://nats.io/documentation/internals/nats-protocol/
[2] https://github.com/nats-io/go-nats
Jira: ZEP-1012
Change-Id: I204adc61c4c533661eacfb8c28c1c08870debd91
Signed-off-by: Leandro Pereira <leandro.pereira@intel.com>
2017-02-25 03:03:30 +08:00
|
|
|
.. _NATS_Client_Sample:
|
|
|
|
|
|
|
|
|
|
|
|
NATS Client Implementation Sample
|
|
|
|
#################################
|
|
|
|
|
|
|
|
|
|
|
|
Overview
|
|
|
|
********
|
|
|
|
|
|
|
|
`NATS <http://nats.io/documentation/internals/nats-protocol/>`__ is a
|
|
|
|
publisher/subscriber protocol implemented on top of TCP. It is specified in
|
|
|
|
`NATS Protocol documentation <http://nats.io/documentation/internals/nats-protocol/>`__,
|
|
|
|
and this is a sample implementation for Zephyr using the new IP stack.
|
|
|
|
The API is loosely based off of the `Golang API
|
|
|
|
<https://github.com/nats-io/go-nats>`__.
|
|
|
|
|
|
|
|
With this sample, it's possible to subscribe/unsubscribe to a given subject,
|
|
|
|
and be notified of changes asynchronously. In order to conserve resources,
|
|
|
|
the implementation does not keep track of subscribed subjects; that
|
|
|
|
must be performed by the application itself, so it can ignore unknown/undesired
|
|
|
|
subjects.
|
|
|
|
|
|
|
|
TLS is not supported yet, although basic authentication is. The client will indicate
|
|
|
|
if it supports username/password if a certain callback is set in the ``struct
|
|
|
|
nats``. This callback will then be called, and the user must copy the
|
|
|
|
username/password to the supplied user/pass buffers.
|
|
|
|
|
|
|
|
Content might be also published for a given subject.
|
|
|
|
|
|
|
|
The sample application lets one observe the subject "led0", and turn it
|
|
|
|
"on", "off", or "toggle" its value. Changing the value will, if supported,
|
|
|
|
act on a status LED on the development board. The new status will be
|
|
|
|
published.
|
|
|
|
|
|
|
|
Also worth noting is that most of the networking and GPIO boilerplate has
|
|
|
|
been shamelessly copied from the IRC bot example. (Curiously, both
|
|
|
|
protocols are similar.)
|
|
|
|
|
|
|
|
Requirements
|
|
|
|
************
|
|
|
|
|
|
|
|
To test the sample, build the Zephyr application for your platform. This
|
|
|
|
has only been tested with the QEMU emulator as provided by the Zephyr SDK,
|
|
|
|
but it should work with other supported hardware as long as they have enough
|
|
|
|
memory, the network stack has TCP enabled, and the connectivity hardware is
|
|
|
|
supported.
|
|
|
|
|
|
|
|
As far as the software goes, this has been tested with the official `gnatsd
|
|
|
|
<https://github.com/nats-io/gnatsd>`__ for the server, and the official
|
|
|
|
`go-nats <https://github.com/nats-io/go-nats>`__ client library. Both the
|
|
|
|
server and clients were set up as per instructions found in their respective
|
|
|
|
``README.md`` files.
|
|
|
|
|
|
|
|
The client was a one-off test that is basically the same code provided in
|
|
|
|
the `Basic Usage
|
|
|
|
<https://github.com/nats-io/go-nats/blob/e6bb81b5a5f37ef7bf364bb6276e13813086c6ee/README.md#basic-usage>`__
|
|
|
|
section as found in the ``go-nats`` README file, however, subscribing to the
|
|
|
|
topic used in this sample: ``led0``, and publishing values as described
|
|
|
|
above (``on``, ``off``, and ``toggle``).
|
|
|
|
|
|
|
|
Library Usage
|
|
|
|
*************
|
|
|
|
|
|
|
|
Allocate enough space for a ``struct nats``, setting a few callbacks so
|
|
|
|
that you're notified as events happen:
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
struct nats nats_ctx = {
|
|
|
|
.on_auth_required = on_auth_required,
|
|
|
|
.on_message = on_message
|
|
|
|
};
|
|
|
|
|
|
|
|
The ``on_auth_required()`` and ``on_message()`` functions are part of
|
|
|
|
your application, and each must have these signatures:
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
int on_auth_required(struct nats *nats, char **user, char **pass);
|
|
|
|
int on_message(struct nats *nats, struct nats_msg *msg);
|
|
|
|
|
|
|
|
Both functions should return 0 to signal that they could successfully
|
|
|
|
handle their role, and a negative value, if they couldn't for any
|
|
|
|
reason. It's recommended to use a negative integer as provided by
|
|
|
|
errno.h in order to ease debugging.
|
|
|
|
|
|
|
|
The first function, ``on_auth_required()``, is called if the server
|
|
|
|
notifies that it requires authentication. It's not going to be called if
|
|
|
|
that's not the case, so it is optional. However, if the server asks for
|
|
|
|
credentials and this function is not provided, the connection will be
|
|
|
|
closed and an error will be returned by ``nats_connect()``.
|
|
|
|
|
|
|
|
The second function, ``on_message()``, will be called whenever the
|
|
|
|
server has been notified of a value change. The ``struct nats_msg`` has the
|
|
|
|
following fields:
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
struct nats_msg {
|
|
|
|
const char *subject;
|
|
|
|
const char *sid;
|
|
|
|
const char *reply_to;
|
|
|
|
};
|
|
|
|
|
|
|
|
The field ``reply_to`` may be passed directly to ``nats_publish()``,
|
|
|
|
in order to publish a reply to this message. If it's ``NULL`` (no
|
|
|
|
reply-to field in the message from the server), the
|
|
|
|
``nats_publish()`` function will not reply to a specific mailbox and
|
|
|
|
will just update the topic value.
|
|
|
|
|
|
|
|
In order to manage topic subscription, these functions can be used:
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
int nats_subscribe(struct nats *nats, const char *subject,
|
|
|
|
const char *queue_group, const char *sid);
|
|
|
|
|
|
|
|
``subject`` and ``sid`` are validated so that they're actually valid
|
|
|
|
per the protocol rules. ``-EINVAL`` is returned if they're not.
|
|
|
|
|
|
|
|
If ``queue_group`` is NULL, it's not sent to the server.
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
int nats_unsubscribe(struct nats *nats, const char *sid,
|
|
|
|
size_t max_msgs);
|
|
|
|
|
|
|
|
``sid`` is validated so it's actually valid per the protocol rules.
|
|
|
|
-EINVAL is returned if it's not.
|
|
|
|
|
|
|
|
``max_msgs`` specifies the number of messages that the server will
|
|
|
|
send before actually unsubscribing the message. Can be 0 to
|
2017-03-07 06:36:12 +08:00
|
|
|
immediately unsubscribe. (See note below.)
|
samples: net: NATS protocol sample
NATS is a publisher/subscriber protocol implemented on top of TCP. It
is specified in [1], and this is a sample implementation for Zephyr
using the new IP stack. The API is loosely based off of [2].
With this sample, it's possible to subscribe/unsubscribe to a given
subject, and be notified of changes asynchronously. In order to
conserve resources, the implementation does not keep its own track of
subscribed subjects; that must be performed by the application itself,
so it ignore unknown/undesired subjects.
TLS is not supported yet, although basic auth is. The client will
indicate if it supports username/password if a certain callback is set
in the struct nats. This callback will then be called, and the user
must copy the username/password to the supplied user/pass buffers.
Content might be also published for a given subject.
The sample application lets one observe the subject "led0", and turn it
"on", "off", or "toggle" its value. Changing the value will, if
supported, act on a status LED on the development board. The new
status will be published.
Also worth noting is that most of the networking and GPIO boilerplate
has been shamelessly copied from the IRC bot example. (Curiously, both
protocols are similar.)
[1] http://nats.io/documentation/internals/nats-protocol/
[2] https://github.com/nats-io/go-nats
Jira: ZEP-1012
Change-Id: I204adc61c4c533661eacfb8c28c1c08870debd91
Signed-off-by: Leandro Pereira <leandro.pereira@intel.com>
2017-02-25 03:03:30 +08:00
|
|
|
|
|
|
|
Both of these functions will return ``-ENOMEM`` if they couldn't build
|
|
|
|
the message to transmit to the server. They can also return any error
|
|
|
|
that ``net_context_send()`` can return.
|
|
|
|
|
2017-03-07 06:36:12 +08:00
|
|
|
Note: In order to conserve resources, the library implementation will not
|
|
|
|
make note of subscribed topics. Both ``nats_subscribe()`` and
|
|
|
|
``nats_unsubscribe()`` functions will only notify the server that the client
|
|
|
|
is either interested or uninterested in a particular topic. The
|
|
|
|
``on_message()`` callback may be called to notify of changes in topics that
|
|
|
|
have not been subscribed to (or have been recently unsubscribed). It's up
|
|
|
|
to the application to decide to ignore the message.
|
samples: net: NATS protocol sample
NATS is a publisher/subscriber protocol implemented on top of TCP. It
is specified in [1], and this is a sample implementation for Zephyr
using the new IP stack. The API is loosely based off of [2].
With this sample, it's possible to subscribe/unsubscribe to a given
subject, and be notified of changes asynchronously. In order to
conserve resources, the implementation does not keep its own track of
subscribed subjects; that must be performed by the application itself,
so it ignore unknown/undesired subjects.
TLS is not supported yet, although basic auth is. The client will
indicate if it supports username/password if a certain callback is set
in the struct nats. This callback will then be called, and the user
must copy the username/password to the supplied user/pass buffers.
Content might be also published for a given subject.
The sample application lets one observe the subject "led0", and turn it
"on", "off", or "toggle" its value. Changing the value will, if
supported, act on a status LED on the development board. The new
status will be published.
Also worth noting is that most of the networking and GPIO boilerplate
has been shamelessly copied from the IRC bot example. (Curiously, both
protocols are similar.)
[1] http://nats.io/documentation/internals/nats-protocol/
[2] https://github.com/nats-io/go-nats
Jira: ZEP-1012
Change-Id: I204adc61c4c533661eacfb8c28c1c08870debd91
Signed-off-by: Leandro Pereira <leandro.pereira@intel.com>
2017-02-25 03:03:30 +08:00
|
|
|
|
|
|
|
Topics can be published by using the following function:
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
int nats_publish(struct nats *nats, const char *subject,
|
|
|
|
const char *reply_to, const char *payload,
|
|
|
|
size_t payload_len);
|
|
|
|
|
|
|
|
As usual, ``subject`` is validated and ``-EINVAL`` will be returned if
|
|
|
|
it's in an invalid format. The ``reply_to`` field can be ``NULL``, in
|
|
|
|
which case, subscribers to this topic won't receive this information as
|
|
|
|
well.
|
|
|
|
|
|
|
|
As ``net_subscribe()`` and ``net_unsubscribe()``, this function can
|
2017-03-07 06:36:12 +08:00
|
|
|
return ``-ENOMEM`` or any other errors that ``net_context_send()``
|
samples: net: NATS protocol sample
NATS is a publisher/subscriber protocol implemented on top of TCP. It
is specified in [1], and this is a sample implementation for Zephyr
using the new IP stack. The API is loosely based off of [2].
With this sample, it's possible to subscribe/unsubscribe to a given
subject, and be notified of changes asynchronously. In order to
conserve resources, the implementation does not keep its own track of
subscribed subjects; that must be performed by the application itself,
so it ignore unknown/undesired subjects.
TLS is not supported yet, although basic auth is. The client will
indicate if it supports username/password if a certain callback is set
in the struct nats. This callback will then be called, and the user
must copy the username/password to the supplied user/pass buffers.
Content might be also published for a given subject.
The sample application lets one observe the subject "led0", and turn it
"on", "off", or "toggle" its value. Changing the value will, if
supported, act on a status LED on the development board. The new
status will be published.
Also worth noting is that most of the networking and GPIO boilerplate
has been shamelessly copied from the IRC bot example. (Curiously, both
protocols are similar.)
[1] http://nats.io/documentation/internals/nats-protocol/
[2] https://github.com/nats-io/go-nats
Jira: ZEP-1012
Change-Id: I204adc61c4c533661eacfb8c28c1c08870debd91
Signed-off-by: Leandro Pereira <leandro.pereira@intel.com>
2017-02-25 03:03:30 +08:00
|
|
|
returns.
|