pubnub-ruby 3.3.0.7 → 3.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.yardoc/checksums +13 -0
  4. data/.yardoc/object_types +0 -0
  5. data/.yardoc/objects/root.dat +0 -0
  6. data/.yardoc/proxy_types +0 -0
  7. data/LICENSE +27 -0
  8. data/README.md +259 -0
  9. data/Rakefile +7 -0
  10. data/VERSION +1 -0
  11. data/examples/demo_console.rb +198 -0
  12. data/examples/error_server.rb +28 -0
  13. data/examples/pubnub_livestream/.gitignore +16 -0
  14. data/examples/pubnub_livestream/Gemfile +51 -0
  15. data/examples/pubnub_livestream/Gemfile.lock +191 -0
  16. data/examples/pubnub_livestream/README.rdoc +28 -0
  17. data/examples/pubnub_livestream/Rakefile +6 -0
  18. data/examples/pubnub_livestream/app/assets/images/.keep +0 -0
  19. data/examples/pubnub_livestream/app/assets/javascripts/application.js +16 -0
  20. data/examples/pubnub_livestream/app/assets/javascripts/streamer.js.coffee +42 -0
  21. data/examples/pubnub_livestream/app/assets/stylesheets/application.css.sass +22 -0
  22. data/examples/pubnub_livestream/app/assets/stylesheets/streamer.css.scss +3 -0
  23. data/examples/pubnub_livestream/app/controllers/application_controller.rb +5 -0
  24. data/examples/pubnub_livestream/app/controllers/concerns/.keep +0 -0
  25. data/examples/pubnub_livestream/app/controllers/streamer_controller.rb +38 -0
  26. data/examples/pubnub_livestream/app/helpers/application_helper.rb +2 -0
  27. data/examples/pubnub_livestream/app/helpers/streamer_helper.rb +2 -0
  28. data/examples/pubnub_livestream/app/mailers/.keep +0 -0
  29. data/examples/pubnub_livestream/app/models/.keep +0 -0
  30. data/examples/pubnub_livestream/app/models/concerns/.keep +0 -0
  31. data/examples/pubnub_livestream/app/models/message.rb +11 -0
  32. data/examples/pubnub_livestream/app/views/layouts/application.html.erb +14 -0
  33. data/examples/pubnub_livestream/app/views/streamer/index.haml +22 -0
  34. data/examples/pubnub_livestream/bin/bundle +3 -0
  35. data/examples/pubnub_livestream/bin/rails +4 -0
  36. data/examples/pubnub_livestream/bin/rake +4 -0
  37. data/examples/pubnub_livestream/config.ru +4 -0
  38. data/examples/pubnub_livestream/config/application.rb +23 -0
  39. data/examples/pubnub_livestream/config/boot.rb +4 -0
  40. data/examples/pubnub_livestream/config/database.yml +25 -0
  41. data/examples/pubnub_livestream/config/environment.rb +5 -0
  42. data/examples/pubnub_livestream/config/environments/development.rb +29 -0
  43. data/examples/pubnub_livestream/config/environments/production.rb +80 -0
  44. data/examples/pubnub_livestream/config/environments/test.rb +36 -0
  45. data/examples/pubnub_livestream/config/initializers/backtrace_silencers.rb +7 -0
  46. data/examples/pubnub_livestream/config/initializers/filter_parameter_logging.rb +4 -0
  47. data/examples/pubnub_livestream/config/initializers/inflections.rb +16 -0
  48. data/examples/pubnub_livestream/config/initializers/mime_types.rb +5 -0
  49. data/examples/pubnub_livestream/config/initializers/pubnub.rb +12 -0
  50. data/examples/pubnub_livestream/config/initializers/secret_token.rb +12 -0
  51. data/examples/pubnub_livestream/config/initializers/session_store.rb +3 -0
  52. data/examples/pubnub_livestream/config/initializers/wrap_parameters.rb +14 -0
  53. data/examples/pubnub_livestream/config/locales/en.yml +23 -0
  54. data/examples/pubnub_livestream/config/routes.rb +62 -0
  55. data/examples/pubnub_livestream/db/migrate/20130826110322_create_messages.rb +11 -0
  56. data/examples/pubnub_livestream/db/schema.rb +24 -0
  57. data/examples/pubnub_livestream/db/seeds.rb +7 -0
  58. data/examples/pubnub_livestream/lib/assets/.keep +0 -0
  59. data/examples/pubnub_livestream/lib/tasks/.keep +0 -0
  60. data/examples/pubnub_livestream/log/.keep +0 -0
  61. data/examples/pubnub_livestream/public/404.html +58 -0
  62. data/examples/pubnub_livestream/public/422.html +58 -0
  63. data/examples/pubnub_livestream/public/500.html +57 -0
  64. data/examples/pubnub_livestream/public/assets/application-22a604196dfb65fd0d602eb1eb65f9b7.js +4 -0
  65. data/examples/pubnub_livestream/public/assets/application-22a604196dfb65fd0d602eb1eb65f9b7.js.gz +0 -0
  66. data/examples/pubnub_livestream/public/assets/application-3fac0c014bbdf9ee7b3986ff615d5da0.css +5019 -0
  67. data/examples/pubnub_livestream/public/assets/application-3fac0c014bbdf9ee7b3986ff615d5da0.css.gz +0 -0
  68. data/examples/pubnub_livestream/public/assets/application-f06834e402639ad43230e3859b9bdd78.css +1 -0
  69. data/examples/pubnub_livestream/public/assets/application-f06834e402639ad43230e3859b9bdd78.css.gz +0 -0
  70. data/examples/pubnub_livestream/public/assets/application-f91b87f490140d86003c46b4d06b6c70.js +10682 -0
  71. data/examples/pubnub_livestream/public/assets/application-f91b87f490140d86003c46b4d06b6c70.js.gz +0 -0
  72. data/examples/pubnub_livestream/public/assets/manifest-c129e1f5ec52d8b661ebfa902554a2e2.json +1 -0
  73. data/examples/pubnub_livestream/public/assets/twitter/glyphicons-halflings-regular-0bc0341283e3bb8ec518375794cc7c28.eot +0 -0
  74. data/examples/pubnub_livestream/public/assets/twitter/glyphicons-halflings-regular-24dfb40c91db789b8b8faba6886ac1ef.svg +228 -0
  75. data/examples/pubnub_livestream/public/assets/twitter/glyphicons-halflings-regular-4b2130768da98222338d1519f9179528.ttf +0 -0
  76. data/examples/pubnub_livestream/public/assets/twitter/glyphicons-halflings-regular-7a07f26f72466361ac9671de2d33fd1c.woff +0 -0
  77. data/examples/pubnub_livestream/public/assets/twitter/glyphicons-halflings-regular-9f75212cf9fca594cee7e0e3587db9d1.svg +228 -0
  78. data/examples/pubnub_livestream/public/assets/twitter/glyphicons-halflings-regular-ab2f6984951c07fd89e6afdefabd93c7.eot +0 -0
  79. data/examples/pubnub_livestream/public/assets/twitter/glyphicons-halflings-regular-c21928f7d46b397b0af6b9ee4a7bd0dd.ttf +0 -0
  80. data/examples/pubnub_livestream/public/assets/twitter/glyphicons-halflings-regular-fa1d7f79d80d03f8a598822bd9df79bf.woff +0 -0
  81. data/examples/pubnub_livestream/public/favicon.ico +0 -0
  82. data/examples/pubnub_livestream/public/robots.txt +5 -0
  83. data/examples/pubnub_livestream/test/controllers/.keep +0 -0
  84. data/examples/pubnub_livestream/test/controllers/streamer_controller_test.rb +7 -0
  85. data/examples/pubnub_livestream/test/fixtures/.keep +0 -0
  86. data/examples/pubnub_livestream/test/fixtures/messages.yml +9 -0
  87. data/examples/pubnub_livestream/test/helpers/.keep +0 -0
  88. data/examples/pubnub_livestream/test/helpers/streamer_helper_test.rb +4 -0
  89. data/examples/pubnub_livestream/test/integration/.keep +0 -0
  90. data/examples/pubnub_livestream/test/mailers/.keep +0 -0
  91. data/examples/pubnub_livestream/test/models/.keep +0 -0
  92. data/examples/pubnub_livestream/test/models/message_test.rb +7 -0
  93. data/examples/pubnub_livestream/test/test_helper.rb +15 -0
  94. data/examples/pubnub_livestream/vendor/assets/javascripts/.keep +0 -0
  95. data/examples/pubnub_livestream/vendor/assets/stylesheets/.keep +0 -0
  96. data/examples/serial_publish.rb +46 -0
  97. data/examples/sinatra/.sass-cache/65d837cc121fc62381bb76d93e5bd081356aa3f9/application.sassc +0 -0
  98. data/examples/sinatra/.sass-cache/d1525a8542f6e7fb2ecd3275251283768779b344/main.rbc +0 -0
  99. data/examples/sinatra/.sass-cache/d35765d68c1df11fa3368aa802b3d38109cba214/application.sassc +0 -0
  100. data/examples/sinatra/main.rb +54 -0
  101. data/examples/sinatra/public/bootstrap-responsive.min.css +9 -0
  102. data/examples/sinatra/public/bootstrap.css +5909 -0
  103. data/examples/sinatra/public/bootstrap.min.css +845 -0
  104. data/examples/sinatra/public/jquery-1.10.2.min.js +5 -0
  105. data/examples/sinatra/views/application.sass +6 -0
  106. data/examples/sinatra/views/index.slim +16 -0
  107. data/examples/sinatra/views/layout.slim +12 -0
  108. data/examples/sinatra/views/streamer.coffee +41 -0
  109. data/examples/sub_and_unsub_1.rb +56 -0
  110. data/examples/translator.rb +129 -0
  111. data/lib/pubnub.rb +31 -375
  112. data/lib/pubnub/client.rb +527 -0
  113. data/lib/pubnub/configuration.rb +25 -0
  114. data/lib/pubnub/crypto.rb +53 -0
  115. data/lib/pubnub/error.rb +23 -0
  116. data/lib/pubnub/request.rb +288 -0
  117. data/lib/pubnub/response.rb +126 -0
  118. data/lib/pubnub/subscription.rb +24 -0
  119. data/lib/tasks/examples.rake +39 -0
  120. data/lib/version.rb +1 -0
  121. data/pubnub.gemspec +26 -0
  122. data/spec/lib/client_spec.rb +346 -0
  123. data/spec/lib/crypto_spec.rb +89 -0
  124. data/spec/lib/history_integration_spec.rb +0 -0
  125. data/spec/lib/presence_integration_spec.rb +16 -0
  126. data/spec/lib/publish_integration_spec.rb +994 -0
  127. data/spec/lib/pubnub_spec.rb +12 -0
  128. data/spec/lib/request_spec.rb +151 -0
  129. data/spec/lib/subscribe_integration_spec.rb +944 -0
  130. data/spec/lib/time_integration_spec.rb +0 -0
  131. data/spec/spec_helper.rb +15 -0
  132. metadata +158 -45
  133. data/lib/pubnub_crypto.rb +0 -53
  134. data/lib/pubnub_request.rb +0 -310
@@ -0,0 +1,527 @@
1
+ require 'pubnub/configuration.rb'
2
+ require 'pubnub/subscription.rb'
3
+ require 'em-http-request'
4
+ require 'httparty'
5
+ require 'persistent_httparty'
6
+ require 'timeout'
7
+
8
+ module Pubnub
9
+ class PubNubHTTParty
10
+ include HTTParty
11
+ default_timeout 310
12
+
13
+ def first_run?
14
+ @first_run ? true : false
15
+ end
16
+
17
+ def send_request(path, options={}, &block)
18
+ if @first_run.nil?
19
+ @first_run = true
20
+ else
21
+ @first_run = false
22
+ end
23
+ self.class.get path, options
24
+
25
+ end
26
+ end
27
+
28
+ class Client
29
+ include Configuration
30
+
31
+ attr_accessor :uuid, :cipher_key, :host, :query, :response, :timetoken, :url, :operation, :callback, :publish_key, :subscribe_key, :secret_key, :channel, :jsonp, :message, :ssl, :port
32
+ attr_accessor :close_connection, :history_limit, :history_count, :history_start, :history_end, :history_reverse, :session_uuid, :last_timetoken, :origin, :error
33
+
34
+
35
+ DEFAULT_CONNECT_CALLBACK = lambda { |msg| $log.info "CONNECTED: #{msg}" }
36
+ DEFAULT_ERROR_CALLBACK = lambda { |msg| $log.error "AN ERROR OCCURRED: #{msg}" }
37
+
38
+ def initialize(options = {})
39
+ $log = options[:logger]
40
+ $log = Logger.new('pubnub.log', 0, 100 * 1024 * 1024) unless $log
41
+
42
+ @subscriptions = Array.new
43
+
44
+ @subscription_request = nil
45
+ @retry = true
46
+ @retry_count = 0
47
+ @callback = options[:callback]
48
+ @error_callback = options[:error_callback]
49
+ @error_callback = DEFAULT_ERROR_CALLBACK unless @error_callback
50
+ @connect_callback = options[:connect_callback]
51
+ @connect_callback = DEFAULT_CONNECT_CALLBACK unless @connect_callback
52
+ @cipher_key = options[:cipher_key]
53
+ @publish_key = options[:publish_key] || DEFAULT_PUBLISH_KEY
54
+ @subscribe_key = options[:subscribe_key] || DEFAULT_SUBSCRIBE_KEY
55
+ @channel = options[:channel] || DEFAULT_CHANNEL
56
+ @message = options[:message]
57
+ @ssl = options[:ssl]
58
+ @secret_key = options[:secret_key]
59
+ @timetoken = options[:timetoken]
60
+ @session_uuid = options[:uuid] || options[:session_uuid] || UUID.new.generate
61
+
62
+ @history_count = options[:count]
63
+ @history_start = options[:start]
64
+ @history_end = options[:end]
65
+ @history_reverse = options[:reverse]
66
+
67
+ @port = options[:port]
68
+ @url = options[:url]
69
+ @origin = options[:origin]
70
+ @origin = DEFAULT_ORIGIN unless @origin
71
+ @query = options[:query]
72
+
73
+ @http_sync = options[:http_sync]
74
+
75
+ @max_retries = options[:max_retries]
76
+ @max_retries = MAX_RETRIES unless @max_retries
77
+
78
+ @non_subscribe_timeout = options[:non_subscribe_timeout]
79
+ @non_subscribe_timeout = 5 unless @non_subscribe_timeout
80
+
81
+ @reconnect_max_attempts = options[:reconnect_max_attempts]
82
+ @reconnect_max_attempts = 60 unless @reconnect_max_attempts
83
+
84
+ @reconnect_retry_interval = options[:reconnect_retry_interval]
85
+ @reconnect_retry_interval = 5 unless @reconnect_retry_interval
86
+
87
+ @reconnect_response_timeout = options[:reconnect_response_timeout]
88
+ @reconnect_response_timeout = 5 unless @reconnect_response_timeout
89
+
90
+ @sync_connection_sub = Pubnub::PubNubHTTParty.new
91
+ @sync_connection = Pubnub::PubNubHTTParty.new
92
+
93
+ @pause_subscribe = false
94
+ end
95
+
96
+ def publish(options = {}, &block)
97
+ options[:callback] = block if block_given?
98
+ options = merge_options(options, 'publish')
99
+ verify_operation('publish', options)
100
+ start_request options
101
+
102
+ end
103
+
104
+ def subscribe(options = {}, &block)
105
+ options[:callback] = block if block_given?
106
+ options = merge_options(options, 'subscribe')
107
+ verify_operation('subscribe', options)
108
+ @error_callback.call 'YOU ARE ALREADY SUBSCRIBED TO THAT CHANNEL' if get_channels_for_subscription.include? options[:channel]
109
+ $log.error 'YOU ARE ALREADY SUBSCRIBED TO THAT CHANNEL' if get_channels_for_subscription.include? options[:channel]
110
+ start_request options
111
+ end
112
+
113
+ def presence(options = {}, &block)
114
+ options[:callback] = block if block_given?
115
+ options = merge_options(options, 'presence')
116
+ verify_operation('presence', options)
117
+ start_request options
118
+ end
119
+
120
+ def history(options = {}, &block)
121
+ options[:callback] = block if block_given?
122
+ options = merge_options(options, 'history')
123
+ verify_operation('history', options)
124
+ options[:params].merge!({:count => options[:count]})
125
+ options[:params].merge!({:start => options[:start]}) unless options[:start].nil?
126
+ options[:params].merge!({:end => options[:end]}) unless options[:end].nil?
127
+ options[:params].merge!({:reverse => 'true'}) if options[:reverse]
128
+ start_request options
129
+ end
130
+
131
+ def leave(options = {}, &block)
132
+ options[:callback] = block if block_given?
133
+ options = merge_options(options, 'leave')
134
+ verify_operation('leave', options)
135
+ return false unless get_channels_for_subscription.include? options[:channel]
136
+ remove_from_subscription options[:channel]
137
+ if @subscriptions.empty?
138
+ @timetoken = 0
139
+ @subscription_request.timetoken = 0
140
+ @subscribe_connection.close
141
+ @wait_for_response = false
142
+ end
143
+ start_request options
144
+
145
+ end
146
+
147
+ alias_method :unsubscribe, :leave
148
+
149
+ def here_now(options = {}, &block)
150
+ options[:callback] = block if block_given?
151
+ options = merge_options(options, 'here_now')
152
+ verify_operation('here_now', options)
153
+ start_request options
154
+ end
155
+
156
+ def time(options = {}, &block)
157
+ options[:callback] = block if block_given?
158
+ options = merge_options(options, 'time')
159
+ verify_operation('time', options)
160
+ start_request options
161
+ end
162
+
163
+ def subscription_running?
164
+ @subscription_running
165
+ end
166
+
167
+ def active_subscriptions
168
+ @subscription_request
169
+ end
170
+
171
+ private
172
+
173
+ def remove_from_subscription(channel)
174
+ @subscriptions.delete_if { |s| s.channel.to_s == channel.to_s }
175
+ end
176
+
177
+ def merge_options(options = {}, operation = '')
178
+ options[:channel] = compile_channel_parameter(options[:channel],options[:channels]) if options[:channel] || options[:channels]
179
+ return {
180
+ :ssl => @ssl,
181
+ :cipher_key => @cipher_key,
182
+ :publish_key => @publish_key,
183
+ :subscribe_key => @subscribe_key,
184
+ :secret_key => @secret_key,
185
+ :origin => @origin,
186
+ :operation => operation,
187
+ :params => { :uuid => @session_uuid },
188
+ :timetoken => @timetoken,
189
+ :error_callback=> @error_callback
190
+ }.merge(options)
191
+ end
192
+
193
+ def start_em_if_not_running
194
+ Thread.new do
195
+ EM.run
196
+ end unless EM.reactor_running?
197
+
198
+ until EM.reactor_running? do end
199
+ end
200
+
201
+ def get_channels_for_subscription
202
+ @subscriptions.map do |sub|
203
+ sub.channel
204
+ end
205
+ end
206
+
207
+ def fire_subscriptions_callback_for(envelope)
208
+ @subscriptions.each do |subscription|
209
+ subscription.fire_callback_for envelope
210
+ end
211
+ end
212
+
213
+ def start_request(options)
214
+ request = Pubnub::Request.new(options)
215
+ unless options[:http_sync]
216
+ start_em_if_not_running
217
+
218
+ if %w(subscribe presence).include? request.operation
219
+ options[:channel].split(',').each do |channel|
220
+ @subscriptions << Subscription.new(:channel => channel, :callback => options[:callback], :error_callback => options[:error_callback]) unless get_channels_for_subscription.include? channel
221
+ end
222
+
223
+ @subscription_request = request unless @subscription_request
224
+
225
+ if @subscription_request.channel != get_channels_for_subscription.join(',') && @subscription_running
226
+ @subscribe_connection.close
227
+ @timetoken = 0
228
+ @subscription_request.timetoken = 0
229
+ @wait_for_response = false
230
+ end
231
+
232
+ @subscription_request.channel = get_channels_for_subscription.join(',')
233
+
234
+ @subscription_running = EM.add_periodic_timer(PERIODIC_TIMER) do
235
+
236
+ unless @wait_for_response || get_channels_for_subscription.empty?
237
+ @wait_for_response = true
238
+ $log.debug 'SETTING CHANNELS'
239
+ @subscription_request.channel = get_channels_for_subscription.join(',')
240
+ $log.debug 'SENDING SUBSCRIBE REQUEST'
241
+ http = send_request(@subscription_request)
242
+
243
+ http.callback do
244
+ $log.debug 'GOT SUBSCRIBE RESPONSE'
245
+ @wait_for_response = false
246
+ if http.response_header.status.to_i == 200
247
+ if is_valid_json?(http.response)
248
+ $log.debug 'GOT VALID JSON'
249
+ @subscription_request.handle_response(http)
250
+ $log.debug 'HANDLED RESPONSE'
251
+ if is_update?(@subscription_request.timetoken)
252
+ $log.debug 'TIMETOKEN UPDATED'
253
+ @subscription_request.envelopes.each do |envelope|
254
+ fire_subscriptions_callback_for envelope
255
+ end
256
+ else
257
+ $log.debug 'TIMETOKEN NOT UPDATED'
258
+ end
259
+ end
260
+ else
261
+ if request.error_callback
262
+ request.error_callback.call Pubnub::Response.new(
263
+ :error_init => true,
264
+ :message => [0, "Bad server response: #{http.response_header.status.to_i}"].to_json,
265
+ :response => [0, "Bad server response: #{http.response_header.status.to_i}"].to_json
266
+ )
267
+ else
268
+ fire_subscriptions_callback_for Pubnub::Response.new(
269
+ :error_init => true,
270
+ :message => [0, "Bad server response: #{http.response_header.status.to_i}"].to_json,
271
+ :response => [0, "Bad server response: #{http.response_header.status.to_i}"].to_json
272
+ )
273
+ end
274
+
275
+ end
276
+ end
277
+ http.errback do
278
+ $log.error 'GOT SUBSCRIBE ERROR'
279
+ @error_callback.call [0, http.error]
280
+ end
281
+ end
282
+ end unless @subscription_running
283
+ else
284
+ EM.next_tick do
285
+ $log.debug 'SENDING OTHER REQUEST'
286
+
287
+ http = send_request(request)
288
+
289
+ http.errback do
290
+ @error_callback.call [0, http.error]
291
+ end
292
+
293
+ http.callback do
294
+ $log.debug 'GOT OTHER RESPONSE'
295
+ #byebug
296
+ if http.response_header.status.to_i == 200
297
+ if is_valid_json?(http.response)
298
+ request.handle_response(http)
299
+ request.envelopes.each do |envelope|
300
+ $log.debug 'CALLING PARAMETER CALLBACK'
301
+ request.callback.call envelope
302
+ end
303
+ end
304
+ else
305
+ begin
306
+ request.handle_response(http)
307
+ request.envelopes.each do |envelope|
308
+ if request.error_callback
309
+ request.error_callback.call envelope
310
+ else
311
+ @error_callback.call envelope
312
+ end
313
+ end
314
+
315
+ rescue
316
+ if request.error_callback
317
+ request.error_callback.call Pubnub::Response.new(
318
+ :error_init => true,
319
+ :message => [0, "Bad server response: #{http.response_header.status.to_i}"].to_json,
320
+ :response => [0, "Bad server response: #{http.response_header.status.to_i}"].to_json
321
+ )
322
+ else
323
+ @error_callback.call Pubnub::Response.new(
324
+ :error_init => true,
325
+ :message => [0, "Bad server response: #{http.response_header.status.to_i}"].to_json,
326
+ :response => [0, "Bad server response: #{http.response_header.status.to_i}"].to_json
327
+ )
328
+ end
329
+ end
330
+ end
331
+ end
332
+ end
333
+ end
334
+ else
335
+ begin
336
+ if @timetoken.to_i == 0 && request.operation == 'subscribe'
337
+ time(:http_sync => true){|envelope| @timetoken = envelope.message.to_i }
338
+ end
339
+ begin
340
+ if request.query.to_s.empty?
341
+ if %w(subscribe presence).include? request.operation
342
+ response = @sync_connection_sub.send_request(request.origin + request.path, :timeout => 370)
343
+ else
344
+ response = @sync_connection.send_request(request.origin + request.path, :timeout => @non_subscribe_timeout)
345
+ end
346
+ else
347
+ if %w(subscribe presence).include? request.operation
348
+ response = @sync_connection_sub.send_request(request.origin + request.path, :query => request.query, :timeout => 370)
349
+ else
350
+ response = @sync_connection.send_request(request.origin + request.path, :query => request.query, :timeout => @non_subscribe_timeout)
351
+ end
352
+ end
353
+ rescue
354
+ msg = 'ERROR SENDING REQUEST'
355
+ @error_callback.call Pubnub::Response.new(
356
+ :error_init => true,
357
+ :message => [0, msg].to_s,
358
+ :response => [0, msg].to_s
359
+ )
360
+ @retries = 0 unless @retries
361
+ @retries += 1
362
+ if @retries <= @max_retries
363
+ return start_request options
364
+ else
365
+ msg = "ERROR SENDING REQUEST AFTER #{@retries} RETRIES"
366
+ @retries = 0
367
+ return Pubnub::Response.new(
368
+ :error_init => true,
369
+ :message => [0, msg].to_s,
370
+ :response => [0, msg].to_s
371
+ )
372
+ end
373
+ end
374
+
375
+ if @sync_connection_sub.first_run?
376
+ @connect_callback.call 'SYNC CONNECTION ESTABLISHED'
377
+ end
378
+ if response.response.code.to_i == 200
379
+ if is_valid_json?(response.body)
380
+ request.handle_response(response)
381
+ @timetoken = request.timetoken
382
+
383
+ if request.operation == 'leave'
384
+ Subscription.remove_from_subscription request.channel
385
+ end
386
+
387
+ if !request.callback.nil?
388
+ request.envelopes.each do |envelope|
389
+ request.callback.call envelope
390
+ end
391
+ else
392
+ if %w(publish leave here_now time).include? request.operation
393
+ return request.envelopes[0]
394
+ else
395
+ return request.envelopes
396
+ end
397
+ end
398
+ end
399
+ else
400
+ begin
401
+ request.handle_response(response)
402
+ if !request.callback.nil?
403
+ request.envelopes.each do |envelope|
404
+ request.callback.call envelope
405
+ end
406
+ else
407
+ if %w(publish leave here_now time).include? request.operation
408
+ return request.envelopes[0]
409
+ else
410
+ return request.envelopes
411
+ end
412
+ end
413
+ rescue
414
+ if request.error_callback
415
+ request.error_callback.call Pubnub::Response.new(
416
+ :error_init => true,
417
+ :message => [0, "Bad server response: #{response.response.code.to_i}"].to_json,
418
+ :response => [0, "Bad server response: #{response.response.code.to_i}"].to_json
419
+ )
420
+ else
421
+ @error_callback.call Pubnub::Response.new(
422
+ :error_init => true,
423
+ :message => [0, "Bad server response: #{response.response.code.to_i}"].to_json,
424
+ :response => [0, "Bad server response: #{response.response.code.to_i}"].to_json
425
+ )
426
+ end
427
+ end
428
+
429
+ if @sync_retries
430
+ @sync_retries += 1
431
+ else
432
+ @sync_retries = 1
433
+ end
434
+
435
+ if @sync_retries < @max_retries
436
+ start_request options
437
+ end
438
+ end
439
+ rescue Timeout::Error
440
+ if request.error_callback
441
+ request.error_callback.call [0, 'TIMEOUT']
442
+ else
443
+ @error_callback.call [0, 'TIMEOUT']
444
+ end
445
+ end
446
+ end
447
+ end
448
+
449
+ def send_request(request)
450
+ if %w(subscribe presence).include? request.operation
451
+ unless @subscribe_connection
452
+ @subscribe_connection = EM::HttpRequest.new(request.origin, :connect_timeout => 370, :inactivity_timeout => 370)
453
+ connection = @subscribe_connection.get :path => '/time/0', :keepalive => true, :query => request.query
454
+ #EM.next_tick do
455
+ connection.callback do
456
+ EM.defer do @connect_callback.call 'ASYNC SUBSCRIBE CONNECTION' end
457
+ end
458
+ #end
459
+ end
460
+
461
+ @subscribe_connection.get :path => request.path, :query => request.query, :keepalive => true
462
+ else
463
+ unless @connection
464
+ @connection = EM::HttpRequest.new request.origin
465
+ end
466
+ @connection.get :path => request.path, :query => request.query, :keepalive => true
467
+ end
468
+ end
469
+
470
+ def is_update?(timetoken)
471
+ if @timetoken.to_i < timetoken.to_i
472
+ @timetoken = timetoken
473
+ else
474
+ false
475
+ end
476
+
477
+ end
478
+
479
+ def is_valid_json?(response)
480
+ begin
481
+ JSON.parse(response)
482
+ valid = true
483
+ rescue
484
+ valid = false
485
+ end
486
+ valid
487
+ end
488
+
489
+ def verify_operation(operation, options)
490
+ case operation
491
+ when 'publish'
492
+ raise(ArgumentError, 'publish() requires :channel, :message parameters and, if async, callback parameter or block given.') unless (options[:channel] || options[:channels]) && (options[:callback] || options[:block_given] || options[:http_sync]) && options[:message]
493
+ when 'subscribe'
494
+ raise(ArgumentError, 'subscribe() requires :channel parameters and, if async, callback parameter or block given.') unless (options[:channel] || options[:channels]) && (options[:callback] || options[:block_given] || options[:http_sync])
495
+ when 'presence'
496
+ raise(ArgumentError, 'presence() requires :channel parameters and, if async, callback parameter or block given.') unless (options[:channel] || options[:channels]) && (options[:callback] || options[:block_given] || options[:http_sync])
497
+ when 'time'
498
+ raise(ArgumentError, 'time() require, if async, callback parameter or block given.') unless (options[:callback] || options[:block_given] || options[:http_sync])
499
+ when 'history'
500
+ raise(ArgumentError, 'history() requires :channel, :count parameters and, if async, callback parameter or block given.') unless (options[:channel] || options[:channels]) && (options[:callback] || options[:block_given] || options[:http_sync]) && options[:count]
501
+ when 'here_now'
502
+ raise(ArgumentError, 'here_now() requires :channel parameters and, if async, callback parameter or block given.') unless (options[:channel] || options[:channels]) && (options[:callback] || options[:block_given] || options[:http_sync])
503
+ when 'leave'
504
+ raise(ArgumentError, 'leave() requires :channel parameters and, if async, callback parameter or block given.') unless (options[:channel] || options[:channels]) && (options[:callback] || options[:block_given] || options[:http_sync])
505
+ end
506
+
507
+ unless options[:callback].nil?
508
+ raise('callback is invalid.') unless options[:callback].respond_to? 'call'
509
+ end
510
+
511
+ unless options[:error_callback].nil?
512
+ raise('error_callback is invalid.') unless options[:error_callback].respond_to? 'call'
513
+ end
514
+
515
+ end
516
+
517
+ def compile_channel_parameter(channel, channels)
518
+ raise(ArgumentError, 'Can\'t handle both :channel and :channels parameters given.') if channel && channels
519
+ channel = channels if channels
520
+ channel = channel.to_s if channel.class == Symbol
521
+ channel = channel.map! {|c| c.to_s}.join(',') if channel.class == Array
522
+ return channel
523
+ end
524
+
525
+ end
526
+ end
527
+