Skip to content

Commit

Permalink
Merge pull request #174 from inaka/ferigis.167.get_feedback
Browse files Browse the repository at this point in the history
[#167] adding apns:get_feedback/1
  • Loading branch information
cabol authored May 24, 2017
2 parents cacf9ef + 2123163 commit 11e0eda
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 20 deletions.
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ First we have to fill our `config` data. There are two ways for do this, one is
, {apns_priority, 10}
, {apns_topic, "com.example.myapp"}
, {apns_collapse_id, undefined}
%% Feedback
, {feedback_host, "feedback.push.apple.com"}
, {feedback_port, 2195}
]
]
}
```
Expand Down Expand Up @@ -222,7 +227,16 @@ But when closing a connection makes sense `apns4erl` gives us the function `apns

`apns4erl` also allows us to get feedback from APNs service. It does it thru the [binary API](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/BinaryProviderAPI.html).

In order to get feedback we would need a `Provider Certificate` and have it set at `config` file as we do for `push notifications`. Then we will call `apns:get_feedback/0`. The response will be a list of `feedback()`
In order to get feedback we would need a `Provider Certificate`. `apns4erl` provides us two functions, `apns:get_feedback/0` and `apns:get_feedback/1` which require some Feedback's information like url, port, timeout... We can set that info in our `config` file and use `apns:get_feedback/0`. We can also send all that configuration as a parameter to `apns:get_feedback/1` where the config structure must looks like this:
```erlang
#{ host := string()
, port := pos_integer()
, certfile := string()
, keyfile => string()
, timeout := pos_integer()
}.
```
The response for both functions will be a list of `feedback()`

```erlang
-type feedback() :: {calendar:datetime(), string()}.
Expand Down
3 changes: 2 additions & 1 deletion elvis.config
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
{config,
[#{dirs => ["src", "test"],
filter => "*.erl",
ruleset => erl_files
ruleset => erl_files,
rules => [{elvis_style, line_length, #{limit => 100}}]
},
#{dirs => ["."],
filter => "Makefile",
Expand Down
18 changes: 17 additions & 1 deletion src/apns.erl
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
, default_headers/0
, generate_token/2
, get_feedback/0
, get_feedback/1
]).

-export_type([ json/0
Expand Down Expand Up @@ -174,8 +175,23 @@ default_headers() ->
%% Requests for feedback to APNs. This requires Provider Certificate.
-spec get_feedback() -> [feedback()] | {error, term()} | timeout.
get_feedback() ->
{ok, Host} = application:get_env(apns, feedback_host),
{ok, Port} = application:get_env(apns, feedback_port),
{ok, Certfile} = application:get_env(apns, certfile),
Keyfile = application:get_env(apns, keyfile, undefined),
{ok, Timeout} = application:get_env(apns, timeout),
apns_feedback:get_feedback(Timeout).
Config = #{ host => Host
, port => Port
, certfile => Certfile
, keyfile => Keyfile
, timeout => Timeout
},
get_feedback(Config).

%% Requests for feedback to APNs. This requires Provider Certificate.
-spec get_feedback(apns_feedback:feedback_config()) -> [feedback()] | {error, term()} | timeout.
get_feedback(Config) ->
apns_feedback:get_feedback(Config).

%%%===================================================================
%%% Internal Functions
Expand Down
37 changes: 20 additions & 17 deletions src/apns_feedback.erl
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,25 @@
% API
-export([get_feedback/1]).

-export_type([feedback/0]).
-export_type([feedback/0, feedback_config/0]).

-type feedback() :: {calendar:datetime(), string()}.
-type socket() :: gen_tcp:socket().
-type feedback() :: {calendar:datetime(), string()}.
-type socket() :: gen_tcp:socket().
-type feedback_config() :: #{ host := string()
, port := pos_integer()
, certfile := string()
, keyfile => string()
, timeout := pos_integer()
}.

%%%===================================================================
%%% API
%%%===================================================================

%% Requests for feedback to APNs. This requires Provider Certificate.
-spec get_feedback(timeout()) -> [feedback()] | {error, term()} | timeout.
get_feedback(Timeout) ->
case open_feedback(Timeout) of
-spec get_feedback(feedback_config()) -> [feedback()] | {error, term()} | timeout.
get_feedback(#{timeout := Timeout} = Config) ->
case open_feedback(Config) of
{ok, Socket} ->
Result = wait_for_feedback(Socket, Timeout),
ssl:close(Socket),
Expand All @@ -47,19 +53,16 @@ get_feedback(Timeout) ->
%%% Internal Functions
%%%===================================================================

-spec open_feedback(timeout()) -> {ok, socket()} | {error, term()}.
open_feedback(Timeout) ->
{ok, Host} = application:get_env(apns, feedback_host),
{ok, Port} = application:get_env(apns, feedback_port),
ssl:connect(Host, Port, ssl_opts(), Timeout).
-spec open_feedback(feedback_config()) -> {ok, socket()} | {error, term()}.
open_feedback(#{host := Host, port := Port, timeout := Timeout} = Config) ->
ssl:connect(Host, Port, ssl_opts(Config), Timeout).

-spec ssl_opts() -> list().
ssl_opts() ->
Opts = case application:get_env(apns, keyfile) of
{ok, KeyFile} -> [{keyfile, KeyFile}];
undefined -> []
-spec ssl_opts(feedback_config()) -> list().
ssl_opts(#{certfile := Certfile} = Config) ->
Opts = case maps:get(keyfile, Config, undefined) of
undefined -> [];
KeyFile -> [{keyfile, KeyFile}]
end,
{ok, Certfile} = application:get_env(apns, certfile),
[{certfile, Certfile} | Opts].

-spec wait_for_feedback(socket(), timeout()) -> [feedback()] | timeout.
Expand Down

0 comments on commit 11e0eda

Please sign in to comment.