This is part 4 of the Push notification tutorial. Here you can find part 3.
Provider Communication with Apple Push Notification Service
This chapter describes the interfaces that providers use for communication with Apple Push Notification Service (APNs) and discusses some of the functions that providers are expected to fulfill.
General Provider Requirements
As a provider you may communicate with Apple Push Notification Service over a “raw” (binary) interface. The raw interface is a high-speed, high-capacity interface for bulk-data providers; it uses a streaming socket design in conjunction with binary content. The raw interface is asynchronous.
The binary interface of the production environment is available through gateway.push.apple.com, port 2195; the binary interface of the sandbox (development) environment is available through gateway.sandbox.push.apple.com, port 2195. You may establish multiple, parallel connections to the same gateway or to multiple gateway instances. Although there is no hard limit to the number of gateway connections a provider can make, you should limit them to no more than 15.
For each interface you should use TLS (or SSL) to establish a secured communications channel. The SSL certificate required for these connections is provisioned through the iPhone Developer Program portal. (See “Provisioning and Development” for details.) To establish a trusted provider identity, you should present this certificate to APNs at connection time using peer-to-peer authentication. You should also retain connections with APNs across multiple notifications. (APNs may consider connections that are rapidly and repeatedly established and torn down as a denial-of-service attack.)
As a provider, you are responsible for the following aspects of push notifications:
- You must compose the notification payload (see “The Notification Payload”).
- You are responsible for supplying the badge number to be displayed on the application icon.
- You should regularly connect with the feedback web server and fetch the current list of those devices that have repeatedly reported failed-delivery attempts. Then you should cease sending notifications to the devices associated with those applications. See “The Feedback Service” for more information.
If you intend to support notification messages in multiple languages, but do not use the loc-key and loc-args properties of the aps payload dictionary for client-side fetching of localized alert strings, you need to localize the text of alert messages on the server side. To do this, you need to find out the current language preference from the client application. “iPhone OS Client Implementation” suggests an approach for obtaining this information. See “The Notification Payload” for information about the loc-key and loc-args properties.
The Raw Interface
The raw interface employs a raw socket, has binary content, is streaming in nature, and has zero acknowledgment responses. Figure 4-1 illustrates the format of a remote-notification packet.
The lengths of the device token and the payload must be in network order (that is, big endian). In addition, you should encode the device token in binary format. The payload must not be null-terminated. For optimum performance, you should batch multiple notifications in a single transmission, either explicitly or using a TCP/IP Nagle algorithm.
Listing 4-1 gives an example of a function that sends a push notification to APNs using the raw interface. The example assumes prior SSL connection to gateway.push.apple.com (or gateway.sandbox.push.apple.com) and peer-exchange authentication.
Listing 4-1 Sending a notification via the raw interface
static bool sendPayload(SSL *sslPtr, char *deviceTokenBinary, char *payloadBuff, size_t payloadLength)
|
{
|
bool rtn = false;
|
if (sslPtr && deviceTokenBinary && payloadBuff && payloadLength)
|
{
|
uint8_t command = 0; /* command number */ |
char binaryMessageBuff[sizeof(uint8_t) + sizeof(uint16_t) + DEVICE_BINARY_SIZE + sizeof(uint16_t) + MAXPAYLOAD_SIZE]; |
/* message format is, |COMMAND|TOKENLEN|TOKEN|PAYLOADLEN|PAYLOAD| */ |
char *binaryMessagePt = binaryMessageBuff; |
uint16_t networkOrderTokenLength = htons(DEVICE_BINARY_SIZE); |
uint16_t networkOrderPayloadLength = htons(payloadLength); |
/* command */ |
*binaryMessagePt++ = command; |
/* token length network order */ |
memcpy(binaryMessagePt, &networkOrderTokenLength, sizeof(uint16_t)); |
binaryMessagePt += sizeof(uint16_t); |
/* device token */ |
memcpy(binaryMessagePt, deviceTokenBinary, DEVICE_BINARY_SIZE); |
binaryMessagePt += DEVICE_BINARY_SIZE; |
/* payload length network order */ |
memcpy(binaryMessagePt, &networkOrderPayloadLength, sizeof(uint16_t)); |
binaryMessagePt += sizeof(uint16_t); |
/* payload */ |
memcpy(binaryMessagePt, payloadBuff, payloadLength); |
binaryMessagePt += payloadLength; |
if (SSL_write(sslPtr, binaryMessageBuff, (binaryMessagePt - binaryMessageBuff)) > 0) |
rtn = true; |
} |
return rtn; |
} |
The Feedback Service
If a provider attempts to deliver a push notification to an application, but the application no longer exists on the device, the device reports that fact to Apple Push Notification Service. This situation often happens when the user has uninstalled the application. If a device reports failed-delivery attempts for an application, APNs needs some way to inform the provider so that it can refrain from sending notifications to that device. Doing this reduces unnecessary message overhead and improves overall system performance.
For this purpose Apple Push Notification Service includes a feedback service that APNs continually updates with a per-application list of devices for which there were failed-delivery attempts. The devices are identified by device tokens encoded in binary format. Providers should periodically query the feedback service to get the list of device tokens for their applications, each of which is identified by its topic. Then, after verifying that the application hasn’t recently been re-registered on the identified devices, a provider should stop sending notifications to these devices.
Access to the feedback service takes place through a binary interface similar to that used for sending push notifications. You access the production feedback service via feedback.push.apple.com, port 2196; you access the sandbox feedback service via feedback.sandbox.push.apple.com, port 2196. As with the binary interface for push notifications, you should use TLS (or SSL) to establish a secured communications channel. The SSL certificate required for these connections is the same one that is provisioned for sending notifications. To establish a trusted provider identity, you should present this certificate to APNs at connection time using peer-to-peer authentication.
Once you are connected, transmission begins immediately; you do not need to send any command to APNs. Begin reading the stream written by the feedback service until there is no more data to read. The received data is in tuples having the following format:
<illo>
time_t |
A timestamp (as a four-byte time_t value) indicating when the APNs determined that the application no longer exists on the device. This value, which is in network order, represents the seconds since 1970, anchored to UTC.
You should use the timestamp to determine if the application on the device re-registered with your service since the moment the device token was recorded on the feedback service. If it hasn’t, you should cease sending push notifications to the device. |
| token length | The length of the device token as a two-byte integer value in network order. |
| device token | The device token in binary format. |
credit: apple.com
                                   




[...] iPhone Programming: Push notifications, Part 4 Jun 30 [...]