0
votes

I'm writing a custom ejabberd module. When I send a custom IQ stanza using strophe js, ejabberd processes the request and returns the result IQ back to the sender.

Below is the IQ request I send using strophe js,

connection.sendIQ($iq({
    to: 'john@localhost',
    type: 'set',
    id: 'abc1234567890'
})
.c('query', {
    xmlns: 'jabber:iq:custom_module',
    msg_id: 'xyz9876543210'
})
.tree());

and this is the ejabberd module code,

-module(mod_custom_module).
-behaviour(gen_mod).
-define(NS_CUSTOM_MODULE, <<"jabber:iq:custom_module">>).

-export([start/2, stop/1, depends/2, mod_options/1, process_sm_iq/1, decode_iq_subel/1]).

-include("xmpp.hrl").
-include("logger.hrl").
-include("ejabberd_sql_pt.hrl").

start(_Host, _Opts) ->
    gen_iq_handler:add_iq_handler(ejabberd_sm, _Host, ?NS_CUSTOM_MODULE, ?MODULE, process_sm_iq, one_queue).
stop(_Host) ->
    gen_iq_handler:remove_iq_handler(ejabberd_sm, _Host, ?NS_CUSTOM_MODULE).

depends(_Host, _Opts) ->
    [].

mod_options(_Host) ->
    [].

-spec decode_iq_subel(xmpp_element()) -> xmpp_element();
            (xmlel()) -> xmlel().
decode_iq_subel(El) ->
    El.

-spec process_sm_iq(iq()) -> iq().
process_sm_iq(#iq{from = _From, to = _To, sub_els = _sub_els} = IQ) ->
    % My module actions here...
    [First | Rest] = _sub_els,
    xmpp:make_iq_result(IQ, First).

After processing the IQ, I also want to notify the other user 'john@localhost' about the custom event. I tried to do this using ejabberd_router:route/3, but it did not work.

I don't know what I am doing wrong.

Update

When I use the following code, the other user is not receiving stanza.

NewIQ = #iq{id = _Id, type = result, to = _To, from = _From, sub_els = _sub_els},

ejabberd_router:route(xmpp:set_from_to(NewIQ, _From, _To)),
% or ejabberd_router:route(NewIQ),
% or ejabberd_sm:route(NewIQ),

And when I checked the debug console, it is showing the following message in it. Not sure whether this is relevant as it is just a debug type message and there is no other failure error message.

17:07:47.173 [debug] Dropping packet to unavailable resource:
#iq{id = <<"abc1234567890">>,type = result,lang = <<>>,
from = #jid{user = <<"nikhil">>,server = <<"localhost">>,
            resource = <<"49230572059507447681762">>,luser = <<"nikhil">>,
            lserver = <<"localhost">>,
            lresource = <<"49230572059507447681762">>},
to = #jid{user = <<"john">>,server = <<"localhost">>,
          resource = <<>>,luser = <<"john">>,
          lserver = <<"localhost">>,lresource = <<>>},
sub_els = [#xmlel{name = <<"query">>,
            attrs = [{<<"xmlns">>,<<"jabber:iq:custom_module">>},
            {<<"msg_id">>,<<"xyz9876543210">>}],
            children = []}],
meta = #{}}
1

1 Answers

1
votes

Try this function. It sends a headline message to the destination account with some details about the original IQ.

process_sm_iq(#iq{from = From, to = To, sub_els = SubEls} = IQ) ->
    [First | Rest] = SubEls,
    MsgId = fxml:get_tag_attr_s(<<"msg_id">>, First),
    Subject = "Event alert",
    Body = "An IQ was received by custom_module with msg_id: "++MsgId,
    Packet = #message{from = From,
                      to = To,
                      type = headline,
                      body = xmpp:mk_text(Body),
                      subject = xmpp:mk_text(Subject)},
    ejabberd_router:route(Packet),
    xmpp:make_iq_result(IQ, First).