rpush 3.1.1 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: deccc35a73da0b426daeb20fdbbe287be5e9df9e4b8c8fcd5ef2b69c6663da68
4
- data.tar.gz: c7038ba47604bde8a322beff513ab999e1a2692e56bd83b983cb757301e7e590
3
+ metadata.gz: 2177b25e8710a0539b82b9bade18da563e0b1b1f5509da42be346969a909e83b
4
+ data.tar.gz: 2c46fec2c2c9858caf0447e2dc5843fae5249edc5b08604141ea3ecbaa95fb5f
5
5
  SHA512:
6
- metadata.gz: 2a405b20855ef2d3c77f33c842058f95da8c7436a911712e221d5d199af82708dc8b5757f11219d2e31787311f8ea8f25384f85821c806f5492998436770743e
7
- data.tar.gz: 4fdfe15b520768b4cbcc24c09c8859fa220fccfe18aed3a00680ff317d70ef95a4503f240262a1bdaf4aa0c4ea10be20478a4d1080e11b9b466458a8a68374c0
6
+ metadata.gz: c45d7e698704104dc19487636dba80a7278b739a6377d091b334ecedbe90c9b8475f08329e4a767e2ad45d7c3e9981d927558dd21c09e9de7c3cba20fb825993
7
+ data.tar.gz: 2ae04d72abc05c39c16605f545f78a2a8e829a60a1c6280b68df4e66d28d4c522e47b29ef9b259c18bf2e9b61c90955a686af07582d6426b679c2550851dc16e
data/CHANGELOG.md CHANGED
@@ -12,8 +12,22 @@
12
12
 
13
13
  - None
14
14
 
15
+ ## 3.2.0 (2018-06-13)
16
+
17
+ When upgrading, don't forget to run `bundle exec rpush init` to get all the latest migrations.
18
+
19
+ ### Breaking Changes
20
+
21
+ - None
22
+
23
+ ### Added
24
+
25
+ - Added support for P8 certificate Apple push notifications [#386](https://github.com/rpush/rpush/pull/386) (by [@mariannegru](https://github.com/mariannegru)
26
+
15
27
  ## 3.1.1 (2018-04-16)
16
28
 
29
+ When upgrading, don't forget to run `bundle exec rpush init` to get all the latest migrations.
30
+
17
31
  ### Breaking Changes
18
32
 
19
33
  - None
data/README.md CHANGED
@@ -80,10 +80,34 @@ You should also implement the [ssl_certificate_will_expire](https://github.com/r
80
80
 
81
81
  To use the newer APNs Api replace `Rpush::Apns::App` with `Rpush::Apns2::App`.
82
82
 
83
+ To use the p8 APNs Api replace `Rpush::Apns::App` with `Rpush::Apnsp8::App`.
84
+
85
+ ```ruby
86
+ app = Rpush::Apnsp8::App.new
87
+ app.name = "ios_app"
88
+ app.apn_key = File.read("/path/to/sandbox.p8")
89
+ app.environment = "development" # APNs environment.
90
+ app.apn_key_id = "APN KEY ID"
91
+ app.team_id = "TEAM ID"
92
+ app.bundle_id = "BUNDLE ID"
93
+ app.connections = 1
94
+ app.save!
95
+ ```
96
+
97
+ ```ruby
98
+ n = Rpush::Apns::Notification.new
99
+ n.app = Rpush::Apnsp8::App.find_by_name("ios_app")
100
+ n.device_token = "..." # 64-character hex string
101
+ n.alert = "hi mom!"
102
+ n.data = { foo: :bar }
103
+ n.save!
104
+ ```
83
105
  #### Firebase Cloud Messaging
84
106
 
85
107
  FCM and GCM are – as of writing – compatible with each other. See also [this comment](https://github.com/rpush/rpush/issues/284#issuecomment-228330206) for further references.
86
108
 
109
+ Please refer to the Firebase Console on where to find your `auth_key` (probably called _Server Key_ there). To verify you have the right key, use tools like [Postman](https://www.getpostman.com/), [HTTPie](https://httpie.org/), `curl` or similar before reporting a new issue. See also [this comment](https://github.com/rpush/rpush/issues/346#issuecomment-289218776).
110
+
87
111
  ```ruby
88
112
  app = Rpush::Gcm::App.new
89
113
  app.name = "android_app"
@@ -46,6 +46,7 @@ class RpushMigrationGenerator < Rails::Generators::Base
46
46
  add_rpush_migration('rpush_3_0_1_updates')
47
47
  add_rpush_migration('rpush_3_1_0_add_pushy')
48
48
  add_rpush_migration('rpush_3_1_1_updates')
49
+ add_rpush_migration('rpush_3_2_0_add_apns_p8')
49
50
  end
50
51
 
51
52
  protected
@@ -0,0 +1,15 @@
1
+ class Rpush320AddApnsP8 < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
2
+ def self.up
3
+ add_column :rpush_apps, :apn_key, :string, null: true
4
+ add_column :rpush_apps, :apn_key_id, :string, null: true
5
+ add_column :rpush_apps, :team_id, :string, null: true
6
+ add_column :rpush_apps, :bundle_id, :string, null: true
7
+ end
8
+
9
+ def self.down
10
+ remove_column :rpush_apps, :apn_key
11
+ remove_column :rpush_apps, :apn_key_id
12
+ remove_column :rpush_apps, :team_id
13
+ remove_column :rpush_apps, :bundle_id
14
+ end
15
+ end
data/lib/rpush.rb CHANGED
@@ -2,6 +2,7 @@ require 'logger'
2
2
  require 'multi_json'
3
3
  require 'active_support/all'
4
4
  require 'net-http2'
5
+ require 'jwt'
5
6
 
6
7
  require 'rails'
7
8
 
@@ -12,6 +12,9 @@ require 'rpush/client/active_model/apns/notification'
12
12
  require 'rpush/client/active_model/apns2/app'
13
13
  require 'rpush/client/active_model/apns2/notification'
14
14
 
15
+ require 'rpush/client/active_model/apnsp8/app'
16
+ require 'rpush/client/active_model/apnsp8/notification'
17
+
15
18
  require 'rpush/client/active_model/adm/data_validator'
16
19
  require 'rpush/client/active_model/adm/app'
17
20
  require 'rpush/client/active_model/adm/notification'
@@ -0,0 +1,23 @@
1
+ module Rpush
2
+ module Client
3
+ module ActiveModel
4
+ module Apnsp8
5
+ module App
6
+ def self.included(base)
7
+ base.instance_eval do
8
+ validates :environment, presence: true, inclusion: { in: %w(development production sandbox) }
9
+ validates :apn_key, presence: true
10
+ validates :apn_key_id, presence: true
11
+ validates :team_id, presence: true
12
+ validates :bundle_id, presence: true
13
+ end
14
+ end
15
+
16
+ def service_name
17
+ 'apnsp8'
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,9 @@
1
+ module Rpush
2
+ module Client
3
+ module ActiveModel
4
+ module Apnsp8
5
+ include Rpush::Client::ActiveModel::Apns
6
+ end
7
+ end
8
+ end
9
+ end
@@ -12,6 +12,9 @@ require 'rpush/client/active_record/apns/app'
12
12
  require 'rpush/client/active_record/apns2/notification'
13
13
  require 'rpush/client/active_record/apns2/app'
14
14
 
15
+ require 'rpush/client/active_record/apnsp8/notification'
16
+ require 'rpush/client/active_record/apnsp8/app'
17
+
15
18
  require 'rpush/client/active_record/gcm/notification'
16
19
  require 'rpush/client/active_record/gcm/app'
17
20
 
@@ -0,0 +1,11 @@
1
+ module Rpush
2
+ module Client
3
+ module ActiveRecord
4
+ module Apnsp8
5
+ class App < Rpush::Client::ActiveRecord::App
6
+ include Rpush::Client::ActiveModel::Apnsp8::App
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ module Rpush
2
+ module Client
3
+ module ActiveRecord
4
+ module Apnsp8
5
+ class Notification < Rpush::Client::ActiveRecord::Apns::Notification
6
+ end
7
+ end
8
+ end
9
+ end
10
+ end
@@ -24,6 +24,9 @@ require 'rpush/client/redis/apns/feedback'
24
24
  require 'rpush/client/redis/apns2/app'
25
25
  require 'rpush/client/redis/apns2/notification'
26
26
 
27
+ require 'rpush/client/redis/apnsp8/app'
28
+ require 'rpush/client/redis/apnsp8/notification'
29
+
27
30
  require 'rpush/client/redis/gcm/app'
28
31
  require 'rpush/client/redis/gcm/notification'
29
32
 
@@ -0,0 +1,11 @@
1
+ module Rpush
2
+ module Client
3
+ module Redis
4
+ module Apnsp8
5
+ class App < Rpush::Client::Redis::App
6
+ include Rpush::Client::ActiveModel::Apnsp8::App
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Rpush
2
+ module Client
3
+ module Redis
4
+ module Apnsp8
5
+ class Notification < Rpush::Client::Redis::Notification
6
+ include Rpush::Client::ActiveModel::Apnsp8::Notification
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -14,7 +14,11 @@ module Rpush
14
14
  attribute :client_id, :string
15
15
  attribute :client_secret, :string
16
16
  attribute :api_key, :string
17
-
17
+ attribute :apn_key, :string
18
+ attribute :apn_key_id, :string
19
+ attribute :team_id, :string
20
+ attribute :bundle_id, :string
21
+
18
22
  index :name
19
23
 
20
24
  validates :name, presence: true
data/lib/rpush/daemon.rb CHANGED
@@ -25,6 +25,7 @@ require 'rpush/daemon/dispatcher/http'
25
25
  require 'rpush/daemon/dispatcher/tcp'
26
26
  require 'rpush/daemon/dispatcher/apns_tcp'
27
27
  require 'rpush/daemon/dispatcher/apns_http2'
28
+ require 'rpush/daemon/dispatcher/apnsp8_http2'
28
29
  require 'rpush/daemon/service_config_methods'
29
30
  require 'rpush/daemon/retry_header_parser'
30
31
  require 'rpush/daemon/ring_buffer'
@@ -44,6 +45,10 @@ require 'rpush/daemon/apns'
44
45
  require 'rpush/daemon/apns2/delivery'
45
46
  require 'rpush/daemon/apns2'
46
47
 
48
+ require 'rpush/daemon/apnsp8/delivery'
49
+ require 'rpush/daemon/apnsp8/token'
50
+ require 'rpush/daemon/apnsp8'
51
+
47
52
  require 'rpush/daemon/gcm/delivery'
48
53
  require 'rpush/daemon/gcm'
49
54
 
@@ -0,0 +1,10 @@
1
+ module Rpush
2
+ module Daemon
3
+ module Apnsp8
4
+ extend ServiceConfigMethods
5
+
6
+ batch_deliveries true
7
+ dispatcher :apnsp8_http2
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,166 @@
1
+ module Rpush
2
+ module Daemon
3
+ module Apnsp8
4
+ # https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CommunicatingwithAPNs.html
5
+
6
+ HTTP2_HEADERS_KEY = 'headers'
7
+
8
+ class Delivery < Rpush::Daemon::Delivery
9
+ RETRYABLE_CODES = [ 429, 500, 503 ]
10
+
11
+ def initialize(app, http2_client, token_provider, batch)
12
+ @app = app
13
+ @client = http2_client
14
+ @batch = batch
15
+ @first_push = true
16
+ @token_provider = token_provider
17
+ end
18
+
19
+ def perform
20
+ @client.on(:error) { |err| mark_batch_retryable(Time.now + 10.seconds, err) }
21
+
22
+ @batch.each_notification do |notification|
23
+ prepare_async_post(notification)
24
+ end
25
+
26
+ # Send all preprocessed requests at once
27
+ @client.join
28
+ rescue Errno::ECONNREFUSED, SocketError, HTTP2::Error::StreamLimitExceeded => error
29
+ # TODO restart connection when StreamLimitExceeded
30
+ mark_batch_retryable(Time.now + 10.seconds, error)
31
+ raise
32
+ rescue StandardError => error
33
+ mark_batch_failed(error)
34
+ raise
35
+ ensure
36
+ @batch.all_processed
37
+ end
38
+
39
+ protected
40
+ ######################################################################
41
+
42
+ def prepare_async_post(notification)
43
+ response = {}
44
+
45
+ request = build_request(notification)
46
+ log_warn(request)
47
+ http_request = @client.prepare_request(:post, request[:path],
48
+ body: request[:body],
49
+ headers: request[:headers]
50
+ )
51
+
52
+ http_request.on(:headers) do |hdrs|
53
+ response[:code] = hdrs[':status'].to_i
54
+ end
55
+
56
+ http_request.on(:body_chunk) do |body_chunk|
57
+ next unless body_chunk.present?
58
+
59
+ response[:failure_reason] = JSON.parse(body_chunk)['reason']
60
+ end
61
+
62
+ http_request.on(:close) { handle_response(notification, response) }
63
+
64
+ if @first_push
65
+ @first_push = false
66
+ @client.call_async(http_request)
67
+ else
68
+ delayed_push_async(http_request)
69
+ end
70
+ end
71
+
72
+ def delayed_push_async(http_request)
73
+ until streams_available? do
74
+ sleep 0.001
75
+ end
76
+ @client.call_async(http_request)
77
+ end
78
+
79
+ def streams_available?
80
+ remote_max_concurrent_streams - @client.stream_count > 0
81
+ end
82
+
83
+ def remote_max_concurrent_streams
84
+ # 0x7fffffff is the default value from http-2 gem (2^31)
85
+ if @client.remote_settings[:settings_max_concurrent_streams] == 0x7fffffff
86
+ 0
87
+ else
88
+ @client.remote_settings[:settings_max_concurrent_streams]
89
+ end
90
+ end
91
+
92
+ def handle_response(notification, response)
93
+ code = response[:code]
94
+ case code
95
+ when 200
96
+ ok(notification)
97
+ when *RETRYABLE_CODES
98
+ service_unavailable(notification, response)
99
+ else
100
+ reflect(:notification_id_failed,
101
+ @app,
102
+ notification.id, code,
103
+ response[:failure_reason])
104
+ @batch.mark_failed(notification, response[:code], response[:failure_reason])
105
+ failed_message_to_log(notification, response)
106
+ end
107
+ end
108
+
109
+ def ok(notification)
110
+ log_info("#{notification.id} sent to #{notification.device_token}")
111
+ @batch.mark_delivered(notification)
112
+ end
113
+
114
+ def service_unavailable(notification, response)
115
+ @batch.mark_retryable(notification, Time.now + 10.seconds)
116
+ # Logs should go last as soon as we need to initialize
117
+ # retry time to display it in log
118
+ failed_message_to_log(notification, response)
119
+ retry_message_to_log(notification)
120
+ end
121
+
122
+ def build_request(notification)
123
+ {
124
+ path: "/3/device/#{notification.device_token}",
125
+ headers: prepare_headers(notification),
126
+ body: prepare_body(notification)
127
+ }
128
+ end
129
+
130
+ def prepare_body(notification)
131
+ hash = notification.as_json.except(HTTP2_HEADERS_KEY)
132
+ JSON.dump(hash).force_encoding(Encoding::BINARY)
133
+ end
134
+
135
+ def prepare_headers(notification)
136
+ jwt_token = @token_provider.token
137
+
138
+ headers = {}
139
+
140
+ headers['content-type'] = 'application/json'
141
+ headers['apns-expiration'] = '0'
142
+ headers['apns-priority'] = '10'
143
+ headers['apns-topic'] = @app.bundle_id
144
+ headers['authorization'] = "bearer #{jwt_token}"
145
+
146
+ headers.merge notification_data(notification)[HTTP2_HEADERS_KEY] || {}
147
+ end
148
+
149
+ def notification_data(notification)
150
+ notification.data || {}
151
+ end
152
+
153
+ def retry_message_to_log(notification)
154
+ log_warn("Notification #{notification.id} will be retried after "\
155
+ "#{notification.deliver_after.strftime('%Y-%m-%d %H:%M:%S')} "\
156
+ "(retry #{notification.retries}).")
157
+ end
158
+
159
+ def failed_message_to_log(notification, response)
160
+ log_error("Notification #{notification.id} failed, "\
161
+ "#{response[:code]}/#{response[:failure_reason]}")
162
+ end
163
+ end
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,33 @@
1
+ module Rpush
2
+ module Daemon
3
+ module Apnsp8
4
+ TOKEN_TTL = 30 * 60
5
+ class Token
6
+
7
+ def initialize(app)
8
+ @app = app
9
+ end
10
+
11
+ def token
12
+ if @cached_token && !expired_token?
13
+ @cached_token
14
+ else
15
+ new_token
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def new_token
22
+ @cached_token_at = Time.now
23
+ ec_key = OpenSSL::PKey::EC.new(@app.apn_key)
24
+ @cached_token = JWT.encode({iss: @app.team_id, iat: Time.now.to_i}, ec_key, 'ES256', {alg: 'ES256', kid: @app.apn_key_id})
25
+ end
26
+
27
+ def expired_token?
28
+ Time.now - @cached_token_at >= TOKEN_TTL
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,33 @@
1
+ module Rpush
2
+ module Daemon
3
+ module Dispatcher
4
+ class Apnsp8Http2
5
+
6
+ URLS = {
7
+ production: 'https://api.push.apple.com',
8
+ development: 'https://api.development.push.apple.com'
9
+ }
10
+
11
+ DEFAULT_TIMEOUT = 60
12
+
13
+ def initialize(app, delivery_class, _options = {})
14
+ @app = app
15
+ @delivery_class = delivery_class
16
+
17
+ url = URLS[app.environment.to_sym]
18
+ @client = NetHttp2::Client.new(url, connect_timeout: DEFAULT_TIMEOUT)
19
+ @token_provider = Rpush::Daemon::Apnsp8::Token.new(@app)
20
+ end
21
+
22
+ def dispatch(payload)
23
+
24
+ @delivery_class.new(@app, @client, @token_provider, payload.batch).perform
25
+ end
26
+
27
+ def cleanup
28
+ @client.close
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -5,7 +5,8 @@ module Rpush
5
5
  http: Rpush::Daemon::Dispatcher::Http,
6
6
  tcp: Rpush::Daemon::Dispatcher::Tcp,
7
7
  apns_tcp: Rpush::Daemon::Dispatcher::ApnsTcp,
8
- apns_http2: Rpush::Daemon::Dispatcher::ApnsHttp2
8
+ apns_http2: Rpush::Daemon::Dispatcher::ApnsHttp2,
9
+ apnsp8_http2: Rpush::Daemon::Dispatcher::Apnsp8Http2
9
10
  }
10
11
 
11
12
  def batch_deliveries(value = nil)
data/lib/rpush/version.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  module Rpush
2
2
  module VERSION
3
3
  MAJOR = 3
4
- MINOR = 1
5
- TINY = 1
4
+ MINOR = 2
5
+ TINY = 0
6
6
  PRE = nil
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".").freeze
@@ -35,6 +35,7 @@ require 'generators/templates/rpush_3_0_0_updates'
35
35
  require 'generators/templates/rpush_3_0_1_updates'
36
36
  require 'generators/templates/rpush_3_1_0_add_pushy'
37
37
  require 'generators/templates/rpush_3_1_1_updates'
38
+ require 'generators/templates/rpush_3_2_0_add_apns_p8'
38
39
 
39
40
  migrations = [
40
41
  AddRpush,
@@ -45,7 +46,8 @@ migrations = [
45
46
  Rpush300Updates,
46
47
  Rpush301Updates,
47
48
  Rpush310AddPushy,
48
- Rpush311Updates
49
+ Rpush311Updates,
50
+ Rpush320AddApnsP8
49
51
  ]
50
52
 
51
53
  unless ENV['TRAVIS']
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rpush
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.1
4
+ version: 3.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ian Leitch
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-16 00:00:00.000000000 Z
11
+ date: 2018-06-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: multi_json
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0.14'
55
+ - !ruby/object:Gem::Dependency
56
+ name: jwt
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 1.5.6
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 1.5.6
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: activesupport
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -372,6 +386,7 @@ files:
372
386
  - lib/generators/templates/rpush_3_0_1_updates.rb
373
387
  - lib/generators/templates/rpush_3_1_0_add_pushy.rb
374
388
  - lib/generators/templates/rpush_3_1_1_updates.rb
389
+ - lib/generators/templates/rpush_3_2_0_add_apns_p8.rb
375
390
  - lib/rpush.rb
376
391
  - lib/rpush/apns_feedback.rb
377
392
  - lib/rpush/cli.rb
@@ -385,6 +400,8 @@ files:
385
400
  - lib/rpush/client/active_model/apns/notification.rb
386
401
  - lib/rpush/client/active_model/apns2/app.rb
387
402
  - lib/rpush/client/active_model/apns2/notification.rb
403
+ - lib/rpush/client/active_model/apnsp8/app.rb
404
+ - lib/rpush/client/active_model/apnsp8/notification.rb
388
405
  - lib/rpush/client/active_model/gcm/app.rb
389
406
  - lib/rpush/client/active_model/gcm/expiry_collapse_key_mutual_inclusion_validator.rb
390
407
  - lib/rpush/client/active_model/gcm/notification.rb
@@ -406,6 +423,8 @@ files:
406
423
  - lib/rpush/client/active_record/apns/notification.rb
407
424
  - lib/rpush/client/active_record/apns2/app.rb
408
425
  - lib/rpush/client/active_record/apns2/notification.rb
426
+ - lib/rpush/client/active_record/apnsp8/app.rb
427
+ - lib/rpush/client/active_record/apnsp8/notification.rb
409
428
  - lib/rpush/client/active_record/app.rb
410
429
  - lib/rpush/client/active_record/gcm/app.rb
411
430
  - lib/rpush/client/active_record/gcm/notification.rb
@@ -426,6 +445,8 @@ files:
426
445
  - lib/rpush/client/redis/apns/notification.rb
427
446
  - lib/rpush/client/redis/apns2/app.rb
428
447
  - lib/rpush/client/redis/apns2/notification.rb
448
+ - lib/rpush/client/redis/apnsp8/app.rb
449
+ - lib/rpush/client/redis/apnsp8/notification.rb
429
450
  - lib/rpush/client/redis/app.rb
430
451
  - lib/rpush/client/redis/gcm/app.rb
431
452
  - lib/rpush/client/redis/gcm/notification.rb
@@ -447,6 +468,9 @@ files:
447
468
  - lib/rpush/daemon/apns/feedback_receiver.rb
448
469
  - lib/rpush/daemon/apns2.rb
449
470
  - lib/rpush/daemon/apns2/delivery.rb
471
+ - lib/rpush/daemon/apnsp8.rb
472
+ - lib/rpush/daemon/apnsp8/delivery.rb
473
+ - lib/rpush/daemon/apnsp8/token.rb
450
474
  - lib/rpush/daemon/app_runner.rb
451
475
  - lib/rpush/daemon/batch.rb
452
476
  - lib/rpush/daemon/constants.rb
@@ -454,6 +478,7 @@ files:
454
478
  - lib/rpush/daemon/delivery_error.rb
455
479
  - lib/rpush/daemon/dispatcher/apns_http2.rb
456
480
  - lib/rpush/daemon/dispatcher/apns_tcp.rb
481
+ - lib/rpush/daemon/dispatcher/apnsp8_http2.rb
457
482
  - lib/rpush/daemon/dispatcher/http.rb
458
483
  - lib/rpush/daemon/dispatcher/tcp.rb
459
484
  - lib/rpush/daemon/dispatcher_loop.rb