Search code examples
erlangelixirejabberd

How to register IQ handler in Ejabberd elixir module?


I'm trying to register IQ handler in elixir module (using Ejabberds gen_iq_handler module), but cannot make it work. It seems that it registers the handler, but function is not called.

Registration of hooks works as expected (calling on_presence function), but handler is not picked up.

:gen_iq_handler.add_iq_handler returns :ok

I've tried passing fully qualified name (atom) for function (e.g. :"Elixir.ModPresenceDemo.on_iq_received") without success and passing namespace parameter as char list also without success

Here are start and on_iq_received functions:

def start(host, _opts) do
  info("Starting ejabberd module Presence Demo #{host}")
  Ejabberd.Hooks.add(:set_presence_hook, host, __MODULE__, :on_presence, 50)
  result = :gen_iq_handler.add_iq_handler(:ejabberd_sm, host, "module:test", __MODULE__, :on_iq_received)
  info(host)
  info(__MODULE__)
  info(result)
  :ok
end
...
def on_iq_received(iq) do
  info('Received data for IQ handler')
  IO.inspect(iq)
  iq
end

upon calling handler with iq stanza:

<iq type="set" id="test" to="<user>@<host>">
  <query xmlns="module:test"/>
</iq>

I get IQ error stanza with error code 400: Unknown tag <query/> qualified by namespace 'module:test'


Solution

  • Wild guess: add a function called decode_iq_subel in the handler module that returns its argument:

    def decode_iq_subel(el) do
       el
    end
    

    I suspect that the error you're getting comes from here - ejabberd calls the xmpp library to decode the subelement of the iq stanza, but since xmpp knows nothing of your custom namespace, it throws an unknown_tag error, which gets formatted into Unknown tag ... qualified by namespace ... here.