-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapnsender.go
More file actions
121 lines (96 loc) · 2.4 KB
/
apnsender.go
File metadata and controls
121 lines (96 loc) · 2.4 KB
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package apnsender
import (
"crypto/tls"
"net"
"encoding/hex"
"encoding/binary"
"bytes"
"errors"
"strconv"
)
type Device struct {
Token string
Timestamp uint32
}
type Message struct {
Token string
Content []byte
}
type sender interface {
Connect() error
Send(chan []byte, chan error)
Feedback() []Device
}
type APS struct {
Config APSConfig
Connection net.Conn
}
func New(config *APSConfig) (a APS, err error) {
if checkConfig(config) {
a = APS{Config: *config}
} else {
err = errors.New("Config check failed.")
return
}
return
}
func (a *APS) Connect() (err error) {
// load certificate from files
cert, err := tls.LoadX509KeyPair(
a.Config.sslCert,
a.Config.sslKey,
)
if err != nil { return }
// connect to apple push service
conn, err := net.Dial(
"tcp",
a.Config.host + ":" + strconv.Itoa(int(a.Config.port)),
)
if err != nil { return }
// wrap socket with tls client
tlsconn := tls.Client(conn, &tls.Config{
Certificates: []tls.Certificate{cert},
})
// test connection
err = tlsconn.Handshake()
if err != nil { return }
a.Connection = tlsconn
return
}
func checkConfig(config *APSConfig) bool {
return true
}
func (a *APS) Send(c chan Message, errors chan error) {
go func() {
for {
message := <- c
payload, err := a.generatePayload(message)
if err != nil {
errors <- err
} else {
a.Connection.Write(payload)
}
}
}()
}
func (a *APS) generatePayload(m Message) (pdu []byte, err error) {
deviceToken, err := hex.DecodeString(m.Token)
if err != nil { return }
json_s := m.Content
payload := bytes.NewBuffer([]byte{})
// command
binary.Write(payload, binary.BigEndian, uint8(1))
// transaction id
binary.Write(payload, binary.BigEndian, uint32(1))
// expiration time, 1h
binary.Write(payload, binary.BigEndian, uint32(3600))
// device token
binary.Write(payload, binary.BigEndian, uint16(len(deviceToken)))
binary.Write(payload, binary.BigEndian, deviceToken)
// push notification
binary.Write(payload, binary.BigEndian, uint16(len(json_s)))
binary.Write(payload, binary.BigEndian, json_s)
// binary
pdu = payload.Bytes()
return
}