An Erlang Lightweight XMPP Client library


Keywords
amqp, erlang, http, rabbitmq, xmpp, xmpp-client, xmpp-component
License
Apache-2.0

Documentation

snatch

Copyright (c) 2017 Thiago Camargo

Authors: "Thiago Camargo" (barata7@gmail.com).

Build Status Codecov License: Apache 2.0

Lightweight XMPP Client Library for Erlang. This library is intended to handle client connections in an agnostic way. The system is launched using the snatch process and configuring as many claws as you need.

The built-in claws are:

Installation

The system requires OTP 19+ because we use gen_statem and remove the code_change/3 and terminate/2. For OTP 19+ those callbacks are optional.

In the same way we prefer to use rebar3 instead of older versions. To install snatch only needs:

{deps, [
    {snatch, {git, "https://github.com/manuel-rubio/snatch.git", {branch, master}}}
]}

Or if you are using erlang.mk instead, you can use:

DEPS += snatch
dep_snatch = git https://github.com/manuel-rubio/snatch.git master

The used dependencies are:

You'll need a C/C++ compiler installed in your system for fast_xml and stringprep.

Configuring

There are no strict configuration for the application. You have to send the specific information when you start the specific process:

{ok, PID} = snatch:start_link(claws_xmpp, my_module, []).

This format helps to start snatch using my_module as our implementation of the snatch behaviour to use the callbacks to implement the behaviour we want to achieve.

The third element ([]) are the arguments passed to the init/1 callback in my_module. You can send all of the information you need for your callback.

The specific claws should be started spearately. See the specific information about each one in their specific documentation pages (see above).

Callbacks

You can use this template to develop your own modules:

-module(my_own_module).
-behaviour(snatch).

-include_lib("snatch/include/snatch.hrl").

-export([init/1, handle_info/2, terminate/2]).

-record(state, {}).

init([]) ->
    {ok, #state{}}.

handle_info({connected, _Claw}, State) ->
    {noreply, State};

handle_info({disconnected, _Claw}, State) ->
    {noreply, State};

handle_info({received, _Packet, #via{}}, State) ->
    {noreply, State};

handle_info({received, _Packet}, State) ->
    {noreply, State}.

terminate(_Reason, _State) ->
    ok.

Note that if you're using rebar3 you can use this command instead to create your template:

./rebar3 new snatch name=my_own_module

The call to the init/1 function is performed each time the snatch system is started and terminate/2 when the system is finished properly. Note that in case of internal errors this code will not be called.

The callback handle_info/2 will be called when a message arrives to snatch.

The events you can receive are:

  • connected: says the claw (passed as second element in the tuple) is connected properly.
  • disconnected: says the claw (passed as second element in the tuple) was disconnected.
  • received: this event has two ways. Only receive a packet (as second element in the tuple) or receive the packet and the #via{} information as well. This information gives us information about the way the packet was sent.

The #via{} record has the following information:

  • jid as the JID (Jabber Identification) of the via.
  • exchange (only for AMQP) says the exchange in use for the element.
  • claws is the module used to receive the message.
  • id the identification of the packet.

Router / Listener

Although the previous (Callbacks) section let you to create a router or listener for all of the events received from the claws, maybe you want to receive in your gen_server or gen_statem those events instead of create a module only for that.

In this case you can use the snatch_router and instead of use snatch:start_link/3 you can use snatch:start_link/2. This way the second parameter to use for snatch will be a registered name or a PID.

All of the previous events will be send to that process using this way.

Sending

To send information thru snatch to the claws you can use the following functions:

  • send/1 to send a packet directly to the default claw. The JID will be configured as unknown for the claw.
  • send/2 to send a packet using a specific JID (as second param). The JID will be in use to retrieve a route from the internal snatch information.
  • send/3 to send a packet using a specific JID (as second param) and pointing the ID of the packet to be handled properly by the claw.

The packet should be a valid XML construction. Your application is in charge to create it in the way you want.

For example:

snatch:send(<<"<presence/>">>).

Testing

There are a framework to test XMPP easily. For further information: testing framework.

Troubleshooting

Feel free to create an issue in github to point a bug, flaw or improvement and even send a pull request with a specific change. Read the LICENSE if you have doubts about what you can do with the code.

Enjoy!

Modules

claws
claws_fcm
claws_fcm_worker
claws_kafka
claws_lp
claws_rabbitmq
claws_rest
claws_xmpp
claws_xmpp_comp
snatch
snatch_fun_test
snatch_jid
snatch_router
snatch_stanza
snatch_xml