offline_message_hook
вызывается только тогда, когда сервер перенаправляет сообщение пользователю, который не находится в сети. user_send_packet
запускается каждый раз, когда сервер получает раздел от клиента. Это может объяснить, почему обработчик не запускается, хотя это зависит от того, как вы тестируете. Есть статья с одним разделом, описывающим некоторые хуки в MongooseIM доступен на официальной вики.
Что касается проблем с получением атрибутов пакета, то либо регистрация входящего пакета для проверки, либо использование 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
. Это показано в списке, который я добавил ранее. Я не буду вдаваться в описание того, как использовать 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) и более явно указывает на то, что вы не можете найти запрашиваемый атрибут:
case exml_query:attr(Packet, <<"some-attribute">>) of
undefined ->
%% not found
ok;
<<"some-value">> ->
%% do something
...
end
15.03.2015
httpc:request
никогда не вызывается - я описал ошибку выше. Вы можете опубликовать весь пакет в приложении PHP, но вы должны заранее сериализовать его в строку. Почему ваша сессия dbg не была успешной? 15.03.2015