I'm learning to use Hooks to build an Ejabberd module. This is the tutorial I'm referring. Following is my code:-
-module(mod_sunshine).
-behavior(gen_mod).
-include("ejabberd.hrl").
-include("logger.hrl").
-export([start/2, stop/1, receive_packet/1]).
start(_Host, _Opts) ->
?INFO_MSG("mod_sunshine starting", []),
ejabberd_hooks:add(user_receive_packet, _Host, ?MODULE, receive_packet, 50),
ok.
stop(_Host) ->
?INFO_MSG("mod_sunshine stopping", []),
ejabberd_hooks:delete(user_receive_packet, _Host, ?MODULE, receive_packet, 50),
ok.
receive_packet({_JID, From, To} = Packet) ->
?INFO_MSG("receive_packet JID: ~p From: ~p To: ~p Packet: ~p~n",[_JID, From, To, Packet]),
ok.
I'm receiving and logging the received packet(using user_receive_packet
Hook) and but it throws an error. Following is the error:-
** Reason = {error,function_clause,[{mod_sunshine,receive_packet,[{file,"src/mod_sunshine.erl"},{line,20}],[{{iq,<<"purplead8c6fd0">>,result,<<"en">>,{jid,<<"praful1">>,<<"localhost">>,<<>>,<<"praful1">>,<<"localhost">>,<<>>},{jid,<<"praful1">>,<<"localhost">>,<<"Prafuls-MacBook-Pro">>,<<"praful1">>,<<"localhost">>,<<"Prafuls-MacBook-Pro">>},[],#{ip => {0,0,0,0,0,0,0,1}}},#{socket => {socket_state,gen_tcp,#Port<0.16027>,<0.479.0>},socket_monitor => #Ref<0.0.1.726>,stream_direction => in,caps_resources => {1,{{<<"praful1">>,<<"localhost">>,<<"Prafuls-MacBook-Pro">>},{caps,<<"http://pidgin.im/">>,<<"DdnydQG7RGhP9E3k9Sf+b+bF0zo=">>,<<"sha-1">>,[]},nil,nil}},tls_enabled => false,auth_module => ejabberd_auth_mnesia,mgmt_stanzas_out => 0,server => <<"localhost">>,sockmod => ejabberd_socket,privacy_list => {userlist,none,[],false},mgmt_resend => false,stream_id => <<"8641864023627389616">>,stream_authenticated => true,mgmt_ack_timeout => 60000,mgmt_queue_type => ram,mgmt_stanzas_req => 0,stream_timeout => infinity,stream_state => established,stream_compressed => false,shaper => c2s_shaper,sid => {{1495,527854,1},<0.480.0>},stream_version => {1,0},user => <<"praful1">>,mgmt_timeout => 300,ip => {{0,0,0,0,0,0,0,1},50783},stream_header_sent => true,csi_state => active,mgmt_state => inactive,conn => c2s,mod => ejabberd_c2s,stream_encrypted => false,pres_f => {1,{{<<"praful1">>,<<"localhost">>,<<>>},nil,nil}},tls_required => false,csi_queue => {0,#{}},jid => {jid,<<"praful1">>,<<"localhost">>,<<"Prafuls-MacBook-Pro">>,<<"praful1">>,<<"localhost">>,<<"Prafuls-MacBook-Pro">>},stream_restarted => true,pres_timestamp => {1495,527854,960838},xmlns => <<"jabber:client">>,mgmt_max_queue => 1000,tls_options => [compression_none],owner => <0.480.0>,resource => <<"Prafuls-MacBook-Pro">>,access => c2s,zlib => false,pres_last => {presence,<<>>,available,<<"en">>,{jid,<<"praful1">>,<<"localhost">>,<<"Prafuls-MacBook-Pro">>,<<"praful1">>,<<"localhost">>,<<"Prafuls-...">>},...},...}}]},...]}
** Arguments = [{{iq,<<"purplead8c6fd0">>,result,<<"en">>,{jid,<<"praful1">>,<<"localhost">>,<<>>,<<"praful1">>,<<"localhost">>,<<>>},{jid,<<"praful1">>,<<"localhost">>,<<"Prafuls-MacBook-Pro">>,<<"praful1">>,<<"localhost">>,<<"Prafuls-MacBook-Pro">>},[],#{ip => {0,0,0,0,0,0,0,1}}},#{socket => {socket_state,gen_tcp,#Port<0.16027>,<0.479.0>},socket_monitor => #Ref<0.0.1.726>,stream_direction => in,caps_resources => {1,{{<<"praful1">>,<<"localhost">>,<<"Prafuls-MacBook-Pro">>},{caps,<<"http://pidgin.im/">>,<<"DdnydQG7RGhP9E3k9Sf+b+bF0zo=">>,<<"sha-1">>,[]},nil,nil}},tls_enabled => false,auth_module => ejabberd_auth_mnesia,mgmt_stanzas_out => 0,server => <<"localhost">>,sockmod => ejabberd_socket,privacy_list => {userlist,none,[],false},mgmt_resend => false,stream_id => <<"8641864023627389616">>,stream_authenticated => true,mgmt_ack_timeout => 60000,mgmt_queue_type => ram,mgmt_stanzas_req => 0,stream_timeout => infinity,stream_state => established,stream_compressed => false,shaper => c2s_shaper,sid => {{1495,527854,1},<0.480.0>},stream_version => {1,0},user => <<"praful1">>,mgmt_timeout => 300,ip => {{0,0,0,0,0,0,0,1},50783},stream_header_sent => true,csi_state => active,mgmt_state => inactive,conn => c2s,mod => ejabberd_c2s,stream_encrypted => false,pres_f => {1,{{<<"praful1">>,<<"localhost">>,<<>>},nil,nil}},tls_required => false,csi_queue => {0,#{}},jid => {jid,<<"praful1">>,<<"localhost">>,<<"Prafuls-MacBook-Pro">>,<<"praful1">>,<<"localhost">>,<<"Prafuls-MacBook-Pro">>},stream_restarted => true,pres_timestamp => {1495,527854,960838},xmlns => <<"jabber:client">>,mgmt_max_queue => 1000,tls_options => [compression_none],owner => <0.480.0>,resource => <<"Prafuls-MacBook-Pro">>,access => c2s,zlib => false,pres_last => {presence,<<>>,available,<<"en">>,{jid,<<"praful1">>,<<"localhost">>,<<"Prafuls-MacBook-Pro">>,<<"praful1">>,<<"localhost">>,<<"Prafuls-MacBook-Pro">>},{jid,<<"praful1">>,<<"localhost">>,<<>>,<<"praful1">>,<<"lo...">>,...},...},...}}]
Where exactly am I wrong?
UPDATE
Upon looking at the hook written in one of the ejabberd module, it clearly shows that the hook function will have only 1 parameter. Hence, I updated my code as follow:-
-module(mod_sunshine).
-behavior(gen_mod).
-include("ejabberd.hrl").
-include("logger.hrl").
-include("xmpp.hrl").
-export([start/2, stop/1, user_receive_packet/1]).
start(_Host, _Opts) ->
?INFO_MSG("mod_sunshine starting", []),
ejabberd_hooks:add(user_receive_packet, _Host, ?MODULE, user_receive_packet, 50),
ok.
stop(_Host) ->
?INFO_MSG("mod_sunshine stopping", []),
ejabberd_hooks:delete(user_receive_packet, _Host, ?MODULE, user_receive_packet, 50),
ok.
-spec user_receive_packet({stanza(), ejabberd_c2s:state()}) -> {stanza(), ejabberd_c2s:state()}.
user_receive_packet({Packet, C2SState}) ->
?INFO_MSG("INSIDEEEEEEEE", []),
ok.
But the moment I receive a packet, it throws an error :-
13:59:28.118 [error] Hook user_receive_packet crashed when running mod_carboncopy:user_receive_packet/1:
** Reason = {error,function_clause,[{mod_carboncopy,user_receive_packet,[{file,"src/mod_carboncopy.erl"},{line,159}],[ok]},{ejabberd_hooks,safe_apply,[{file,"src/ejabberd_hooks.erl"},{line,380}],4},{ejabberd_hooks,run_fold1,[{file,"src/ejabberd_hooks.erl"},{line,364}],4},{ejabberd_c2s,process_info,[{file,"src/ejabberd_c2s.erl"},{line,231}],2},{ejabberd_hooks,safe_apply,[{file,"src/ejabberd_hooks.erl"},{line,380}],4},{ejabberd_hooks,run_fold1,[{file,"src/ejabberd_hooks.erl"},{line,364}],4},{xmpp_stream_in,handle_info,[{file,"src/xmpp_stream_in.erl"},{line,373}],2},{p1_server,handle_msg,[{file,"src/p1_server.erl"},{line,696}],8}]}
** Arguments = [ok]
13:59:28.119 [error] Hook c2s_handle_info crashed when running ejabberd_c2s:process_info/2:
** Reason = {error,{badmatch,ok},[{ejabberd_c2s,process_info,[{file,"src/ejabberd_c2s.erl"},{line,231}],2},{ejabberd_hooks,safe_apply,[{file,"src/ejabberd_hooks.erl"},{line,380}],4},{ejabberd_hooks,run_fold1,[{file,"src/ejabberd_hooks.erl"},{line,364}],4},{xmpp_stream_in,handle_info,[{file,"src/xmpp_stream_in.erl"},{line,373}],2},{p1_server,handle_msg,[{file,"src/p1_server.erl"},{line,696}],8},{proc_lib,init_p_do_apply,[{file,"proc_lib.erl"},{line,247}],3}]}
** Arguments = [#{socket => {socket_state,gen_tcp,#Port<0.15488>,<0.467.0>},stream_authenticated => true,tls_enabled => false,auth_module => ejabberd_auth_mnesia,mgmt_stanzas_out => 0,server => <<"localhost">>,sockmod => ejabberd_socket,privacy_list => {userlist,none,[],false},mgmt_resend => false,stream_id => <<"11245006342381720927">>,stream_encrypted => false,stream_state => established,mgmt_ack_timeout => 60000,mgmt_queue_type => ram,mgmt_stanzas_req => 0,stream_direction => in,stream_restarted => true,sid => {{1495,614568,1},<0.468.0>},user => <<"praful1">>,mgmt_timeout => 300,ip => {{0,0,0,0,0,0,0,1},52732},socket_monitor => #Ref<0.0.2.683>,csi_state => active,mgmt_state => inactive,conn => c2s,stream_timeout => infinity,mod => ejabberd_c2s,stream_compressed => false,pres_f => {1,{{<<"praful1">>,<<"localhost">>,<<>>},nil,nil}},tls_required => false,csi_queue => {0,#{}},jid => {jid,<<"praful1">>,<<"localhost">>,<<"Prafuls-MacBook-Pro">>,<<"praful1">>,<<"localhost">>,<<"Prafuls-MacBook-Pro">>},stream_header_sent => true,shaper => c2s_shaper,xmlns => <<"jabber:client">>,mgmt_max_queue => 1000,tls_options => [compression_none],owner => <0.468.0>,resource => <<"Prafuls-MacBook-Pro">>,access => c2s,zlib => false,mgmt_max_timeout => 300,pres_a => {0,nil},lang => <<"en">>,mgmt_stanzas_in => 0,lserver => <<"localhost">>,tls_verify => false,pres_t => {1,{{<<"praful1">>,<<"localhost">>,<<>>},nil,nil}},stream_version => {1,0}},{route,{iq,<<"purple3d24e94d">>,result,<<"en">>,{jid,<<>>,<<"localhost">>,<<>>,<<>>,<<"localhost">>,<<>>},{jid,<<"praful1">>,<<"localhost">>,<<"Prafuls-MacBook-Pro">>,<<"praful1">>,<<"localhost">>,<<"Prafuls-MacBook-Pro">>},[{disco_items,<<>>,[{disco_item,{jid,<<>>,<<"conference.localhost">>,<<>>,<<>>,<<"conference.localhost">>,<<>>},<<>>,<<>>},{disco_item,{jid,<<>>,<<"echo.localhost">>,<<>>,<<>>,<<"echo.localhost">>,<<>>},<<>>,<<>>},{disco_item,{jid,<<>>,<<"irc.localhost">>,<<>>,<<>>,<<"irc.localhost">>,<<>>},<<>>,<<>>},{disco_item,{jid,<<>>,<<"pubsub.localhost">>,<<>>,<<>>,<<"pubsub.localhost">>,<<>>},<<>>,<<>>},{disco_item,{jid,<<>>,<<"localhost">>,<<>>,<<>>,<<"localhost">>,<<>>},<<"Announcements">>,<<"announce">>},{disco_item,{jid,<<>>,<<"localhost">>,<<>>,<<>>,<<"localhost">>,<<>>},<<"Configuration">>,<<"config">>},{disco_item,{jid,<<>>,<<"localhost">>,<<>>,<<>>,<<"localhost">>,<<>>},<<"User Management">>,<<"user">>},{disco_item,{jid,<<>>,<<"localhost">>,<<>>,<<>>,<<"localhost">>,<<>>},<<"Online Users">>,<<"online users">>},{disco_item,{jid,<<>>,<<"localhost">>,<<>>,<<>>,<<"localhost">>,<<>>},<<"All Users">>,<<"all users">>},{disco_item,{jid,<<>>,<<"localhost">>,<<>>,<<>>,<<"localhost">>,<<>>},<<"Outgoing s2s Connections">>,<<"outgoing s2s">>},{disco_item,{jid,<<>>,<<"localhost">>,<<>>,<<>>,<<"localhost">>,<<>>},<<"Running Nodes">>,<<"running nodes">>},{disco_item,{jid,<<>>,<<"localhost">>,<<>>,<<>>,<<"localhost">>,<<>>},<<"Stopped Nodes">>,<<"stopped nodes">>}],undefined}],#{ip => {0,0,0,0,0,0,0,1}}}}]
Kindly provide your valuable inputs.
It seems that tutorial did not update for newer version of Ejabberd and i think you are using ejabberd >= 16.12.
according to the Code, Ejabberd passed
Packet
,ClientState
,ClientJid
,FromJid
andToJid
to your function.In newer versions,
Packet
is#iq{}
,#presence{}
or#message{}
record. Read this include file of xmpp lib for more info.