Tuesday, 16 July 2013

API for communicating through APNS

I developed an API for communicating through APNS with iOS mobile devices ([1]).
For this, I designed a way of building the messages, sending them and handling the result.
One important thing that I had to take into account, was how to maintain the connection. For APNS, I needed to communicate through a streaming SSL connection, so I couldn't use conduit as I 've done with GCM. So, to face this problem, I developed an APNSManager.
The API looks like this:

 startAPNS     :: APNSAppConfig -> IO APNSManager  
 closeAPNS     :: APNSManager   -> IO ()  
 sendAPNS      :: APNSManager   -> APNSmessage -> IO APNSresult  
 feedBackAPNS  :: APNSAppConfig -> IO APNSFeedBackresult  

The main idea is:

- First of all, the sevice is started with: 'startAPNS'.
  This function:
    * Creates a channel to put the notifications to be sent.
    * Starts a worker thread, which maintains the connection with APNS servers, and sends the data it receives through the cannel.
    * Returns an APNSManager.

- Then, I can use 'sendAPNS' to send messages. Every time I call it:
    * It puts the message on the channel.
    * Wait until the time the message is taken by the worker thread.
    * When the message is taken from the channel, the worker thread will send me a duplicate copy of the error channel. So, I will wait for the end of the sending, or an error msg through the error channel.
    * I return the appropiate result depending on a successful or not operation.

- I stop the service with 'closeAPNS'. It kills the worker thread.

The worker identifies each message it sends with a number, which is sent to APNS. If an error ocurred, this number is returned in an error messages by the APNS servers, representing the number of the last message that was successfully sent.
Then, the worker continually sends messages until it receives an error message. In this case, it resends the error message to the error channel for all the threads waiting for a response, and then it restarts itself, because after an error, APNS servers close the connection.
The time we wait for an error response, after having sent all the messages, can be stablished with the timeoutLimit parameter, when creating a Manager.

As to use this service, Apple requires you to be an enrolled iOS Developer or something similar, I decided to test the API with a local server. This server was taken from: [3] . It simulates the APNS servers and I modified it to test different common scenes.

The code is available on GitHub:
 - The APNS Api : [1]
 - Test example for APNS: [2]

For more information about:
 - The APNS Service: [4]
 The communication between providers and APNS servers:  [5]

1 comment: