What is mod_rpc ?
mod_rpc is an ejabberd module which will handle rpc queries … in a modular way.
It is is easily extensible, and is designed to access the mnesia database from XMPP clients.
It plugs in the access control list to allow or prevent access to the rpc modules.
Installing mod_rpc
Download the mod_rpc.erl file and copy it over your ejabberd src/ directory.
make ejabberd.
Do not restart yet, we have some configuration to do !
Using mod_rpc
Let’s say you want to publish two functions, echo and mult. The code would go as follow :
rpc_test.erl :
-module(rpc_test).
-export([handle/2]).
handle(_State, {call, echo, [A]}) -> {response, [A]};
handle(_State, {call, mult, [A, B]}) -> {response, [A*B]};
Copy into your ejabberd source directory and make.
Now you need to configure access to your functions. In
ejabberd.cfg
% 2 groups : admins, and the rest.
{access, rpc_admin, [{allow, admin}]}.
{access, rpc_all, [{allow, all}]}.
%...
%... in modules configuration
%...
{mod_register, [{access, register}]},
{mod_rpc, [{access, [{rpc_test, rpc_admin}] }]}, % only admins can call echo and mult
{mod_roster, []},
%....
Now start ejabberd. (of course you could do the hot code stuff if you want)
From now on I have rpc_test@rpc.localhost answering to my rpc queries.
Let’s test from ruby using xmpp4r. Get the SVN version for jabber-RPC support.
require 'xmpp4r'
require 'xmpp4r/rpc/helper/client'
require 'xmpp4r/rpc/helper/server'
include Jabber
jid = JID::new('cstar@localhost') #this one is admin !
cl = Client::new(jid)
cl.connect
cl.auth("PASS")
rpc= RPC::Client.new(cl, 'rpc_test@rpc.localhost')
puts rpc.call("echo", 'Test string') # outputs Test string
puts rpc.call("mult", 2,4) # outputs ... 8
If you try with a non-admin user, you’d get
Jabber::AuthenticationFailure: not-authorized
About Groovy Jabber-RPC
I have been playing with it, and it does not work directly out of the box. The groovy lib will try to see if rpc_test@rpc.localhost is in the user roster.
Patching to making it work is quite simple ; In file xmlrpc-groovy/src/main/java/groovy/net/xmlrpc/JabberRPCServerProxy.java
Just replace : request.setTo(getId(connection.getRoster(), this.to)); (line 102)
with : request.setTo(this.to);
And the following will work :
import groovy.net.xmlrpc.*
import org.jivesoftware.smack.XMPPConnection
def clientConnection = new XMPPConnection("localhost")
clientConnection.connect()
clientConnection.login("cstar", "PASS")
def serverProxy = new JabberRPCServerProxy(clientConnection, "rpc_test@rpc.localhost")
serverProxy.echo("test")
clientConnection.disconnect()
Necessary caveats
This is my first foray in developping a module in ejabberd, I still have to check how this actually scales. I only have one process handling all queries, which is not very concurrency oriented programming :)
Thanks
The guys from ejabberd, for making software really easy to use and extend ;)
Download :
Feedback
I really welcome enhancements and fixes (especially regarding the concurrency stuff!)
License
Don’t sue me, don’t remove copyright/name kind of license.