Подтвердить что ты не робот

Как отправить push-уведомление с помощью Erlang?

Я пытаюсь отправить push-уведомление для APN, используя Erlang. Это код, который я придумал до сих пор:

-module(apnstest2).
-export([connect/0]).

connect() ->
    application:start(ssl),
    ssl:seed("someseedstring"),
    Address = "gateway.sandbox.push.apple.com",
    Port = 2195,
    Cert = "/path/to/Certificate.pem",
    Key = "/path/to/Key.unenc.pem",
    Options = [{certfile, Cert}, {keyfile, Key}, {mode, binary}],
    Timeout = 1000,
    {ok, Socket} = ssl:connect(Address, Port, Options, Timeout),

    Token = "195ec05a962b24954693c0b638b6216579a0d1d74b3e1c6f534c6f8fd0d50d03",
    Payload = "{\"aps\":{\"alert\":\"Just testing.\",\"sound\":\"chime\", \"badge\":10}}",
    TokenLength = length(Token),
    PayloadLength = length(Payload),

    Packet = [<<0:8, TokenLength, Token, PayloadLength, Payload>>],

    ssl:send(Socket, list_to_binary(Packet)),
    ssl:close(Socket).

Код не использует Erlang concurrency, а просто прототип. Я только хочу проверить, могу ли я отправить push самым простым способом.

Я думаю, что проблема заключается в том, что пакет отправляется в APN. Это двоичный формат push-уведомления:

alt text http://developer.apple.com/IPhone/library/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Art/aps_provider_binary.jpg

Как создать такой пакет в Erlang? Может кто-нибудь, пожалуйста, взгляните на мой код и скажите мне, где проблема?
Также я использовал приложение Erlang SSL для создания соединения и отправки данных, и я не знаю, является ли это проблемой или пакетом.
Спасибо!

4b9b3361

Ответ 1

Для начала нет необходимости создавать список одного двоичного кода, а затем вызывать list_to_binary/1 на нем. Вы можете просто отправить сам файл.

Кроме того, убедитесь, что длины полей и значения соответствуют протоколу:

TokenLength = 32 = length(Token),
Packet = <<0:8, TokenLength:16/big, Token, PayloadLength:16/big, Payload>>,
ssl:send(Socket, Packet),

Теперь, когда мы достигли этого, мы увидим, что длина (токен) на самом деле равна 64, а не 32: Вы забыли преобразовать шестнадцатеричную строку для Token в двоичный файл, поэтому вы отправляете шестнадцатеричную шестнадцатеричную символьную строку вместо 32 двоичных байтов.

Итак... сделав полезную нагрузку двоичным с самого начала и сделав Token числовой константой, вы можете сделать что-то вроде следующего:

Payload = <<"{\"aps\":{\"alert\":\"Just testing.\",\"sound\":\"chime\", \"badge\":10}}">>,
PayloadLength = size(Payload),
Packet = <<0:8, 32:16/big,
          16#195ec05a962b24954693c0b638b6216579a0d1d74b3e1c6f534c6f8fd0d50d03:256/big,
          PayloadLength:16/big, Payload/binary>>,
ssl:send(Socket, Packet),

Благодаря Christian для указания ряда ошибок в предыдущих версиях этого ответа.

Ответ 2

Я вижу две ошибки:

  • Токен должен быть передан двоичным, а не шестнадцатеричным ascii.
  • Вы не можете использовать бинарный синтаксис для преобразования списков в двоичные файлы.

Для разбора шестнадцатеричного целого числа, а затем до двоичного кода используйте что-то вроде этого:

Token = "dead",
TokenNum = erlang:list_to_integer(Token, 16),
TokenBin = <<TokenNum:32/integer-unit:8>>,

Создайте пакет протокола с чем-то вроде этого:

TokenBin = ...,
Payload = <<"Payload">>,
PayloadSize = byte_size(Payload),
Packet = <<0:8, 32:16, TokenBin/binary, PayloadSize:16, Payload/binary>>,

Ответ 3

Попробуйте использовать простую библиотеку epns (Erlang Push Notifications)

Эта библиотека может отправлять push-уведомления в виде APNS и FCM на стороне Erlang. Как использовать библиотеку epns(Erlang Push Notifications) - вы можете прочитать в README.md. Эта библиотека может использоваться как сторонняя организация в проекте, или вы можете запустить ее локально, чтобы посмотреть, как работает эта библиотека:

$ git clone https://github.com/vkatsuba/epns.git
$ cd epns
$ make

Проверено на Erlang 20 ~ 21