Skip to content
This repository was archived by the owner on May 23, 2024. It is now read-only.

Commit 8f2a176

Browse files
committed
prepare to replace mod_pushoff_apns with mod_pushoff_apns_h2
1 parent ebde50a commit 8f2a176

11 files changed

+7147
-72
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.beam

README.md

+8-6
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
mod_pushoff sends empty push notifications for messages in ejabberd's offline queue.
44

55
Supported backends:
6-
- `mod_pushoff_apns`: [Apple Legacy APNS Binary Provider API](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/BinaryProviderAPI.html#//apple_ref/doc/uid/TP40008194-CH13-SW1)
6+
- `mod_pushoff_apns_h2`: [Apple APNs over http/2](https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns)
77
- `mod_pushoff_fcm`: [Google Firebase Cloud Messaging HTTP Protocol](https://firebase.google.com/docs/cloud-messaging/http-server-ref)
88

99
## Prerequisites
@@ -64,23 +64,24 @@ modules:
6464
mod_pushoff:
6565
backends:
6666
-
67-
type: apns
67+
type: mod_pushoff_apns # deprecated
6868
# make sure this pem file contains only one(!) certificate + key pair
6969
certfile: "/etc/ssl/private/apns_example_app.pem"
7070
gateway: "gateway.push.apple.com"
7171
-
72-
type: apns
72+
type: mod_pushoff_apns_h2
7373
# you can add more backends of each type by specifying backend_ref with unique names
7474
backend_ref: "sandbox"
7575
# make sure this pem file contains only one(!) certificate + key pair
7676
certfile: "/etc/ssl/private/apns_example_app_sandbox.pem"
7777
gateway: "gateway.sandbox.push.apple.com"
78+
topic: "com.acme.your.app" # this should be your bundle id
7879
-
79-
type: fcm
80+
type: mod_pushoff_fcm
8081
gateway: "https://fcm.googleapis.com/fcm/send"
8182
api_key: "API_KEY"
8283
-
83-
type: fcm
84+
type: mod_pushoff_fcm
8485
# you can add more backends of each type by specifying backend_ref with unique names
8586
backend_ref: "fcm2"
8687
gateway: "https://fcm.googleapis.com/fcm/send"
@@ -94,6 +95,7 @@ Clients can register for push notifications by sending XEP-0004 adhoc requests.
9495
These are the available adhoc commands:
9596
9697
* `register-push-apns`: register with APNS
98+
* `register-push-apns-h2`: register with APNS/h2
9799
* `register-push-fcm`: register with Firebase
98100
* `list-push-registrations`: request a list of all registrations
99101
* `unregister-push`: delete all user's registrations
@@ -113,7 +115,7 @@ Example (note, `to='localhost'` contain the your user's server name):
113115
</iq>
114116
```
115117

116-
You need to specify a `backend_ref` field to route your subscription to a particular backend:
118+
You need to specify a `backend_ref` field to route your subscription to a particular backend (this is always the case for `mod_pushoff_apns_h2`):
117119

118120
```xml
119121
<iq type='set' to='localhost' id='randomrandomrequestid2'>

ejabberd.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -744,12 +744,12 @@ modules:
744744
mod_pushoff:
745745
backends:
746746
-
747-
type: fcm
747+
type: mod_pushoff_fcm
748748
backend_ref: "ref1"
749749
gateway: "https://fcm.googleapis.com/fcm/send"
750750
api_key: "API_KEY"
751751
-
752-
type: fcm
752+
type: mod_pushoff_fcm
753753
backend_ref: "ref2"
754754
gateway: "https://fcm.googleapis.com/fcm/send"
755755
api_key: "API_KEY_2"

src/mod_pushoff.erl

+45-61
Original file line numberDiff line numberDiff line change
@@ -35,30 +35,11 @@
3535

3636
-include("mod_pushoff.hrl").
3737

38-
-define(MODULE_APNS, mod_pushoff_apns).
39-
-define(MODULE_FCM, mod_pushoff_fcm).
4038
-define(OFFLINE_HOOK_PRIO, 1). % must fire before mod_offline (which has 50)
4139

42-
%
43-
% types
44-
%
45-
46-
-record(apns_config,
47-
{certfile = <<"">> :: binary(),
48-
gateway = <<"">> :: binary()}).
49-
50-
-record(fcm_config,
51-
{gateway = <<"">> :: binary(),
52-
api_key = <<"">> :: binary()}).
53-
54-
-type apns_config() :: #apns_config{}.
55-
-type fcm_config() :: #fcm_config{}.
56-
57-
-record(backend_config,
58-
{ref :: backend_ref(),
59-
config :: apns_config() | fcm_config()}).
60-
61-
-type backend_config() :: #backend_config{}.
40+
-type apns_config() :: #{backend_type := mod_pushoff_apns_h2, certfile := binary(), gateway := binary(), topic := binary()}.
41+
-type fcm_config() :: #{backend_type := mod_pushoff_fcm, gateway := binary(), api_key := binary()}.
42+
-type backend_config() :: #{ref := backend_ref(), config := apns_config() | fcm_config()}.
6243

6344
%
6445
% dispatch to workers
@@ -75,8 +56,7 @@ dispatch(#pushoff_registration{bare_jid = UserBare, token = Token, timestamp = T
7556
backend_id = BackendId},
7657
Payload) ->
7758
DisableArgs = {UserBare, Timestamp},
78-
gen_server:cast(backend_worker(BackendId),
79-
{dispatch, UserBare, Payload, Token, DisableArgs}),
59+
gen_server:cast(backend_worker(BackendId), {dispatch, UserBare, Payload, Token, DisableArgs}),
8060
ok.
8161

8262

@@ -144,10 +124,27 @@ adhoc_local_commands(Acc, _From, _To, _Request) ->
144124
Acc.
145125

146126

127+
adhoc_perform_action(<<"register-push-apns-h2">>, #jid{lserver = LServer} = From, XData) ->
128+
BackendRef = case xmpp_util:get_xdata_values(<<"backend_ref">>, XData) of
129+
[Key] -> {mod_pushoff_apns_h2, Key};
130+
_ -> undefined
131+
end,
132+
case validate_backend_ref(LServer, BackendRef) of
133+
{error, E} -> {error, E};
134+
{ok, BackendRef} ->
135+
case xmpp_util:get_xdata_values(<<"token">>, XData) of
136+
[Base64Token] ->
137+
case catch base64:decode(Base64Token) of
138+
{'EXIT', _} -> {error, xmpp:err_bad_request()};
139+
Token -> mod_pushoff_mnesia:register_client(From, {LServer, BackendRef}, Token)
140+
end;
141+
_ -> {error, xmpp:err_bad_request()}
142+
end
143+
end;
147144
adhoc_perform_action(<<"register-push-apns">>, #jid{lserver = LServer} = From, XData) ->
148145
BackendRef = case xmpp_util:get_xdata_values(<<"backend_ref">>, XData) of
149-
[Key] -> {apns, Key};
150-
_ -> apns
146+
[Key] -> {mod_pushoff_apns, Key};
147+
_ -> mod_pushoff_apns
151148
end,
152149
case validate_backend_ref(LServer, BackendRef) of
153150
{error, E} -> {error, E};
@@ -210,7 +207,7 @@ stop(Host) ->
210207
Worker = backend_worker({Host, Ref}),
211208
supervisor:terminate_child(ejabberd_gen_mod_sup, Worker),
212209
supervisor:delete_child(ejabberd_gen_mod_sup, Worker)
213-
end || #backend_config{ref=Ref} <- backend_configs(Host)],
210+
end || #{ref := Ref} <- backend_configs(Host)],
214211
ok.
215212

216213
depends(_, _) ->
@@ -220,34 +217,36 @@ mod_opt_type(backends) -> fun ?MODULE:parse_backends/1;
220217
mod_opt_type(_) -> [backends].
221218

222219
validate_backend_ref(Host, Ref) ->
223-
case [R || #backend_config{ref=R} <- backend_configs(Host), R == Ref] of
220+
case [R || #{ref := R} <- backend_configs(Host), R == Ref] of
224221
[R] -> {ok, R};
225222
_ -> {error, xmpp:err_bad_request()}
226223
end.
227224

228-
backend_ref(apns, undefined) -> apns;
229-
backend_ref(fcm, undefined) -> fcm;
230-
backend_ref(apns, K) -> {apns, K};
231-
backend_ref(fcm, K) -> {fcm, K}.
225+
backend_ref(X, undefined) -> X;
226+
backend_ref(X, K) -> {X, K}.
232227

233228
backend_type({Type, _}) -> Type;
234229
backend_type(Type) -> Type.
235230

236231
parse_backends(Plists) ->
237232
[parse_backend(Plist) || Plist <- Plists].
238233

234+
-spec(parse_backend(proplist:proplist()) -> backend_config()).
239235
parse_backend(Opts) ->
240236
Ref = backend_ref(proplists:get_value(type, Opts), proplists:get_value(backend_ref, Opts)),
241-
#backend_config{
242-
ref = Ref,
243-
config =
244-
case backend_type(Ref) of
245-
apns ->
246-
#apns_config{certfile = proplists:get_value(certfile, Opts), gateway = proplists:get_value(gateway, Opts)};
247-
fcm ->
248-
#fcm_config{gateway = proplists:get_value(gateway, Opts), api_key = proplists:get_value(api_key, Opts)}
249-
end
250-
}.
237+
#{ref => Ref,
238+
config =>
239+
case backend_type(Ref) of
240+
mod_pushoff_fcm ->
241+
#{backend_type => mod_pushoff_fcm,
242+
gateway => proplists:get_value(gateway, Opts),
243+
api_key => proplists:get_value(api_key, Opts)};
244+
X when X == mod_pushoff_apns orelse X == mod_pushoff_apns_h2 ->
245+
#{backend_type => X,
246+
certfile => proplists:get_value(certfile, Opts),
247+
gateway => proplists:get_value(gateway, Opts),
248+
topic => proplists:get_value(topic, Opts)}
249+
end}.
251250

252251
%
253252
% workers
@@ -262,29 +261,14 @@ backend_configs(Host) ->
262261
gen_mod:get_module_opt(Host, ?MODULE, backends,
263262
fun(O) when is_list(O) -> O end, []).
264263

265-
backend_module(apns) -> ?MODULE_APNS;
266-
backend_module(fcm) -> ?MODULE_FCM.
267-
268264
-spec(start_worker(Host :: binary(), Backend :: backend_config()) -> ok).
269265

270-
start_worker(Host, #backend_config{ref = Ref, config = Config}) ->
266+
start_worker(Host, #{ref := Ref, config := Config}) ->
271267
Worker = backend_worker({Host, Ref}),
272-
BackendSpec =
273-
case backend_type(Ref) of
274-
apns ->
275-
{Worker,
268+
BackendSpec = {Worker,
276269
{gen_server, start_link,
277-
[{local, Worker}, backend_module(backend_type(Ref)),
278-
[Config#apns_config.certfile, Config#apns_config.gateway], []]},
279-
permanent, 1000, worker, [?MODULE]};
280-
fcm ->
281-
{Worker,
282-
{gen_server, start_link,
283-
[{local, Worker}, backend_module(backend_type(Ref)),
284-
[Config#fcm_config.gateway, Config#fcm_config.api_key], []]},
285-
permanent, 1000, worker, [?MODULE]}
286-
end,
287-
270+
[{local, Worker}, backend_type(Ref), Config, []]},
271+
permanent, 1000, worker, [?MODULE]},
288272
supervisor:start_child(ejabberd_gen_mod_sup, BackendSpec).
289273

290274
%

src/mod_pushoff_apns.erl

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
message_id :: pos_integer(),
6363
gateway :: string()}).
6464

65-
init([CertFile, Gateway]) ->
65+
init(#{backend_type := ?MODULE, certfile := CertFile, gateway := Gateway}) ->
6666
inets:start(),
6767
crypto:start(),
6868
ssl:start(),

0 commit comments

Comments
 (0)