pusher-client 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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