fcm-ruby-push-notifications 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +37 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +19 -0
  5. data/CHANGELOG.md +32 -0
  6. data/Gemfile +6 -0
  7. data/LICENSE +22 -0
  8. data/README.md +82 -0
  9. data/Rakefile +12 -0
  10. data/examples/apns.rb +27 -0
  11. data/examples/gcm.rb +25 -0
  12. data/examples/mpns.rb +22 -0
  13. data/examples/wns.rb +25 -0
  14. data/gemfiles/Gemfile-legacy +8 -0
  15. data/lib/ruby-push-notifications.rb +7 -0
  16. data/lib/ruby-push-notifications/apns.rb +44 -0
  17. data/lib/ruby-push-notifications/apns/apns_connection.rb +70 -0
  18. data/lib/ruby-push-notifications/apns/apns_notification.rb +91 -0
  19. data/lib/ruby-push-notifications/apns/apns_pusher.rb +84 -0
  20. data/lib/ruby-push-notifications/apns/apns_results.rb +30 -0
  21. data/lib/ruby-push-notifications/fcm.rb +8 -0
  22. data/lib/ruby-push-notifications/fcm/fcm_connection.rb +60 -0
  23. data/lib/ruby-push-notifications/fcm/fcm_error.rb +17 -0
  24. data/lib/ruby-push-notifications/fcm/fcm_notification.rb +31 -0
  25. data/lib/ruby-push-notifications/fcm/fcm_pusher.rb +29 -0
  26. data/lib/ruby-push-notifications/fcm/fcm_request.rb +28 -0
  27. data/lib/ruby-push-notifications/fcm/fcm_response.rb +89 -0
  28. data/lib/ruby-push-notifications/fcm/fcm_result.rb +52 -0
  29. data/lib/ruby-push-notifications/gcm.rb +6 -0
  30. data/lib/ruby-push-notifications/gcm/gcm_connection.rb +54 -0
  31. data/lib/ruby-push-notifications/gcm/gcm_error.rb +17 -0
  32. data/lib/ruby-push-notifications/gcm/gcm_notification.rb +31 -0
  33. data/lib/ruby-push-notifications/gcm/gcm_pusher.rb +35 -0
  34. data/lib/ruby-push-notifications/gcm/gcm_response.rb +89 -0
  35. data/lib/ruby-push-notifications/gcm/gcm_result.rb +52 -0
  36. data/lib/ruby-push-notifications/mpns.rb +5 -0
  37. data/lib/ruby-push-notifications/mpns/mpns_connection.rb +87 -0
  38. data/lib/ruby-push-notifications/mpns/mpns_notification.rb +94 -0
  39. data/lib/ruby-push-notifications/mpns/mpns_pusher.rb +33 -0
  40. data/lib/ruby-push-notifications/mpns/mpns_response.rb +82 -0
  41. data/lib/ruby-push-notifications/mpns/mpns_result.rb +182 -0
  42. data/lib/ruby-push-notifications/notification_results_manager.rb +14 -0
  43. data/lib/ruby-push-notifications/wns.rb +6 -0
  44. data/lib/ruby-push-notifications/wns/wns_access.rb +82 -0
  45. data/lib/ruby-push-notifications/wns/wns_connection.rb +97 -0
  46. data/lib/ruby-push-notifications/wns/wns_notification.rb +101 -0
  47. data/lib/ruby-push-notifications/wns/wns_pusher.rb +32 -0
  48. data/lib/ruby-push-notifications/wns/wns_response.rb +83 -0
  49. data/lib/ruby-push-notifications/wns/wns_result.rb +208 -0
  50. data/ruby-push-notifications.gemspec +28 -0
  51. data/spec/factories.rb +17 -0
  52. data/spec/factories/notifications.rb +30 -0
  53. data/spec/ruby-push-notifications/apns/apns_connection_spec.rb +92 -0
  54. data/spec/ruby-push-notifications/apns/apns_notification_spec.rb +42 -0
  55. data/spec/ruby-push-notifications/apns/apns_pusher_spec.rb +295 -0
  56. data/spec/ruby-push-notifications/gcm/gcm_connection_spec.rb +46 -0
  57. data/spec/ruby-push-notifications/gcm/gcm_notification_spec.rb +37 -0
  58. data/spec/ruby-push-notifications/gcm/gcm_pusher_spec.rb +45 -0
  59. data/spec/ruby-push-notifications/gcm/gcm_response_spec.rb +82 -0
  60. data/spec/ruby-push-notifications/mpns/mpns_connection_spec.rb +46 -0
  61. data/spec/ruby-push-notifications/mpns/mpns_notification_spec.rb +53 -0
  62. data/spec/ruby-push-notifications/mpns/mpns_pusher_spec.rb +59 -0
  63. data/spec/ruby-push-notifications/mpns/mpns_response_spec.rb +64 -0
  64. data/spec/ruby-push-notifications/wns/wns_access_spec.rb +76 -0
  65. data/spec/ruby-push-notifications/wns/wns_connection_spec.rb +53 -0
  66. data/spec/ruby-push-notifications/wns/wns_notification_spec.rb +177 -0
  67. data/spec/ruby-push-notifications/wns/wns_pusher_spec.rb +58 -0
  68. data/spec/ruby-push-notifications/wns/wns_response_spec.rb +65 -0
  69. data/spec/spec_helper.rb +23 -0
  70. data/spec/support/dummy.pem +44 -0
  71. data/spec/support/factory_girl.rb +5 -0
  72. data/spec/support/results_shared_examples.rb +31 -0
  73. metadata +249 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5043c1d56180cceaae2e9e0c47270dcdb18dc889
4
+ data.tar.gz: 8e83ac1db715886036aab694901fe3e0ed220249
5
+ SHA512:
6
+ metadata.gz: 51cdd15cb84d289715c4794333c11b0217ee2fe59b94b3f47e6c6ebba85ba55aa06e0351c840ef70078b099af1a53e407d3edb5f68646e1282eb48630ec0b02c
7
+ data.tar.gz: 24fb35a54e114c538f36449047956cbb7e2aca35c516d1558e66b33a5de8595a5663943757c9cf76f11674e75d434737a7bcabd8d8b532706c5951e43b8fe700
data/.gitignore ADDED
@@ -0,0 +1,37 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /test/tmp/
9
+ /test/version_tmp/
10
+ /tmp/
11
+
12
+ ## Specific to RubyMotion:
13
+ .dat*
14
+ .repl_history
15
+ build/
16
+
17
+ ## Documentation cache and generated files:
18
+ /.yardoc/
19
+ /_yardoc/
20
+ /doc/
21
+ /rdoc/
22
+
23
+ ## Environment normalisation:
24
+ /.bundle/
25
+ /lib/bundler/man/
26
+
27
+ # for a library or gem, you might want to ignore these files since the code is
28
+ # intended to run in multiple environments; otherwise, check them in:
29
+ Gemfile.lock
30
+ # .ruby-version
31
+ # .ruby-gemset
32
+
33
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
34
+ .rvmrc
35
+ .DS_Store
36
+
37
+ examples/*.bak
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,19 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.4.0
4
+ - 2.3.3
5
+ - 2.2.6
6
+ matrix:
7
+ include:
8
+ - rvm: "2.1.10"
9
+ gemfile: gemfiles/Gemfile-legacy
10
+ - rvm: "2.0.0"
11
+ gemfile: gemfiles/Gemfile-legacy
12
+ env: CODECLIMATE_REPO_TOKEN=efdb12c380287a25b2b26362aa710a9b59020122cbe4edecf0d353bf50e0046a
13
+ notifications:
14
+ webhooks:
15
+ urls:
16
+ - https://webhooks.gitter.im/e/b740ebfeb7e0dba10293
17
+ on_success: change # options: [always|never|change] default: always
18
+ on_failure: always # options: [always|never|change] default: always
19
+ on_start: false # default: false
data/CHANGELOG.md ADDED
@@ -0,0 +1,32 @@
1
+ # CHANGELOG™
2
+ All notable changes to this project will be documented in this file.
3
+ This project adheres to [Semantic Versioning](http://semver.org/).
4
+
5
+ ## [unrealeased] - [unrealease date]
6
+
7
+ ## 1.2.0 - 2017-09-20
8
+ - **Added**: Add support Windows Push Notification Services (WNS)
9
+
10
+ ## 1.1.0 - 2017-03-14
11
+ - **Added**: Option (`url`) to set custom GCM endpoint (Android)
12
+ - **Added**: Option (`host`) to set custom APNS environment (iOS)
13
+
14
+ ## 1.0.1 - 2017-01-12
15
+ - **Fixed**: Loading issue when `'forwardable'` wasn't previously required.
16
+ - **Removed**: Version file
17
+
18
+ ## 1.0.0 - 2016-12-01
19
+ - **Added**: Configurable timeouts for connecting external services.
20
+ - **Removed**: Ruby 1.9.3 support.
21
+
22
+ ## 0.4.0 - 2016-02-23
23
+ - **Added**: Option to provide a password for the PEM file for APNS connection
24
+
25
+ ## 0.3.0 - 2015-04-21
26
+ - **Added**: Unified response interface through `Notifications Results Manager`
27
+
28
+ ## 0.2.0 - 2015-04-15
29
+ - **Added**: Microsoft Push Notifications Service Support
30
+
31
+ ## 0.1.0 - 2015-03-31
32
+ - First release
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ruby-push-notifications.gemspec
4
+ gemspec
5
+
6
+ gem "codeclimate-test-reporter", group: :test, require: nil
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Carlos Alonso
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1,82 @@
1
+ # Ruby Push Notifications
2
+
3
+ [![Build Status](https://travis-ci.org/calonso/ruby-push-notifications.svg)](https://travis-ci.org/calonso/ruby-push-notifications) [![Dependency Status](https://gemnasium.com/calonso/ruby-push-notifications.svg)](https://gemnasium.com/calonso/ruby-push-notifications) [![Code Climate](https://codeclimate.com/github/calonso/ruby-push-notifications/badges/gpa.svg)](https://codeclimate.com/github/calonso/ruby-push-notifications) [![Test Coverage](https://codeclimate.com/github/calonso/ruby-push-notifications/badges/coverage.svg)](https://codeclimate.com/github/calonso/ruby-push-notifications) [![Gem Version](https://badge.fury.io/rb/ruby-push-notifications.svg)](http://badge.fury.io/rb/ruby-push-notifications) [![Join the chat at https://gitter.im/calonso/ruby-push-notifications](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/calonso/ruby-push-notifications?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
4
+
5
+ ### iOS, Android and Windows Phone Push Notifications made easy!
6
+
7
+ ## Features
8
+
9
+ * iOS and Android support
10
+ * Complete error and retry management
11
+ * Easy and intuitive API
12
+
13
+ ## Installation
14
+
15
+ Add this line to your application's Gemfile:
16
+
17
+ gem 'ruby-push-notifications'
18
+
19
+ And then execute:
20
+
21
+ $ bundle
22
+
23
+ Or install it yourself as:
24
+
25
+ $ gem install ruby-push-notifications
26
+
27
+ ## Usage
28
+
29
+ **Ruby Push Notifications** gem usage is really easy.
30
+
31
+ 1. After installing, require the gem
32
+ 2. Create one or more notifications
33
+ 3. Create the corresponding `pusher`
34
+ 4. Push!!
35
+ 5. Get feedback
36
+
37
+ For completely detailed examples:
38
+
39
+ 1. [Apple iOS example](https://github.com/calonso/ruby-push-notifications/tree/master/examples/apns.rb)
40
+ 2. [Google Android example](https://github.com/calonso/ruby-push-notifications/tree/master/examples/gcm.rb)
41
+ 3. [Windows Phone(MPNS) example](https://github.com/calonso/ruby-push-notifications/tree/master/examples/mpns.rb)
42
+ 4. [Windows Phone(WNS) example](https://github.com/calonso/ruby-push-notifications/tree/master/examples/wns.rb)
43
+
44
+ ## Pending tasks
45
+
46
+ Feel free to contribute!!
47
+
48
+ * Validate iOS notifications format and max size
49
+ * Validate iOS tokens format
50
+ * Validate GCM registration ids format
51
+ * Validate GCM notifications format and max size
52
+ * Split GCM notifications in parts if more than 1000 destinations are given (currently raising exception)
53
+ * Integrate with APNS Feedback service
54
+ * Validate MPNS notifications format
55
+ * Validate MPNS data
56
+ * Add other platforms (Amazon Fire...)
57
+
58
+ ## Contributing
59
+
60
+ 1. Fork it ( https://github.com/calonso/ruby-push-notifications/fork )
61
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
62
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
63
+ 4. Push to the branch (`git push origin my-new-feature`)
64
+ 5. Create a new Pull Request
65
+
66
+ ## Troubleshooting
67
+
68
+ **If you see "255 Unknown Error" error code**
69
+
70
+ This error code is assigned when the connection to push notification server wasn't successful
71
+ <a href="https://github.com/calonso/ruby-push-notifications/blob/master/lib/ruby-push-notifications/apns/apns_pusher.rb#L56-L58">255 UNKnown Error code</a>
72
+
73
+ Checking your connection configuration for example with APNS connection.
74
+ When your pem file and token are development make sure you configure the pusher for sandbox mode
75
+ ``` RubyPushNotifications::APNS::APNSPusher.new('the certificate', true)) ```
76
+
77
+ or when your pem file and token are production you should configure the pusher for production mode (Set the sandbox mode to false when creating your pusher)
78
+ ``` RubyPushNotifications::APNS::APNSPusher.new('the certificate', false)) ```
79
+
80
+ ## Changelog
81
+
82
+ Refer to the [CHANGELOG.md](https://github.com/calonso/ruby-push-notifications/blob/master/CHANGELOG.md) file for detailed changes across versions.
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ begin
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task :default => :spec
9
+ rescue LoadError
10
+ # no rspec available
11
+ end
12
+
data/examples/apns.rb ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env bundle exec ruby
2
+
3
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4
+
5
+ require 'ruby-push-notifications'
6
+
7
+ tokens = [
8
+ 'First token here',
9
+ 'Second token here'
10
+ ]
11
+ password = nil # optional password for .pem file
12
+
13
+ notification = RubyPushNotifications::APNS::APNSNotification.new tokens, { aps: { alert: 'Hello APNS World!', sound: 'true', badge: 1 } }
14
+
15
+ pusher = RubyPushNotifications::APNS::APNSPusher.new(File.read('/path/to/your/apps/certificate.pem'), true, password) # enter the password if present
16
+ # Connect timeout defaults to 30s
17
+ # pusher = RubyPushNotifications::APNS::APNSPusher.new(File.read('/path/to/your/apps/certificate.pem'), true, password, { connect_timeout: 20 })
18
+
19
+ # Manually set APNS environment (e.g. useful for load testing)
20
+ # When option `host` is given it always uses this environment, `sandbox` param is ignored.
21
+ # pusher = RubyPushNotifications::APNS::APNSPusher.new(File.read('/path/to/your/apps/certificate.pem'), true, password, { host: "gateway.push.example.com" })
22
+
23
+ pusher.push [notification]
24
+ p 'Notification sending results:'
25
+ p "Success: #{notification.success}, Failed: #{notification.failed}"
26
+ p 'Details:'
27
+ p notification.individual_results
data/examples/gcm.rb ADDED
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env bundle exec ruby
2
+
3
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4
+
5
+ require 'ruby-push-notifications'
6
+
7
+ registration_ids = [
8
+ 'First registration id here',
9
+ 'Second registration id here'
10
+ ]
11
+
12
+ notification = RubyPushNotifications::GCM::GCMNotification.new registration_ids, { text: 'Hello GCM World!' }
13
+
14
+ pusher = RubyPushNotifications::GCM::GCMPusher.new "Your app's GCM key"
15
+ # Open and read timeouts default to 30s
16
+ # pusher = RubyPushNotifications::GCM::GCMPusher.new "Your app's GCM key", { open_timeout: 10, read_timeout: 10 }
17
+
18
+ # Manually set GCM URL (e.g. useful for load testing)
19
+ # pusher = RubyPushNotifications::GCM::GCMPusher.new "Your app's GCM key", { url: "https://example.com/gcm/send" }
20
+
21
+ pusher.push [notification]
22
+ p 'Notification sending results:'
23
+ p "Success: #{notification.success}, Failed: #{notification.failed}"
24
+ p 'Details:'
25
+ p notification.individual_results
data/examples/mpns.rb ADDED
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env bundle exec ruby
2
+
3
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4
+
5
+ require 'ruby-push-notifications'
6
+
7
+ device_urls = [
8
+ 'First device url here',
9
+ 'Second device url here'
10
+ ]
11
+
12
+ # Notification with toast type
13
+ notification = RubyPushNotifications::MPNS::MPNSNotification.new device_urls, { title: 'Title', message: 'Hello MPNS World!', type: :toast }
14
+
15
+ pusher = RubyPushNotifications::MPNS::MPNSPusher.new
16
+ # Open and read timeouts default to 30s
17
+ # pusher = RubyPushNotifications::MPNS::MPNSPusher.new optional_certificate, { open_timeout: 10, read_timeout: 10 }
18
+ pusher.push [notification]
19
+ p 'Notification sending results:'
20
+ p "Success: #{notification.success}, Failed: #{notification.failed}"
21
+ p 'Details:'
22
+ p notification.individual_results
data/examples/wns.rb ADDED
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4
+
5
+ require 'ruby-push-notifications'
6
+
7
+ sid = "ms-app://...."
8
+ secret = "..."
9
+
10
+ wns_access = RubyPushNotifications::WNS::WNSAccess.new(sid, secret).get_token
11
+ access_token = wns_access.response.access_token
12
+
13
+ device_urls = ["https://hk2.notify.windows.com/?token=AwYAAACEIPGNfZtVWJMvU%2fJ67TTdLQNdFl2345SbaCP7dmkvUmy6Cv9Y7hM4UT5uA%2b3obnZlIIhQcse9Hs6RPW0MPFVjf3MugnfD8qjIHMtRKIsKENIFveN1xQ6S38m90%2fgaBsE%3d"]
14
+
15
+ notification = RubyPushNotifications::WNS::WNSNotification.new(device_urls, { type: :toast, title: 'This is a special title', message: 'this is a special message'})
16
+ # notification = RubyPushNotifications::WNS::WNSNotification.new(device_urls, { type: :tile, image: 'https://res-5.cloudinary.com/prepathon/image/fetch/w_21,h_21,c_fill,g_face/http://assets-cdn.github.com/images/icons/emoji/unicode/1f604.png?v6', message: 'this is a special message'})
17
+ # notification = RubyPushNotifications::WNS::WNSNotification.new(device_urls, { type: :badge, value: 'activity'})
18
+
19
+ pusher = RubyPushNotifications::WNS::WNSPusher.new(access_token)
20
+
21
+ pusher.push([notification])
22
+ p 'Notification sending results:'
23
+ p "Success: #{notification.success}, Failed: #{notification.failed}"
24
+ p 'Details:'
25
+ p notification.individual_results
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem "activesupport", "~> 4.2", group: :test
4
+
5
+ # Specify your gem's dependencies in ruby-push-notifications.gemspec
6
+ gemspec path: ".."
7
+
8
+ gem "codeclimate-test-reporter", group: :test, require: nil
@@ -0,0 +1,7 @@
1
+ require 'forwardable'
2
+ require 'ruby-push-notifications/notification_results_manager'
3
+ require 'ruby-push-notifications/apns'
4
+ require 'ruby-push-notifications/gcm'
5
+ require 'ruby-push-notifications/fcm'
6
+ require 'ruby-push-notifications/mpns'
7
+ require 'ruby-push-notifications/wns'
@@ -0,0 +1,44 @@
1
+ #
2
+ # @author Carlos Alonso
3
+ #
4
+ module RubyPushNotifications::APNS
5
+
6
+ # No Status Error Code. Represents a successfully sent notification
7
+ NO_ERROR_STATUS_CODE = 0
8
+
9
+ # An error occurred while processing the notification
10
+ PROCESSING_ERROR_STATUS_CODE = 1
11
+
12
+ # The notification contains no device token
13
+ MISSING_DEVICE_TOKEN_STATUS_CODE = 2
14
+
15
+ # The notification is being sent through the plain TCPSocket,
16
+ # rather than the SSL one
17
+ MISSING_TOPIC_STATUS_CODE = 3
18
+
19
+ # The notification contains no payload
20
+ MISSING_PAYLOAD_STATUS_CODE = 4
21
+
22
+ # The given token sice is invalid (!= 32)
23
+ INVALID_TOKEN_SIZE_STATUS_CODE = 5
24
+
25
+ # The given topic size is invalid
26
+ INVALID_TOPIC_SIZE_STATUS_CODE = 6
27
+
28
+ # Payload size is invalid (256 bytes if iOS < 8, 2Kb otherwise)
29
+ INVALID_PAYLOAD_SIZE_STATUS_CODE = 7
30
+
31
+ # The token is for dev and the env is prod or viceversa, or simply wrong
32
+ INVALID_TOKEN_STATUS_CODE = 8
33
+
34
+ # Connection closed at Apple's end
35
+ SHUTDOWN_STATUS_CODE = 10
36
+
37
+ # Unknown error
38
+ UNKNOWN_ERROR_STATUS_CODE = 255
39
+ end
40
+
41
+ require 'ruby-push-notifications/apns/apns_connection'
42
+ require 'ruby-push-notifications/apns/apns_notification'
43
+ require 'ruby-push-notifications/apns/apns_pusher'
44
+ require 'ruby-push-notifications/apns/apns_results'
@@ -0,0 +1,70 @@
1
+ require 'socket'
2
+ require 'openssl'
3
+
4
+ module RubyPushNotifications
5
+ module APNS
6
+ # This class encapsulates a connection with APNS.
7
+ #
8
+ # @author Carlos Alonso
9
+ class APNSConnection
10
+ extend Forwardable
11
+
12
+ # @private URL of the APNS Sandbox environment
13
+ APNS_SANDBOX_URL = 'gateway.sandbox.push.apple.com'
14
+
15
+ # @private URL of APNS production environment
16
+ APNS_PRODUCTION_URL = 'gateway.push.apple.com'
17
+
18
+ # @private Port to connect to
19
+ APNS_PORT = 2195
20
+
21
+ def_delegators :@sslsock, :write, :flush, :to_io, :read
22
+
23
+ # Opens a connection with APNS
24
+ #
25
+ # @param cert [String]. Contents of the PEM encoded certificate
26
+ # @param sandbox [Boolean]. Whether to use the sandbox environment or not.
27
+ # @param pass [String] optional. Passphrase for the certificate.
28
+ # @param options [Hash] optional. Options for #open. Currently supports:
29
+ # * host [String]: Hostname of the APNS environment. Defaults to the official APNS hostname.
30
+ # * connect_timeout [Integer]: how long the socket will wait for when opening the APNS socket. Defaults to 30.
31
+ # @return [APNSConnection]. The recently stablished connection.
32
+ def self.open(cert, sandbox, pass = nil, options = {})
33
+ ctx = OpenSSL::SSL::SSLContext.new
34
+ ctx.key = OpenSSL::PKey::RSA.new cert, pass
35
+ ctx.cert = OpenSSL::X509::Certificate.new cert
36
+
37
+ h = options.fetch(:host, host(sandbox))
38
+ socket = Socket.tcp h, APNS_PORT, nil, nil, connect_timeout: options.fetch(:connect_timeout, 30)
39
+ ssl = OpenSSL::SSL::SSLSocket.new socket, ctx
40
+ ssl.connect
41
+
42
+ new socket, ssl
43
+ end
44
+
45
+ # Returns the URL to connect to.
46
+ #
47
+ # @param sandbox [Boolean]. Whether it is the sandbox or the production
48
+ # environment we're looking for.
49
+ # @return [String]. The URL for the APNS service.
50
+ def self.host(sandbox)
51
+ sandbox ? APNS_SANDBOX_URL : APNS_PRODUCTION_URL
52
+ end
53
+
54
+ # Initializes the APNSConnection
55
+ #
56
+ # @param tcpsock [TCPSocket]. The used TCP Socket.
57
+ # @param sslsock [SSLSocket]. The connected SSL Socket.
58
+ def initialize(tcpsock, sslsock)
59
+ @tcpsock = tcpsock
60
+ @sslsock = sslsock
61
+ end
62
+
63
+ # Closes the APNSConnection
64
+ def close
65
+ @sslsock.close
66
+ @tcpsock.close
67
+ end
68
+ end
69
+ end
70
+ end