我正在编写一个ejabberd挂钩,以与Apple Push Notification Server创建外发SSL连接。我已经在ejabberd之外(在erlang解释器中)测试了send方法,并可以验证它是否有效。我不确定为什么该模块:
-module(mod_http_offline).
-author("Joseph Martin").
%% Every ejabberd module implements the gen_mod behavior
%% The gen_mod behavior requires two functions: start/2 and stop/1
-behaviour(gen_mod).
%% public methods for this module
-export([start/2, stop/1, create_message/3]).
%% included for writing to ejabberd log file
-include("ejabberd.hrl").
%% ejabberd functions for JID manipulation called jlib.
-include("jlib.hrl").
start(_Host, _Opt) ->
?INFO_MSG("mod_http_offline loading", []),
%send("Test Push"),
ejabberd_hooks:add(offline_message_hook, _Host, ?MODULE, create_message, 50).
stop (_Host) ->
?INFO_MSG("stopping mod_http_offline", []),
ejabberd_hooks:delete(offline_message_hook, _Host, ?MODULE, create_message, 50).
create_message(_From, _To, Packet) ->
Type = xml:get_tag_attr_s("type", Packet),
FromS = xml:get_tag_attr_s("from", Packet),
ToS = xml:get_tag_attr_s("to", Packet),
Body = xml:get_path_s(Packet, [{elem, "body"}, cdata]),
if (Type == "chat") ->
send("You did it!","10","Chime")
end.
% All argument fields expect a string
send(Msg) ->
send_pn([{alert, Msg}]).
% send a string and and a bagde number
send(Msg, Badge) ->
send_pn([{alert, Msg}, {badge, Badge}]).
% send a string, a badge number and play a sound
send(Msg, Badge, Sound) ->
send_pn([{alert, Msg}, {badge, Badge}, {sound, Sound}]).
send_pn(Msg) ->
% start ssl
ssl:start(),
% application:start(ssl),
% socket configuration, may need to increase the timeout if concurrency becomes an issue
Address = "gateway.sandbox.push.apple.com",
% Address = "gateway.push.apple.com",
Port = 2195,
Cert = "/Users/joemartin/Desktop/PushNotificationCertificates/PushChatCert.pem",
Key = "/Users/joemartin/Desktop/PushNotificationCertificates/PushChatKey.pem",
Options = [{certfile, Cert}, {keyfile, Key}, {password, "mypassword"}, {mode, binary}, {verify, verify_none}],
Timeout = 5000,
case ssl:connect(Address, Port, Options, Timeout) of
{ok, Socket} ->
% Convert the device token from hex to int to binary
Token = "3eca19d7...mydevicetokenstring",
TokenNum = erlang:list_to_integer(Token, 16),
TokenBin = <<TokenNum:32/integer-unit:8>>,
% Construct the protocol packet
PayloadString = create_json(Msg),
Payload = list_to_binary(PayloadString),
PayloadLength = byte_size(Payload),
Packet = <<0:8, 32:16, TokenBin/binary, PayloadLength:16, Payload/binary>>,
% Send the packet then close the socket
ssl:send(Socket, Packet),
ssl:close(Socket),
% Return the PayloadString (for debugging purposes)
PayloadString;
{error, Reason} ->
?INFO_MSG("THE SSL CONNECTION FAILED", []),
Reason
end.
% helper for creating json
create_json(List) ->
lists:append(["{\"aps\":{", create_keyvalue(List), "}}"]).
create_keyvalue([Head]) ->
create_pair(Head);
create_keyvalue([Head|Tail]) ->
lists:append([create_pair(Head), ",", create_keyvalue(Tail)]).
create_pair({Key, Value}) ->
lists:append([add_quotes(atom_to_list(Key)), ":", add_quotes(Value)]).
add_quotes(String) ->
lists:append(["\"", String, "\""]).
在我的错误日志中创建此stacktrace:
=ERROR REPORT==== 2013-12-31 16:23:57 ===
E(<0.1558.0>:ejabberd_hooks:294) : {undef,
[{tls,connect,
["gateway.sandbox.push.apple.com",2195,
[{certfile,
"/Users/joemartin/Desktop/PushNotificationCertificates/PushChatCert.pem"},
{keyfile,
"/Users/joemartin/Desktop/PushNotificationCertificates/PushChatKey.pem"},
{password,"mypassword"},
{mode,binary},
{verify,verify_none}],
5000],
[]},
{mod_http_offline,send_pn,1,
[{file,"mod_http_offline.erl"},
{line,69}]},
{ejabberd_hooks,run1,3,
[{file,"ejabberd_hooks.erl"},
{line,290}]},
{ejabberd_sm,route,3,
[{file,"ejabberd_sm.erl"},{line,87}]},
{ejabberd_local,route,3,
[{file,"ejabberd_local.erl"},
{line,120}]},
{ejabberd_router,route,3,
[{file,"ejabberd_router.erl"},
{line,68}]},
{ejabberd_c2s,session_established2,2,
[{file,"ejabberd_c2s.erl"},{line,1122}]},
{p1_fsm,handle_msg,10,
[{file,"p1_fsm.erl"},{line,544}]}]}
我读过ejabberd 2默认情况下禁用了旧式SSL,但认为这仅用于传入的客户端连接。我也没有找到一个建立出站SSL连接的钩子的好例子。我也意识到名称mod_http_offline是一个错误的名称。有任何想法吗?
谢谢,
乔
最佳答案
我看到它在ejabberd buglist on github上报告了。
只是为了让它降级一个或另一个。
要解决生产问题,请根据您的需求定制依赖项。
重新命名模块名称,确保其唯一且与开始/停止回调一致。遵守约定并具有mod前缀可能会很好。新名称也将进入ejabberd.cfg(在“模块”部分中)。
关于ssl - 使用ejabberd Hook 建立传出SSL连接,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20863528/