Class: SockJS::Session

Inherits:
MetaState::Machine show all
Defined in:
lib/sockjs/session.rb

Defined Under Namespace

Classes: Consumer

Constant Summary

Constants inherited from MetaState::Machine

MetaState::Machine::NON_MESSAGES

Instance Attribute Summary collapse

Attributes inherited from MetaState::Machine

#current_state

Instance Method Summary collapse

Methods inherited from MetaState::Machine

add_state, build_void_state, #debug_with, default_state, default_state=, state, #state=, state_names, states, void_state_module

Constructor Details

#initialize(connection) ⇒ Session

Returns a new instance of Session.



306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
# File 'lib/sockjs/session.rb', line 306

def initialize(connection)
  super()

  debug_with do |msg|
    SockJS::debug(msg)
  end

  @connection = connection
  @disconnect_delay = 5 # TODO: make this configurable.
  @received_messages = []
  @outbox = []
  @total_sent_content_length = 0
  @interval = 0.1
  @closing_frame = nil
  @data = {}
  @alive = true
  @timers = {}
end

Instance Attribute Details

#closing_frameObject (readonly)

Returns the value of attribute closing_frame.



304
305
306
# File 'lib/sockjs/session.rb', line 304

def closing_frame
  @closing_frame
end

#dataObject (readonly)

Returns the value of attribute data.



304
305
306
# File 'lib/sockjs/session.rb', line 304

def data
  @data
end

#disconnect_delayObject

Returns the value of attribute disconnect_delay.



303
304
305
# File 'lib/sockjs/session.rb', line 303

def disconnect_delay
  @disconnect_delay
end

#intervalObject

Returns the value of attribute interval.



303
304
305
# File 'lib/sockjs/session.rb', line 303

def interval
  @interval
end

#outboxObject (readonly)

Returns the value of attribute outbox.



304
305
306
# File 'lib/sockjs/session.rb', line 304

def outbox
  @outbox
end

#responseObject (readonly)

Returns the value of attribute response.



304
305
306
# File 'lib/sockjs/session.rb', line 304

def response
  @response
end

#transportObject (readonly)

Returns the value of attribute transport.



304
305
306
# File 'lib/sockjs/session.rb', line 304

def transport
  @transport
end

Instance Method Details

#_set_heartbeat_timerObject



430
431
432
433
434
435
436
# File 'lib/sockjs/session.rb', line 430

def _set_heartbeat_timer
  clear_timer(:disconnect)
  clear_timer(:alive)
  set_timer(:heartbeat, EM::PeriodicTimer, 25) do
    heartbeat_triggered
  end
end

#activatedObject



291
292
# File 'lib/sockjs/session.rb', line 291

def activated
end

#after_app_runObject



285
286
# File 'lib/sockjs/session.rb', line 285

def after_app_run
end

#after_consumer_attachedObject



297
298
# File 'lib/sockjs/session.rb', line 297

def after_consumer_attached
end

#after_consumer_detachedObject



300
301
# File 'lib/sockjs/session.rb', line 300

def after_consumer_detached
end

#alive?Boolean

Returns:

  • (Boolean)


325
326
327
# File 'lib/sockjs/session.rb', line 325

def alive?
  !!@alive
end

#check_content_lengthObject



246
247
248
249
250
251
252
253
254
255
# File 'lib/sockjs/session.rb', line 246

def check_content_length
  if @consumer.total_sent_length >= max_permitted_content_length
    SockJS.debug "Maximum content length exceeded, closing the connection."

    #shouldn't be restarting connection?
    @consumer.disconnect
  else
    SockJS.debug "Permitted content length: #{@consumer.total_sent_length} of #{max_permitted_content_length}"
  end
end

#check_response_aliveObject



367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
# File 'lib/sockjs/session.rb', line 367

def check_response_alive
  if @consumer
    begin
      @consumer.check_alive
    rescue Exception => error
      puts "==> #{error.message}"
      SockJS.debug error
      puts "==> #{error.message}"
      on_close
      @alive_checker.cancel
    end
  else
    puts "~ [TODO] Not checking if still alive, why?"
  end
end

#clear_all_timersObject



411
412
413
414
415
416
# File 'lib/sockjs/session.rb', line 411

def clear_all_timers
  @timers.values.each do |timer|
    timer.cancel
  end
  @timers.clear
end

#clear_timer(name) ⇒ Object



406
407
408
409
# File 'lib/sockjs/session.rb', line 406

def clear_timer(name)
  @timers[name].cancel unless @timers[name].nil?
  @timers.delete(name)
end

#closedObject



288
289
# File 'lib/sockjs/session.rb', line 288

def closed
end

#disconnect_expiredObject

Timer actions:



361
362
363
364
365
# File 'lib/sockjs/session.rb', line 361

def disconnect_expired
  SockJS.debug "#{@disconnect_delay} has passed, firing @disconnect_timer"
  close
  #XXX Shouldn't destroy the session?
end

#heartbeat_triggeredObject



383
384
385
386
387
388
389
390
391
392
393
394
# File 'lib/sockjs/session.rb', line 383

def heartbeat_triggered
  # It's better as we know for sure that
  # clearing the buffer won't change it.
  SockJS.debug "Sending heartbeat frame."
  begin
    send_heartbeat
  rescue Exception => error
    # Nah these exceptions are OK ... let's figure out when they occur
    # and let's just not set the timer for such cases in the first place.
    SockJS.debug "Exception when sending heartbeat frame: #{error.inspect}"
  end
end

#max_permitted_content_lengthObject



335
336
337
# File 'lib/sockjs/session.rb', line 335

def max_permitted_content_length
  @max_permitted_content_length ||= ($DEBUG ? 4096 : 128_000)
end

#on_closeObject

XXX This is probably important - need to examine this case



330
331
332
333
# File 'lib/sockjs/session.rb', line 330

def on_close
  SockJS.debug "The connection has been closed on the client side (current status: #{@status})."
  close_session(1002, "Connection interrupted")
end

#openedObject



282
283
# File 'lib/sockjs/session.rb', line 282

def opened
end

#parse_json(data) ⇒ Object



339
340
341
342
343
344
345
346
347
# File 'lib/sockjs/session.rb', line 339

def parse_json(data)
  if data.empty?
    return []
  end

  JSON.parse("[#{data}]")[0]
rescue JSON::ParserError
  raise SockJS::InvalidJSON.new(500, "Broken JSON encoding.")
end

#process_message(message) ⇒ Object



279
280
# File 'lib/sockjs/session.rb', line 279

def process_message(message)
end

#receive_message(data) ⇒ Object

All incoming data is treated as incoming messages, either single json-encoded messages or an array of json-encoded messages, depending on transport.



228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/sockjs/session.rb', line 228

def receive_message(data)
  clear_timer(:disconnect)
  activate

  SockJS.debug "Session receiving message: #{data.inspect}"
  messages = parse_json(data)
  SockJS.debug "Message parsed as: #{messages.inspect}"
  unless messages.empty?
    @received_messages.push(*messages)
  end

  EM.next_tick do
    run_user_app
  end

  set_disconnect_timer
end

#reset_alive_timerObject



425
426
427
428
# File 'lib/sockjs/session.rb', line 425

def reset_alive_timer
  clear_timer(:alive_check)
  set_alive_timer
end

#reset_close_timerObject



460
461
462
463
# File 'lib/sockjs/session.rb', line 460

def reset_close_timer
  clear_timer(:close)
  set_close_timer
end

#reset_disconnect_timerObject



449
450
451
452
# File 'lib/sockjs/session.rb', line 449

def reset_disconnect_timer
  clear_timer(:disconnect)
  set_disconnect_timer
end

#reset_heartbeat_timerObject



438
439
440
441
# File 'lib/sockjs/session.rb', line 438

def reset_heartbeat_timer
  clear_timer(:heartbeat)
  set_heartbeat_timer
end

#run_user_appObject



257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
# File 'lib/sockjs/session.rb', line 257

def run_user_app
  unless @received_messages.empty?
    reset_heartbeat_timer #XXX Only one point which can set heartbeat while state is closed

    SockJS.debug "Executing user's SockJS app"

    raise @error if @error

    @received_messages.each do |message|
      SockJS.debug "Executing app with message #{message.inspect}"
      process_message(message)
    end
    @received_messages.clear

    after_app_run

    SockJS.debug "User's SockJS app finished"
  end
rescue SockJS::CloseError => error
  Protocol::ClosingFrame.new(error.status, error.message)
end

#set_alive_timerObject



419
420
421
422
423
# File 'lib/sockjs/session.rb', line 419

def set_alive_timer
  set_timer(:alive_check, EM::PeriodicTimer, 1) do
    check_response_alive
  end
end

#set_close_timerObject



454
455
456
457
458
# File 'lib/sockjs/session.rb', line 454

def set_close_timer
  set_timer(:close, EM::Timer, @disconnect_delay) do
    @alive = false
  end
end

#set_disconnect_timerObject



443
444
445
446
447
# File 'lib/sockjs/session.rb', line 443

def set_disconnect_timer
  set_timer(:disconnect, EM::Timer, @disconnect_delay) do
    disconnect_expired
  end
end

#set_timer(name, type, delay, &action) ⇒ Object

Timer machinery



398
399
400
401
402
403
404
# File 'lib/sockjs/session.rb', line 398

def set_timer(name, type, delay, &action)
  @timers[name] ||=
    begin
      SockJS.debug "Setting timer: #{name} to expire after #{delay}"
      type.new(delay, &action)
    end
end

#suspendedObject



294
295
# File 'lib/sockjs/session.rb', line 294

def suspended
end