Release Merge and Message Sending API

A couple of weeks ago I took some time and merged in the latest ejabberd 2.1.x series release.  This bring Fork21 into parity with 2.1.13.

After the update I finally decided to add a feature I’ve been meaning to add for a while now. From time to time applications need to originate XMPP messages, but it can be inconvenient to keep an XMPP connection open for outbound only messages.  It is for this reason that I added send message support to the ejabberd_api module.

At this time if a user has the api_admin access permission they can HTTP POST an XMPP <message> stanza to http://<server>:5280/api/message/send/xml.  As long as the message stanza is properly formatted with a to address the message will be sent as the user that authenticated with HTTP auth.

Posted in Uncategorized | Leave a comment

Host provisioning API

I’ve been working on exposing the new host provisioning functions through a JSON api.  There are a number of endpoints defined.  They all work with GET requests, but if you want to specify a domain configuration when registering a domain you have to post a JSON object.  In order to use this API you need to enable the api in your ejabberd_http listener by adding the ‘ejabberd_api’ config atom.

It should look like this:

{5280, ejabberd_http, [              ejabberd_api,
             captcha,
             http_bind,
             http_poll,
             %%register,
             web_admin
            ]}

After the listener is configured you also need to define acls and access rules.  To allow access to admin@localhost I added the following rules:

{acl, api_admin_acl, {user, "admin", "localhost"}}.
{access, api_admin, [{allow, api_admin_acl}]}.

Endpoints:

/api/domain/register/<domain>
/api/domain/unregister/<domain>
/api/domain/start/<domain>
/api/domain/stop/<domain>
/api/domain/status/<domain>
/api/domain/list

Most of these can be best understood after spending a few minutes experimenting with hitting each URL path in a browser.  The key things to note are that you must register a domain then start it.  When you want to remove a domain you have to stop it before unregistering.  Each step must be done in the correct state or a descriptive error is returned.

To specify special domain configurations POST a JSON object to the domain register function.  Anything that can be put into a {host_config, Host, ConfigList} section of the config can be passed in through the JSON object with the exception of {add, modules} directives.

Here is an example JSON object post:

{"domain_config": "[{modules,[{mod_offline,[]},{mod_version,[]}]}]."}

Authentication, modules, and other details can be configured using this method.  Take note that the configuration is passed as an array instead of individual erlang terms as seen in the config file.

Posted in Uncategorized | Leave a comment

Starting and stopping hosts

Since the last update I added a number of safeties for starting and stopping domains.  A domain has to be a valid configured domain that is not currently running before ejabberd_hosts:start_host(“hostname”) can be called.

The register_host(Host) and unregister_host(Host) functions can now be used to add or remove entries in the dynamic_hosts configuration option.  With the addition of these functions it is now possible to dynamically register, start, stop and unregister domains.  The next parts that need to be solved now are configuring a domain’s local settings.  Currently domains can be provisioned and controlled using ejabberdctl.  Below is one of my command line sessions testing out the dynamic domain provisioning features I’ve been working on.

# sbin/ejabberdctl start
# sbin/ejabberdctl status
The node ejabberd@monitor is started with status: started
ejabberd 2.1.11 is running in that node
# sbin/ejabberdctl start_host fastinfra.com
Host fastinfra.com started.
# sbin/ejabberdctl start_host fastinfra.com
Error: already_running
# sbin/ejabberdctl stop_host fastinfra.com
Host fastinfra.com stopped.
# sbin/ejabberdctl unregister_host fastinfra.com
Host fastinfra.com unregistered.
# sbin/ejabberdctl start_host fastinfra.com
Error: nohost

Now it is time to start testing with clients to see what broke as I went through making these changes.  I have done the basic tests of connecting and passing messages between users.  There is a lot more testing to be done, but the basics appear to be there.  You can test it too as all my changes are in the fork21 branch of ejabberd I have been working on.

Stay tuned for more updates.  I hope to keep these changes moving in new and interesting directions for ejabberd.

Posted in Commits | Leave a comment

Centralize from local_config to config

When fixing vhost startup bugs in a cluster I discovered that having the vhost module configuration in local_config was a source of trouble for configuration data that really was consistent across the cluster almost all the time.

For what it’s worth, the reasons for using local_config may have been driven by requirements and use cases I have no experience with.  The use cases I do have experience with are however harder to solve with the current design so I’m trying a change.

I made some changes and committed them in preparation for my next step.  A common default vhost config will help with dynamic host start/stop in a cluster.  There are still a number of bugs to figure out before taking on dynamic vhosts so for now I’m laying a foundation.

Posted in Commits | Leave a comment

A new fork to play on

This weekend I decided to try making some changes to ejabberd 2.1.x.  I’ve gotten into ejabberd’s internals with Chatmongers and have found a number of things that I didn’t like.

The first thing I decided to go after is how hosts are started and stopped.  This weekend I made some significant changes to how vhosts are started and stopped.  I added a new process that manages the starting and stopping of domains in the system instead of various modules doing their own independent startup and it all starts with a supervisor.

Unfortunately, this new method of starting and stopping domains is not yet complete.  I can halt a domain and start it again which stops all the modules and unregisters all of the routes then start and register again.  These are useful operations, but will be even more useful if I can add dynamic vhost configuration.  There is a mess that is config and local_config.  I’ve stumbled my way though bugs that are related to one being cluster global and the other being node local.  I already had to kludge my way around the mess when fixing dynamic host start/stop in clustered ejabberd3.  Often times it doesn’t make sense why things are in local_config instead of config.

My goal is to move more things into the cluster global config from local_config.  I then can add node local configuration directives.  What I am hoping for in the end is a better centralized configuration for vhosts and modules while still allowing per node configuration for database connections and other node local values.

As a project ejabberd really is exciting to me.  However, there have been some things that I really have not liked about it.  My hope is to fix everything that has bothered me in my last few years of working with it.  I’m not sure if anyone else will like my changes, but I hope to smooth some of the rough edges that bother me.

Posted in Commits | Leave a comment