Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feedback support #4

Open
wants to merge 110 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
110 commits
Select commit Hold shift + click to select a range
5c50800
replaced ActiveSupport with Yajl
jeremytregunna Mar 18, 2011
3fb6edc
Fixed #11256615 in pivotal tracker.
jeremytregunna Mar 18, 2011
7816c19
Fixed a bug where reset connections wouldn't be handled properly. Als…
jeremytregunna Mar 18, 2011
699af5d
added convenience method to parse the feedback data
jeremytregunna Mar 18, 2011
a712797
Removed the requirement for the certificate to be a file. Now it's ex…
jeremytregunna Mar 19, 2011
28eb862
Updated dependency information in gemspec
jeremytregunna Mar 21, 2011
a2f7c7e
Able now to pass the key through to the modified apnserver as a file …
jeremytregunna Mar 21, 2011
54a0975
Feedback service now tied in, though we're only printing records we g…
jeremytregunna Mar 21, 2011
44fcec0
Updated feedback code introducing a callback on the server to handle …
jeremytregunna Mar 23, 2011
45971ad
updated README to reflect state of modifications
jeremytregunna Mar 23, 2011
7e6cc6e
added feedback client spec, minimal.
jeremytregunna Mar 23, 2011
cad9fe5
Added beanstalk requirement
jeremytregunna Mar 27, 2011
46f7bd1
Rewrote Server to use beanstalk for input, instead of opening a liste…
jeremytregunna Mar 27, 2011
cede01d
changed server daemon arguments, some don't apply anymore. cleanup of…
jeremytregunna Mar 27, 2011
d73eaa6
Updated README to reflect state of project
jeremytregunna Mar 27, 2011
0e23f12
removed unnecessary files, renaming project to frac-apnserver to avoi…
jeremytregunna Mar 27, 2011
13822af
refactoring of server handle_job
jeremytregunna Mar 27, 2011
bf6b013
packet formation change
jeremytregunna Mar 28, 2011
36dab26
Rename project from apnserver to racoon, to avoid confusion with apns…
jeremytregunna Apr 23, 2011
5e6a60b
stale reference to apnserver
jeremytregunna Apr 23, 2011
f6963fd
leftover h2.
jeremytregunna Apr 23, 2011
7b649e7
pathnames were still showing as apnserver.log/pid
jeremytregunna Apr 23, 2011
056a691
Removed stale .swp, now closing sockets after 18 hours, apple doesn't…
jeremytregunna Apr 23, 2011
5a16680
README.textile reference left over in Rakefile
jeremytregunna Apr 23, 2011
3925b35
added godfile, fixed an exception in server, wrong require in notific…
Apr 23, 2011
6c7f9b7
cleanup of handle_job
jeremytregunna Apr 23, 2011
f3d5aa8
mistake in notification hash example
jeremytregunna Apr 23, 2011
06cfffe
reflecting custom fields a little better
jeremytregunna Apr 23, 2011
2842e1e
gem building
jeremytregunna Apr 24, 2011
42bebf1
changed periodic killing to 20 minutes of inactivity rather than stat…
jeremytregunna Apr 24, 2011
1213785
fixed glitch in server
Apr 24, 2011
0c3b09f
added racoon-send
jeremytregunna Apr 24, 2011
f53252f
version bump
jeremytregunna Apr 24, 2011
6889868
version bump
jeremytregunna Apr 24, 2011
bec1845
Merge branch 'master' of github.com:jeremytregunna/racoon
jeremytregunna Apr 24, 2011
9d0f6dd
Removed unneeded gems from Gemfile
jeremytregunna Apr 24, 2011
772b46d
Removed some code which doesn't make sense for a multiproject apns
jeremytregunna Apr 24, 2011
c7228c2
fixed typographical error indicating json_payload when it should have…
jeremytregunna Apr 24, 2011
62ddd08
added send_at accessor to notification, updated docs accordingly
jeremytregunna Apr 24, 2011
7c7b373
formatting
jeremytregunna Apr 25, 2011
24c2ede
corrected pivotal url
jeremytregunna Apr 25, 2011
bef4364
now support the enhanced push notification format. No longer the basi…
jeremytregunna Apr 26, 2011
e74f423
version bump
jeremytregunna Apr 26, 2011
a0659ce
version bump
jeremytregunna Apr 26, 2011
50e3362
Merge branch 'master' of github.com:jeremytregunna/racoon
jeremytregunna Apr 26, 2011
affabf1
Merge branch 'master' of github.com:jeremytregunna/racoon
jeremytregunna Apr 26, 2011
65ce07d
Merge branch 'master' of github.com:jeremytregunna/racoon
jeremytregunna Apr 26, 2011
18ac2f7
moved create_notification_from_packet to Notification, renamed it cre…
jeremytregunna Apr 26, 2011
c4ffbb7
after talking with apple, we were doing it right before. don't kill t…
jeremytregunna Apr 27, 2011
1601b5f
typo
jeremytregunna Apr 27, 2011
34a0833
debugging
jeremytregunna Apr 27, 2011
f387ad2
debugging
jeremytregunna Apr 27, 2011
8d7a6c9
Merge branch 'master' of kirk.frac.as:/fracas/git/racoon
jeremytregunna Apr 27, 2011
d049842
Merge branch 'master' of kirk.frac.as:/fracas/git/racoon
jeremytregunna Apr 27, 2011
a8282d0
Merge branch 'master' of kirk.frac.as:/fracas/git/racoon
jeremytregunna Apr 27, 2011
e16897f
Merge branch 'master' of kirk.frac.as:/fracas/git/racoon
jeremytregunna Apr 27, 2011
ee43d78
Merge branch 'master' of kirk.frac.as:/fracas/git/racoon
jeremytregunna Apr 27, 2011
9cf5c0f
Merge branch 'master' of kirk.frac.as:/fracas/git/racoon
jeremytregunna Apr 27, 2011
b92b052
urgh
jeremytregunna Apr 27, 2011
32628ef
think this is it
jeremytregunna Apr 27, 2011
1d13f92
removed debugging code, fixed errors
jeremytregunna Apr 27, 2011
18be556
version bump
jeremytregunna Apr 27, 2011
f8a1a7c
Merge branch 'master' of github.com:jeremytregunna/racoon
jeremytregunna Apr 27, 2011
b6aa384
added firehose and worker -- first draft, probably doesn't work right.
jeremytregunna Apr 28, 2011
bb6d043
removing send_at, doesn't make sense with the new pipeline
jeremytregunna Apr 28, 2011
92b9ab2
version bump, 0.5.0pre1
jeremytregunna Apr 28, 2011
1d353f3
just added header
jeremytregunna Apr 28, 2011
2eaafa7
worker bugfix
jeremytregunna Apr 28, 2011
1dbbfa8
firehose bugfix
jeremytregunna Apr 28, 2011
6913c3f
added worker and firehose scripts
jeremytregunna Apr 29, 2011
c838b6c
changed to new packet format
jeremytregunna Apr 29, 2011
9b3bf96
renamed firehose and worker removing the 'd'
jeremytregunna Apr 29, 2011
7b4e021
reflect new name in help messages
jeremytregunna Apr 29, 2011
305626e
removed server, obsoleted by worker and firehose
jeremytregunna Apr 29, 2011
7ae8592
removed racoond, obsoleted by racoon-worker and racoon-firehose
jeremytregunna Apr 29, 2011
59f2d74
moved client to apns/connection
jeremytregunna Apr 29, 2011
5cfd2cb
renamed feedback_client to apns/feedback_connection
jeremytregunna Apr 29, 2011
b243815
just adding a comment
jeremytregunna Apr 29, 2011
059b722
updated dependency information
jeremytregunna Apr 29, 2011
e841f1a
removed racoon.god, added two new godfiles -- one for worker, one for…
Apr 29, 2011
756906e
Merge branch 'master' of kirk.frac.as:/fracas/git/racoon
jeremytregunna Apr 29, 2011
820055e
fixed paths
jeremytregunna Apr 29, 2011
cbb7562
fixed dep issues
Apr 29, 2011
8ad8c50
using yaml instead of json for beanstalk payload
jeremytregunna Apr 29, 2011
887bfaf
switching to yaml
jeremytregunna Apr 29, 2011
75f4b53
bugfix in firehose
jeremytregunna Apr 29, 2011
aa9deb9
spawned process not finding project_hash, just inlining
jeremytregunna Apr 29, 2011
d65113c
getting rid of the spawned process, i just don't understand eventmach…
jeremytregunna Apr 29, 2011
2d174c5
typo
jeremytregunna Apr 29, 2011
e8508dd
fixed connection
jeremytregunna Apr 29, 2011
3283b7c
forgot to delete the job
jeremytregunna Apr 29, 2011
acc9761
version bump & documentation update
jeremytregunna Apr 29, 2011
83115be
added back integration code for feedback service
jeremytregunna Apr 29, 2011
5bde233
added configurable tube arguments, defaulting to 'racoon'
jeremytregunna Apr 29, 2011
1a54ba4
Optimizing architecture -- using ZMQMachine, dropping EventMachine.
jeremytregunna Apr 29, 2011
a86d5b8
removing eventmachine from gemfile
jeremytregunna Apr 29, 2011
3322913
missing call to join
jeremytregunna Apr 29, 2011
1dfe373
typo
jeremytregunna Apr 29, 2011
589925d
made beanstalks an ivar
jeremytregunna Apr 29, 2011
5a73228
startup message modification
jeremytregunna Apr 29, 2011
50f46e1
Updated arguments in godfile
Apr 29, 2011
e4970cf
missing argument
jeremytregunna Apr 29, 2011
6a169a3
forgot one line of code
jeremytregunna Apr 29, 2011
7343938
removing old startup scripts. use supplied godfiles instead, that's w…
jeremytregunna May 1, 2011
ba49e31
now reading errors from socket and calling a block
jeremytregunna May 1, 2011
3d5fe8d
errant end
jeremytregunna May 1, 2011
21d8d50
safety in case error_callback isn't supplied
jeremytregunna May 1, 2011
668cf92
version bump
jeremytregunna May 1, 2011
f471584
changed api in a very minor way. making error_callback an ivar instead
jeremytregunna May 1, 2011
5e1c435
version bump
jeremytregunna May 1, 2011
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
source "http://rubygems.org"

gem "eventmachine"
gem "daemons"
gem "activesupport", ">= 3.0.0"
gem "i18n" # active support whines without this
gem "yajl-ruby"
gem "beanstalk-client"
gem "ffi"
gem "ffi-rzmq"
gem "zmqmachine", :git => "git://github.com/jeremytregunna/zmqmachine.git"

group :spec do
gem "rspec"
end
end
24 changes: 18 additions & 6 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
GIT
remote: git://github.com/jeremytregunna/zmqmachine.git
revision: fb39523eafa41127d3042f2bbe65c92fc451d412
specs:
zmqmachine (0.4.0)
ffi-rzmq (>= 0.7.0)

GEM
remote: http://rubygems.org/
specs:
activesupport (3.0.3)
beanstalk-client (1.1.0)
daemons (1.0.10)
diff-lcs (1.1.2)
eventmachine (0.12.10)
i18n (0.5.0)
ffi (1.0.7)
rake (>= 0.8.7)
ffi-rzmq (0.8.0)
rake (0.8.7)
rspec (2.3.0)
rspec-core (~> 2.3.0)
rspec-expectations (~> 2.3.0)
Expand All @@ -14,13 +23,16 @@ GEM
rspec-expectations (2.3.0)
diff-lcs (~> 1.1.2)
rspec-mocks (2.3.0)
yajl-ruby (0.8.1)

PLATFORMS
ruby

DEPENDENCIES
activesupport (>= 3.0.0)
beanstalk-client
daemons
eventmachine
i18n
ffi
ffi-rzmq
rspec
yajl-ruby
zmqmachine!
201 changes: 201 additions & 0 deletions README.mdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
# Racoon push notification server

This project started off as a fork of [apnserver](https://github.com/bpoweski/apnserver). It
has since taken on a different path. How does it differ from apnserver? By a few key points:

1. It implements the APNS feedback service;
2. Uses Yajl for JSON encoding/decoding rather than ActiveSupport;
3. Expects certificates as strings instead of paths to files;
4. Does not assume there is only one certificate (read: supports multiple projects); and
5. Receives packets containing notifications from beanstalkd instead of a listening socket;
6. Operates on a distributed architecture (many parallel workers, one firehose).

The above changes were made because of the need to replace an existing APNs provider with something
more robust, and better suited to scaling upwards. This APNs provider had a couple requirements:

1. Support fully the APNs protocol (including feedback)
2. Scale outwards horizontally
3. Support multiple projects

It should be noted that the development of this project is independent of the work bpoweski
is doing on apnserver. If you're looking for that project, [go here](https://github.com/bpoweski/apnserver).

## BIT FAT DEPENDENCY WARNING

Since version 0.6.0, Racoon uses ZMQMachine. However, the mainline ZMQMachine does not support PUSH/PULL
sockets as of the time I wrote this (probably still the same way, else I'd have removed this by now).
As such, I strongly urge you to [fork this repository](https://github.com/jeremytregunna/zmqmachine) and install it before installing racoon.

## Description

Racoon consists of a firehose, which maintains the connections to Apple's APNs service. It also
consists of a worker, which works on a beanstalk tube to pop notifications off and process them,
before sending them off to the firehose. You can run many workers, they all run in parallel to
one another. Additionally, it includes a command line tool to send (test) the system.

At this time, Racoon only supports Apple's APNs service.

## Remaining Tasks & Issues

You can see progress by looking at the [issue tracker](https://www.pivotaltracker.com/projects/279053).

## Preparing Certificates

Certificates must be prepared before they can be used with racoon. Unfortunately, Apple
gives us *.p12* files instead of *.pem* files. As such, we need to convert them. This
can be accomplished by dropping to the command line and running this command:

<pre>
$ openssl pkcs12 -in cert.p12 -out cert.pem -nodes -clcerts
</pre>

This will generate a file suitable for use with this daemon, called *cert.pem*. If you're
using frac.as, this is the file you would upload to the web service.

If you're not using frac.as, then the contents of this file are what you need to use as
your certificate, not the path to the file.

## Firehose

The firehose sits at the end of the pipeline. All the workers deliver messages to this
part of racoon. Think of it as the drain in your sink.

<pre>
Usage: racoon-firehose [switches]
--pid </var/run/racoon-firehose.pid> the path to store the pid
--log </var/log/racoon-firehosed.log> the path to store the log
--daemon to daemonize the server
--help this message
</pre>

## Worker

The worker is the part of the system which interacts with a beanstalk cluster. Each worker
can talk to more than one beanstalk server, thus forming the "cluster". Since beanstalk
clustering is all done client side, it's not a traditional cluster, but I'm going to call
it that way anyway.

The worker pops items that are ready off of the beanstalk cluster. It grabs those packets,
constructs a message out of it, and then forms another packet, suitable for sending to
Apple, before sending that packet to the firehose.

You may run as many workers as your little heart desires. Keep in mind however, there will
come a point when having only one firehose is not suitable to handle the amount of traffic
you will be passing through from the workers. At this point, a second firehose will need
to be started. I doubt anyone will ever be processing enough messages a second to warrant
a second firehose.

<pre>
Usage: racoon-worker [switches]
--beanstalk <127.0.0.1:11300> csv list of ip:port for beanstalk servers
--pid </var/run/racoon-worker.pid> the path to store the pid
--log </var/log/racoon-worker.log> the path to store the log
--daemon to daemonize the server
--help this message
</pre>

It should be noted that the worker's `--beanstalk` parameter requires comma separated values
in `IP:port` pairings. Where `IP` is either an IP address, or a hostname to a host running a
beanstalkd server on the associated port `port`. In the future, I will create a config file
instead of having to specify this information on the command line each time. My apologies for
the inconvenience.

## Sender

The sender is the program used to form a packet, place it on beanstalk for racoon to consume.
It is useful during testing.

<pre>
Usage: racoon-send [switches] (--b64-token | --hex-token) <token>
--beanstalk <127.0.0.1:11300> csv of ip:port for beanstalk servers
--pem <path> the path to the pem file, if a pem is supplied the server defaults to gateway.push.apple.com:2195
--alert <message> the message to send
--sound <default> the sound to play, defaults to 'default'
--badge <number> the badge number
--custom <json string> a custom json string to be added to the main object
--b64-token <token> a base 64 encoded device token
--hex-token <token> a hex encoded device token
--help this message
</pre>

## Preparing packets to place on beanstalk

Until an API can be built that you can tie into with your own applications, please take care
to construct your notifications as YAML payload with the following format. I will use ruby
syntax for this example:

```ruby
{
:project => { :name => "My awesome app", :certificate => "...", :sandbox => true },
:identifier => 12345,
:notification => { :aps => { :alert => "text",
:sound => "default",
:badge => 1,
:custom => { ... }
}
},
:device_token => "..."
}
```

A few key points need to be raised here. For starters, the `sandbox` key should only be true if
you desire to work in the sandbox, and your `certificate` contains the text of your development
certificate.

Secondly, the `identifier` must be a unique 32-bit number identifying your message should you
choose to want useful error messages. (This feature is not presently written, as such, you can
supply anything you want, just make sure it falls within the range of `0` to `4294967295`.

The `notification` key represents the payload we'll send to Apple. The `custom` key must be
present if you intend to send custom data. Note however, that `custom` will be removed, and the
items you place in its hash will be substituted in with the payload when the message is passed
to Apple. As such, if you want a custom key -> value pair of: `"foo" => "bar"`, you would ensure
you have: `:custom => { "foo" => "bar" }` in the notification. Your application should just look
for "foo" in the payload delivered to the app.

Finally, the ```device_token``` is a binary encoded representation of your devices token. Your
app gets it in hex, please ensure you convert it to binary before sending it to beanstalk.

TODO: Document new way of handling scheduling notifications in the future. Abstract beanstalk
away from users of the library, give them a proper client interface to use instead.

## Installation

Racoon is hosted on [rubygems](https://rubygems.org/gems/racoon)

<pre>
$ gem install racoon
</pre>

Adding racoon to your Rails application

```ruby
gem 'racoon'
```

## License

(The MIT License)

Copyright (c) 2011 Jeremy Tregunna
Copyright (c) 2011 Ben Poweski

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Loading