offline_message_hook
サーバーがオンラインでないユーザーにメッセージをルーティングしているときにのみ呼び出されます。user_send_packet
サーバーがクライアントからスタンザを受信するたびに実行されます。これは、テスト方法にもよりますが、ハンドラーが実行されない理由を説明している可能性があります。MongooseIM のいくつかのフックを説明する 1 つのセクションを含む記事が、公式 wiki で入手できます。
パケット属性の取得に関する問題については、検査のために着信パケットをログに記録するかdbg
、サーバーの Erlang シェルを使用して、モジュールによって行われた実際の呼び出しをトレースすることで、何が起こっているかを知ることができます。
問題をデバッグするセッションの例dbg
は、次のようになります。
(mongooseim@localhost)1> dbg:tracer().
{ok,<0.570.0>}
(mongooseim@localhost)2> dbg:p(all, call).
{ok,[{matched,mongooseim@localhost,279}]}
(mongooseim@localhost)3> dbg:tpl(mod_test, x).
{ok,[{matched,mongooseim@localhost,5},{saved,x}]}
(mongooseim@localhost)4> (<0.576.0>) call mod_test:fetchPacketData({jid,<<"alice">>,<<"localhost">>,<<"escalus-default-resource">>,<<"alice">>,
<<"localhost">>,<<"escalus-default-resource">>},{jid,<<"alice">>,<<"localhost">>,<<>>,<<"alice">>,<<"localhost">>,<<>>},{xmlel,<<"presence">>,[{<<"xml:lang">>,<<"en">>}],[]})
(<0.576.0>) exception_from {mod_test,fetchPacketData,3} {error,function_clause}
2015-03-15 11:46:03.028 [error] <0.576.0>@ejabberd_hooks:run1:240 {function_clause,[{lists,thing_to_list,[<<>>],[{file,"lists.erl"},{line,601}]},{lists,flatmap,2,[{file,"lists.erl"},{line,1248}]},{lists,flatmap,2,[{file,"lists.erl"},{line,1248}]},{mod_test,fetchPacketData,3,[{file,"src/mod_test.erl"},{line,15}]},{safely,apply,3,[{file,"src/safely.erl"},{line,19}]},{ejabberd_hooks,run1,3,[{file,"src/ejabberd_hooks.erl"},{line,236}]},{ejabberd_c2s,session_established2,2,[{file,"src/ejabberd_c2s.erl"},{line,1063}]},{p1_fsm_old,handle_msg,10,[{file,"src/p1_fsm_old.erl"},{line,542}]}]}
Running hook: {user_send_packet,[{jid,<<"alice">>,<<"localhost">>,<<"escalus-default-resource">>,<<"alice">>,<<"localhost">>,<<"escalus-default-resource">>},{jid,<<"alice">>,<<"localhost">>,<<>>,<<"alice">>,<<"localhost">>,<<>>},{xmlel,<<"presence">>,[{<<"xml:lang">>,<<"en">>}],[]}]}
Callback: mod_test:fetchPacketData
function_clause
を呼び出すと、ハンドラーが でエラーになることがわかりlists:thing_to_list(<<>>)
ます。空のバイナリは、xml:get_tag_attr_s/2
要求された属性が見つからない場合の結果です。lists:thing_to_list/1
の各パラメーターをlists:concat/1
リストに変換するために呼び出されますが、空のバイナリ<<>>
をリストに変換することはできないため、クラッシュします。
の結果を照合し、xml:get_tag_attr_s/2
それぞれのケース (属性が見つかった場合と見つからなかった場合) に合わせてロジックを作成します。
dbg でモジュールを開始する方法がわかりません。上記で共有したことを試しましたが、モジュールを開始する方法の例となる4番目のコマンドを見逃していたと思います.
これは、編集を加えていない私のコンソールの生のダンプです。どの部分も見逃していません。「dbg でモジュールを開始」しません。通常の方法でモジュールを起動dbg
し、サーバー シェルから使用するだけです。
私がしたことは、あなたのサンプルコードを取り、それをapps/ejabberd/src/mod_test.erl
ファイルに入れ、リリースを構築することでした. その後ejabberd.cfg
、リリースのいずれかでモジュールを有効にすることができます (セクションを探して、modules
そこに示されている例と同様に実行します)。または、ライブ モードでサーバーをmongooseimctl live
起動し、モジュールを手動で起動できますgen_mod:start_module(<<"localhost">>, mod_test, [])
(ここで<<"localhost">>
は、XMPP ドメインの例です)。 - 独自の適切なドメインに置き換えてください)。
モジュールが実行されている場合 ( で確認できますgen_mod:is_loaded(<<"your-xmpp-domain">>, mod_name_goes_here)
)、 を有効にする必要がありますdbg
。これは、以前に追加したリストに表示されています。非常に優れた紹介が StackOverflow で既に利用可能であるdbg
ため、使用方法については詳しく説明しません。
属性が存在するかどうかをテストする方法の例
case xml:get_tag_attr_s(<<"some-attribute">>, Packet) of
<<>> ->
%% attribute does not exist, as get_tag_attr_s returned the default value
ok;
<<"some-value">> ->
%% do something sensible with <<"some-value">>
ok
end
exml
または、 MongooseIM の一部でもあり (元の ejabberd ではありません)、必要な属性が見つからないことをより明示的に示す which を使用することもできます。
case exml_query:attr(Packet, <<"some-attribute">>) of
undefined ->
%% not found
ok;
<<"some-value">> ->
%% do something
...
end