fcm-ruby-push-notifications 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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