Now that we’ve converted our notification data into a format that’s suitable for
sending to Apple, our fledgling push provider needs a connection into APNs in
order to send that data. Once again, Apple’s documentation comes to our rescue:
the chapter “Provider Communication with Apple Push Notification
Service”
describes how to manage connections to the push notification service.

Among the important bits in this chapter:

When connecting, the provider needs the SSL certificate from the Member Center
available for authenticating itself to Apple.

The provider should maintain a persistent connection to APNs, rather than
connecting and disconnecting for each notification. (At higher volumes, Apple
might even consider this behavior to be a DDOS attack!)

There are two different environments for push notifications:
development and production. A connection is specific to one app’s
bundle ID, and therefore (at least in Omni’s bundle ID configuration) specific
to one of these environments.

To handle all this, we need to build a little flexibility into the provider. We
turned to the open-source gcfg library, which
can be imported into a Go project simply by running

go get "code.google.com/p/gcfg"

and then importing that same URL at the head of a Go file. With this library,
we can define a configuration file that tells the provider about what APNs
host(s) it should connect to, and what certificates it should use along the way.

Let’s take a look first at the Go struct that the provider reads its APNs
configuration into:

This struct expresses a single connection to APNs. It defines the domain
we’ll connect to, letting us switch between sandbox and production environments
by changing the host we contact. It also lets us tell the provider where its
certificates are, so that it can establish a secure connection and identify
itself to APNs, all in one swoop.

For OmniFocus, though, we have multiple bundle IDs – one for the Universal
version of the app, and one for the iPhone-only variant – so we’ll need a way to
connect to APNs multiple times. To accomplish this, we parse something slightly
more complex out of the configuration file:

Instead of just reading a single instance of the ConnConfig struct, we’ll read
an entire map of them, keyed by strings. The gcfg package uses maps to
represent configuration subsections – instead of just specifying a single
apns section, we can specify a bunch, each with its own key:

This way, parsing a configuration file can return one ConnConfig struct for
each bundle ID that we’ll use to connect. The provider’s connection code can
then iterate over these structs, establishing multiple connections along the
way. For each connection, that code is fairly straightforward:

Once this connection is established, the provider can hang on to this tls.Conn
pointer as long as it needs to, sending multiple notifications – in the form of
the frames described in the previous post – when changes
occur in OmniFocus. In the next post, we’ll take a look at how the provider
manages all the notifications it needs to send across these connections.