2009-11-18 22 views
20

Sto tentando di inviare una notifica push agli APN utilizzando Erlang. Questo è il codice mi è venuto in mente finora:Come inviare una notifica push usando 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). 

Il codice non sfruttare concorrenza di Erlang, ma è solo un prototipo. Voglio solo testare se riesco a inviare la spinta nel modo più semplice.

Penso che il problema sia nel pacchetto inviato agli APN. Questo è il formato binario di una notifica push:

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

Come devo creare un tale pacchetto in Erlang? Qualcuno potrebbe dare un'occhiata al mio codice e dirmi dove si trova il problema?
Inoltre ho utilizzato l'applicazione SSL di Erlang per creare la connessione e inviare i dati e non so se questo è il problema o il pacchetto.
Grazie!

risposta

21

Per iniziare, non è necessario creare un elenco di un singolo binario e quindi chiamare list_to_binary/1 su di esso. Puoi semplicemente inviare il file binario.

Inoltre, assicurarsi che le lunghezze e valori di campo sono appropriati secondo il protocollo:

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

Ora che abbiamo ottenuto fino a questo punto, vedremo che la lunghezza (Token) è infatti a 64, non 32 : Hai dimenticato di convertire la stringa esadecimale per Token in un file binario, quindi stai inviando una stringa di caratteri esadecimali a 64 byte invece di 32 byte binari.

Quindi ... facendo Payload un binario fin dall'inizio, e facendo Token una costante numerica, si può fare qualcosa di simile a quanto segue:

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), 

Grazie a Christian per indicare una serie di errori nella precedenti revisioni di questa risposta.

3

Vedo due errori:

  • provvisoria dovrebbe essere passato in binario e non in esadecimale ascii.
  • Non è possibile utilizzare la sintassi binaria per trasformare gli elenchi in binari.

Per parsing esagono in un intero e poi verso il basso per usare qualcosa di simile binario:

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

crea il pacchetto protocollo con qualcosa di simile:

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