Python APNs does not process request
Question: I'm trying to implement a server side script for sending push notifications to
apple push notification server. I create the ssl connection, I send the
payload - but am unable to get a response from the APNs. Here is my code:

    
    
    import socket, ssl, pprint, struct, time, binascii
    
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    # require a certificate from the server
    ssl_sock = ssl.wrap_socket( s,
                                keyfile="/Users/Jeff/Desktop/pickmeup-key2-noenc.pem",
                                certfile="/Users/Jeff/Desktop/pickmeup-cert2.pem",
                                server_side=False,
                                do_handshake_on_connect=True,
                                cert_reqs=ssl.CERT_REQUIRED,
                                ca_certs="/Users/Jeff/Desktop/entrustrootcert.pem",)
                                #ciphers="ALL")
    ssl_sock.connect(('gateway.sandbox.push.apple.com', 2195))
    
    print repr(ssl_sock.getpeername())
    print ssl_sock.cipher()
    print pprint.pformat(ssl_sock.getpeercert())
    
    command = '\x00'
    identifier = 1987
    expiry = time.time()
    deviceToken = "9858d81caa236a86cc67d01e1a07ba1df0982178dd7c95aae115d033b93cb3f5"
    alert = "This is a test message"
    sound = "UILocalNotificationDefaultSoundName"
    payload = "{\"aps\":{\"alert\":\"%s\",\"sound\":\"%s\"}}" %(alert, sound)
    
    packetFormat = "!cIIH%dsH%ds" %(32, len(payload))
    
    packet = struct.pack(packetFormat, 
                        command, 
                        identifier,
                        int(expiry),
                        32, 
                        binascii.unhexlify(deviceToken), 
                        len(payload), 
                        payload)
    nBytesWritten = ssl_sock.write(packet)
    print "nBytesWritten = %d" %(nBytesWritten)
    
    data = ssl_sock.read(1024)
    print len(data)
    
    ssl_sock.close()
    

Running this script, I generate the following output:

    
    
    ('17.149.34.132', 2195)
    ('AES256-SHA', 'TLSv1/SSLv3', 256)
    {'notAfter': 'May 31 00:04:27 2012 GMT',
     'subject': ((('countryName', u'US'),),
                 (('stateOrProvinceName', u'California'),),
                 (('localityName', u'Cupertino'),),
                 (('organizationName', u'Apple Inc'),),
                 (('organizationalUnitName', u'Internet Services'),),
                 (('commonName', u'gateway.sandbox.push.apple.com'),))}
    nBytesWritten = 133
    0
    

Any ideas on what might be going wrong? (I am sending enhanced push
notifications so I am expecting a response from apple push notification
server)


Answer: The key thing to note is that read() is returning no data. In Python, read()
is supposed to block until data is available or the connection closes. _Apple
is closing your connection._

Why? Well, probably because you sent a malformed request. `command=0` is a
normal push notification; `command=1` is enhanced. The big-endian `1987` will
be interpreted as a 0-byte device token and a 1987-byte payload, neither of
which are valid.

(And FWIW, I'd use `B` instead of `c` for the command ID; it seems to make
more sense.)

