Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple iPhone APN messages, single connection

I have a strange issue. I'm trying to get Apple Push Notifications working with Python. I can connect and send individual messages without a problem. The issues pop up when I start sending more than one message, but it's more bizarre than even that.

I'm testing with multiple devices... some iPhones and some iPod Touches. I can send multiple messages to the iPhones without a hitch, but if I have an iPod Touch device id in the list, any message that goes after will fail.

So if I send 4 messages in sequence like this:

1 - iPhone
2 - iPhone
3 - ipod Touch
4 - iPhone

1 and 2 will be delivered, 3 and 4 fail.

Using the same device ID's, if I move any of the iPod Touch device ID's to be the first message, all messages will fail. Likewise, if I only send to iPhones, all messages will succeed.

Here's the code I'm testing with, in it's current state, I would only get the first two messages, the last two will fail every time.

import struct, ssl, json, sys, time, socket, binascii
from optparse import OptionParser

class PushSender(object):

    def __init__(self, host, cert, key):
        self.apnhost = (host, 2195)
        self.sock = ssl.wrap_socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM),
                                    keyfile = key,
                                    certfile = cert,
                                    do_handshake_on_connect=False)
        self.sock.connect(self.apnhost)
        while True:
            try:
                self.sock.do_handshake()
                break
            except ssl.SSLError, err:
                if err.args[0] == ssl.SSL_ERROR_WANT_READ:
                    select.select([self.sock], [], [])
                elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
                    select.select([], [self.sock], [])
                else:
                    raise

    def send_message(self, token, message):
        payload = {'aps':{'alert':message}}
        token = binascii.unhexlify(token)
        payloadstr = json.dumps(payload, separators=(',',':'))
        payloadLen = len(payloadstr)
        fmt = "!BH32sH%ds" % payloadLen
        notification = struct.pack(fmt, 0, 32, token, payloadLen, payloadstr)
        self.sock.write(notification)
        self.sock.


    def close(self):
        self.sock.close()

def main():
    parser = OptionParser()
    parser.add_option("-c", "--certificate", dest="cert",
                      metavar="FILE",
                      help="Certificate file", )

    parser.add_option("-p", "--privatekey", dest="key",
                      metavar="FILE",
                      help="Key file", )
    parser.add_option("--host", help="apn host", dest='host')
    (options, args) = parser.parse_args()

    sender = PushSender(options.host, options.cert, options.key)

    iphone1 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    print 'Sending iPhone #1 a message.'
    print sender.send_message(iphone1,'Hey iPhone #1.')

    iphone2 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    print 'Sending iPhone #2 a message.'
    print sender.send_message(iphone2,'Hey iPhone #2.')

    ipod1 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    print 'Sending iPod #1 a message.'
    print sender.send_message(ipod1,'Hey iPod #1.')

    iphone3 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    print 'Sending iPhone #3 a message.'
    print sender.send_message(iphone3,'Hey iPhone #3.')

    sender.close()

if __name__=="__main__":
    main()

Any help would be appreciated...

like image 853
Sangraal Avatar asked Nov 18 '09 21:11

Sangraal


People also ask

What is iPhone APN changer?

APN or Access Point Name is a gateway between a mobile network (3G, 4G, or 5G) and another network such as a public internet. It provides your iPhone with the information to connect to any wireless network or service. You can configure this APN in your iPhone's settings panel via the cellular or mobile network.

Why doesn't my iPhone have APN settings?

If the setting is missing from Settings > General > Network > Cellular Data Network, you can try updating the carrier settings. Try tapping Settings > General > About. You can also use the iPhone Configuration Utility to change APN settings.


1 Answers

Apple will silently drop your connection if it receives an invalid device token or a message that's too long. The next couple of messages after that will fail because they're just sent into the ether, essentially - the connection is closed, but the TCP window isn't exhausted.

At Urban Airship, where I work, we have a debug mode to use when people test their applications with push on our service. This will pause for a little bit after sending a message to ensure that this wasn't the issue - if the connection drops, we know it's an issue with the device token and report an error as such. A similar method might be a good way for you to check that this is, or is not, what's going on. Obviously this kills throughput and so we don't recommend it for a production environment.

like image 57
Michael Richardson Avatar answered Sep 22 '22 10:09

Michael Richardson