banjo-apn_sender 2.1.5 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/apn_sender.gemspec +1 -1
- data/lib/apn/connection.rb +29 -10
- data/lib/apn/notification.rb +24 -4
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 067eaa2184fdd9171fcbe18c5bde69809e449a2b
|
4
|
+
data.tar.gz: 99746b0d5bb810c3358737e140d62c40fe2a64c4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 95bd7c3aed59c3b8fe66a558a053f27b4b46c1f76f1f871d6c66157664d688edd1dba7c222bd6e7003b174e635ba015f09a6815b0cf1ba3f379dd71a7e450e9b
|
7
|
+
data.tar.gz: 12b2ecaba23309970959fb7d7e376fd4a84fe4fd1042918e261c866db697bc2ce7f36f02c429d3f84ed069d96d177ede50c808d97fb4de62047c9743acfcd3fa
|
data/apn_sender.gemspec
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{banjo-apn_sender}
|
8
|
-
s.version = "2.
|
8
|
+
s.version = "2.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = [%q{Kali Donovan}, %q{KW Justin Leung}]
|
data/lib/apn/connection.rb
CHANGED
@@ -12,12 +12,24 @@ class APN::Connection
|
|
12
12
|
@fifos[env].shift if @fifos[env][FIFO_SIZE]
|
13
13
|
end
|
14
14
|
|
15
|
-
def
|
15
|
+
def error_response
|
16
|
+
if socket.flush && IO.select([socket], nil, nil, 1) && (error = socket.read(6))
|
17
|
+
error = error.unpack("ccA*")
|
18
|
+
log(:error, "Error response: #{error}")
|
19
|
+
end
|
20
|
+
|
21
|
+
error
|
22
|
+
end
|
23
|
+
|
24
|
+
def send_to_apple(notification, token, env, tag, debug = false)
|
16
25
|
retries = 0
|
17
26
|
push_fifo(env, token)
|
18
27
|
|
19
28
|
begin
|
20
|
-
|
29
|
+
socket.write(notification.to_s)
|
30
|
+
return false if debug && error_response
|
31
|
+
|
32
|
+
true
|
21
33
|
rescue => e
|
22
34
|
log(:error, "Try #{retries}: #{e.class} to #{apn_host}: #{e.message}, recent_tokens: #{@fifos[env]}")
|
23
35
|
|
@@ -34,14 +46,11 @@ class APN::Connection
|
|
34
46
|
end
|
35
47
|
end
|
36
48
|
|
37
|
-
def self.
|
38
|
-
msg = APN::Notification.new(token, options)
|
39
|
-
raise "Invalid notification options (did you provide :alert, :badge, :sound, or :'content-available'?): #{options.inspect}" unless msg.valid?
|
40
|
-
|
49
|
+
def self.current(sandbox = false, enterprise = false)
|
41
50
|
thread_id = Thread.current.object_id
|
42
51
|
|
43
52
|
# Use only 1 single thread for internal enterprise cert
|
44
|
-
|
53
|
+
if enterprise
|
45
54
|
if sandbox
|
46
55
|
@sandbox_enterprise_sender ||= new(worker_count: 1, sandbox: 1, verbose: 1, enterprise: 1)
|
47
56
|
else
|
@@ -54,18 +63,28 @@ class APN::Connection
|
|
54
63
|
@production_senders[thread_id] ||= new(worker_count: 1, verbose: 1)
|
55
64
|
end
|
56
65
|
end
|
57
|
-
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.send_apn(token, message, sandbox = false, enterprise = false, style = { format: :frame })
|
69
|
+
msg = APN::Notification.new(token, message, style.reverse_merge(identifier: token.byteslice(0, 4)))
|
70
|
+
raise "Invalid notification message (did you provide :alert, :badge, :sound, or :'content-available'?): #{message.inspect}" unless msg.valid?
|
71
|
+
|
72
|
+
sender = current(sandbox, enterprise)
|
58
73
|
env = sandbox ? 'sandbox' : enterprise ? 'enterprise' : 'production'
|
59
74
|
tag = "#{sandbox ? 'sandbox' : 'production'}#{enterprise ? ' enterprise' : ''}"
|
60
|
-
sender.log(:info, "token: #{token} message: #{
|
75
|
+
sender.log(:info, "token: #{token} message: #{message}, style: #{style}")
|
61
76
|
|
62
77
|
if enterprise
|
63
|
-
@enterprise_semaphore.synchronize { sender.send_to_apple(msg, token, env, tag) }
|
78
|
+
@enterprise_semaphore.synchronize { sender.send_to_apple(msg, token, env, tag, !!style[:debug]) }
|
64
79
|
else
|
65
80
|
sender.send_to_apple(msg, token, env, tag)
|
66
81
|
end
|
82
|
+
|
83
|
+
sender
|
67
84
|
end
|
68
85
|
|
86
|
+
self.singleton_class.send(:alias_method, :send, :send_apn)
|
87
|
+
|
69
88
|
protected
|
70
89
|
def apn_host
|
71
90
|
@apn_host ||= apn_sandbox? ? "gateway.sandbox.push.apple.com" : "gateway.push.apple.com"
|
data/lib/apn/notification.rb
CHANGED
@@ -23,10 +23,15 @@ module APN
|
|
23
23
|
# character overhead, so there are 199 characters available for the alert string.
|
24
24
|
MAX_ALERT_LENGTH = 199
|
25
25
|
|
26
|
-
attr_accessor :options, :token
|
27
|
-
|
28
|
-
|
26
|
+
attr_accessor :options, :token, :format, :identifier, :expiry_epoch, :priority
|
27
|
+
|
28
|
+
def initialize(token, opts, style = {})
|
29
29
|
@token = token
|
30
|
+
@options = hash_as_symbols(opts.is_a?(Hash) ? opts : {:alert => opts})
|
31
|
+
@format = style[:format] || :frame
|
32
|
+
@identifier = style[:identifier] || OpenSSL::Random.random_bytes(4)
|
33
|
+
@expiry_epoch = (style[:expiry_epoch] || Time.now + 1.hour).to_i
|
34
|
+
@priority = (style[:priority] || 10).to_i
|
30
35
|
payload_size = packaged_message.bytesize.to_i
|
31
36
|
|
32
37
|
raise "Payload bytesize of #{payload_size} is > the maximum allowed size of 255." if payload_size > 255
|
@@ -71,7 +76,22 @@ module APN
|
|
71
76
|
def packaged_notification
|
72
77
|
pt = packaged_token
|
73
78
|
pm = packaged_message
|
74
|
-
|
79
|
+
|
80
|
+
case format
|
81
|
+
when :simple
|
82
|
+
[0, 0, pt.bytesize, pt, 0, pm.bytesize, pm].pack("ccca*cca*")
|
83
|
+
when :frame
|
84
|
+
data = ''
|
85
|
+
data << [1, pt.bytesize, pt].pack("CnA*")
|
86
|
+
data << [2, pm.bytesize, pm].pack("CnA*")
|
87
|
+
data << [3, identifier.bytesize, identifier].pack("CnA*")
|
88
|
+
data << [4, 4, expiry_epoch].pack("CnN")
|
89
|
+
data << [5, 1, priority].pack("CnC")
|
90
|
+
|
91
|
+
[2, data.bytesize].pack('CN') + data
|
92
|
+
else
|
93
|
+
raise "Unsupported apn format #{format} with token: #{pt} message: #{options}"
|
94
|
+
end
|
75
95
|
end
|
76
96
|
|
77
97
|
# Device token, compressed and hex-ified
|