bpoweski-apnserver 0.0.2

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.
data/README.rdoc ADDED
@@ -0,0 +1,48 @@
1
+ = apnserver
2
+
3
+ * http://github.com/bpoweski/apnserver
4
+
5
+ == DESCRIPTION:
6
+
7
+ FIX (describe your package)
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * FIX (list of features or problems)
12
+
13
+ == SYNOPSIS:
14
+
15
+ FIX (code sample of usage)
16
+
17
+ == REQUIREMENTS:
18
+
19
+ * FIX (list of requirements)
20
+
21
+ == INSTALL:
22
+
23
+ * FIX (sudo gem install, anything else)
24
+
25
+ == LICENSE:
26
+
27
+ (The MIT License)
28
+
29
+ Copyright (c) 2009 Ben Poweski
30
+
31
+ Permission is hereby granted, free of charge, to any person obtaining
32
+ a copy of this software and associated documentation files (the
33
+ 'Software'), to deal in the Software without restriction, including
34
+ without limitation the rights to use, copy, modify, merge, publish,
35
+ distribute, sublicense, and/or sell copies of the Software, and to
36
+ permit persons to whom the Software is furnished to do so, subject to
37
+ the following conditions:
38
+
39
+ The above copyright notice and this permission notice shall be
40
+ included in all copies or substantial portions of the Software.
41
+
42
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
43
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
44
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
45
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
46
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
47
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
48
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/bin/apns ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ require 'socket'
3
+ require 'base64'
4
+ require 'rubygems'
5
+
6
+ socket = TCPSocket.new('localhost', 22195)
7
+ token = Base64.decode64(ARGV.last)
8
+ socket.write("\0\0 #{token}\0#{22.chr}{\"aps\":{\"alert\":\"Hi\"}}")
9
+ socket.close
data/bin/apnsend ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ require 'getoptlong'
3
+ require 'rubygems'
4
+ require 'apnserver'
5
+ require 'base64'
6
+
7
+ client = ApnServer::Client.new(ARGV.first)
8
+ client.connect!
9
+
10
+ token = Base64.decode64(ARGV.last)
11
+ client.write("\0\0 #{token}\0#{22.chr}{\"aps\":{\"alert\":\"Hi\"}}")
data/bin/apnserverd ADDED
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env ruby
2
+ require 'getoptlong'
3
+ require 'rubygems'
4
+ require 'apnserver'
5
+ require 'daemons'
6
+
7
+ def usage
8
+ puts "Usage: apnserverd [switches] --pem <path>"
9
+ puts " --bind-address [0.0.0.0] bind address of proxy"
10
+ puts " --proxy-port [22195] port proxy listens on"
11
+ puts " --server <gateway.push.apple.com> the apn server to send messages to"
12
+ puts " --port <2195> the port of the apn server"
13
+ puts " --help this message"
14
+ end
15
+
16
+ opts = GetoptLong.new(
17
+ ["--bind-address", "-b", GetoptLong::REQUIRED_ARGUMENT],
18
+ ["--proxy-port", "-P", GetoptLong::REQUIRED_ARGUMENT],
19
+ ["--server", "-s", GetoptLong::REQUIRED_ARGUMENT],
20
+ ["--port", "-p", GetoptLong::REQUIRED_ARGUMENT],
21
+ ["--pem", "-c", GetoptLong::REQUIRED_ARGUMENT],
22
+ ["--help", "-h", GetoptLong::NO_ARGUMENT]
23
+ )
24
+
25
+ bind_address = '0.0.0.0'
26
+ proxy_port = 22195
27
+ server = 'gateway.push.apple.com'
28
+ port = 2295
29
+ pem = nil
30
+
31
+ opts.each do |opt, arg|
32
+ case opt
33
+ when '--help'
34
+ usage
35
+ when '--bind-address'
36
+ bind_address = arg
37
+ when '--proxy-port'
38
+ proxy_port = arg.to_i
39
+ when '--server'
40
+ server = arg
41
+ when '--port'
42
+ port = arg
43
+ when '--pem'
44
+ pem = arg
45
+ end
46
+ end
47
+
48
+ if pem.nil?
49
+ usage
50
+ else
51
+ # Become a daemon
52
+ Daemons.daemonize
53
+
54
+ server = ApnServer::Server.new(pem, bind_address, proxy_port)
55
+ server.start!
56
+ end
@@ -0,0 +1,11 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class TestClient < Test::Unit::TestCase
4
+
5
+ def test_creates_client
6
+ client = ApnServer::Client.new('cert.pem', 'gateway.sandbox.push.apple.com', 2196)
7
+ assert_equal 'cert.pem', client.pem
8
+ assert_equal 'gateway.sandbox.push.apple.com', client.host
9
+ assert_equal 2196, client.port
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ require 'stringio'
2
+ require 'test/unit'
3
+ require File.dirname(__FILE__) + '/../lib/apnserver'
@@ -0,0 +1,78 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class NotificationTest < Test::Unit::TestCase
4
+ include ApnServer
5
+
6
+ def setup
7
+ @notification = Notification.new
8
+ end
9
+
10
+ def test_should_generate_byte_array
11
+ payload = '{"aps":{"alert":"You have not mail!"}}'
12
+ device_token = "12345678123456781234567812345678"
13
+ @notification.device_token = device_token
14
+ @notification.alert = "You have not mail!"
15
+ expected = [0, 0, device_token.size, device_token, 0, payload.size, payload]
16
+ assert_equal expected.pack("ccca*cca*"), @notification.to_bytes
17
+ end
18
+
19
+ def test_should_create_payload_with_badge_attribute
20
+ expected = { :aps => { :badge => 1 }}
21
+ @notification.badge = 1
22
+ assert_equal expected, @notification.payload
23
+ end
24
+
25
+ def test_should_create_payload_with_alert_attribute
26
+ expected = { :aps => { :alert => 'Hi' }}
27
+ @notification.alert = 'Hi'
28
+ assert_equal expected, @notification.payload
29
+ end
30
+
31
+ def test_should_create_json_payload
32
+ expected = '{"aps":{"alert":"Hi"}}'
33
+ @notification.alert = 'Hi'
34
+ assert_equal expected, @notification.json_payload
35
+ end
36
+
37
+ def test_should_not_allow_for_payloads_larger_than_256_chars
38
+ assert_raise Payload::PayloadInvalid do
39
+ alert = []
40
+ 256.times { alert << 'Hi' }
41
+ @notification.alert = alert.join
42
+ @notification.json_payload
43
+ end
44
+ end
45
+
46
+ def test_should_recognize_valid_request
47
+ device_token = '12345678123456781234567812345678'
48
+ payload = '{"aps":{"alert":"You have not mail!"}}'
49
+ request = [0, 0, device_token.size, device_token, 0, payload.size, payload].pack("ccca*cca*")
50
+ assert Notification.valid?(request)
51
+ notification = Notification.parse(request)
52
+ assert_equal device_token, notification.device_token
53
+ assert_equal "You have not mail!", notification.alert
54
+ end
55
+
56
+ def test_should_not_recognize_invalid_request
57
+ device_token = '12345678123456781234567812345678'
58
+ payload = '{"aps":{"alert":"You have not mail!"}}'
59
+ request = [0, 0, 20, device_token, 0, payload.size, payload].pack("ccca*cca*")
60
+ assert !Notification.valid?(request)
61
+ end
62
+
63
+ def test_should_pack_and_unpack_json
64
+ device_token = '12345678123456781234567812345678'
65
+ notification = Notification.new
66
+ notification.device_token = device_token
67
+ notification.badge = 10
68
+ notification.alert = 'Hi'
69
+ notification.sound = 'default'
70
+ notification.custom = { 'acme1' => "bar", 'acme2' => 42}
71
+
72
+ parsed = Notification.parse(notification.to_bytes)
73
+ [:device_token, :badge, :alert, :sound, :custom].each do |k|
74
+ expected = notification.send(k)
75
+ assert_equal expected, parsed.send(k), "Expected #{k} to be #{expected}"
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,59 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class NotificationTest < Test::Unit::TestCase
4
+ include ApnServer::Payload
5
+
6
+ def test_should_create_payload_with_simple_string
7
+ expected = { :aps => { :alert => 'Hi' }}
8
+ assert_equal expected, create_payload('Hi')
9
+ end
10
+
11
+ def test_should_create_payload_with_alert_key
12
+ expected = { :aps => { :alert => 'Hi' }}
13
+ assert_equal expected, create_payload(:alert => 'Hi')
14
+ end
15
+
16
+ def test_should_create_payload_with_badge_and_alert
17
+ expected = { :aps => { :alert => 'Hi', :badge => 1 }}
18
+ assert_equal expected, create_payload(:alert => 'Hi', :badge => 1)
19
+ end
20
+
21
+ # example 1
22
+ def test_should_create_payload_with_custom_payload
23
+ alert = 'Message received from Bob'
24
+ expected = {
25
+ :aps => { :alert => alert },
26
+ :acme2 => [ "bang", "whiz" ]
27
+ }
28
+ assert_equal expected, create_payload(:alert => alert, :custom => { :acme2 => ['bang', 'whiz']})
29
+ end
30
+
31
+ # example 3
32
+ def test_should_create_payload_with_sound_and_multiple_custom
33
+ expected = {
34
+ :aps => {
35
+ :alert => "You got your emails.",
36
+ :badge => 9,
37
+ :sound => "bingbong.aiff"
38
+ },
39
+ :acme1 => "bar",
40
+ :acme2 => 42
41
+ }
42
+ assert_equal expected, create_payload({
43
+ :alert => "You got your emails.",
44
+ :badge => 9,
45
+ :sound => "bingbong.aiff",
46
+ :custom => { :acme1 => "bar", :acme2 => 42}
47
+ })
48
+ end
49
+
50
+ # example 5
51
+ def test_should_create_payload_with_empty_aps
52
+ expected = {
53
+ :aps => {},
54
+ :acme2 => [ 5, 8 ]
55
+ }
56
+ assert_equal expected, create_payload(:custom => { :acme2 => [ 5, 8 ] })
57
+ end
58
+
59
+ end
@@ -0,0 +1,29 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestServer
4
+ attr_accessor :queue
5
+ include ApnServer::Protocol
6
+
7
+ def address
8
+ [12345, '127.0.0.1']
9
+ end
10
+ end
11
+
12
+ class TestProtocol < Test::Unit::TestCase
13
+
14
+ def setup
15
+ @server = TestServer.new
16
+ @server.queue = Array.new # fake out EM::Queue
17
+ end
18
+
19
+ def test_adds_notification_to_queue
20
+ token = "12345678123456781234567812345678"
21
+ @server.receive_data("\0\0 #{token}\0#{22.chr}{\"aps\":{\"alert\":\"Hi\"}}")
22
+ assert_equal 1, @server.queue.size
23
+ end
24
+
25
+ def test_does_not_add_invalid_notification
26
+ @server.receive_data('fakedata')
27
+ assert @server.queue.empty?
28
+ end
29
+ end
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bpoweski-apnserver
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Ben Poweski
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-09-14 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: eventmachine
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: daemons
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ description: A toolkit for proxying and sending Apple Push Notifications
36
+ email: bpoweski@3factors.com
37
+ executables:
38
+ - apns
39
+ - apnsend
40
+ - apnserverd
41
+ extensions: []
42
+
43
+ extra_rdoc_files:
44
+ - README.rdoc
45
+ files:
46
+ - README.rdoc
47
+ has_rdoc: true
48
+ homepage: http://github.com/bpoweski/apnserver
49
+ licenses:
50
+ post_install_message:
51
+ rdoc_options:
52
+ - --charset=UTF-8
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: "0"
60
+ version:
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: "0"
66
+ version:
67
+ requirements: []
68
+
69
+ rubyforge_project:
70
+ rubygems_version: 1.3.5
71
+ signing_key:
72
+ specification_version: 3
73
+ summary: Apple Push Notification Server
74
+ test_files:
75
+ - test/test_client.rb
76
+ - test/test_helper.rb
77
+ - test/test_notification.rb
78
+ - test/test_payload.rb
79
+ - test/test_protocol.rb