Class: RSence::Transporter

Inherits:
Object
  • Object
show all
Defined in:
lib/rsence/transporter.rb

Overview

Transporter handles incoming requests targeted at RSence and distributes calls and data accordingly. It’s called via Broker.

See Also:

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeTransporter

Returns a new instance of Transporter.



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/rsence/transporter.rb', line 38

def initialize
  RSence.transporter = self
  @config = RSence.config[:transporter_conf]
  @accept_req = false
  core_pkgs = {
    :core => [:transporter, :session_storage, :session_manager, :value_manager]
  }
  @plugins = PluginManager.new( {
    :plugin_paths => RSence.config[:plugin_paths],
    :transporter => self,
    :autoreload => RSence.args[:autoupdate],
    :name_prefix => false,
    :resolved_deps => core_pkgs[:core],
    :resolved_categories => core_pkgs
  })
  @valuemanager = ValueManager.new
  RSence.value_manager = @valuemanager
  @sessions = SessionManager.new( self )
  @plugins.sessions = @sessions
  RSence.session_manager = @sessions
  if RSence.config[:session_conf][:reset_sessions]
    puts "Resetting all sessions..."
    @sessions.reset_sessions()
  else
    @sessions.restore_sessions()
  end

  if RSence.launch_pid != Process.pid
    Process.kill( 'TERM', RSence.launch_pid )
  end
end

Instance Attribute Details

#pluginsPluginManager

The main instance of the PluginManager

Returns:



36
37
38
# File 'lib/rsence/transporter.rb', line 36

def plugins
  @plugins
end

#sessionsSessionManager

The single instance of the SessionManager

Returns:



32
33
34
# File 'lib/rsence/transporter.rb', line 32

def sessions
  @sessions
end

#valuemanagerValueManager

The single instance of the ValueManager

Returns:

  • (ValueManager)


28
29
30
# File 'lib/rsence/transporter.rb', line 28

def valuemanager
  @valuemanager
end

Instance Method Details

#find_client_sync_error(options) ⇒ Object



131
132
133
134
135
136
137
138
139
140
141
# File 'lib/rsence/transporter.rb', line 131

def find_client_sync_error( options )
  return false if options.length == 0
  errors = []
  options.each do |err|
    if err.class == Hash and err.has_key?('err_msg')
      errors.push( err['err_msg'] )
    end
  end
  return false if errors.length == 0
  return errors
end

#online=(state) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
# File 'lib/rsence/transporter.rb', line 74

def online=(state)
  return if @accept_req == state
  if RSence.args[:verbose]
    if state
      puts "RSence is online now."
    else
      puts "RSence is offline now."
    end
  end
  @accept_req = state
end

#online?Boolean

Returns:

  • (Boolean)


70
71
72
# File 'lib/rsence/transporter.rb', line 70

def online?
  @accept_req
end

#servlet(request_type, request, response) ⇒ Object



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/rsence/transporter.rb', line 92

def servlet( request_type, request, response )
  broker_urls = RSence.config[:broker_urls]
  uri = request.fullpath

  if request_type == :post
    ## /x handles sync without cookies
    if uri == broker_urls[:x] and @sessions.accept_requests
      sync( request, response, { :cookies => true, :servlet => false } )
      return true
    ## /hello handles the first sync (with cookies, for session key)
    elsif uri == broker_urls[:hello] and @sessions.accept_requests
      sync( request, response, { :cookies => true, :servlet => false } )
      return true
    end
  end
  return @plugins.match_servlet( request_type, request, response, @sessions.servlet_cookie_ses( request, response ) )
end

#shutdownObject



86
87
88
89
90
# File 'lib/rsence/transporter.rb', line 86

def shutdown
  online=false
  @sessions.shutdown
  @plugins.shutdown
end

#sync(request, response, options = { :cookies => false, :servlet => false }) ⇒ Object

handles incoming XMLHttpRequests from the browser



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
# File 'lib/rsence/transporter.rb', line 144

def sync(request, response, options = { :cookies => false, :servlet => false } )
  request_body = request.body.read
  begin
    request_content = JSON.parse( request_body )
  rescue JSON::ParseError
    warn "Request body isn't valid JSON: #{request_body}"
    request_content = ['-1:.o.:INVALID',{},[]]
  end
  options[:ses_key] = request_content[0]
  options[:values] = request_content[1]
  options[:messages] = request_content[2]

  session_conf = RSence.config[:session_conf]

  options[:cookies] = false unless options.has_key?(:cookies)

  if session_conf[:session_cookies] and session_conf[:trust_cookies]
    options[:cookies] = true
  end

  # Creates the msg object, also checks or creates a new session; verifies session keys and such
  msg = @sessions.init_msg( request, response, options )

  response_success = true
  
  client_errors = find_client_sync_error( options[:messages] )

  # If the client encounters an error, display error message
  if client_errors #request.query.has_key?('err_msg')
    response_success = false
    client_error_msg = client_errors.inspect
    puts "\nCLIENT ERROR:\n#{client_error_msg}\n" if RSence.args[:debug]
    sync_error_handler(msg,:client_error,client_error_msg)
  end

  # If the session is valid, continue:
  if msg.ses_valid and response_success
    
    # If cookies are true, it means the url base needs to
    # be changed from /hello to /x to prevent further cookie juggling.
    if options[:cookies] and not options[:servlet]
      conf_sync_url = RSence.config[:broker_urls][:x]
    else
      conf_sync_url = RSence.config[:broker_urls][:hello]
    end
    if msg.request.path != conf_sync_url
      msg.reply("COMM.Transporter.url=#{conf_sync_url.to_json};")
    end
    
    # Appends a 'new session.' message for new sessions in RSence.args[:verbose]:
    if RSence.args[:verbose]
      puts "new session." if msg.new_session
      puts "restored session." if msg.restored_session
      puts "clone source." if msg.cloned_targets
      puts "clone target." if msg.cloned_source
    end
    
    ## Pass the client XML to the value manager
    if options[:values].has_key?('set')#request.query.has_key?( 'values' )
      # syncdata_str = request.query[ 'values' ]
      begin
        @valuemanager.sync( msg, options[:values]['set'] )
      rescue => e
        response_success = false
        sync_error_handler( msg, :valuemanager_sync_error, e.message )
        sync_traceback_handler( e, "Transporter::ValueManagerXHRError: @valuemanager.sync failed." )
      end
    end
  
    ## Calls the restore_ses of plugins, when a session is restored (page reload with previously active session)
    if msg.restored_session
      msg.session[:deps] = []
      
      if msg.cloned_source
        begin
          @plugins.delegate( :cloned_target, msg, msg.cloned_source )
        rescue => e
          response_success = false
          sync_error_handler( msg, :plugin_delegate_cloned_target_error, e.message )
          sync_traceback_handler( e, "Transporter::PluginDelegateClonedTargetError: @plugins.delegate 'cloned_target' failed." )
        end
      end
      
      begin
        @plugins.delegate( :restore_ses, msg )
        msg.session[:plugin_incr] = @plugins.incr
      rescue => e
        response_success = false
        sync_error_handler( msg, :plugin_delegate_restore_ses_error, e.message )
        sync_traceback_handler( e, "Transporter::PluginDelegateRestoreSesError: @plugins.delegate 'restore_ses' failed." )
      end
      
    elsif msg.new_session
      
      begin
        @plugins.delegate( :init_ses, msg )
        msg.session[:plugin_incr] = @plugins.incr
      rescue => e
        response_success = false
        sync_error_handler( msg, :plugin_delegate_init_ses_error, e.message )
        sync_traceback_handler( e, "Transporter::PluginDelegateInitSesError: @plugins.delegate 'init_ses' failed." )
      end
      
    elsif msg.cloned_targets
      
      begin
        @plugins.delegate( :cloned_source, msg, msg.cloned_targets )
      rescue => e
        response_success = false
        sync_error_handler( msg, :plugin_delegate_cloned_source_error, e.message )
        sync_traceback_handler( e, "Transporter::PluginDelegateClonedSourceError: @plugins.delegate 'cloned_source' failed." )
      end
      
    elsif msg.refresh_page?( @plugins.incr ) and @config[:client_autoreload]
      while msg.refresh_page?( @plugins.incr )
        msg.session[:plugin_incr] = @plugins.incr
        sleep 0.5
      end
      # Forces the client to reload, if plugins are incremented
      msg.reply("window.location.reload( true );")
    end
    
    ## Calls validators for changed values
    begin
      @valuemanager.validate( msg )
    rescue => e
      response_success = false
      sync_error_handler( msg, :valuemanager_validate_error, e.message )
      sync_traceback_handler( e, "Transporter::ValueManagerValidateError: @valuemanager.validate failed." )
    end
    
    ### Allows every plugin to respond to the idle call
    begin
      @plugins.delegate( :idle, msg )
    rescue => e
      response_success = false
      sync_error_handler( msg, :plugin_idle_error, e.message )
      sync_traceback_handler( e, "Transporter::PluginIdleError: @plugins.idle failed." )
    end
    
    ### Processes outgoing values to client
    begin
      @valuemanager.sync_client( msg )
    rescue => e
      response_success = false
      sync_error_handler( msg, :valuemanager_sync_client_error, e.message )
      sync_traceback_handler( e, "Transporter::ValueManagerSyncClientError: @valuemanager.sync_client failed." )
    end
    
  else
  
    # session is not valid, the error was set in SessionManager
    response_success = false
  
  end

  msg.response_success = response_success

  unless options[:servlet]
    msg.response_done()
  end

  return msg
end

#sync_error_handler(msg, err_name, err_extra_descr = '') ⇒ Object

wrapper for the session manager stop client functionality



111
112
113
114
115
116
117
# File 'lib/rsence/transporter.rb', line 111

def sync_error_handler(msg,err_name,err_extra_descr='')
  @sessions.stop_client_with_message( msg,
    @config[:messages][err_name][:title],
    @config[:messages][err_name][:descr]+err_extra_descr,
    @config[:messages][err_name][:uri]
  )
end

#sync_traceback_handler(e, err_descr = 'Transporter::UnspecifiedError') ⇒ Object

wrapper for tracebacks in sync



120
121
122
123
124
125
126
127
128
129
# File 'lib/rsence/transporter.rb', line 120

def sync_traceback_handler(e,err_descr='Transporter::UnspecifiedError')
  puts "=="*40 if RSence.args[:debug]
  puts err_descr
  if RSence.args[:debug]
    puts "--"*40
    puts e.message
    puts "  #{e.backtrace.join("\n  ")}"
    puts "=="*40
  end
end