-
Notifications
You must be signed in to change notification settings - Fork 463
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update pusher application #4033
Conversation
maybe_load_apns(App, ETS, kapps_config:get_binary(?CONFIG_CAT, <<"apple">>, 'undefined', App)). | ||
Config = kapps_config:get_json(?CONFIG_CAT, <<"apple">>, kz_json:new(), App), | ||
CertBin = kz_json:get_ne_binary_value(<<"certificate">>, Config), | ||
Host = kz_json:get_ne_binary_value(<<"host">>, Config, ?DEFAULT_APNS_HOST), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rather you call kapps_config:get_ne_binary(?CONFIG_CAT, [<<"apple">>,<<"certificate">>])
for these two parameters.They do the same thing extraction and it's more explicit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Of course same goes for <<"host">>
-spec apns_topic(kz_json:object()) -> binary(). | ||
apns_topic(JObj) -> | ||
TokenApp = kz_json:get_ne_binary_value(<<"Token-App">>, JObj), | ||
re:replace(TokenApp, <<"\.(?:dev|prod)$">>, <<>>, [{'return', 'binary'}]). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to escape the backslash for it to have value in the eyes of re
, as "\." = "."
.
Config = kz_json:from_list([{<<"certificate">>, Binary} | ||
,{<<"host">>, Host} | ||
]), | ||
kapps_config:set_node(?CONFIG_CAT, <<"apple">>, Config, AppId), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would also prefer you setting these using multiple calls to set_node
(using a path like [<<"apple">>,<<"host">>]
in the second argument.
@@ -1177,6 +1177,12 @@ build_push_failover(Endpoint, Clid, PushJObj, Call) -> | |||
,{<<"Metaflows">>, kz_json:get_value(<<"metaflows">>, Endpoint)} | |||
])). | |||
|
|||
-spec push_headers(kz_json:object()) -> kz_json:object(). | |||
push_headers(PushJObj) -> | |||
kz_json:foldl(fun(K, V, Acc) -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry I know this is not related but I hate seeing fold called when a map is implemented.
Can you replace this with:
push_headers(PushJObj) ->
kz_json:from_list(
lists:keymap(fun prefix_header/1, 1, kz_json:to_proplist(PushJObj)).
prepend_header(Header) ->
<<"X-KAZOO-PUSHER-", Header/binary>>.
Please remove mention of apns' readme from the mkdocs files kazoo-dev.yml and mkdocs.yml (should fix circleci). |
@@ -46,6 +47,7 @@ ifeq ($(USER),travis) | |||
endif | |||
|
|||
dep_amqp_client_commit = rabbitmq_v3_6_0 | |||
dep_apns = git https://github.com/inaka/apns4erl.git 2.2.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you tried specifying this as an hex.pm package? https://hex.pm/packages/apns4erl
I'm guessing it wouldn't work due to the app having a different name than the package but I haven't tried it.
Looks like inaka's APNS needs OTP >= 19. Can you remove the line about OTP 18 in .travis.yml? EDIT: depend on inaka/apns4erl#198 for now maybe? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this pr has some issues. i will address this later.
just putting this so it doesn't get merged
f6bbafe
to
0741205
Compare
@fenollp Looks like you were right, can't specify it as a hex package right now. Everything actually works up to starting the apns4erl application -- because 'mod' isn't in the apns4erl.app, the module to start isn't specified and since it doesn't match the application name, it won't start |
@danielfinke I think you just need to add "pusher.host" and "pusher.certificate" to the descriptions file. At least, locally, You'll also need to update pusher's .app.src to point to apns4erl, apparently to satisfy relx. |
@jamesaimonetti Yeah, it just doesn't make sense since it should technically be "pusher.apple.host" and "pusher.apple.certificate". Edit: to clarify, apns_app.erl is the module to start using the Erlang application framework. It should launch apns_sup. I don't think apns_app.erl even gets run, since its name does not match the application name. |
@danielfinke ah, gotcha. Will look at the keys to see why it's omitting "apple". As for the apns startup, that is strange. The .app file does name it apns but the directory is apns4erl...wonder if we can specify the directory name to apns when fetching... |
Yeah weird WRT the kapps_config path not being properly handled. But yes otherwise it's only a matter of adding the description to the json file. WRT relx failing to build: it probably has to do with the fact that apns is fetched into deps/apns4 instead of deps/apns or the other way arround. If so, look into rel/relx.config.src to do some renaming. @lazedo Mind voicing your reserves here? |
@danielfinke I think #4045 addresses the issue with the configs (at least merging it with this PR doesn't break |
@jamesaimonetti I'll rebase this once #4045 is merged, thanks!
and this apns4erl.app when using hex:
Aside from the obvious issue of the omitted data, I'm not familiar with what part of the make process generates these. Thoughts? |
Merged the other PR. |
c106c12
to
9b0a432
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@danielfinke thanks for this pr, awesome work.
the concern here is a device app that gets an INVITE and a PUSH. i think that you may be trying to fix a client app that should behave differently. existing apps may broke because of that double signaling.
one minor issue
the apns_topic should come from the registered App doc. for that you'll probably need to change handle_cast({'push' ..
/ get_apns
to pass the App or apns_topic from App to maybe_send_push_notification
@lazedo So my understanding is pusher was designed specifically for the Linphone project, given the code lines up with how the UA string in Linphone contains exactly the right fields as pusher is looking for. I'm trying to handle a situation that is broken in Linphone (iOS) at this time: the app transitioning to the Suspended state (after user presses Home for example). Because you will have a registration that is still valid, the existing pusher implementation will not send you a push and iOS will have already closed the socket that would be receiving the INVITE. Apple finished deprecating support for persistent background TCP sockets in 10.2.1 (I think that's the version). UDP already did not work. We had been previously using persistent background TCP sockets without any push notifications which was fine until Apple removed support. This will have become broken for old apps compiled with Linphone - we know, it happened to us ;) So we moved to using Linphone with push, but I made the quick discovery that it wouldn't work after the app was Suspended until my registration expired. My changes fix this problem. The Linphone source code is also smart enough to discard the push if the app is in the foreground and received the INVITE (checks for the call in an active calls array). For the apns_topic, are you thinking it should be stored in the system_config/pusher doc per application? |
@danielfinke thanks for the reply. AFAIR linphone used to unregister before going into background, it needed a patch to do so. it was developed with linphone as an example but it works for others with the principle of having apps unregister when going into background mode. trying to figure out a way to make this work. for the apnstopic my thought is to put it in the app registration doc. |
@lazedo That was actually my first approach. I couldn't find a public function in liblinphone that would send a deregister (i.e. disabling a proxy config) without storing that in the proxy config and preventing a register the next time the app was opened (push, launch from switcher, launch from home screen). The answer here might be exposing (or adding if necessary) functions to liblinphone to simply send a single deregister/REGISTER with 0 expiry. |
I guess beyond getting this use case solved, could there be a worthwhile benefit to having the redundancy of both push and INVITE? |
@danielfinke or have a way to choose between push/sip when registered. |
@lazedo Are you thinking statically configured or dynamically? |
@danielfinke i'm thinking in a |
@lazedo I've added the "X-KAZOO-PUSHER-Simultaneous-Push-and-Invite" header for this purpose. If it is not set and true, the default behaviour is retained. The code is still shuffled around a little bit to avoid duplication and multiple checks of the header value, but the behaviour is the same as it was originally. The change was made in the kazoo-configs-kamailio PR. |
Let's see what @lazedo thinks about this but if he likes it let's not forget to document this new header in Kazoo. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no reflection of X-KAZOO-PUSHER-Simultaneous-Push-and-Invite
in this pr
-spec apns_topic(kz_json:object()) -> binary(). | ||
apns_topic(JObj) -> | ||
TokenApp = kz_json:get_ne_binary_value(<<"Token-App">>, JObj), | ||
re:replace(TokenApp, <<"\\.(?:dev|prod)$">>, <<>>, [{'return', 'binary'}]). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@danielfinke this still needs to be fixed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lazedo that is the fix - it was previously <<"\.(?:dev|prod)$">>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah wait, you mean to pass it via the registered app - will take care of it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lazedo can you elaborate a bit on what you are thinking I should do here? I think if I do not retain this behaviour some old apps may break. If it needs to be specified in the pusher config that will also break existing deployments. And adding it to the UA of apps will naturally require changes to those apps
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@danielfinke the .dev|.prod
replacement at the end of the TokenApp is restrictive. the topic
can also be part of the app configuration the same way you did in kz_endpoint
to get the extra headers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lazedo sure, I'll add it the same way as the extra headers. I'm going to leave a fallback to the .dev|.prod replacement to preserve old apps' behaviour
@danielfinke global per app, ie, merged at runtime before push. you may also change the location to |
14d8e13
to
d6d32ce
Compare
@lazedo I've updated this PR to load some "extra_headers" just before each push. I am also using the TokenType as it will help distinguish between iOS/Android - our AppId is identical for both, so I needed to handle that case. You'll see the relevant code in kz_endpoint. Example of system_config/pusher for app:
I'll probably need to update some API docs - will see what Circle says I've also updated the kazoo-configs-kamailio PR |
-spec apns_topic(kz_json:object()) -> binary(). | ||
apns_topic(JObj) -> | ||
TokenApp = kz_json:get_ne_binary_value(<<"Token-App">>, JObj), | ||
re:replace(TokenApp, <<"\\.(?:dev|prod)$">>, <<>>, [{'return', 'binary'}]). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@danielfinke the .dev|.prod
replacement at the end of the TokenApp is restrictive. the topic
can also be part of the app configuration the same way you did in kz_endpoint
to get the extra headers
@danielfinke hi, can you please check the conflict in mkdocs.yml and address the |
@danielfinke ping |
PISTON-449: WIP update apns4erl PISTON-449: OriginalContact doesn't exist anymore PISTON-449: update to apns4erl 2.2.0 with certdata/keydata binary support PISTON-449: dialyzed PISTON-449: always send push headers (even if device is registered)
This reverts commit a68897b.
d6d32ce
to
730c7f7
Compare
) | ||
of | ||
'undefined' -> | ||
%% Retain the old behaviour |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@danielfinke i think this comment is making the formatting
break in circle ci. can you move to it to description of apns_topic (above the spec) ? sorry about that.
@danielfinke i added the fix and merged. thanks. |
@lazedo thanks for your work with me on this! |
Update apns4erl
Fix bugs
Send push even if registered to fix iOS BG bug
Support multiple APNs configs (allow both dev/prod APNs)
Also see: 2600hz/kazoo-configs-kamailio#17