pusher-client 0.2.1 → 0.2.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.
@@ -6,7 +6,7 @@ require 'pp'
6
6
 
7
7
  APP_KEY = ENV['PUSHER_KEY'] # || "YOUR_APPLICATION_KEY"
8
8
 
9
- PusherClient.logger = Logger.new('/dev/null')
9
+ PusherClient.logger = Logger.new(STDOUT)
10
10
  socket = PusherClient::Socket.new(APP_KEY)
11
11
 
12
12
  # Subscribe to a channel
@@ -1,21 +1,24 @@
1
1
  require 'json'
2
+ require 'hmac-sha2'
3
+ require 'digest/md5'
2
4
 
3
5
  module PusherClient
4
6
  class Socket
5
-
7
+
6
8
  # Mimick the JavaScript client
7
- CLIENT_ID = 'js'
8
- VERSION = '1.7.1'
9
+ CLIENT_ID = 'pusher-ruby-client'
10
+ VERSION = '0.2.2'
11
+ PROTOCOL = '5'
9
12
 
10
13
  attr_accessor :encrypted, :secure
11
14
  attr_reader :path, :connected, :channels, :global_channel, :socket_id
12
15
 
13
16
  def initialize(application_key, options={})
14
-
15
17
  raise ArgumentError if (!application_key.is_a?(String) || application_key.size < 1)
16
18
 
17
- @path = "/app/#{application_key}?client=#{CLIENT_ID}&version=#{VERSION}"
19
+ @path = "/app/#{application_key}?client=#{CLIENT_ID}&version=#{VERSION}&protocol=#{PROTOCOL}"
18
20
  @key = application_key
21
+ @secret = options[:secret]
19
22
  @socket_id = nil
20
23
  @channels = Channels.new
21
24
  @global_channel = Channel.new('pusher_global_channel')
@@ -25,8 +28,9 @@ module PusherClient
25
28
  @encrypted = options[:encrypted] || false
26
29
 
27
30
  bind('pusher:connection_established') do |data|
31
+ socket = JSON.parse(data)
28
32
  @connected = true
29
- @socket_id = data['socket_id']
33
+ @socket_id = socket['socket_id']
30
34
  subscribe_all
31
35
  end
32
36
 
@@ -35,7 +39,7 @@ module PusherClient
35
39
  end
36
40
 
37
41
  bind('pusher:error') do |data|
38
- PusherClient.logger.fatal("Pusher : error : #{data.message}")
42
+ PusherClient.logger.fatal("Pusher : error : #{data.inspect}")
39
43
  end
40
44
  end
41
45
 
@@ -48,7 +52,8 @@ module PusherClient
48
52
  PusherClient.logger.debug("Pusher : connecting : #{url}")
49
53
 
50
54
  @connection_thread = Thread.new {
51
- @connection = WebSocket.new(url)
55
+ options = {:ssl => @encrypted || @secure}
56
+ @connection = WebSocket.new(url, options)
52
57
  PusherClient.logger.debug "Websocket connected"
53
58
  loop do
54
59
  msg = @connection.receive[0]
@@ -77,13 +82,12 @@ module PusherClient
77
82
  end
78
83
  end
79
84
 
80
- def subscribe(channel_name)
85
+ def subscribe(channel_name, user_id = nil)
86
+ @user_data = {:user_id => user_id}.to_json unless user_id.nil?
87
+
81
88
  channel = @channels << channel_name
82
89
  if @connected
83
- send_event('pusher:subscribe', {
84
- 'channel' => channel.name
85
- })
86
- channel.acknowledge_subscription(nil)
90
+ authorize(channel, method(:authorize_callback))
87
91
  end
88
92
  return channel
89
93
  end
@@ -112,13 +116,55 @@ module PusherClient
112
116
  end
113
117
 
114
118
  def subscribe_all
115
- @channels.channels.clone.each{ |k,v|
119
+ @channels.channels.clone.each{ |k,v|
116
120
  subscribe(k)
117
121
  }
118
122
  end
119
-
123
+
124
+ #auth for private and presence
125
+ def authorize(channel, callback)
126
+ if is_private_channel(channel.name)
127
+ auth_data = get_private_auth(channel)
128
+ elsif is_presence_channel(channel.name)
129
+ auth_data = get_presence_auth(channel)
130
+ channel_data = @user_data
131
+ end
132
+ # could both be nil if didn't require auth
133
+ callback.call(channel, auth_data, channel_data)
134
+ end
135
+
136
+ def authorize_callback(channel, auth_data, channel_data)
137
+ send_event('pusher:subscribe', {
138
+ 'channel' => channel.name,
139
+ 'auth' => auth_data,
140
+ 'channel_data' => channel_data
141
+ })
142
+ channel.acknowledge_subscription(nil)
143
+ end
144
+
145
+ def is_private_channel(channel_name)
146
+ channel_name.match(/^private-/)
147
+ end
148
+
149
+ def is_presence_channel(channel_name)
150
+ channel_name.match(/^presence-/)
151
+ end
152
+
153
+ def get_private_auth(channel)
154
+ string_to_sign = @socket_id + ':' + channel.name
155
+ signature = HMAC::SHA256.hexdigest(@secret, string_to_sign)
156
+ return "#{@key}:#{signature}"
157
+ end
158
+
159
+ def get_presence_auth(channel)
160
+ string_to_sign = @socket_id + ':' + channel.name + ':' + @user_data
161
+ signature = HMAC::SHA256.hexdigest(@secret, string_to_sign)
162
+ return "#{@key}:#{signature}"
163
+ end
164
+
165
+
120
166
  # For compatibility with JavaScript client API
121
- alias :subscribeAll :subscribe_all
167
+ alias :subscribeAll :subscribe_all
122
168
 
123
169
  def send_event(event_name, data)
124
170
  payload = {'event' => event_name, 'data' => data}.to_json
@@ -1,6 +1,7 @@
1
1
  require 'rubygems'
2
2
  require 'socket'
3
3
  require 'libwebsocket'
4
+ require 'openssl'
4
5
 
5
6
  module PusherClient
6
7
  class WebSocket
@@ -11,6 +12,21 @@ module PusherClient
11
12
 
12
13
  @socket = TCPSocket.new(@hs.url.host, @hs.url.port || 80)
13
14
 
15
+ if params[:ssl] == true
16
+
17
+ ctx = OpenSSL::SSL::SSLContext.new
18
+ ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
19
+ # http://curl.haxx.se/ca/cacert.pem
20
+ ctx.ca_file = path_to_cert()
21
+
22
+ ssl_sock = OpenSSL::SSL::SSLSocket.new(@socket, ctx)
23
+ ssl_sock.sync_close = true
24
+ ssl_sock.connect
25
+
26
+ @socket = ssl_sock
27
+
28
+ end
29
+
14
30
  @socket.write(@hs.to_s)
15
31
  @socket.flush
16
32
 
@@ -29,6 +45,10 @@ module PusherClient
29
45
  end
30
46
  end
31
47
 
48
+ def path_to_cert
49
+ File.join(File.dirname(File.expand_path(__FILE__)), '../../certs/cacert.pem')
50
+ end
51
+
32
52
  def send(data)
33
53
  raise "no handshake!" unless @handshaked
34
54
 
@@ -1,17 +1,14 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
1
  # -*- encoding: utf-8 -*-
5
2
 
6
3
  Gem::Specification.new do |s|
7
4
  s.name = %q{pusher-client}
8
- s.version = "0.2.1"
5
+ s.version = "0.2.2"
9
6
 
10
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Logan Koester"]
8
+ s.authors = ["Logan Koester", "Phil Leggetter"]
12
9
  s.date = %q{2011-01-07}
13
- s.description = %q{Ruby client for consuming WebSockets from http://pusherapp.com}
14
- s.email = %q{logan@logankoester.com}
10
+ s.description = %q{Ruby client for consuming WebSockets from http://pusher.com}
11
+ s.email = %q{support@pusher.com}
15
12
  s.extra_rdoc_files = [
16
13
  "LICENSE.txt",
17
14
  "README.rdoc"
@@ -23,7 +20,6 @@ Gem::Specification.new do |s|
23
20
  "LICENSE.txt",
24
21
  "README.rdoc",
25
22
  "Rakefile",
26
- "VERSION",
27
23
  "examples/hello_pusher.rb",
28
24
  "examples/hello_pusher_async.rb",
29
25
  "lib/pusher-client.rb",
@@ -31,16 +27,17 @@ Gem::Specification.new do |s|
31
27
  "lib/pusher-client/channels.rb",
32
28
  "lib/pusher-client/socket.rb",
33
29
  "lib/pusher-client/websocket.rb",
30
+ "certs/cacert.pem",
34
31
  "pusher-client.gemspec",
35
32
  "test/pusherclient_test.rb",
36
33
  "test/test.watchr",
37
34
  "test/teststrap.rb"
38
35
  ]
39
- s.homepage = %q{http://github.com/logankoester/pusher-client}
36
+ s.homepage = %q{http://github.com/pusher/pusher-ruby-client}
40
37
  s.licenses = ["MIT"]
41
38
  s.require_paths = ["lib"]
42
39
  s.rubygems_version = %q{1.3.7}
43
- s.summary = %q{Ruby client for consuming WebSockets from http://pusherapp.com}
40
+ s.summary = %q{Ruby client for consuming WebSockets from http://pusher.com}
44
41
  s.test_files = [
45
42
  "examples/hello_pusher.rb",
46
43
  "examples/hello_pusher_async.rb",
@@ -48,32 +45,12 @@ Gem::Specification.new do |s|
48
45
  "test/teststrap.rb"
49
46
  ]
50
47
 
51
- if s.respond_to? :specification_version then
52
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
53
- s.specification_version = 3
48
+ s.add_runtime_dependency(%q<libwebsocket>, ["0.1.5"])
49
+ s.add_runtime_dependency(%q<ruby-hmac>, ["~> 0.4.0"])
50
+ s.add_runtime_dependency(%q<addressable>, ["~> 2.3.1"])
51
+ s.add_development_dependency(%q<bacon>, [">= 0"])
52
+ s.add_development_dependency(%q<rake>, [">= 0"])
53
+ s.add_development_dependency(%q<ruby-debug19>, [">= 0"])
54
54
 
55
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
56
- s.add_runtime_dependency(%q<eventmachine>, ["~> 0.12.10"])
57
- s.add_runtime_dependency(%q<libwebsocket>, ["~> 0.1.0"])
58
- s.add_development_dependency(%q<bacon>, [">= 0"])
59
- s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
60
- s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
61
- s.add_development_dependency(%q<rcov>, [">= 0"])
62
- else
63
- s.add_dependency(%q<eventmachine>, ["~> 0.12.10"])
64
- s.add_dependency(%q<libwebsocket>, ["~> 0.1.0"])
65
- s.add_dependency(%q<bacon>, [">= 0"])
66
- s.add_dependency(%q<bundler>, ["~> 1.0.0"])
67
- s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
68
- s.add_dependency(%q<rcov>, [">= 0"])
69
- end
70
- else
71
- s.add_dependency(%q<eventmachine>, ["~> 0.12.10"])
72
- s.add_dependency(%q<libwebsocket>, ["~> 0.1.0"])
73
- s.add_dependency(%q<bacon>, [">= 0"])
74
- s.add_dependency(%q<bundler>, ["~> 1.0.0"])
75
- s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
76
- s.add_dependency(%q<rcov>, [">= 0"])
77
- end
78
55
  end
79
56
 
data/test/teststrap.rb CHANGED
@@ -32,7 +32,7 @@ module PusherClient
32
32
  def connect(async = false)
33
33
  @connection_thread = Thread.new do
34
34
  @connection = TestConnection.new
35
- @global_channel.dispatch('pusher:connection_established', {'socket_id' => '123abc'})
35
+ @global_channel.dispatch('pusher:connection_established', JSON.dump({'socket_id' => '123abc'}))
36
36
  end
37
37
  @connection_thread.run
38
38
  @connection_thread.join unless async
metadata CHANGED
@@ -1,125 +1,127 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: pusher-client
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 2
8
- - 1
9
- version: 0.2.1
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.2
5
+ prerelease:
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - Logan Koester
9
+ - Phil Leggetter
13
10
  autorequire:
14
11
  bindir: bin
15
12
  cert_chain: []
16
-
17
- date: 2011-01-07 00:00:00 -05:00
18
- default_executable:
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
21
- name: eventmachine
22
- requirement: &id001 !ruby/object:Gem::Requirement
13
+ date: 2011-01-07 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: libwebsocket
17
+ requirement: !ruby/object:Gem::Requirement
23
18
  none: false
24
- requirements:
25
- - - ~>
26
- - !ruby/object:Gem::Version
27
- segments:
28
- - 0
29
- - 12
30
- - 10
31
- version: 0.12.10
19
+ requirements:
20
+ - - '='
21
+ - !ruby/object:Gem::Version
22
+ version: 0.1.5
32
23
  type: :runtime
33
24
  prerelease: false
34
- version_requirements: *id001
35
- - !ruby/object:Gem::Dependency
36
- name: libwebsocket
37
- requirement: &id002 !ruby/object:Gem::Requirement
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - '='
29
+ - !ruby/object:Gem::Version
30
+ version: 0.1.5
31
+ - !ruby/object:Gem::Dependency
32
+ name: ruby-hmac
33
+ requirement: !ruby/object:Gem::Requirement
38
34
  none: false
39
- requirements:
35
+ requirements:
40
36
  - - ~>
41
- - !ruby/object:Gem::Version
42
- segments:
43
- - 0
44
- - 1
45
- - 0
46
- version: 0.1.0
37
+ - !ruby/object:Gem::Version
38
+ version: 0.4.0
47
39
  type: :runtime
48
40
  prerelease: false
49
- version_requirements: *id002
50
- - !ruby/object:Gem::Dependency
51
- name: bacon
52
- requirement: &id003 !ruby/object:Gem::Requirement
41
+ version_requirements: !ruby/object:Gem::Requirement
53
42
  none: false
54
- requirements:
55
- - - ">="
56
- - !ruby/object:Gem::Version
57
- segments:
58
- - 0
59
- version: "0"
60
- type: :development
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ version: 0.4.0
47
+ - !ruby/object:Gem::Dependency
48
+ name: addressable
49
+ requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 2.3.1
55
+ type: :runtime
61
56
  prerelease: false
62
- version_requirements: *id003
63
- - !ruby/object:Gem::Dependency
64
- name: bundler
65
- requirement: &id004 !ruby/object:Gem::Requirement
57
+ version_requirements: !ruby/object:Gem::Requirement
66
58
  none: false
67
- requirements:
59
+ requirements:
68
60
  - - ~>
69
- - !ruby/object:Gem::Version
70
- segments:
71
- - 1
72
- - 0
73
- - 0
74
- version: 1.0.0
61
+ - !ruby/object:Gem::Version
62
+ version: 2.3.1
63
+ - !ruby/object:Gem::Dependency
64
+ name: bacon
65
+ requirement: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ! '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
75
71
  type: :development
76
72
  prerelease: false
77
- version_requirements: *id004
78
- - !ruby/object:Gem::Dependency
79
- name: jeweler
80
- requirement: &id005 !ruby/object:Gem::Requirement
73
+ version_requirements: !ruby/object:Gem::Requirement
81
74
  none: false
82
- requirements:
83
- - - ~>
84
- - !ruby/object:Gem::Version
85
- segments:
86
- - 1
87
- - 5
88
- - 2
89
- version: 1.5.2
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ - !ruby/object:Gem::Dependency
80
+ name: rake
81
+ requirement: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
90
87
  type: :development
91
88
  prerelease: false
92
- version_requirements: *id005
93
- - !ruby/object:Gem::Dependency
94
- name: rcov
95
- requirement: &id006 !ruby/object:Gem::Requirement
89
+ version_requirements: !ruby/object:Gem::Requirement
96
90
  none: false
97
- requirements:
98
- - - ">="
99
- - !ruby/object:Gem::Version
100
- segments:
101
- - 0
102
- version: "0"
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ - !ruby/object:Gem::Dependency
96
+ name: ruby-debug19
97
+ requirement: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ! '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
103
  type: :development
104
104
  prerelease: false
105
- version_requirements: *id006
106
- description: Ruby client for consuming WebSockets from http://pusherapp.com
107
- email: logan@logankoester.com
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: Ruby client for consuming WebSockets from http://pusher.com
112
+ email: support@pusher.com
108
113
  executables: []
109
-
110
114
  extensions: []
111
-
112
- extra_rdoc_files:
115
+ extra_rdoc_files:
113
116
  - LICENSE.txt
114
117
  - README.rdoc
115
- files:
118
+ files:
116
119
  - .document
117
120
  - Gemfile
118
121
  - Gemfile.lock
119
122
  - LICENSE.txt
120
123
  - README.rdoc
121
124
  - Rakefile
122
- - VERSION
123
125
  - examples/hello_pusher.rb
124
126
  - examples/hello_pusher_async.rb
125
127
  - lib/pusher-client.rb
@@ -127,44 +129,37 @@ files:
127
129
  - lib/pusher-client/channels.rb
128
130
  - lib/pusher-client/socket.rb
129
131
  - lib/pusher-client/websocket.rb
132
+ - certs/cacert.pem
130
133
  - pusher-client.gemspec
131
134
  - test/pusherclient_test.rb
132
135
  - test/test.watchr
133
136
  - test/teststrap.rb
134
- has_rdoc: true
135
- homepage: http://github.com/logankoester/pusher-client
136
- licenses:
137
+ homepage: http://github.com/pusher/pusher-ruby-client
138
+ licenses:
137
139
  - MIT
138
140
  post_install_message:
139
141
  rdoc_options: []
140
-
141
- require_paths:
142
+ require_paths:
142
143
  - lib
143
- required_ruby_version: !ruby/object:Gem::Requirement
144
+ required_ruby_version: !ruby/object:Gem::Requirement
144
145
  none: false
145
- requirements:
146
- - - ">="
147
- - !ruby/object:Gem::Version
148
- hash: 3350793472905548965
149
- segments:
150
- - 0
151
- version: "0"
152
- required_rubygems_version: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ required_rubygems_version: !ruby/object:Gem::Requirement
153
151
  none: false
154
- requirements:
155
- - - ">="
156
- - !ruby/object:Gem::Version
157
- segments:
158
- - 0
159
- version: "0"
152
+ requirements:
153
+ - - ! '>='
154
+ - !ruby/object:Gem::Version
155
+ version: '0'
160
156
  requirements: []
161
-
162
157
  rubyforge_project:
163
- rubygems_version: 1.3.7
158
+ rubygems_version: 1.8.25
164
159
  signing_key:
165
160
  specification_version: 3
166
- summary: Ruby client for consuming WebSockets from http://pusherapp.com
167
- test_files:
161
+ summary: Ruby client for consuming WebSockets from http://pusher.com
162
+ test_files:
168
163
  - examples/hello_pusher.rb
169
164
  - examples/hello_pusher_async.rb
170
165
  - test/pusherclient_test.rb