apnserver 0.1.10 → 0.2.1
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.textile +31 -22
 - data/bin/apnsend +10 -6
 - data/bin/apnserverd +24 -6
 - data/bin/apnserverd.fedora.init +0 -0
 - data/bin/apnserverd.ubuntu.init +116 -0
 - data/lib/apnserver.rb +0 -4
 - data/lib/apnserver/client.rb +9 -10
 - data/lib/apnserver/notification.rb +27 -28
 - data/lib/apnserver/payload.rb +3 -7
 - data/lib/apnserver/protocol.rb +6 -8
 - data/lib/apnserver/server.rb +10 -11
 - data/spec/models/client_spec.rb +21 -0
 - data/spec/models/notification_spec.rb +85 -0
 - data/spec/models/payload_spec.rb +57 -0
 - data/spec/models/protocol_spec.rb +19 -0
 - data/spec/spec_helper.rb +26 -0
 - data/spec/support/test_server.rb +10 -0
 - metadata +74 -42
 - data/Rakefile +0 -41
 - data/VERSION +0 -1
 - data/test/test_client.rb +0 -11
 - data/test/test_helper.rb +0 -4
 - data/test/test_notification.rb +0 -79
 - data/test/test_payload.rb +0 -59
 - data/test/test_protocol.rb +0 -29
 
    
        data/README.textile
    CHANGED
    
    | 
         @@ -5,48 +5,54 @@ h1. Apple Push Notification Server Toolkit 
     | 
|
| 
       5 
5 
     | 
    
         
             
            h2. Description
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
7 
     | 
    
         
             
            apnserver is a server and set of command line programs to send push notifications to the iPhone.
         
     | 
| 
       8 
     | 
    
         
            -
            Apple  
     | 
| 
       9 
     | 
    
         
            -
            opening up and tearing down SSL connections  
     | 
| 
       10 
     | 
    
         
            -
            network server is introduced that queues are requests to the APN service and sends them via a 
     | 
| 
      
 8 
     | 
    
         
            +
            Apple recommends to maintain an open connection to the push notification service and refrain from
         
     | 
| 
      
 9 
     | 
    
         
            +
            opening up and tearing down SSL connections repeated.  To solve this problem an intermediate
         
     | 
| 
      
 10 
     | 
    
         
            +
            network server is introduced that queues are requests to the APN service and sends them via a
         
     | 
| 
       11 
11 
     | 
    
         
             
            persistent connection.
         
     | 
| 
       12 
12 
     | 
    
         | 
| 
       13 
13 
     | 
    
         
             
            h2. Remaining Tasks
         
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
       15 
15 
     | 
    
         
             
             * Implement feedback service mechanism
         
     | 
| 
       16 
16 
     | 
    
         
             
             * Implement robust notification sending in reactor periodic scheduler
         
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
       18 
18 
     | 
    
         
             
            h2. Issues Fixed
         
     | 
| 
       19 
19 
     | 
    
         | 
| 
       20 
20 
     | 
    
         
             
             * second attempt at retry logic, SSL Errors close down sockets now
         
     | 
| 
       21 
21 
     | 
    
         
             
             * apnsend --badge option correctly sends integer number rather than string of number for aps json payload
         
     | 
| 
       22 
22 
     | 
    
         
             
             * connections are properly closed in Notification#push method now
         
     | 
| 
       23 
     | 
    
         
            -
             *  
     | 
| 
      
 23 
     | 
    
         
            +
             * removed json gem in favor of ActiveSupport
         
     | 
| 
      
 24 
     | 
    
         
            +
             * Rails 3.x support
         
     | 
| 
      
 25 
     | 
    
         
            +
             * drop the erroneous puts statements in favor a configurable logger
         
     | 
| 
      
 26 
     | 
    
         
            +
             * moved to Rspec
         
     | 
| 
       24 
27 
     | 
    
         | 
| 
       25 
28 
     | 
    
         
             
            h2. APN Server Daemon
         
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
       27 
30 
     | 
    
         
             
            <pre>
         
     | 
| 
       28 
31 
     | 
    
         
             
              <code>
         
     | 
| 
       29 
32 
     | 
    
         
             
            Usage: apnserverd [options] --pem /path/to/pem
         
     | 
| 
       30 
33 
     | 
    
         
             
              --bind-address bind address (defaults to 0.0.0.0)
         
     | 
| 
       31 
34 
     | 
    
         
             
                bind address of the server daemon
         
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
       33 
     | 
    
         
            -
              --proxy-port port 
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
              --proxy-port port
         
     | 
| 
       34 
37 
     | 
    
         
             
                the port that the daemon will listen on (defaults to 22195)
         
     | 
| 
       35 
     | 
    
         
            -
             
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
       36 
39 
     | 
    
         
             
              --server server
         
     | 
| 
       37 
40 
     | 
    
         
             
                APN Server (defaults to gateway.push.apple.com)
         
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
       39 
42 
     | 
    
         
             
              --port port of the APN Server
         
     | 
| 
       40 
43 
     | 
    
         
             
                APN server port (defaults to 2195)
         
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
       42 
45 
     | 
    
         
             
              --pem pem file path
         
     | 
| 
       43 
46 
     | 
    
         
             
                The PEM encoded private key and certificate.
         
     | 
| 
       44 
     | 
    
         
            -
                To export a PEM ecoded file execute 
     | 
| 
      
 47 
     | 
    
         
            +
                To export a PEM ecoded file execute
         
     | 
| 
       45 
48 
     | 
    
         
             
                # openssl pkcs12 -in cert.p12 -out cert.pem -nodes -clcerts
         
     | 
| 
       46 
     | 
    
         
            -
             
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
              --pem-passphrase passphrase
         
     | 
| 
      
 51 
     | 
    
         
            +
                The PEM passphrase to decode key.
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
       47 
53 
     | 
    
         
             
              --help
         
     | 
| 
       48 
     | 
    
         
            -
                usage message 
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
      
 54 
     | 
    
         
            +
                usage message
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
       50 
56 
     | 
    
         
             
              --daemon
         
     | 
| 
       51 
57 
     | 
    
         
             
                Runs process as daemon, not available on Windows
         
     | 
| 
       52 
58 
     | 
    
         
             
              </code>
         
     | 
| 
         @@ -54,7 +60,7 @@ Usage: apnserverd [options] --pem /path/to/pem 
     | 
|
| 
       54 
60 
     | 
    
         | 
| 
       55 
61 
     | 
    
         
             
            h2. APN Server Client
         
     | 
| 
       56 
62 
     | 
    
         | 
| 
       57 
     | 
    
         
            -
            With the APN server client script you can send push notifications directly to 
     | 
| 
      
 63 
     | 
    
         
            +
            With the APN server client script you can send push notifications directly to
         
     | 
| 
       58 
64 
     | 
    
         
             
            Apple's APN server over an SSL connection or to the above daemon using a plain socket.
         
     | 
| 
       59 
65 
     | 
    
         
             
            To send a notification to Apple's APN server using SSL the *--pem* option must be used.
         
     | 
| 
       60 
66 
     | 
    
         | 
| 
         @@ -63,8 +69,9 @@ To send a notification to Apple's APN server using SSL the *--pem* option must b 
     | 
|
| 
       63 
69 
     | 
    
         
             
            Usage: apnsend [switches] (--b64-token | --hex-token) <token>
         
     | 
| 
       64 
70 
     | 
    
         
             
              --server <localhost>                 the apn server defaults to a locally running apnserverd
         
     | 
| 
       65 
71 
     | 
    
         
             
              --port <2195>                        the port of the apn server
         
     | 
| 
       66 
     | 
    
         
            -
              --pem <path>                         the path to the pem file, if a pem is supplied the server 
     | 
| 
      
 72 
     | 
    
         
            +
              --pem <path>                         the path to the pem file, if a pem is supplied the server
         
     | 
| 
       67 
73 
     | 
    
         
             
                                                   defaults to gateway.push.apple.com:2195
         
     | 
| 
      
 74 
     | 
    
         
            +
              --pem-passphrase <passphrase>        the pem passphrase
         
     | 
| 
       68 
75 
     | 
    
         
             
              --alert <message>                    the message to send"
         
     | 
| 
       69 
76 
     | 
    
         
             
              --sound <default>                    the sound to play, defaults to 'default'
         
     | 
| 
       70 
77 
     | 
    
         
             
              --badge <number>                     the badge number
         
     | 
| 
         @@ -94,6 +101,7 @@ To configure the client to send to the local apnserverd process configure the Ap 
     | 
|
| 
       94 
101 
     | 
    
         
             
              # configured for a using the apnserverd proxy
         
     | 
| 
       95 
102 
     | 
    
         
             
              ApnServer::Config.host = 'localhost'
         
     | 
| 
       96 
103 
     | 
    
         
             
              ApnServer::Config.port = 22195
         
     | 
| 
      
 104 
     | 
    
         
            +
              ApnServer::Config.logger = Rails.logger
         
     | 
| 
       97 
105 
     | 
    
         
             
              </code>
         
     | 
| 
       98 
106 
     | 
    
         
             
            </pre>
         
     | 
| 
       99 
107 
     | 
    
         | 
| 
         @@ -123,11 +131,11 @@ Finally within we can send a push notification using the following code 
     | 
|
| 
       123 
131 
     | 
    
         | 
| 
       124 
132 
     | 
    
         
             
            h2. Installation
         
     | 
| 
       125 
133 
     | 
    
         | 
| 
       126 
     | 
    
         
            -
             
     | 
| 
      
 134 
     | 
    
         
            +
            Apnserver is hosted on "rubygems":https://rubygems.org/gems/apnserver
         
     | 
| 
       127 
135 
     | 
    
         | 
| 
       128 
136 
     | 
    
         
             
            <pre>
         
     | 
| 
       129 
137 
     | 
    
         
             
            <code>
         
     | 
| 
       130 
     | 
    
         
            -
              $ gem install  
     | 
| 
      
 138 
     | 
    
         
            +
              $ gem install apnserver
         
     | 
| 
       131 
139 
     | 
    
         
             
            </code>
         
     | 
| 
       132 
140 
     | 
    
         
             
            </pre>
         
     | 
| 
       133 
141 
     | 
    
         | 
| 
         @@ -135,15 +143,16 @@ Adding apnserver to your Rails application 
     | 
|
| 
       135 
143 
     | 
    
         | 
| 
       136 
144 
     | 
    
         
             
            <pre>
         
     | 
| 
       137 
145 
     | 
    
         
             
              <code>
         
     | 
| 
       138 
     | 
    
         
            -
               
     | 
| 
      
 146 
     | 
    
         
            +
              gem 'apnserver', '>= 0.2.0
         
     | 
| 
       139 
147 
     | 
    
         
             
              </code>
         
     | 
| 
       140 
148 
     | 
    
         
             
            </pre>
         
     | 
| 
       141 
149 
     | 
    
         | 
| 
      
 150 
     | 
    
         
            +
             
     | 
| 
       142 
151 
     | 
    
         
             
            h2. License
         
     | 
| 
       143 
152 
     | 
    
         | 
| 
       144 
153 
     | 
    
         
             
            (The MIT License)
         
     | 
| 
       145 
154 
     | 
    
         | 
| 
       146 
     | 
    
         
            -
            Copyright (c)  
     | 
| 
      
 155 
     | 
    
         
            +
            Copyright (c) 2011 Ben Poweski
         
     | 
| 
       147 
156 
     | 
    
         | 
| 
       148 
157 
     | 
    
         
             
            Permission is hereby granted, free of charge, to any person obtaining
         
     | 
| 
       149 
158 
     | 
    
         
             
            a copy of this software and associated documentation files (the
         
     | 
    
        data/bin/apnsend
    CHANGED
    
    | 
         @@ -13,12 +13,13 @@ def usage 
     | 
|
| 
       13 
13 
     | 
    
         
             
              puts " --server <localhost>                 the apn server defaults to a locally running apnserverd"
         
     | 
| 
       14 
14 
     | 
    
         
             
              puts " --port <2195>                        the port of the apn server"
         
     | 
| 
       15 
15 
     | 
    
         
             
              puts " --pem <path>                         the path to the pem file, if a pem is supplied the server defaults to gateway.push.apple.com:2195"
         
     | 
| 
      
 16 
     | 
    
         
            +
              puts " --pem-passphrase <passphrase>        the pem passphrase"
         
     | 
| 
       16 
17 
     | 
    
         
             
              puts " --alert <message>                    the message to send"
         
     | 
| 
       17 
18 
     | 
    
         
             
              puts " --sound <default>                    the sound to play, defaults to 'default'"
         
     | 
| 
       18 
19 
     | 
    
         
             
              puts " --badge <number>                     the badge number"
         
     | 
| 
       19 
     | 
    
         
            -
              puts " --custom <json string>               a custom json string to be added to the main object" 
     | 
| 
      
 20 
     | 
    
         
            +
              puts " --custom <json string>               a custom json string to be added to the main object"
         
     | 
| 
       20 
21 
     | 
    
         
             
              puts " --b64-token <token>                  a base 64 encoded device token"
         
     | 
| 
       21 
     | 
    
         
            -
              puts " --hex-token <token>                  a hex encoded device token" 
     | 
| 
      
 22 
     | 
    
         
            +
              puts " --hex-token <token>                  a hex encoded device token"
         
     | 
| 
       22 
23 
     | 
    
         
             
              puts " --help                               this message"
         
     | 
| 
       23 
24 
     | 
    
         
             
            end
         
     | 
| 
       24 
25 
     | 
    
         | 
| 
         @@ -26,10 +27,11 @@ opts = GetoptLong.new( 
     | 
|
| 
       26 
27 
     | 
    
         
             
              ["--server", "-s", GetoptLong::REQUIRED_ARGUMENT],
         
     | 
| 
       27 
28 
     | 
    
         
             
              ["--port", "-p", GetoptLong::REQUIRED_ARGUMENT],
         
     | 
| 
       28 
29 
     | 
    
         
             
              ["--pem", "-c", GetoptLong::REQUIRED_ARGUMENT],
         
     | 
| 
      
 30 
     | 
    
         
            +
              ["--pem-passphrase", "-C", GetoptLong::REQUIRED_ARGUMENT],
         
     | 
| 
       29 
31 
     | 
    
         
             
              ["--alert", "-a", GetoptLong::REQUIRED_ARGUMENT],
         
     | 
| 
       30 
32 
     | 
    
         
             
              ["--sound", "-S", GetoptLong::REQUIRED_ARGUMENT],
         
     | 
| 
       31 
33 
     | 
    
         
             
              ["--badge", "-b", GetoptLong::REQUIRED_ARGUMENT],
         
     | 
| 
       32 
     | 
    
         
            -
              ["--custom", "-j", GetoptLong::REQUIRED_ARGUMENT], 
     | 
| 
      
 34 
     | 
    
         
            +
              ["--custom", "-j", GetoptLong::REQUIRED_ARGUMENT],
         
     | 
| 
       33 
35 
     | 
    
         
             
              ["--b64-token", "-B", GetoptLong::REQUIRED_ARGUMENT],
         
     | 
| 
       34 
36 
     | 
    
         
             
              ["--hex-token", "-H", GetoptLong::REQUIRED_ARGUMENT],
         
     | 
| 
       35 
37 
     | 
    
         
             
              ["--help", "-h", GetoptLong::NO_ARGUMENT]
         
     | 
| 
         @@ -48,6 +50,8 @@ opts.each do |opt, arg| 
     | 
|
| 
       48 
50 
     | 
    
         
             
                ApnServer::Config.port = arg.to_i
         
     | 
| 
       49 
51 
     | 
    
         
             
              when '--pem'
         
     | 
| 
       50 
52 
     | 
    
         
             
                ApnServer::Config.pem = arg
         
     | 
| 
      
 53 
     | 
    
         
            +
              when '--pem-passphrase'
         
     | 
| 
      
 54 
     | 
    
         
            +
                ApnServer::Config.password = arg
         
     | 
| 
       51 
55 
     | 
    
         
             
              when '--alert'
         
     | 
| 
       52 
56 
     | 
    
         
             
                notification.alert = arg
         
     | 
| 
       53 
57 
     | 
    
         
             
              when '--sound'
         
     | 
| 
         @@ -55,16 +59,16 @@ opts.each do |opt, arg| 
     | 
|
| 
       55 
59 
     | 
    
         
             
              when '--badge'
         
     | 
| 
       56 
60 
     | 
    
         
             
                notification.badge = arg.to_i
         
     | 
| 
       57 
61 
     | 
    
         
             
              when '--custom'
         
     | 
| 
       58 
     | 
    
         
            -
                notification.custom = arg
         
     | 
| 
      
 62 
     | 
    
         
            +
                notification.custom = ActiveSupport::JSON.decode(arg)
         
     | 
| 
       59 
63 
     | 
    
         
             
              when '--b64-token'
         
     | 
| 
       60 
64 
     | 
    
         
             
                notification.device_token = Base64::decode64(arg)
         
     | 
| 
       61 
65 
     | 
    
         
             
              when '--hex-token'
         
     | 
| 
       62 
     | 
    
         
            -
                notification.device_token  = arg. 
     | 
| 
      
 66 
     | 
    
         
            +
                notification.device_token  = arg.scan(/[0-9a-f][0-9a-f]/).map {|s| s.hex.chr}.join
         
     | 
| 
       63 
67 
     | 
    
         
             
              end
         
     | 
| 
       64 
68 
     | 
    
         
             
            end
         
     | 
| 
       65 
69 
     | 
    
         | 
| 
       66 
70 
     | 
    
         
             
            if notification.device_token.nil?
         
     | 
| 
       67 
     | 
    
         
            -
              usage 
     | 
| 
      
 71 
     | 
    
         
            +
              usage
         
     | 
| 
       68 
72 
     | 
    
         
             
              exit
         
     | 
| 
       69 
73 
     | 
    
         
             
            else
         
     | 
| 
       70 
74 
     | 
    
         
             
              notification.push
         
     | 
    
        data/bin/apnserverd
    CHANGED
    
    | 
         @@ -5,24 +5,28 @@ require 'getoptlong' 
     | 
|
| 
       5 
5 
     | 
    
         
             
            require 'rubygems'
         
     | 
| 
       6 
6 
     | 
    
         
             
            require 'daemons'
         
     | 
| 
       7 
7 
     | 
    
         
             
            require 'apnserver'
         
     | 
| 
      
 8 
     | 
    
         
            +
            require 'apnserver/server'
         
     | 
| 
       8 
9 
     | 
    
         | 
| 
       9 
10 
     | 
    
         
             
            def usage
         
     | 
| 
       10 
11 
     | 
    
         
             
              puts "Usage: apnserverd [switches] --pem <path>"
         
     | 
| 
      
 12 
     | 
    
         
            +
              puts " --pem-passphrase <passphrase>        pem passphrase"
         
     | 
| 
       11 
13 
     | 
    
         
             
              puts " --bind-address [0.0.0.0]             bind address of proxy"
         
     | 
| 
       12 
14 
     | 
    
         
             
              puts " --proxy-port [22195]                 port proxy listens on"
         
     | 
| 
       13 
15 
     | 
    
         
             
              puts " --server <gateway.push.apple.com>    the apn server to send messages to"
         
     | 
| 
       14 
16 
     | 
    
         
             
              puts " --port <2195>                        the port of the apn server"
         
     | 
| 
      
 17 
     | 
    
         
            +
              puts " --pid </var/run/apnserverd.pid       the path to store the pid"
         
     | 
| 
      
 18 
     | 
    
         
            +
              puts " --log </var/log/apnserverd.log       the path to store the log"
         
     | 
| 
      
 19 
     | 
    
         
            +
              puts " --daemon                             to daemonize the server"
         
     | 
| 
       15 
20 
     | 
    
         
             
              puts " --help                               this message"
         
     | 
| 
       16 
21 
     | 
    
         
             
            end
         
     | 
| 
       17 
22 
     | 
    
         | 
| 
       18 
23 
     | 
    
         
             
            def daemonize
         
     | 
| 
       19 
     | 
    
         
            -
              Daemonize.daemonize( 
     | 
| 
       20 
     | 
    
         
            -
              @pid_file  
     | 
| 
       21 
     | 
    
         
            -
              open(@pid_file,"w") {|f| f.write(Process.pid) } # copied from mongrel
         
     | 
| 
      
 24 
     | 
    
         
            +
              Daemonize.daemonize(@log_file, 'apnserverd')
         
     | 
| 
      
 25 
     | 
    
         
            +
              open(@pid_file,"w") { |f| f.write(Process.pid) }
         
     | 
| 
       22 
26 
     | 
    
         
             
              open(@pid_file,"w") do |f|
         
     | 
| 
       23 
27 
     | 
    
         
             
                f.write(Process.pid)
         
     | 
| 
       24 
28 
     | 
    
         
             
                File.chmod(0644, @pid_file)
         
     | 
| 
       25 
     | 
    
         
            -
              end 
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
       26 
30 
     | 
    
         
             
            end
         
     | 
| 
       27 
31 
     | 
    
         | 
| 
       28 
32 
     | 
    
         
             
            opts = GetoptLong.new(
         
     | 
| 
         @@ -30,7 +34,10 @@ opts = GetoptLong.new( 
     | 
|
| 
       30 
34 
     | 
    
         
             
              ["--proxy-port", "-P", GetoptLong::REQUIRED_ARGUMENT],
         
     | 
| 
       31 
35 
     | 
    
         
             
              ["--server", "-s", GetoptLong::REQUIRED_ARGUMENT],
         
     | 
| 
       32 
36 
     | 
    
         
             
              ["--port", "-p", GetoptLong::REQUIRED_ARGUMENT],
         
     | 
| 
      
 37 
     | 
    
         
            +
              ["--pid", "-i", GetoptLong::REQUIRED_ARGUMENT],
         
     | 
| 
      
 38 
     | 
    
         
            +
              ["--log", "-l", GetoptLong::REQUIRED_ARGUMENT],
         
     | 
| 
       33 
39 
     | 
    
         
             
              ["--pem", "-c", GetoptLong::REQUIRED_ARGUMENT],
         
     | 
| 
      
 40 
     | 
    
         
            +
              ["--pem-passphrase", "-C", GetoptLong::REQUIRED_ARGUMENT],
         
     | 
| 
       34 
41 
     | 
    
         
             
              ["--help", "-h", GetoptLong::NO_ARGUMENT],
         
     | 
| 
       35 
42 
     | 
    
         
             
              ["--daemon", "-d", GetoptLong::NO_ARGUMENT]
         
     | 
| 
       36 
43 
     | 
    
         
             
            )
         
     | 
| 
         @@ -40,22 +47,32 @@ proxy_port = 22195 
     | 
|
| 
       40 
47 
     | 
    
         
             
            host = 'gateway.push.apple.com'
         
     | 
| 
       41 
48 
     | 
    
         
             
            port = 2195
         
     | 
| 
       42 
49 
     | 
    
         
             
            pem = nil
         
     | 
| 
      
 50 
     | 
    
         
            +
            pem_passphrase = nil
         
     | 
| 
      
 51 
     | 
    
         
            +
            @pid_file = '/var/run/apnserverd.pid'
         
     | 
| 
      
 52 
     | 
    
         
            +
            @log_file = '/var/log/apnserverd.log'
         
     | 
| 
       43 
53 
     | 
    
         
             
            daemon = false
         
     | 
| 
       44 
54 
     | 
    
         | 
| 
       45 
55 
     | 
    
         
             
            opts.each do |opt, arg|
         
     | 
| 
       46 
56 
     | 
    
         
             
              case opt
         
     | 
| 
       47 
57 
     | 
    
         
             
              when '--help'
         
     | 
| 
       48 
58 
     | 
    
         
             
                usage
         
     | 
| 
      
 59 
     | 
    
         
            +
                exit 1
         
     | 
| 
       49 
60 
     | 
    
         
             
              when '--bind-address'
         
     | 
| 
       50 
61 
     | 
    
         
             
                bind_address = arg
         
     | 
| 
       51 
62 
     | 
    
         
             
              when '--proxy-port'
         
     | 
| 
       52 
63 
     | 
    
         
             
                proxy_port = arg.to_i
         
     | 
| 
       53 
64 
     | 
    
         
             
              when '--server'
         
     | 
| 
       54 
     | 
    
         
            -
             
     | 
| 
      
 65 
     | 
    
         
            +
                host = arg
         
     | 
| 
       55 
66 
     | 
    
         
             
              when '--port'
         
     | 
| 
       56 
     | 
    
         
            -
             
     | 
| 
      
 67 
     | 
    
         
            +
                port = arg.to_i
         
     | 
| 
      
 68 
     | 
    
         
            +
              when '--pid'
         
     | 
| 
      
 69 
     | 
    
         
            +
                @pid_file = arg
         
     | 
| 
      
 70 
     | 
    
         
            +
              when '--log'
         
     | 
| 
      
 71 
     | 
    
         
            +
                @log_file = arg
         
     | 
| 
       57 
72 
     | 
    
         
             
              when '--pem'
         
     | 
| 
       58 
73 
     | 
    
         
             
                pem = arg
         
     | 
| 
      
 74 
     | 
    
         
            +
              when '--pem-passphrase'
         
     | 
| 
      
 75 
     | 
    
         
            +
                pem_passphrase = arg
         
     | 
| 
       59 
76 
     | 
    
         
             
              when '--daemon'
         
     | 
| 
       60 
77 
     | 
    
         
             
                daemon = true
         
     | 
| 
       61 
78 
     | 
    
         
             
              end
         
     | 
| 
         @@ -69,5 +86,6 @@ else 
     | 
|
| 
       69 
86 
     | 
    
         
             
              server = ApnServer::Server.new(pem, bind_address, proxy_port)
         
     | 
| 
       70 
87 
     | 
    
         
             
              server.client.host = host
         
     | 
| 
       71 
88 
     | 
    
         
             
              server.client.port = port
         
     | 
| 
      
 89 
     | 
    
         
            +
              server.client.password = pem_passphrase
         
     | 
| 
       72 
90 
     | 
    
         
             
              server.start!
         
     | 
| 
       73 
91 
     | 
    
         
             
            end
         
     | 
    
        data/bin/apnserverd.fedora.init
    CHANGED
    
    | 
         
            File without changes
         
     | 
| 
         @@ -0,0 +1,116 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #! /bin/sh
         
     | 
| 
      
 2 
     | 
    
         
            +
            ### BEGIN INIT INFO
         
     | 
| 
      
 3 
     | 
    
         
            +
            # Provides:          apnserverd
         
     | 
| 
      
 4 
     | 
    
         
            +
            # Required-Start:    $remote_fs
         
     | 
| 
      
 5 
     | 
    
         
            +
            # Required-Stop:     $remote_fs
         
     | 
| 
      
 6 
     | 
    
         
            +
            # Default-Start:     2 3 4 5
         
     | 
| 
      
 7 
     | 
    
         
            +
            # Default-Stop:      0 1 6
         
     | 
| 
      
 8 
     | 
    
         
            +
            # Short-Description: Apple Push Notification Server Daemon
         
     | 
| 
      
 9 
     | 
    
         
            +
            ### END INIT INFO
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            # Author: Philipp Schmid <philipp.schmid@openresearch.com>
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            PATH=/sbin:/usr/sbin:/bin:/usr/bin
         
     | 
| 
      
 14 
     | 
    
         
            +
            DESC="Apple Push Notification Server Daemon"
         
     | 
| 
      
 15 
     | 
    
         
            +
            NAME=apnserverd
         
     | 
| 
      
 16 
     | 
    
         
            +
            DAEMON=/usr/bin/$NAME
         
     | 
| 
      
 17 
     | 
    
         
            +
            PEMPATH=""
         
     | 
| 
      
 18 
     | 
    
         
            +
            DAEMON_ARGS="--daemon --pem $PEMPATH"
         
     | 
| 
      
 19 
     | 
    
         
            +
            PIDFILE=/var/run/$NAME.pid
         
     | 
| 
      
 20 
     | 
    
         
            +
            SCRIPTNAME=/etc/init.d/$NAME
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            # Exit if the package is not installed
         
     | 
| 
      
 23 
     | 
    
         
            +
            [ -x "$DAEMON" ] || exit 0
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            # Load the VERBOSE setting and other rcS variables
         
     | 
| 
      
 26 
     | 
    
         
            +
            . /lib/init/vars.sh
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
            # Define LSB log_* functions.
         
     | 
| 
      
 29 
     | 
    
         
            +
            # Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
         
     | 
| 
      
 30 
     | 
    
         
            +
            . /lib/lsb/init-functions
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            #
         
     | 
| 
      
 33 
     | 
    
         
            +
            # Function that starts the daemon/service
         
     | 
| 
      
 34 
     | 
    
         
            +
            #
         
     | 
| 
      
 35 
     | 
    
         
            +
            do_start()
         
     | 
| 
      
 36 
     | 
    
         
            +
            {
         
     | 
| 
      
 37 
     | 
    
         
            +
            	# Return
         
     | 
| 
      
 38 
     | 
    
         
            +
            	#   0 if daemon has been started
         
     | 
| 
      
 39 
     | 
    
         
            +
            	#   1 if daemon was already running
         
     | 
| 
      
 40 
     | 
    
         
            +
            	#   2 if daemon could not be started
         
     | 
| 
      
 41 
     | 
    
         
            +
            	start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
         
     | 
| 
      
 42 
     | 
    
         
            +
            		|| return 1
         
     | 
| 
      
 43 
     | 
    
         
            +
            	start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
         
     | 
| 
      
 44 
     | 
    
         
            +
            		$DAEMON_ARGS \
         
     | 
| 
      
 45 
     | 
    
         
            +
            		|| return 2
         
     | 
| 
      
 46 
     | 
    
         
            +
            }
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
            #
         
     | 
| 
      
 49 
     | 
    
         
            +
            # Function that stops the daemon/service
         
     | 
| 
      
 50 
     | 
    
         
            +
            #
         
     | 
| 
      
 51 
     | 
    
         
            +
            do_stop()
         
     | 
| 
      
 52 
     | 
    
         
            +
            {
         
     | 
| 
      
 53 
     | 
    
         
            +
            	# Return
         
     | 
| 
      
 54 
     | 
    
         
            +
            	#   0 if daemon has been stopped
         
     | 
| 
      
 55 
     | 
    
         
            +
            	#   1 if daemon was already stopped
         
     | 
| 
      
 56 
     | 
    
         
            +
            	#   2 if daemon could not be stopped
         
     | 
| 
      
 57 
     | 
    
         
            +
            	#   other if a failure occurred
         
     | 
| 
      
 58 
     | 
    
         
            +
            	start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
         
     | 
| 
      
 59 
     | 
    
         
            +
            	RETVAL="$?"
         
     | 
| 
      
 60 
     | 
    
         
            +
            	[ "$RETVAL" = 2 ] && return 2
         
     | 
| 
      
 61 
     | 
    
         
            +
            	# Wait for children to finish too if this is a daemon that forks
         
     | 
| 
      
 62 
     | 
    
         
            +
            	# and if the daemon is only ever run from this initscript.
         
     | 
| 
      
 63 
     | 
    
         
            +
            	# If the above conditions are not satisfied then add some other code
         
     | 
| 
      
 64 
     | 
    
         
            +
            	# that waits for the process to drop all resources that could be
         
     | 
| 
      
 65 
     | 
    
         
            +
            	# needed by services started subsequently.  A last resort is to
         
     | 
| 
      
 66 
     | 
    
         
            +
            	# sleep for some time.
         
     | 
| 
      
 67 
     | 
    
         
            +
            	start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
         
     | 
| 
      
 68 
     | 
    
         
            +
            	[ "$?" = 2 ] && return 2
         
     | 
| 
      
 69 
     | 
    
         
            +
            	# Many daemons don't delete their pidfiles when they exit.
         
     | 
| 
      
 70 
     | 
    
         
            +
            	rm -f $PIDFILE
         
     | 
| 
      
 71 
     | 
    
         
            +
            	return "$RETVAL"
         
     | 
| 
      
 72 
     | 
    
         
            +
            }
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
            case "$1" in
         
     | 
| 
      
 76 
     | 
    
         
            +
              start)
         
     | 
| 
      
 77 
     | 
    
         
            +
            	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
         
     | 
| 
      
 78 
     | 
    
         
            +
            	do_start
         
     | 
| 
      
 79 
     | 
    
         
            +
            	case "$?" in
         
     | 
| 
      
 80 
     | 
    
         
            +
            		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
         
     | 
| 
      
 81 
     | 
    
         
            +
            		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
         
     | 
| 
      
 82 
     | 
    
         
            +
            	esac
         
     | 
| 
      
 83 
     | 
    
         
            +
            	;;
         
     | 
| 
      
 84 
     | 
    
         
            +
              stop)
         
     | 
| 
      
 85 
     | 
    
         
            +
            	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
         
     | 
| 
      
 86 
     | 
    
         
            +
            	do_stop
         
     | 
| 
      
 87 
     | 
    
         
            +
            	case "$?" in
         
     | 
| 
      
 88 
     | 
    
         
            +
            		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
         
     | 
| 
      
 89 
     | 
    
         
            +
            		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
         
     | 
| 
      
 90 
     | 
    
         
            +
            	esac
         
     | 
| 
      
 91 
     | 
    
         
            +
            	;;
         
     | 
| 
      
 92 
     | 
    
         
            +
              restart|force-reload)
         
     | 
| 
      
 93 
     | 
    
         
            +
            	log_daemon_msg "Restarting $DESC" "$NAME"
         
     | 
| 
      
 94 
     | 
    
         
            +
            	do_stop
         
     | 
| 
      
 95 
     | 
    
         
            +
            	case "$?" in
         
     | 
| 
      
 96 
     | 
    
         
            +
            	  0|1)
         
     | 
| 
      
 97 
     | 
    
         
            +
            		do_start
         
     | 
| 
      
 98 
     | 
    
         
            +
            		case "$?" in
         
     | 
| 
      
 99 
     | 
    
         
            +
            			0) log_end_msg 0 ;;
         
     | 
| 
      
 100 
     | 
    
         
            +
            			1) log_end_msg 1 ;; # Old process is still running
         
     | 
| 
      
 101 
     | 
    
         
            +
            			*) log_end_msg 1 ;; # Failed to start
         
     | 
| 
      
 102 
     | 
    
         
            +
            		esac
         
     | 
| 
      
 103 
     | 
    
         
            +
            		;;
         
     | 
| 
      
 104 
     | 
    
         
            +
            	  *)
         
     | 
| 
      
 105 
     | 
    
         
            +
            	  	# Failed to stop
         
     | 
| 
      
 106 
     | 
    
         
            +
            		log_end_msg 1
         
     | 
| 
      
 107 
     | 
    
         
            +
            		;;
         
     | 
| 
      
 108 
     | 
    
         
            +
            	esac
         
     | 
| 
      
 109 
     | 
    
         
            +
            	;;
         
     | 
| 
      
 110 
     | 
    
         
            +
              *)
         
     | 
| 
      
 111 
     | 
    
         
            +
            	echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
         
     | 
| 
      
 112 
     | 
    
         
            +
            	exit 3
         
     | 
| 
      
 113 
     | 
    
         
            +
            	;;
         
     | 
| 
      
 114 
     | 
    
         
            +
            esac
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
            :
         
     | 
    
        data/lib/apnserver.rb
    CHANGED
    
    
    
        data/lib/apnserver/client.rb
    CHANGED
    
    | 
         @@ -3,40 +3,39 @@ require 'socket' 
     | 
|
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            module ApnServer
         
     | 
| 
       5 
5 
     | 
    
         
             
              class Client
         
     | 
| 
       6 
     | 
    
         
            -
                
         
     | 
| 
       7 
6 
     | 
    
         
             
                attr_accessor :pem, :host, :port, :password
         
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
       9 
8 
     | 
    
         
             
                def initialize(pem, host = 'gateway.push.apple.com', port = 2195, pass = nil)
         
     | 
| 
       10 
9 
     | 
    
         
             
                  @pem, @host, @port, @password = pem, host, port, pass
         
     | 
| 
       11 
10 
     | 
    
         
             
                end
         
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
       13 
12 
     | 
    
         
             
                def connect!
         
     | 
| 
       14 
13 
     | 
    
         
             
                  raise "The path to your pem file is not set." unless self.pem
         
     | 
| 
       15 
14 
     | 
    
         
             
                  raise "The path to your pem file does not exist!" unless File.exist?(self.pem)
         
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
       17 
16 
     | 
    
         
             
                  @context      = OpenSSL::SSL::SSLContext.new
         
     | 
| 
       18 
17 
     | 
    
         
             
                  @context.cert = OpenSSL::X509::Certificate.new(File.read(self.pem))
         
     | 
| 
       19 
18 
     | 
    
         
             
                  @context.key  = OpenSSL::PKey::RSA.new(File.read(self.pem), self.password)
         
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
       21 
20 
     | 
    
         
             
                  @sock         = TCPSocket.new(self.host, self.port.to_i)
         
     | 
| 
       22 
21 
     | 
    
         
             
                  @ssl          = OpenSSL::SSL::SSLSocket.new(@sock, @context)
         
     | 
| 
       23 
22 
     | 
    
         
             
                  @ssl.connect
         
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
       25 
24 
     | 
    
         
             
                  return @sock, @ssl
         
     | 
| 
       26 
25 
     | 
    
         
             
                end
         
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
       28 
27 
     | 
    
         
             
                def disconnect!
         
     | 
| 
       29 
28 
     | 
    
         
             
                  @ssl.close
         
     | 
| 
       30 
29 
     | 
    
         
             
                  @sock.close
         
     | 
| 
       31 
30 
     | 
    
         
             
                  @ssl = nil
         
     | 
| 
       32 
31 
     | 
    
         
             
                  @sock = nil
         
     | 
| 
       33 
32 
     | 
    
         
             
                end
         
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
       35 
34 
     | 
    
         
             
                def write(notification)
         
     | 
| 
       36 
     | 
    
         
            -
                   
     | 
| 
      
 35 
     | 
    
         
            +
                  Config.logger.debug "#{Time.now} [#{host}:#{port}] Device: #{notification.device_token.unpack('H*')} sending #{notification.json_payload}"
         
     | 
| 
       37 
36 
     | 
    
         
             
                  @ssl.write(notification.to_bytes)
         
     | 
| 
       38 
37 
     | 
    
         
             
                end
         
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
       40 
39 
     | 
    
         
             
                def connected?
         
     | 
| 
       41 
40 
     | 
    
         
             
                  @ssl
         
     | 
| 
       42 
41 
     | 
    
         
             
                end
         
     |