2009-11-18 4 views
20

Ich versuche, eine Push-Benachrichtigung an APNs mit Erlang zu senden. Dies ist der Code, den ich mit so weit kam:Wie sende ich eine Push-Benachrichtigung mit 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). 

Der Code nicht den Vorteil von Erlang Gleichzeitigkeit dauert aber nur ein Prototyp. Ich möchte nur testen, ob ich den Push auf die einfachste Art und Weise senden kann.

Ich denke, das Problem besteht darin, dass das Paket an die APNs gesendet wird. Dies ist das Binärformat einer Push-Benachrichtigung:

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

Wie soll ich ein solches Paket in Erlang erstellen? Könnte jemand bitte meinen Code ansehen und mir sagen, wo das Problem liegt?
Auch ich verwendete Erlangs SSL-Anwendung, um die Verbindung zu erstellen und die Daten zu senden, und ich weiß nicht, ob das das Problem oder das Paket ist.
Danke!

Antwort

21

Zunächst müssen Sie keine Liste einer einzelnen Binärdatei erstellen und dann list_to_binary/1 aufrufen. Sie können einfach die Binärdatei selbst senden.

Stellen Sie außerdem sicher, dass die Feldlängen und Werte entsprechend angemessen sind das Protokoll:

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

Jetzt, da wir so weit gekommen sind, werden wir diese Länge (Token) ist in der Tat 64, nicht 32 sehen : Sie haben vergessen, die hexadezimale Zeichenfolge für Token in eine Binärdatei zu konvertieren, sodass Sie eine 64-Byte-Hexadezimalzeichenfolge anstelle von 32 Binärbytes senden.

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

Dank Christian für den Hinweis auf eine Reihe von Fehlern in der:

So ... Payload eine binäre von Anfang an zu machen, und Token eine numerische Konstante zu machen, können Sie so etwas wie die folgenden tun frühere Überarbeitungen dieser Antwort.

3

Ich sehe zwei Fehler:

  • Token sollte in Binär- und nicht in hex ascii weitergegeben werden.
  • Sie können die binäre Syntax nicht verwenden, um Listen in Binärdateien umzuwandeln.

Für hex auf eine ganze Zahl und dann nach unten, um binäre Verwendung so etwas wie dieses Parsen:

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

Erstellen Sie das Protokollpaket mit so etwas wie folgt aus:

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