agent_xmpp 0.1.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.
Files changed (73) hide show
  1. data/.document +5 -0
  2. data/.gitignore +11 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +417 -0
  5. data/Rakefile +75 -0
  6. data/VERSION +1 -0
  7. data/agent_xmpp.gemspec +144 -0
  8. data/lib/agent_xmpp.rb +22 -0
  9. data/lib/agent_xmpp/admin.rb +113 -0
  10. data/lib/agent_xmpp/client.rb +7 -0
  11. data/lib/agent_xmpp/client/boot.rb +83 -0
  12. data/lib/agent_xmpp/client/client.rb +64 -0
  13. data/lib/agent_xmpp/client/connection.rb +108 -0
  14. data/lib/agent_xmpp/client/controller.rb +394 -0
  15. data/lib/agent_xmpp/client/message_delegate.rb +720 -0
  16. data/lib/agent_xmpp/client/message_pipe.rb +193 -0
  17. data/lib/agent_xmpp/client/response.rb +102 -0
  18. data/lib/agent_xmpp/config.rb +48 -0
  19. data/lib/agent_xmpp/main.rb +175 -0
  20. data/lib/agent_xmpp/models.rb +7 -0
  21. data/lib/agent_xmpp/models/contact.rb +85 -0
  22. data/lib/agent_xmpp/models/message.rb +152 -0
  23. data/lib/agent_xmpp/models/publication.rb +53 -0
  24. data/lib/agent_xmpp/models/roster.rb +107 -0
  25. data/lib/agent_xmpp/models/service.rb +91 -0
  26. data/lib/agent_xmpp/models/subscription.rb +61 -0
  27. data/lib/agent_xmpp/models/table_definitions.rb +107 -0
  28. data/lib/agent_xmpp/patches.rb +7 -0
  29. data/lib/agent_xmpp/patches/array.rb +32 -0
  30. data/lib/agent_xmpp/patches/float.rb +10 -0
  31. data/lib/agent_xmpp/patches/hash.rb +13 -0
  32. data/lib/agent_xmpp/patches/object.rb +15 -0
  33. data/lib/agent_xmpp/patches/rexml.rb +69 -0
  34. data/lib/agent_xmpp/patches/string.rb +15 -0
  35. data/lib/agent_xmpp/xmpp.rb +18 -0
  36. data/lib/agent_xmpp/xmpp/element.rb +158 -0
  37. data/lib/agent_xmpp/xmpp/entry.rb +36 -0
  38. data/lib/agent_xmpp/xmpp/error_response.rb +189 -0
  39. data/lib/agent_xmpp/xmpp/iq.rb +90 -0
  40. data/lib/agent_xmpp/xmpp/iq_command.rb +54 -0
  41. data/lib/agent_xmpp/xmpp/iq_disco.rb +206 -0
  42. data/lib/agent_xmpp/xmpp/iq_pubsub.rb +270 -0
  43. data/lib/agent_xmpp/xmpp/iq_roster.rb +183 -0
  44. data/lib/agent_xmpp/xmpp/iq_version.rb +89 -0
  45. data/lib/agent_xmpp/xmpp/jid.rb +150 -0
  46. data/lib/agent_xmpp/xmpp/message.rb +82 -0
  47. data/lib/agent_xmpp/xmpp/presence.rb +127 -0
  48. data/lib/agent_xmpp/xmpp/sasl.rb +241 -0
  49. data/lib/agent_xmpp/xmpp/stanza.rb +107 -0
  50. data/lib/agent_xmpp/xmpp/x_data.rb +357 -0
  51. data/test/app/app.rb +339 -0
  52. data/test/cases/test_application_message_processing.rb +65 -0
  53. data/test/cases/test_errors.rb +24 -0
  54. data/test/cases/test_presence_management.rb +139 -0
  55. data/test/cases/test_roster_management.rb +214 -0
  56. data/test/cases/test_service_discovery.rb +168 -0
  57. data/test/cases/test_session_management.rb +120 -0
  58. data/test/cases/test_version_discovery.rb +67 -0
  59. data/test/helpers/matchers.rb +23 -0
  60. data/test/helpers/mocks.rb +82 -0
  61. data/test/helpers/test_case_extensions.rb +45 -0
  62. data/test/helpers/test_client.rb +44 -0
  63. data/test/helpers/test_delegate.rb +60 -0
  64. data/test/helpers/test_helper.rb +91 -0
  65. data/test/messages/application_messages.rb +206 -0
  66. data/test/messages/error_messages.rb +35 -0
  67. data/test/messages/presence_messages.rb +66 -0
  68. data/test/messages/roster_messages.rb +126 -0
  69. data/test/messages/service_discovery_messages.rb +201 -0
  70. data/test/messages/session_messages.rb +158 -0
  71. data/test/messages/version_discovery_messages.rb +69 -0
  72. data/test/peer/peer.rb +21 -0
  73. metadata +187 -0
@@ -0,0 +1,64 @@
1
+ ##############################################################################################################
2
+ module AgentXmpp
3
+
4
+ #####-------------------------------------------------------------------------------------------------------
5
+ class Client
6
+
7
+ #####-------------------------------------------------------------------------------------------------------
8
+ class << self
9
+
10
+ #### self
11
+ end
12
+
13
+ #---------------------------------------------------------------------------------------------------------
14
+ attr_reader :connection
15
+ #---------------------------------------------------------------------------------------------------------
16
+
17
+ #.........................................................................................................
18
+ def initialize
19
+ end
20
+
21
+ #.........................................................................................................
22
+ def connect
23
+ while (true)
24
+ EventMachine.run do
25
+ @connection = EventMachine.connect(AgentXmpp.jid.domain, AgentXmpp.port, Connection, self)
26
+ end
27
+ Boot.call_if_implemented(:call_restarting_client, pipe)
28
+ sleep(10.0)
29
+ AgentXmpp.logger.warn "RESTARTING CLIENT"
30
+ end
31
+ end
32
+
33
+ #.........................................................................................................
34
+ def close_connection
35
+ AgentXmpp.logger.info "CLOSE CONNECTION"
36
+ connection.close_connection_after_writing unless connection.nil?
37
+ end
38
+
39
+ #.........................................................................................................
40
+ def reconnect
41
+ AgentXmpp.logger.info "RECONNECTING"
42
+ connection.reconnect(jid.domain, port) unless connection.nil?
43
+ end
44
+
45
+ #.........................................................................................................
46
+ def pipe
47
+ connection.pipe
48
+ end
49
+
50
+ #.........................................................................................................
51
+ def add_delegate(delegate)
52
+ connection.pipe.add_delegate(delegate)
53
+ end
54
+
55
+ #.........................................................................................................
56
+ def remove_delegate(delegate)
57
+ connection.pipe.remove_delegate(delegate)
58
+ end
59
+
60
+ #### Client
61
+ end
62
+
63
+ #### AgentXmpp
64
+ end
@@ -0,0 +1,108 @@
1
+ ##############################################################################################################
2
+ module AgentXmpp
3
+
4
+ #####-------------------------------------------------------------------------------------------------------
5
+ class Connection < EventMachine::Connection
6
+
7
+ #---------------------------------------------------------------------------------------------------------
8
+ include EventMachine::XmlPushParser
9
+ #---------------------------------------------------------------------------------------------------------
10
+
11
+ #---------------------------------------------------------------------------------------------------------
12
+ attr_reader :client, :delegates, :keepalive, :pipe
13
+ #---------------------------------------------------------------------------------------------------------
14
+
15
+ #.........................................................................................................
16
+ def initialize(client)
17
+ @client = client
18
+ @pipe = MessagePipe.new(self)
19
+ end
20
+
21
+ #---------------------------------------------------------------------------------------------------------
22
+ # EventMachine::Connection callbacks
23
+ #.........................................................................................................
24
+ def connection_completed
25
+ @keepalive = EventMachine::PeriodicTimer.new(60) do
26
+ send_data("\n")
27
+ end
28
+ AgentXmpp.start_garbage_collection(pipe)
29
+ pipe.connection_completed
30
+ end
31
+
32
+ #.........................................................................................................
33
+ def receive_data(data)
34
+ super(data)
35
+ end
36
+
37
+ #.........................................................................................................
38
+ def unbind
39
+ if @keepalive
40
+ @keepalive.cancel
41
+ @keepalive = nil
42
+ end
43
+ pipe.unbind
44
+ end
45
+
46
+ #---------------------------------------------------------------------------------------------------------
47
+ # EventMachine::XmlPushParser callbacks
48
+ #.........................................................................................................
49
+ def start_document
50
+ end
51
+
52
+ #.........................................................................................................
53
+ def start_element(name, attrs)
54
+ e = REXML::Element.new(name)
55
+ e.add_attributes(attrs)
56
+ @current = @current.nil? ? e : @current.add_element(e)
57
+ if @current.xpath == 'stream:stream'
58
+ process
59
+ @current = nil
60
+ end
61
+ end
62
+
63
+ #.........................................................................................................
64
+ def end_element(name)
65
+ if @current and @current.parent
66
+ @current = @current.parent
67
+ else
68
+ process
69
+ @current = nil
70
+ end
71
+ end
72
+
73
+ #.........................................................................................................
74
+ def characters(text)
75
+ @current.text = @current.text.to_s + text if @current
76
+ end
77
+
78
+ #.........................................................................................................
79
+ def error(*args)
80
+ AgentXmpp.logger.error *args
81
+ end
82
+
83
+ #.........................................................................................................
84
+ def process
85
+ if @current
86
+ @current.add_namespace(@streamns) if @current.namespace('').to_s.eql?('')
87
+ begin
88
+ stanza = Xmpp::Stanza::import(@current)
89
+ rescue Xmpp::NoNameXmlnsRegistered
90
+ stanza = @current
91
+ end
92
+ if @current.xpath.eql?('stream:stream')
93
+ @streamns = @current.namespace('') if @current.namespace('')
94
+ end
95
+ receive(stanza) if respond_to?(:receive)
96
+ end
97
+ end
98
+
99
+ #.........................................................................................................
100
+ def receive(stanza)
101
+ pipe.receive(stanza)
102
+ end
103
+
104
+ #### Connection
105
+ end
106
+
107
+ #### AgentXmpp
108
+ end
@@ -0,0 +1,394 @@
1
+ ##############################################################################################################
2
+ module AgentXmpp
3
+
4
+ #####-------------------------------------------------------------------------------------------------------
5
+ class BaseController
6
+
7
+ #---------------------------------------------------------------------------------------------------------
8
+ @routes = {}
9
+ @before_filters = {}
10
+ @commands_list = {}
11
+ @commands_list_mutex = Mutex.new
12
+
13
+ #---------------------------------------------------------------------------------------------------------
14
+ class << self
15
+
16
+ #.........................................................................................................
17
+ attr_reader :routes, :before_filters, :commands_list, :commands_list_mutex
18
+
19
+ #.........................................................................................................
20
+ # application interface
21
+ #.........................................................................................................
22
+ def command(node, opts = {}, &blk)
23
+ route(:command, {:node => node, :opts => opts, :blk => blk})
24
+ end
25
+
26
+ #.........................................................................................................
27
+ def event(jid, node, opts = {}, &blk)
28
+ j = Xmpp::Jid.new(jid)
29
+ route(:event, {:node => "/home/#{j.domain}/#{j.node}/#{node}", :domain => j.domain, :opts => opts, :blk => blk})
30
+ end
31
+
32
+ #.........................................................................................................
33
+ def chat(opts = {}, &blk)
34
+ route(:chat, {:opts => opts, :blk => blk})
35
+ end
36
+
37
+ #.........................................................................................................
38
+ def before(args=nil, &blk)
39
+ args = {:command => :all, :event => :all, :chat => :all} if args.nil? or args.eql?(:all)
40
+ args.each {|(msg_type, nodes)| add_before_filter(msg_type, {:nodes => nodes, :blk => blk})}
41
+ end
42
+
43
+ #.........................................................................................................
44
+ def include_module(mod)
45
+ include(mod)
46
+ end
47
+
48
+ #.........................................................................................................
49
+ # managment
50
+ #.........................................................................................................
51
+ def route(msg_type, nroute)
52
+ (routes[msg_type] ||= []).push(nroute).last
53
+ end
54
+
55
+ #.........................................................................................................
56
+ def add_before_filter(msg_type, nodes)
57
+ (before_filters[msg_type] ||= []).push(nodes).last
58
+ end
59
+
60
+ #.........................................................................................................
61
+ def command_nodes(jid=nil)
62
+ (routes[:command] ||= []).inject([]) do |nodes, route|
63
+ if jid and not AgentXmpp.is_account_jid?(jid)
64
+ groups, access = Contact.find_by_jid(jid)[:groups], [route[:opts][:access] || []].flatten
65
+ (access.empty? or access.any?{|a| groups.include?(a)}) ? nodes << route[:node] : nodes
66
+ else; nodes << route[:node]; end
67
+ end
68
+ end
69
+
70
+ #.........................................................................................................
71
+ def subscriptions(service)
72
+ (routes[:event] ||= []).inject([]){|s,r| /#{r[:domain]}/.match(service) ? s << r[:node] : s}
73
+ end
74
+
75
+ #.........................................................................................................
76
+ def event_domains
77
+ (routes[:event] ||= []).map{|r| r[:domain]}.uniq
78
+ end
79
+
80
+ #.........................................................................................................
81
+ def add_command_to_list(session_id, controller)
82
+ commands_list_mutex.synchronize do
83
+ commands_list[session_id] = {:controller=>controller, :created_at=>Time.now}
84
+ end
85
+ end
86
+
87
+ #.........................................................................................................
88
+ def remove_command_from_list(session_id)
89
+ if commands_list[session_id]
90
+ commands_list_mutex.synchronize{commands_list.delete(session_id)}
91
+ end
92
+ end
93
+
94
+ #### self
95
+ end
96
+
97
+ #.........................................................................................................
98
+ attr_reader :params, :pipe, :route, :params_list, :submits
99
+
100
+ #.........................................................................................................
101
+ def initialize(pipe, params)
102
+ @params, @pipe = params, pipe
103
+ @params_list, @submits = [params], []
104
+ end
105
+
106
+ #.........................................................................................................
107
+ def next(params)
108
+ @params = params
109
+ @params_list << params
110
+ self
111
+ end
112
+
113
+ #.........................................................................................................
114
+ # internal interface
115
+ #.......................................................................................................
116
+ def invoke_command
117
+ params[:sessionid] = Xmpp::IdGenerator.generate_id
118
+ invoke_command_on_route do
119
+ define_meta_class_method(:request, &route[:blk])
120
+ define_meta_class_method(:request_handler) do
121
+ run_command(request)
122
+ end
123
+ define_meta_class_method(:request_callback) do |*resp|
124
+ resp = resp.length.eql?(1) ? resp.first : resp
125
+ add_payload_to_container(resp)
126
+ end
127
+ process_request
128
+ end
129
+ end
130
+
131
+ #.......................................................................................................
132
+ def invoke_command_next
133
+ invoke_command_on_route do
134
+ define_meta_class_method(:request_handler) do
135
+ if params[:x_data_type].eql?(:submit)
136
+ on_submit
137
+ end
138
+ end
139
+ process_request
140
+ end
141
+ end
142
+
143
+ #.......................................................................................................
144
+ def invoke_event
145
+ @route = get_route(:event)
146
+ unless route.nil?
147
+ define_meta_class_method(:request, &route[:blk])
148
+ define_meta_class_method(:request_handler) do
149
+ request; delegate_methods.delegate(pipe, self); flush_messages
150
+ end
151
+ process_request
152
+ else
153
+ AgentXmpp.logger.error "ROUTING ERROR: no route for {:node => '#{params[:node]}'}."
154
+ end
155
+ end
156
+
157
+ #.......................................................................................................
158
+ def invoke_chat
159
+ @route = chat_route
160
+ unless route.nil?
161
+ define_meta_class_method(:request_handler, &route[:blk])
162
+ else
163
+ define_meta_class_method(:request_handler) do
164
+ "#{AgentXmpp::AGENT_XMPP_NAME} #{AgentXmpp::VERSION}, #{AgentXmpp::OS_VERSION}"
165
+ end
166
+ end
167
+ define_meta_class_method(:request_callback) do |result|
168
+ add_payload_to_container(result) if result.kind_of?(String)
169
+ end
170
+ process_request
171
+ end
172
+
173
+ #.......................................................................................................
174
+ def delegate_methods
175
+ @delegate_methods ||= AgentXmpp::Delegate.new
176
+ end
177
+
178
+ #.......................................................................................................
179
+ def messages
180
+ @messages ||= []
181
+ end
182
+
183
+ #.......................................................................................................
184
+ def flush_messages
185
+ pipe.send_resp(messages); messages.clear
186
+ end
187
+
188
+ #.........................................................................................................
189
+ # application interface
190
+ #.......................................................................................................
191
+ def error(err, *args)
192
+ AgentXmpp::Error.new(err, *args)
193
+ end
194
+
195
+ #.......................................................................................................
196
+ def on(action, opts= {}, &blk)
197
+ if action.eql?(:submit)
198
+ @submits << {:opts=>opts, :blk=>blk}
199
+ else
200
+ define_meta_class_method(("on_"+action.to_s).to_sym, &blk)
201
+ end
202
+ end
203
+
204
+ #.......................................................................................................
205
+ def xmpp_msg(msg)
206
+ messages << msg
207
+ end
208
+
209
+ #.......................................................................................................
210
+ def delegate_to(methods)
211
+ delegate_methods.add_delegate_methods(methods); delegate_methods
212
+ end
213
+
214
+ #.........................................................................................................
215
+ def command_completed
216
+ Xmpp::IqCommand.send_command(:to=>params[:from], :node=>params[:node], :iq_type=>:result, :status=>:completed,
217
+ :id => params[:id], :sessionid => params[:sessionid])
218
+ end
219
+
220
+ #.........................................................................................................
221
+ def command_request(args, &blk)
222
+ raise ArgmentError ':to and :node are required' unless args[:to] and args[:node]
223
+ Xmpp::IqCommand.send_command(:to=>args[:to], :node=>args[:node], :iq_type=>:set, :action=>:execute, :payload=>args[:payload], &blk)
224
+ end
225
+
226
+ #.........................................................................................................
227
+ # managment
228
+ #.......................................................................................................
229
+ def on_submit
230
+ unless(sub = submits.shift).nil?
231
+ update_command_list
232
+ blk, guard = sub[:blk], sub[:opts][:guard]
233
+ call_blk = lambda{|| blk.arity.eql?(1) ? blk.call(Xmpp::XData.new('form')) : blk.call}
234
+ result = if guard.nil?
235
+ call_blk[]
236
+ else
237
+ (guard.arity.eql?(1) ? guard.call(self) : guard.call) ? call_blk[] : on_submit
238
+ end
239
+ result.nil? ? on_submit : result
240
+ end
241
+ end
242
+
243
+ ####......................................................................................................
244
+ # private
245
+ ####......................................................................................................
246
+ def run_command(req)
247
+ request_method = ("on_"+(params[:x_data_type] || params[:action]).to_s).to_sym
248
+ if respond_to?(request_method)
249
+ if params[:action].eql?(:execute) and params[:x_data_type].nil?
250
+ form = Xmpp::XData.new('form')
251
+ on_execute(form); form
252
+ elsif params[:action].eql?(:cancel)
253
+ on_cancel
254
+ else
255
+ send(request_method)
256
+ end
257
+ else
258
+ req
259
+ end
260
+ end
261
+
262
+ #.........................................................................................................
263
+ def process_request
264
+ if route and route[:opts] and route[:opts][:defer]
265
+ EventMachine.defer(method(:request_handler).to_proc, respond_to?(:request_callback) ? method(:request_callback).to_proc : nil)
266
+ else
267
+ respond_to?(:request_callback) ? request_callback(request_handler) : request_handler
268
+ end
269
+ end
270
+
271
+ #.........................................................................................................
272
+ # add payloads
273
+ #.........................................................................................................
274
+ def result_jabber_x_data(payload)
275
+ delegate_methods.delegate(pipe, self)
276
+ flush_messages
277
+ if params[:action].eql?(:cancel)
278
+ command_canceled
279
+ elsif payload.kind_of?(AgentXmpp::Error)
280
+ payload.responce
281
+ elsif payload.kind_of?(AgentXmpp::Delegate)
282
+ nil
283
+ elsif payload.kind_of?(AgentXmpp::Response)
284
+ payload
285
+ else
286
+ command_result(payload.nil? ? nil : payload.to_x_data, params[:sessionid])
287
+ end
288
+ end
289
+
290
+ #.........................................................................................................
291
+ def result_message_chat(payload)
292
+ Xmpp::Message.chat(params[:from], payload)
293
+ end
294
+
295
+ #.........................................................................................................
296
+ def add_payload_to_container(payload)
297
+ meth = "result_#{params[:xmlns].gsub(/:/, "_")}".to_sym
298
+ if respond_to?(meth, true)
299
+ if res = send(meth, payload)
300
+ pipe.send_resp(res)
301
+ end
302
+ else
303
+ AgentXmpp.logger.error "PAYLOAD ERROR: unsupported payload {:xmlns => '#{params[:xmlns]}', :node => '#{params[:node]}', :action => '#{params[:action]}'}."
304
+ Xmpp::ErrorResponse.unsupported_payload(params)
305
+ end
306
+ end
307
+
308
+ #.........................................................................................................
309
+ # commands
310
+ #.........................................................................................................
311
+ def update_command_list
312
+ if not BaseController.commands_list[params[:sessionid]] and submits.length > 0
313
+ BaseController.add_command_to_list(params[:sessionid], self)
314
+ elsif BaseController.commands_list[params[:sessionid]] and submits.length.eql?(0)
315
+ BaseController.remove_command_from_list(params[:sessionid])
316
+ end
317
+ end
318
+
319
+ #.........................................................................................................
320
+ def command_result(payload, sessionid)
321
+ if payload
322
+ Xmpp::IqCommand.send_command(:to=>params[:from], :node=>params[:node], :status=>payload.type.eql?(:form) ? :executing : :completed,
323
+ :id => params[:id], :sessionid => sessionid, :payload => payload, :iq_type=>:result)
324
+ else
325
+ Xmpp::IqCommand.send_command(:to=>params[:from], :node=>params[:node], :status=> :completed, :id => params[:id],
326
+ :sessionid => sessionid, :iq_type=>:result)
327
+ end
328
+ end
329
+
330
+ #.........................................................................................................
331
+ def command_canceled
332
+ BaseController.remove_command_from_list(params[:sessionid])
333
+ Xmpp::IqCommand.send_command(:to=>params[:from], :node=>params[:node], :status=>:canceled, :id => params[:id],
334
+ :sessionid => params[:sessionid], :iq_type=>:result)
335
+ end
336
+
337
+ #.......................................................................................................
338
+ def invoke_command_on_route
339
+ @route = get_route(:command)
340
+ unless route.nil?
341
+ if apply_before_filters(:command, params[:node])
342
+ yield
343
+ else
344
+ AgentXmpp.logger.error "ACCESS ERROR: before_filter prevented '#{params[:from]}' access {:node => '#{params[:node]}', :action => '#{params[:action]}'}."
345
+ Xmpp::ErrorResponse.forbidden(params)
346
+ end
347
+ else
348
+ AgentXmpp.logger.error "ROUTING ERROR: no route for {:node => '#{params[:node]}', :action => '#{params[:action]}'}."
349
+ Xmpp::ErrorResponse.no_route(params)
350
+ end
351
+ end
352
+
353
+ #.........................................................................................................
354
+ # routes
355
+ #.........................................................................................................
356
+ def get_route(msg_type)
357
+ (BaseController.routes[msg_type] || []).select{|r| r[:node].eql?(params[:node].to_s)}.first
358
+ end
359
+
360
+ #.........................................................................................................
361
+ def chat_route
362
+ (BaseController.routes[:chat] ||= []).first
363
+ end
364
+
365
+ #.........................................................................................................
366
+ # filters
367
+ #.........................................................................................................
368
+ def apply_before_filters(msg_type, node=nil)
369
+ (BaseController.before_filters[msg_type] || []).inject([]) do |fs, f|
370
+ nodes = [f[:nodes]].flatten
371
+ (nodes.include?(node) or nodes.include?(:all)) ? fs << f : fs
372
+ end.inject(true) do |r,f|
373
+ define_meta_class_method(:filter, &f[:blk])
374
+ r and filter
375
+ end
376
+ end
377
+
378
+ #.........................................................................................................
379
+ private :add_payload_to_container, :chat_route, :get_route, :result_jabber_x_data, :result_message_chat,
380
+ :process_request, :run_command, :command_result, :invoke_command_on_route, :update_command_list,
381
+ :command_canceled
382
+
383
+ #### BaseController
384
+ end
385
+
386
+ ##############################################################################################################
387
+ class Controller < BaseController
388
+
389
+ #### Controller
390
+ end
391
+
392
+ #### AgentXmpp
393
+ end
394
+