push-c2dm 0.0.1.pre

Sign up to get free protection for your applications and to get access to all the features.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2012 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # PushC2dm
2
+
3
+ This project rocks and uses MIT-LICENSE.
@@ -0,0 +1,24 @@
1
+ module Push
2
+ module Daemon
3
+ class C2dm
4
+ attr_accessor :configuration
5
+ def initialize(options)
6
+ self.configuration = options
7
+ end
8
+
9
+ def pushconnections
10
+ self.configuration[:connections]
11
+ end
12
+
13
+ def totalconnections
14
+ pushconnections
15
+ end
16
+
17
+ def connectiontype
18
+ C2dmSupport::ConnectionC2dm
19
+ end
20
+
21
+ def stop; end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,90 @@
1
+ module Push
2
+ module Daemon
3
+ module C2dmSupport
4
+ class ConnectionC2dm
5
+ attr_reader :response, :name
6
+ AUTH_URL = "https://www.google.com/accounts/ClientLogin"
7
+ PUSH_URL = "https://android.apis.google.com/c2dm/send"
8
+
9
+ def initialize(provider, i)
10
+ @provider = provider
11
+ @name = "ConnectionC2dm #{i}"
12
+
13
+ @email = @provider.configuration[:email]
14
+ @password = @provider.configuration[:password]
15
+ end
16
+
17
+ def connect
18
+ @auth_token = fetch_auth_token
19
+ @last_use = Time.now
20
+ uri = URI.parse(PUSH_URL)
21
+ @connection = open_http(uri.host, uri.port)
22
+ @connection.start
23
+ Push::Daemon.logger.info("[#{@name}] Connected to #{PUSH_URL}")
24
+ end
25
+
26
+ def write(data)
27
+ @response = notification_request(data)
28
+
29
+ # the response can be one of three codes:
30
+ # 200 (success)
31
+ # 401 (auth failed)
32
+ # 503 (retry later with exponential backoff)
33
+ # see more documentation here: http://code.google.com/android/c2dm/#testing
34
+ if @response.code.eql? "200"
35
+ # look for the header 'Update-Client-Auth' in the response you get after sending
36
+ # a message. It indicates that this is the token to be used for the next message to send.
37
+ @response.header.each_header do |key, value|
38
+ if key.capitalize == "Update-Client-Auth".capitalize
39
+ Push::Daemon.logger.info("[#{@name}] Received new authentication token")
40
+ @auth_token = value
41
+ end
42
+ end
43
+
44
+ elsif @response.code.eql? "401"
45
+ # auth failed. Refresh auth key and requeue
46
+ @auth_token = fetch_auth_token
47
+ @response = notification_request(data)
48
+
49
+ elsif response.code.eql? "503"
50
+ # service un-available.
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ def open_http(host, port)
57
+ http = Net::HTTP.new(host, port)
58
+ http.use_ssl = true
59
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
60
+ return http
61
+ end
62
+
63
+ def fetch_auth_token
64
+ data = "accountType=HOSTED_OR_GOOGLE&Email=#{@email}&Passwd=#{@password}&service=ac2dm&source=push"
65
+ headers = { 'Content-Type' => 'application/x-www-form-urlencoded' }
66
+ uri = URI.parse(AUTH_URL)
67
+ http = open_http(uri.host, uri.port)
68
+ response = http.post(uri.path, data, headers)
69
+ return response.body[/Auth=(.*)/, 1]
70
+ end
71
+
72
+ def notification_request(data)
73
+ headers = { "Authorization" => "GoogleLogin auth=#{@auth_token}",
74
+ "Content-type" => "application/x-www-form-urlencoded",
75
+ "Content-length" => "#{data.length}" }
76
+ uri = URI.parse(PUSH_URL)
77
+
78
+ # Timeout on the http connection is 5 minutes, reconnect after 5 minutes
79
+ if @last_use + 5.minutes < Time.now
80
+ @connection.finish
81
+ @connection.start
82
+ end
83
+ @last_use = Time.now
84
+
85
+ @connection.post(uri.path, data, headers)
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,5 @@
1
+ module Push
2
+ class FeedbackC2dm < Push::Feedback
3
+
4
+ end
5
+ end
@@ -0,0 +1,52 @@
1
+ module Push
2
+ class MessageC2dm < Push::Message
3
+ validates :collapse_key, :presence => true
4
+ # TODO: validates max size -> The message size limit is 1024 bytes.
5
+ # TODO" QuotaExceeded — Too many messages sent by the sender. Retry after a while.
6
+ # TODO: DeviceQuotaExceeded — Too many messages sent by the sender to a specific device. Retry after a while.
7
+
8
+ store :properties, accessors: [:collapse_key, :delay_when_idle, :payload ]
9
+
10
+ def to_message
11
+ as_hash.map{|k, v| "&#{k}=#{URI.escape(v.to_s)}"}.reduce{|k, v| k + v}
12
+ end
13
+
14
+ def use_connection
15
+ Push::Daemon::C2dmSupport::ConnectionC2dm
16
+ end
17
+
18
+ private
19
+
20
+ def as_hash
21
+ json = ActiveSupport::OrderedHash.new
22
+ json['registration_id'] = self.device
23
+ json['collapse_key'] = self.collapse_key
24
+ json['delay_when_idle'] = "1" if self.delay_when_idle == true
25
+ self.payload.each { |k, v| json["data.#{k.to_s}"] = v.to_s } if self.payload
26
+ json
27
+ end
28
+
29
+ def check_for_error(connection)
30
+ response = connection.response
31
+ error_type = response.body[/Error=(.*)/, 1]
32
+ if response.code.eql? "200" and error_type
33
+ error = Push::DeliveryError.new(response.code, id, error_type, "C2DM")
34
+
35
+ # if error_type is one of the following, the registration_id (device) should
36
+ # not be used anymore
37
+ if ["InvalidRegistration", "NotRegistered"].index(error_type)
38
+ with_database_reconnect_and_retry(connection.name) do
39
+ Push::FeedbackC2dm.create!(:failed_at => Time.now, :device => device)
40
+ end
41
+ end
42
+
43
+ Push::Daemon.logger.error("[#{connection.name}] Error received.")
44
+ raise error if error
45
+ elsif !response.code.eql? "200"
46
+ error = Push::DeliveryError.new(response.code, id, response.description, "C2DM")
47
+ Push::Daemon.logger.error("[#{connection.name}] Error received.")
48
+ raise error if error
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,3 @@
1
+ module PushC2dm
2
+ VERSION = "0.0.1.pre"
3
+ end
data/lib/push-c2dm.rb ADDED
@@ -0,0 +1,7 @@
1
+ require 'net/http'
2
+ require 'net/https'
3
+ require 'push-c2dm/version'
4
+ require 'push/message_c2dm'
5
+ require 'push/feedback_c2dm'
6
+ require 'push/daemon/c2dm'
7
+ require 'push/daemon/c2dm_support/connection_c2dm'
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: push-c2dm
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1.pre
5
+ prerelease: 6
6
+ platform: ruby
7
+ authors:
8
+ - Tom Pesman
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-06-15 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: push-core
16
+ requirement: &70243205562300 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - =
20
+ - !ruby/object:Gem::Version
21
+ version: 0.0.1.pre
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70243205562300
25
+ - !ruby/object:Gem::Dependency
26
+ name: sqlite3
27
+ requirement: &70243205561860 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70243205561860
36
+ description: Plugin with C2DM specific push information.
37
+ email:
38
+ - tom@tnux.net
39
+ executables: []
40
+ extensions: []
41
+ extra_rdoc_files: []
42
+ files:
43
+ - lib/push-c2dm.rb
44
+ - lib/push-c2dm/version.rb
45
+ - lib/push/daemon/c2dm.rb
46
+ - lib/push/daemon/c2dm_support/connection_c2dm.rb
47
+ - lib/push/feedback_c2dm.rb
48
+ - lib/push/message_c2dm.rb
49
+ - README.md
50
+ - MIT-LICENSE
51
+ homepage: https://github.com/tompesman/push-c2dm
52
+ licenses: []
53
+ post_install_message:
54
+ rdoc_options: []
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ! '>'
67
+ - !ruby/object:Gem::Version
68
+ version: 1.3.1
69
+ requirements: []
70
+ rubyforge_project:
71
+ rubygems_version: 1.8.5
72
+ signing_key:
73
+ specification_version: 3
74
+ summary: C2DM (Android) part of the modular push daemon.
75
+ test_files: []