pusher-client 0.2.2 → 0.3.0

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/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ *.log
2
+ .DS_Store
3
+ coverage
4
+ *.swp
5
+ *.swn
6
+ *.swm
7
+ *.swo
8
+ mkmf.log
9
+ test/rcov/*
10
+ .project
11
+ .bundle
12
+ pkg/*
13
+ run_example_playground
14
+ examples/hello_pusher_playground.rb
15
+ Gemfile.lock
data/Gemfile CHANGED
@@ -1,2 +1,7 @@
1
- source :rubygems
1
+ source 'https://www.rubygems.org'
2
+
2
3
  gemspec
4
+
5
+ gem 'json', :platform => :ruby_18
6
+ gem 'openssl-nonblock', :platform => :ruby_18
7
+ gem 'ruby-debug19', :platform => :ruby_19
data/README.rdoc CHANGED
@@ -11,6 +11,11 @@ may be sent on. You can't just bind a global event without subscribing to any ch
11
11
 
12
12
  == Installation
13
13
  gem install pusher-client
14
+
15
+ If you're using Ruby 1.8.7, then you'll also need the openssl-nonblock gem:
16
+
17
+ gem install openssl-nonblock
18
+
14
19
  == Single-Threaded Usage
15
20
  The application will pause at socket.connect and handle events from Pusher as they happen.
16
21
 
@@ -71,6 +76,14 @@ and you can continue to subscribe/unsubscribe to channels and bind new events.
71
76
  For further documentation, read the source & test suite. Some features of the JavaScript client
72
77
  are not yet implemented.
73
78
 
79
+ == Native extension
80
+ Pusher depends on the websocket[https://github.com/imanel/websocket-ruby] gem
81
+ which is a pure Ruby implementation of websockets.
82
+
83
+ However it can optionally use a native C or Java implementation for a 25% speed
84
+ increase by including the websocket-native[https://github.com/imanel/websocket-ruby-native]
85
+ gem in your Gemfile.
86
+
74
87
  == Contributing to pusher-client
75
88
 
76
89
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
@@ -0,0 +1,20 @@
1
+ # Usage: $ PUSHER_KEY=YOURKEY ruby examples/hello_pusher.rb
2
+
3
+ require 'rubygems'
4
+ require './lib/pusher-client.rb'
5
+ require 'pp'
6
+
7
+ APP_KEY = ENV['PUSHER_KEY'] # || "YOUR_APPLICATION_KEY"
8
+
9
+ PusherClient.logger = Logger.new(STDOUT)
10
+ socket = PusherClient::Socket.new(APP_KEY, { :encrypted => true } )
11
+
12
+ # Subscribe to a channel
13
+ socket.subscribe('hellopusher')
14
+
15
+ # Bind to a channel event
16
+ socket['hellopusher'].bind('hello') do |data|
17
+ pp data
18
+ end
19
+
20
+ socket.connect
@@ -0,0 +1,21 @@
1
+ # Usage: $ PUSHER_KEY=YOURKEY ruby examples/hello_pusher.rb
2
+
3
+ require 'rubygems'
4
+ require './lib/pusher-client.rb'
5
+ require 'pp'
6
+
7
+ APP_KEY = ENV['PUSHER_KEY'] # || "YOUR_APPLICATION_KEY"
8
+ APP_SECRET = ENV['PUSHER_SECRET'] # || "YOUR_APPLICATION_SECRET"
9
+
10
+ PusherClient.logger = Logger.new(STDOUT)
11
+ socket = PusherClient::Socket.new(APP_KEY, { :encrypted => true, :secret => APP_SECRET } )
12
+
13
+ # Subscribe to a channel
14
+ socket.subscribe('private-hellopusher')
15
+
16
+ # Bind to a channel event
17
+ socket['hellopusher'].bind('hello') do |data|
18
+ pp data
19
+ end
20
+
21
+ socket.connect
@@ -5,9 +5,8 @@ require 'digest/md5'
5
5
  module PusherClient
6
6
  class Socket
7
7
 
8
- # Mimick the JavaScript client
9
8
  CLIENT_ID = 'pusher-ruby-client'
10
- VERSION = '0.2.2'
9
+ VERSION = '0.3.0'
11
10
  PROTOCOL = '5'
12
11
 
13
12
  attr_accessor :encrypted, :secure
@@ -41,6 +40,12 @@ module PusherClient
41
40
  bind('pusher:error') do |data|
42
41
  PusherClient.logger.fatal("Pusher : error : #{data.inspect}")
43
42
  end
43
+
44
+ # Keep this in case we're using a websocket protocol that doesn't
45
+ # implement ping/pong
46
+ bind('pusher:ping') do
47
+ send_event('pusher:pong', nil)
48
+ end
44
49
  end
45
50
 
46
51
  def connect(async = false)
@@ -52,23 +57,23 @@ module PusherClient
52
57
  PusherClient.logger.debug("Pusher : connecting : #{url}")
53
58
 
54
59
  @connection_thread = Thread.new {
55
- options = {:ssl => @encrypted || @secure}
56
- @connection = WebSocket.new(url, options)
60
+ options = {:ssl => @encrypted || @secure}
61
+ @connection = PusherWebSocket.new(url, options)
57
62
  PusherClient.logger.debug "Websocket connected"
63
+
58
64
  loop do
59
- msg = @connection.receive[0]
60
- params = parser(msg)
61
- next if (params['socket_id'] && params['socket_id'] == self.socket_id)
62
- event_name = params['event']
63
- event_data = params['data']
64
- channel_name = params['channel']
65
- send_local_event(event_name, event_data, channel_name)
65
+ msg = @connection.receive[0]
66
+ next if msg.nil?
67
+ params = parser(msg)
68
+ next if params['socket_id'] && params['socket_id'] == self.socket_id
69
+
70
+ send_local_event params['event'], params['data'], params['channel']
66
71
  end
67
72
  }
68
73
 
69
74
  @connection_thread.run
70
75
  @connection_thread.join unless async
71
- return self
76
+ self
72
77
  end
73
78
 
74
79
  def disconnect
@@ -1,19 +1,22 @@
1
1
  require 'rubygems'
2
2
  require 'socket'
3
- require 'libwebsocket'
3
+ require 'websocket'
4
4
  require 'openssl'
5
+ require 'openssl/nonblock' if RUBY_VERSION == '1.8.7'
5
6
 
6
7
  module PusherClient
7
- class WebSocket
8
+ class PusherWebSocket
9
+ WAIT_EXCEPTIONS = [Errno::EAGAIN, Errno::EWOULDBLOCK]
10
+ WAIT_EXCEPTIONS << IO::WaitReadable if defined?(IO::WaitReadable)
11
+
12
+ attr_accessor :socket
8
13
 
9
14
  def initialize(url, params = {})
10
- @hs ||= LibWebSocket::OpeningHandshake::Client.new(:url => url, :version => params[:version])
11
- @frame ||= LibWebSocket::Frame.new
12
-
13
- @socket = TCPSocket.new(@hs.url.host, @hs.url.port || 80)
15
+ @hs ||= WebSocket::Handshake::Client.new(:url => url, :version => params[:version])
16
+ @frame ||= WebSocket::Frame::Incoming::Server.new(:version => @hs.version)
17
+ @socket = TCPSocket.new(@hs.host, @hs.port || 80)
14
18
 
15
19
  if params[:ssl] == true
16
-
17
20
  ctx = OpenSSL::SSL::SSLContext.new
18
21
  ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
19
22
  # http://curl.haxx.se/ca/cacert.pem
@@ -24,7 +27,6 @@ module PusherClient
24
27
  ssl_sock.connect
25
28
 
26
29
  @socket = ssl_sock
27
-
28
30
  end
29
31
 
30
32
  @socket.write(@hs.to_s)
@@ -34,11 +36,10 @@ module PusherClient
34
36
  data = @socket.getc
35
37
  next if data.nil?
36
38
 
37
- result = @hs.parse(data.chr)
39
+ @hs << data
38
40
 
39
- raise @hs.error unless result
40
-
41
- if @hs.done?
41
+ if @hs.finished?
42
+ raise Exception unless @hs.valid?
42
43
  @handshaked = true
43
44
  break
44
45
  end
@@ -49,10 +50,10 @@ module PusherClient
49
50
  File.join(File.dirname(File.expand_path(__FILE__)), '../../certs/cacert.pem')
50
51
  end
51
52
 
52
- def send(data)
53
+ def send(data, type = :text)
53
54
  raise "no handshake!" unless @handshaked
54
55
 
55
- data = @frame.new(data).to_s
56
+ data = WebSocket::Frame::Outgoing::Server.new(:version => @hs.version, :data => data, :type => type).to_s
56
57
  @socket.write data
57
58
  @socket.flush
58
59
  end
@@ -60,25 +61,32 @@ module PusherClient
60
61
  def receive
61
62
  raise "no handshake!" unless @handshaked
62
63
 
63
- data = @socket.gets("\xff")
64
- @frame.append(data)
64
+ begin
65
+ data = @socket.read_nonblock(1024)
66
+ rescue *WAIT_EXCEPTIONS
67
+ IO.select([@socket])
68
+ retry
69
+ end
70
+ @frame << data
65
71
 
66
72
  messages = []
67
73
  while message = @frame.next
68
- messages << message
74
+ if message.type === :ping
75
+ send(message.data, :pong)
76
+ return messages
77
+ end
78
+ messages << message.to_s
69
79
  end
70
80
  messages
71
- end
72
-
73
- def socket
74
- @socket
81
+ rescue IOError, Errno::EBADF => error
82
+ PusherClient.logger.debug error.message
83
+ []
75
84
  end
76
85
 
77
86
  def close
78
87
  @socket.close
88
+ rescue IOError => error
89
+ PusherClient.logger.debug error.message
79
90
  end
80
-
81
91
  end
82
92
  end
83
-
84
-
@@ -1,56 +1,25 @@
1
1
  # -*- encoding: utf-8 -*-
2
-
3
2
  Gem::Specification.new do |s|
4
- s.name = %q{pusher-client}
5
- s.version = "0.2.2"
3
+ s.name = 'pusher-client'
4
+ s.version = "0.3.0"
5
+ s.authors = ["Logan Koester", "Phil Leggetter"]
6
+ s.email = ['support@pusher.com']
7
+ s.homepage = 'http://github.com/pusher/pusher-ruby-client'
8
+ s.summary = 'Client for consuming WebSockets from http://pusher.com'
9
+ s.description = 'Client for consuming WebSockets from http://pusher.com'
6
10
 
7
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
- s.authors = ["Logan Koester", "Phil Leggetter"]
9
- s.date = %q{2011-01-07}
10
- s.description = %q{Ruby client for consuming WebSockets from http://pusher.com}
11
- s.email = %q{support@pusher.com}
12
- s.extra_rdoc_files = [
13
- "LICENSE.txt",
14
- "README.rdoc"
15
- ]
16
- s.files = [
17
- ".document",
18
- "Gemfile",
19
- "Gemfile.lock",
20
- "LICENSE.txt",
21
- "README.rdoc",
22
- "Rakefile",
23
- "examples/hello_pusher.rb",
24
- "examples/hello_pusher_async.rb",
25
- "lib/pusher-client.rb",
26
- "lib/pusher-client/channel.rb",
27
- "lib/pusher-client/channels.rb",
28
- "lib/pusher-client/socket.rb",
29
- "lib/pusher-client/websocket.rb",
30
- "certs/cacert.pem",
31
- "pusher-client.gemspec",
32
- "test/pusherclient_test.rb",
33
- "test/test.watchr",
34
- "test/teststrap.rb"
35
- ]
36
- s.homepage = %q{http://github.com/pusher/pusher-ruby-client}
37
- s.licenses = ["MIT"]
38
- s.require_paths = ["lib"]
39
- s.rubygems_version = %q{1.3.7}
40
- s.summary = %q{Ruby client for consuming WebSockets from http://pusher.com}
41
- s.test_files = [
42
- "examples/hello_pusher.rb",
43
- "examples/hello_pusher_async.rb",
44
- "test/pusherclient_test.rb",
45
- "test/teststrap.rb"
46
- ]
11
+ s.files = `git ls-files`.split("\n")
12
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
13
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f|
14
+ File.basename(f)
15
+ }
16
+ s.extra_rdoc_files = %w(LICENSE.txt README.rdoc)
17
+ s.require_paths = ['lib']
18
+ s.licenses = ['MIT']
47
19
 
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"])
20
+ s.add_runtime_dependency 'websocket', '~> 1.0.0'
21
+ s.add_runtime_dependency 'ruby-hmac', '~> 0.4.0'
54
22
 
23
+ s.add_development_dependency 'bacon', '>= 0'
24
+ s.add_development_dependency 'rake', '>= 0'
55
25
  end
56
-
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pusher-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,59 +10,33 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2011-01-07 00:00:00.000000000 Z
13
+ date: 2013-04-05 00:00:00.000000000Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
- name: libwebsocket
17
- requirement: !ruby/object:Gem::Requirement
16
+ name: websocket
17
+ requirement: &70212587581360 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
- - - '='
20
+ - - ~>
21
21
  - !ruby/object:Gem::Version
22
- version: 0.1.5
22
+ version: 1.0.0
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: !ruby/object:Gem::Requirement
26
- none: false
27
- requirements:
28
- - - '='
29
- - !ruby/object:Gem::Version
30
- version: 0.1.5
25
+ version_requirements: *70212587581360
31
26
  - !ruby/object:Gem::Dependency
32
27
  name: ruby-hmac
33
- requirement: !ruby/object:Gem::Requirement
34
- none: false
35
- requirements:
36
- - - ~>
37
- - !ruby/object:Gem::Version
38
- version: 0.4.0
39
- type: :runtime
40
- prerelease: false
41
- version_requirements: !ruby/object:Gem::Requirement
28
+ requirement: &70212587580880 !ruby/object:Gem::Requirement
42
29
  none: false
43
30
  requirements:
44
31
  - - ~>
45
32
  - !ruby/object:Gem::Version
46
33
  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
34
  type: :runtime
56
35
  prerelease: false
57
- version_requirements: !ruby/object:Gem::Requirement
58
- none: false
59
- requirements:
60
- - - ~>
61
- - !ruby/object:Gem::Version
62
- version: 2.3.1
36
+ version_requirements: *70212587580880
63
37
  - !ruby/object:Gem::Dependency
64
38
  name: bacon
65
- requirement: !ruby/object:Gem::Requirement
39
+ requirement: &70212587580420 !ruby/object:Gem::Requirement
66
40
  none: false
67
41
  requirements:
68
42
  - - ! '>='
@@ -70,31 +44,10 @@ dependencies:
70
44
  version: '0'
71
45
  type: :development
72
46
  prerelease: false
73
- version_requirements: !ruby/object:Gem::Requirement
74
- none: false
75
- requirements:
76
- - - ! '>='
77
- - !ruby/object:Gem::Version
78
- version: '0'
47
+ version_requirements: *70212587580420
79
48
  - !ruby/object:Gem::Dependency
80
49
  name: rake
81
- requirement: !ruby/object:Gem::Requirement
82
- none: false
83
- requirements:
84
- - - ! '>='
85
- - !ruby/object:Gem::Version
86
- version: '0'
87
- type: :development
88
- prerelease: false
89
- version_requirements: !ruby/object:Gem::Requirement
90
- none: false
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
50
+ requirement: &70212587579960 !ruby/object:Gem::Requirement
98
51
  none: false
99
52
  requirements:
100
53
  - - ! '>='
@@ -102,14 +55,10 @@ dependencies:
102
55
  version: '0'
103
56
  type: :development
104
57
  prerelease: false
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
58
+ version_requirements: *70212587579960
59
+ description: Client for consuming WebSockets from http://pusher.com
60
+ email:
61
+ - support@pusher.com
113
62
  executables: []
114
63
  extensions: []
115
64
  extra_rdoc_files:
@@ -117,19 +66,21 @@ extra_rdoc_files:
117
66
  - README.rdoc
118
67
  files:
119
68
  - .document
69
+ - .gitignore
120
70
  - Gemfile
121
- - Gemfile.lock
122
71
  - LICENSE.txt
123
72
  - README.rdoc
124
73
  - Rakefile
74
+ - certs/cacert.pem
125
75
  - examples/hello_pusher.rb
126
76
  - examples/hello_pusher_async.rb
77
+ - examples/hello_pusher_ssl.rb
78
+ - examples/subscribe_private.rb
127
79
  - lib/pusher-client.rb
128
80
  - lib/pusher-client/channel.rb
129
81
  - lib/pusher-client/channels.rb
130
82
  - lib/pusher-client/socket.rb
131
83
  - lib/pusher-client/websocket.rb
132
- - certs/cacert.pem
133
84
  - pusher-client.gemspec
134
85
  - test/pusherclient_test.rb
135
86
  - test/test.watchr
@@ -155,12 +106,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
155
106
  version: '0'
156
107
  requirements: []
157
108
  rubyforge_project:
158
- rubygems_version: 1.8.25
109
+ rubygems_version: 1.8.10
159
110
  signing_key:
160
111
  specification_version: 3
161
- summary: Ruby client for consuming WebSockets from http://pusher.com
112
+ summary: Client for consuming WebSockets from http://pusher.com
162
113
  test_files:
163
- - examples/hello_pusher.rb
164
- - examples/hello_pusher_async.rb
165
114
  - test/pusherclient_test.rb
115
+ - test/test.watchr
166
116
  - test/teststrap.rb
data/Gemfile.lock DELETED
@@ -1,41 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- pusher-client (0.2.2)
5
- addressable (~> 2.3.1)
6
- libwebsocket (= 0.1.5)
7
- ruby-hmac (~> 0.4.0)
8
-
9
- GEM
10
- remote: http://rubygems.org/
11
- specs:
12
- addressable (2.3.2)
13
- archive-tar-minitar (0.5.2)
14
- bacon (1.2.0)
15
- columnize (0.3.6)
16
- libwebsocket (0.1.5)
17
- addressable
18
- linecache19 (0.5.12)
19
- ruby_core_source (>= 0.1.4)
20
- rake (10.0.3)
21
- ruby-debug-base19 (0.11.25)
22
- columnize (>= 0.3.1)
23
- linecache19 (>= 0.5.11)
24
- ruby_core_source (>= 0.1.4)
25
- ruby-debug19 (0.11.6)
26
- columnize (>= 0.3.1)
27
- linecache19 (>= 0.5.11)
28
- ruby-debug-base19 (>= 0.11.19)
29
- ruby-hmac (0.4.0)
30
- ruby_core_source (0.1.5)
31
- archive-tar-minitar (>= 0.5.2)
32
-
33
- PLATFORMS
34
- java
35
- ruby
36
-
37
- DEPENDENCIES
38
- bacon
39
- pusher-client!
40
- rake
41
- ruby-debug19