Skip to content
This repository has been archived by the owner on Dec 22, 2023. It is now read-only.

Commit

Permalink
Find default APNS topic from APNS certificate
Browse files Browse the repository at this point in the history
  • Loading branch information
cheungpat committed Jul 8, 2016
1 parent 88ad563 commit 7c36846
Showing 1 changed file with 54 additions and 1 deletion.
55 changes: 54 additions & 1 deletion push/apns.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ package push

import (
"crypto/tls"
"crypto/x509"
"encoding/asn1"
"encoding/json"
"errors"
"fmt"
Expand Down Expand Up @@ -49,13 +51,53 @@ type APNSPusher struct {
conn skydb.Conn
service pushService
failed chan failedNotification
topic string
}

type failedNotification struct {
deviceToken string
err push.Error
}

func parseDefaultCertificateLeaf(certificate *tls.Certificate) error {
if certificate.Leaf != nil {
return nil
}

for _, cert := range certificate.Certificate {
x509Cert, err := x509.ParseCertificate(cert)
if err != nil {
return err
}
certificate.Leaf = x509Cert
return nil
}
return errors.New("push/apns: provided APNS certificate does not contain leaf")
}

// findDefaultAPNSTopic returns the APNS topic in the TLS certificate.
func findDefaultAPNSTopic(certificate tls.Certificate) (string, error) {
if certificate.Leaf == nil {
err := parseDefaultCertificateLeaf(&certificate)
if err != nil {
return "", err
}
}

uidObjectIdentifier := asn1.ObjectIdentifier([]int{0, 9, 2342, 19200300, 100, 1, 1})
for _, attr := range certificate.Leaf.Subject.Names {
if uidObjectIdentifier.Equal(attr.Type) {
switch value := attr.Value.(type) {
case string:
return value, nil
}
break
}
}

return "", errors.New("push/apns: cannot find UID in APNS certificate subject name")
}

// NewAPNSPusher returns a new APNSPusher from content of certificate
// and private key as string
func NewAPNSPusher(connOpener func() (skydb.Conn, error), gwType GatewayType, cert string, key string) (*APNSPusher, error) {
Expand All @@ -64,6 +106,11 @@ func NewAPNSPusher(connOpener func() (skydb.Conn, error), gwType GatewayType, ce
return nil, err
}

topic, err := findDefaultAPNSTopic(certificate)
if err != nil {
return nil, err
}

client, err := push.NewClient(certificate)
if err != nil {
return nil, err
Expand All @@ -82,6 +129,7 @@ func NewAPNSPusher(connOpener func() (skydb.Conn, error), gwType GatewayType, ce
return &APNSPusher{
connOpener: connOpener,
service: service,
topic: topic,
}, nil
}

Expand Down Expand Up @@ -163,6 +211,7 @@ func (pusher *APNSPusher) Send(m Mapper, device skydb.Device) error {
logger := log.WithFields(log.Fields{
"deviceToken": device.Token,
"deviceID": device.ID,
"apnsTopic": pusher.topic,
})

if m == nil {
Expand All @@ -180,8 +229,12 @@ func (pusher *APNSPusher) Send(m Mapper, device skydb.Device) error {
return err
}

headers := push.Headers{
Topic: pusher.topic,
}

// push the notification:
apnsid, err := pusher.service.Push(device.Token, nil, serializedPayload)
apnsid, err := pusher.service.Push(device.Token, &headers, serializedPayload)
if err != nil {
if pushError, ok := err.(*push.Error); ok && pushError != nil {
// We recognize the error, and that error comes from APNS
Expand Down

0 comments on commit 7c36846

Please sign in to comment.