-
Notifications
You must be signed in to change notification settings - Fork 383
/
services_push_apns.go
105 lines (84 loc) · 2.5 KB
/
services_push_apns.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package bertypushrelay
import (
"encoding/base64"
"fmt"
"strings"
"github.com/sideshow/apns2"
"github.com/sideshow/apns2/certificate"
"github.com/sideshow/apns2/payload"
"berty.tech/berty/v2/go/pkg/errcode"
"berty.tech/berty/v2/go/pkg/protocoltypes"
"berty.tech/berty/v2/go/pkg/pushtypes"
)
const (
asn1UID = "0.9.2342.19200300.100.1.1"
appleCertDevNamePart = "Apple Development IOS Push Services"
)
type pushDispatcherAPNS struct {
client *apns2.Client
bundleID string
}
func (d *pushDispatcherAPNS) TokenType() pushtypes.PushServiceTokenType {
return pushtypes.PushServiceTokenType_PushTokenApplePushNotificationService
}
func PushDispatcherLoadAPNSCertificates(input *string) ([]PushDispatcher, error) {
if input == nil || *input == "" {
return nil, nil
}
paths := strings.Split(*input, ",")
dispatchers := make([]PushDispatcher, len(paths))
for i, path := range paths {
var err error
dispatchers[i], err = pushDispatcherLoadAPNSCertificate(path)
if err != nil {
return nil, err
}
}
return dispatchers, nil
}
func pushDispatcherLoadAPNSCertificate(path string) (PushDispatcher, error) {
cert, err := certificate.FromP12File(path, "")
if err != nil {
return nil, errcode.ErrPushInvalidServerConfig
}
bundleID := ""
for _, kv := range cert.Leaf.Subject.Names {
if kv.Type.String() == asn1UID {
bundleID = kv.Value.(string)
break
}
}
if bundleID == "" {
return nil, errcode.ErrPushMissingBundleID
}
production := !strings.Contains(cert.Leaf.Subject.CommonName, appleCertDevNamePart)
client := apns2.NewClient(cert)
if production {
client = client.Production()
} else {
client = client.Development()
}
return &pushDispatcherAPNS{
bundleID: bundleID,
client: client,
}, nil
}
func (d *pushDispatcherAPNS) Dispatch(data []byte, receiver *protocoltypes.PushServiceReceiver) error {
pushPayload := payload.NewPayload()
pushPayload.Custom(pushtypes.ServicePushPayloadKey, base64.RawURLEncoding.EncodeToString(data))
pushPayload.ContentAvailable()
notification := &apns2.Notification{}
notification.DeviceToken = string(receiver.Token)
notification.Topic = d.bundleID
notification.Payload = pushPayload
response, err := d.client.Push(notification)
if err != nil {
return errcode.ErrPushProvider.Wrap(err)
} else if response.StatusCode != 200 {
return errcode.ErrPushProvider.Wrap(fmt.Errorf("apns: status %d, reason %s", response.StatusCode, response.Reason))
}
return nil
}
func (d *pushDispatcherAPNS) BundleID() string {
return d.bundleID
}