troystribling-agent_xmpp 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. data/README.rdoc +397 -2
  2. data/Rakefile +33 -21
  3. data/VERSION +1 -1
  4. data/agent_xmpp.gemspec +78 -33
  5. data/lib/agent_xmpp.rb +11 -7
  6. data/lib/agent_xmpp/app.rb +0 -5
  7. data/lib/agent_xmpp/app/boot.rb +47 -33
  8. data/lib/agent_xmpp/app/controller.rb +135 -19
  9. data/lib/agent_xmpp/client.rb +6 -1
  10. data/lib/agent_xmpp/client/client.rb +22 -155
  11. data/lib/agent_xmpp/client/connection.rb +41 -250
  12. data/lib/agent_xmpp/client/message_delegate.rb +706 -0
  13. data/lib/agent_xmpp/client/message_pipe.rb +176 -0
  14. data/lib/agent_xmpp/client/publish_model.rb +65 -0
  15. data/lib/agent_xmpp/{app/format.rb → client/response.rb} +19 -24
  16. data/lib/agent_xmpp/client/roster_model.rb +139 -0
  17. data/lib/agent_xmpp/client/services_model.rb +97 -0
  18. data/lib/agent_xmpp/config.rb +45 -0
  19. data/lib/agent_xmpp/main.rb +126 -0
  20. data/lib/agent_xmpp/patches.rb +6 -2
  21. data/lib/agent_xmpp/patches/{standard_library_patches/array.rb → array.rb} +14 -7
  22. data/lib/agent_xmpp/patches/{standard_library_patches/float.rb → float.rb} +0 -0
  23. data/lib/agent_xmpp/patches/{standard_library_patches/hash.rb → hash.rb} +3 -3
  24. data/lib/agent_xmpp/patches/{standard_library_patches/object.rb → object.rb} +3 -3
  25. data/lib/agent_xmpp/patches/rexml.rb +69 -0
  26. data/lib/agent_xmpp/patches/{standard_library_patches/string.rb → string.rb} +5 -0
  27. data/lib/agent_xmpp/xmpp.rb +17 -0
  28. data/lib/agent_xmpp/xmpp/element.rb +159 -0
  29. data/lib/agent_xmpp/xmpp/error_response.rb +179 -0
  30. data/lib/agent_xmpp/xmpp/iq.rb +90 -0
  31. data/lib/agent_xmpp/xmpp/iq_command.rb +47 -0
  32. data/lib/agent_xmpp/xmpp/iq_disco.rb +205 -0
  33. data/lib/agent_xmpp/xmpp/iq_pubsub.rb +268 -0
  34. data/lib/agent_xmpp/xmpp/iq_roster.rb +183 -0
  35. data/lib/agent_xmpp/xmpp/iq_version.rb +89 -0
  36. data/lib/agent_xmpp/xmpp/jid.rb +150 -0
  37. data/lib/agent_xmpp/xmpp/message.rb +82 -0
  38. data/lib/agent_xmpp/xmpp/presence.rb +127 -0
  39. data/lib/agent_xmpp/xmpp/sasl.rb +241 -0
  40. data/lib/agent_xmpp/xmpp/stanza.rb +107 -0
  41. data/lib/agent_xmpp/xmpp/x_data.rb +269 -0
  42. data/test/app/app.rb +134 -0
  43. data/test/cases/test_application_message_processing.rb +65 -0
  44. data/test/cases/test_errors.rb +24 -0
  45. data/test/cases/test_presence_management.rb +139 -0
  46. data/test/cases/test_roster_management.rb +214 -0
  47. data/test/cases/test_service_discovery.rb +168 -0
  48. data/test/cases/test_session_management.rb +120 -0
  49. data/test/cases/test_version_discovery.rb +67 -0
  50. data/test/helpers/matchers.rb +23 -0
  51. data/test/helpers/mocks.rb +82 -0
  52. data/test/helpers/test_case_extensions.rb +45 -0
  53. data/test/helpers/test_client.rb +44 -0
  54. data/test/helpers/test_delegate.rb +61 -0
  55. data/test/helpers/test_helper.rb +91 -0
  56. data/test/messages/application_messages.rb +206 -0
  57. data/test/messages/error_messages.rb +35 -0
  58. data/test/messages/presence_messages.rb +66 -0
  59. data/test/messages/roster_messages.rb +126 -0
  60. data/test/messages/service_discovery_messages.rb +201 -0
  61. data/test/messages/session_messages.rb +158 -0
  62. data/test/messages/version_discovery_messages.rb +69 -0
  63. data/test/peer/peer.rb +36 -0
  64. data/test/xml_messages.txt +197 -0
  65. metadata +82 -42
  66. data/bin/agent_xmpp +0 -56
  67. data/lib/agent_xmpp/app/chat_message_body_controller.rb +0 -16
  68. data/lib/agent_xmpp/app/map.rb +0 -45
  69. data/lib/agent_xmpp/app/routes.rb +0 -77
  70. data/lib/agent_xmpp/app/view.rb +0 -49
  71. data/lib/agent_xmpp/client/parser.rb +0 -71
  72. data/lib/agent_xmpp/patches/standard_library_patches.rb +0 -5
  73. data/lib/agent_xmpp/patches/xmpp4r_patches.rb +0 -3
  74. data/lib/agent_xmpp/patches/xmpp4r_patches/command.rb +0 -26
  75. data/lib/agent_xmpp/patches/xmpp4r_patches/iq.rb +0 -26
  76. data/lib/agent_xmpp/patches/xmpp4r_patches/x_data.rb +0 -116
  77. data/lib/agent_xmpp/utils.rb +0 -2
  78. data/lib/agent_xmpp/utils/logger.rb +0 -24
  79. data/lib/agent_xmpp/utils/roster.rb +0 -23
  80. data/lib/agent_xmpp/version.rb +0 -6
  81. data/test/agent_xmpp_test.rb +0 -7
  82. data/test/test_helper.rb +0 -10
@@ -0,0 +1,706 @@
1
+ ##############################################################################################################
2
+ module AgentXmpp
3
+
4
+ #####-------------------------------------------------------------------------------------------------------
5
+ class MessageDelegate
6
+
7
+ #####-------------------------------------------------------------------------------------------------------
8
+ class << self
9
+
10
+ #.........................................................................................................
11
+ attr_reader :pubsub_service
12
+
13
+ #---------------------------------------------------------------------------------------------------------
14
+ # event flow delegate methods
15
+ #.........................................................................................................
16
+ # process command
17
+ #.........................................................................................................
18
+ def did_receive_command_set(pipe, stanza)
19
+ command = stanza.command
20
+ params = {:xmlns => 'jabber:x:data', :action => command.action, :to => stanza.from.to_s,
21
+ :from => stanza.from.to_s, :node => command.node, :id => stanza.id}
22
+ AgentXmpp.logger.info "RECEIVED COMMAND NODE: #{command.node}, FROM: #{stanza.from.to_s}"
23
+ Controller.new(pipe, params).invoke_execute
24
+ end
25
+
26
+ #.........................................................................................................
27
+ # process chat messages
28
+ #.........................................................................................................
29
+ def did_receive_message_chat(pipe, stanza)
30
+ params = {:xmlns => 'message:chat', :to => stanza.from.to_s, :from => stanza.from.to_s, :id => stanza.id,
31
+ :body => stanza.body}
32
+ AgentXmpp.logger.info "RECEIVED CHAT MESSAGE FROM: #{stanza.from.to_s}"
33
+ Controller.new(pipe, params).invoke_chat
34
+ end
35
+
36
+ #.........................................................................................................
37
+ # process normal messages
38
+ #.........................................................................................................
39
+ def did_receive_message_normal(pipe, stanza)
40
+ AgentXmpp.logger.info "RECEIVED NORMAL MESSAGE FROM: #{stanza.from.to_s}"
41
+ if event = stanza.event
42
+ did_receive_pubsub_event(pipe, event, stanza.to.to_s, stanza.from.to_s)
43
+ else
44
+ did_receive_unsupported_message(pipe, stanza)
45
+ end
46
+ end
47
+
48
+ #.........................................................................................................
49
+ # process events
50
+ #.........................................................................................................
51
+ def did_receive_pubsub_event(pipe, event, to, from)
52
+ AgentXmpp.logger.info "RECEIVED EVENT FROM: #{from.to_s}"
53
+ event.items.each do |is|
54
+ is.item.each do |i|
55
+ if data = i.x and data.type.eql?(:result)
56
+ src = is.node.split('/')
57
+ src_jid = "#{src[3]}@#{src[2]}"
58
+ params = {:xmlns => 'http://jabber.org/protocol/pubsub#event', :to => to, :pubsub => from,
59
+ :node => is.node, :data => data.to_native, :from => src_jid, :id => i.id,
60
+ :resources => AgentXmpp.roster.available_resources(Xmpp::Jid.new(src_jid))}
61
+ Controller.new(pipe, params).invoke_event
62
+ else
63
+ did_receive_unsupported_message(pipe, event)
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ #.........................................................................................................
70
+ # errors
71
+ #.........................................................................................................
72
+ def did_receive_unsupported_message(pipe, stanza)
73
+ AgentXmpp.logger.info "RECEIVED UNSUPPORTED MESSAGE: #{stanza.to_s}"
74
+ if stanza.class.eql?(AgentXmpp::Xmpp::Iq)
75
+ Xmpp::ErrorResponse.feature_not_implemented(stanza)
76
+ end
77
+ end
78
+
79
+ #.........................................................................................................
80
+ # connection
81
+ #.........................................................................................................
82
+ def did_connect(pipe)
83
+ AgentXmpp.logger.info "CONNECTED"
84
+ end
85
+
86
+ #.........................................................................................................
87
+ def did_disconnect(pipe)
88
+ AgentXmpp.logger.warn "DISCONNECTED"
89
+ EventMachine::stop_event_loop
90
+ end
91
+
92
+ #.........................................................................................................
93
+ def did_not_connect(pipe)
94
+ AgentXmpp.logger.warn "CONNECTION FAILED"
95
+ end
96
+
97
+ #.........................................................................................................
98
+ # authentication
99
+ #.........................................................................................................
100
+ def did_bind(pipe)
101
+ AgentXmpp.logger.info "DID BIND TO RESOURCE: #{AgentXmpp.jid.resource}"
102
+ Xmpp::Iq.session(pipe) if pipe.stream_features.has_key?('session')
103
+ end
104
+
105
+ #.........................................................................................................
106
+ def did_receive_preauthenticate_features(pipe)
107
+ AgentXmpp.logger.info "SESSION INITIALIZED"
108
+ Xmpp::SASL.authenticate(pipe.stream_mechanisms)
109
+ end
110
+
111
+ #.........................................................................................................
112
+ def did_authenticate(pipe)
113
+ AgentXmpp.logger.info "AUTHENTICATED"
114
+ end
115
+
116
+ #.........................................................................................................
117
+ def did_not_authenticate(pipe)
118
+ AgentXmpp.logger.info "AUTHENTICATION FAILED"
119
+ raise AgentXmppError, "authentication failed"
120
+ end
121
+
122
+ #.........................................................................................................
123
+ def did_receive_postauthenticate_features(pipe)
124
+ AgentXmpp.logger.info "SESSION STARTED"
125
+ Xmpp::Iq.bind(pipe) if pipe.stream_features.has_key?('bind')
126
+ end
127
+
128
+ #.........................................................................................................
129
+ def did_start_session(pipe)
130
+ AgentXmpp.logger.info "SESSION STARTED"
131
+ config_roster_item = AgentXmpp.roster.find_by_jid(AgentXmpp.jid)
132
+ add_command_method(pipe)
133
+ add_message_method(pipe)
134
+ [Send(Xmpp::Presence.new(nil, nil, AgentXmpp.priority)), Xmpp::IqRoster.get(pipe),
135
+ Xmpp::IqDiscoInfo.get(pipe, AgentXmpp.jid.domain),
136
+ Xmpp::IqDiscoInfo.get(pipe, AgentXmpp.jid.bare)]
137
+ end
138
+
139
+ #.........................................................................................................
140
+ # presence
141
+ #.........................................................................................................
142
+ def did_receive_presence(pipe, presence)
143
+ if AgentXmpp.roster.has_jid?(presence.from)
144
+ from_jid = presence.from
145
+ AgentXmpp.roster.update_resource(presence)
146
+ AgentXmpp.logger.info "RECEIVED PRESENCE FROM: #{from_jid.to_s}"
147
+ response = []
148
+ unless from_jid.to_s.eql?(AgentXmpp.jid.to_s)
149
+ Boot.call_if_implemented(:call_received_presence, from_jid.to_s, :available)
150
+ response << Xmpp::IqVersion.request(pipe, from_jid) unless AgentXmpp.roster.has_version?(from_jid)
151
+ unless AgentXmpp.services.has_jid?(from_jid)
152
+ response << Xmpp::IqDiscoInfo.get(pipe, from_jid)
153
+ response << Xmpp::IqDiscoItems.get(pipe, from_jid, 'http://jabber.org/protocol/commands')
154
+ end
155
+ end; response
156
+ else
157
+ AgentXmpp.logger.warn "RECEIVED PRESENCE FROM JID NOT IN ROSTER: #{from_jid}"
158
+ end
159
+ end
160
+
161
+ #.........................................................................................................
162
+ def did_receive_presence_subscribe(pipe, presence)
163
+ from_jid = presence.from.to_s
164
+ if AgentXmpp.roster.has_jid?(presence.from)
165
+ AgentXmpp.logger.info "RECEIVED SUBSCRIBE REQUEST: #{from_jid}"
166
+ Xmpp::Presence.accept(from_jid)
167
+ else
168
+ AgentXmpp.logger.warn "RECEIVED SUBSCRIBE REQUEST FROM JID NOT IN ROSTER: #{from_jid}"
169
+ Xmpp::Presence.decline(from_jid)
170
+ end
171
+ end
172
+
173
+ #.........................................................................................................
174
+ def did_receive_presence_subscribed(pipe, presence)
175
+ AgentXmpp.logger.warn "SUBSCRIPTION ACCEPTED: #{presence.from.to_s}"
176
+ end
177
+
178
+ #.........................................................................................................
179
+ def did_receive_presence_unavailable(pipe, presence)
180
+ from_jid = presence.from
181
+ if AgentXmpp.roster.has_jid?(from_jid)
182
+ AgentXmpp.roster.update_resource(presence)
183
+ Boot.call_if_implemented(:call_received_presence, from_jid.to_s, :unavailable)
184
+ AgentXmpp.logger.info "RECEIVED UNAVAILABLE PRESENCE FROM: #{from_jid.to_s }"
185
+ else
186
+ AgentXmpp.logger.warn "RECEIVED UNAVAILABLE PRESENCE FROM JID NOT IN ROSTER: #{from_jid}"
187
+ end
188
+ end
189
+
190
+ #.........................................................................................................
191
+ def did_receive_presence_unsubscribed(pipe, presence)
192
+ from_jid = presence.from.to_s
193
+ if AgentXmpp.roster.destroy_by_jid(presence.from)
194
+ AgentXmpp.logger.info "RECEIVED UNSUBSCRIBED REQUEST: #{from_jid}"
195
+ Xmpp::IqRoster.remove(pipe, presence.from)
196
+ else
197
+ AgentXmpp.logger.warn "RECEIVED UNSUBSCRIBED REQUEST FROM JID NOT IN ROSTER: #{from_jid}"
198
+ end
199
+ end
200
+
201
+ #.........................................................................................................
202
+ def did_receive_presence_error(pipe, presence)
203
+ AgentXmpp.logger.warn "RECEIVED PRESENCE ERROR FROM: #{presence.from.to_s}"
204
+ if AgentXmpp.roster.has_jid?(presence.from)
205
+ AgentXmpp.logger.warn "REMOVING '#{presence.from.to_s}' FROM ROSTER"
206
+ Xmpp::IqRoster.remove(pipe, presence.from.to_s)
207
+ end
208
+ end
209
+
210
+ #.........................................................................................................
211
+ # roster management
212
+ #.........................................................................................................
213
+ def did_receive_roster_result(pipe, stanza)
214
+ process_roster_items(pipe, stanza)
215
+ end
216
+
217
+ #.........................................................................................................
218
+ def did_receive_roster_set(pipe, stanza)
219
+ process_roster_items(pipe, stanza)
220
+ end
221
+
222
+ #.........................................................................................................
223
+ def did_receive_roster_item(pipe, roster_item)
224
+ roster_item_jid = roster_item.jid
225
+ AgentXmpp.logger.info "RECEIVED ROSTER ITEM: #{roster_item_jid.to_s}"
226
+ if AgentXmpp.roster.has_jid?(roster_item_jid)
227
+ case roster_item.subscription
228
+ when :none
229
+ if roster_item.ask.eql?(:subscribe)
230
+ AgentXmpp.logger.info "CONTACT SUBSCRIPTION PENDING: #{roster_item_jid.to_s}"
231
+ AgentXmpp.roster.update_status(roster_item_jid, :ask)
232
+ else
233
+ AgentXmpp.logger.info "CONTACT ADDED TO ROSTER: #{roster_item_jid.to_s}"
234
+ AgentXmpp.roster.update_status(roster_item_jid, :added)
235
+ end
236
+ when :to
237
+ AgentXmpp.logger.info "SUBSCRIBED TO CONTACT PRESENCE: #{roster_item_jid.to_s}"
238
+ AgentXmpp.roster.update_status(roster_item_jid, :to)
239
+ when :from
240
+ AgentXmpp.logger.info "CONTACT SUBSCRIBED TO PRESENCE: #{roster_item_jid.to_s}"
241
+ AgentXmpp.roster.update_status(roster_item_jid, :from)
242
+ when :both
243
+ AgentXmpp.logger.info "CONTACT SUBSCRIPTION BIDIRECTIONAL: #{roster_item_jid.to_s}"
244
+ AgentXmpp.roster.update_status(roster_item_jid, :both)
245
+ end
246
+ AgentXmpp.roster.update_roster_item(roster_item)
247
+ check_roster_item_group(pipe, roster_item)
248
+ else
249
+ AgentXmpp.logger.info "REMOVING ROSTER ITEM: #{roster_item_jid.to_s}"
250
+ Xmpp::IqRoster.remove(pipe, roster_item_jid)
251
+ end
252
+ end
253
+
254
+ #.........................................................................................................
255
+ def did_remove_roster_item(pipe, roster_item)
256
+ AgentXmpp.logger.info "REMOVE ROSTER ITEM"
257
+ roster_item_jid = roster_item.jid
258
+ if AgentXmpp.roster.has_jid?(roster_item_jid)
259
+ AgentXmpp.logger.info "REMOVED ROSTER ITEM: #{roster_item_jid.to_s}"
260
+ AgentXmpp.roster.destroy_by_jid(roster_item_jid)
261
+ end
262
+ end
263
+
264
+ #.........................................................................................................
265
+ def did_receive_all_roster_items(pipe)
266
+ AgentXmpp.logger.info "RECEIVED ALL ROSTER ITEMS"
267
+ AgentXmpp.roster.find_all_by_status(:inactive).map do |r|
268
+ AgentXmpp.logger.info "ADDING CONTACT: #{r.jid}"
269
+ [Xmpp::IqRoster.update(pipe, r.jid, r.groups), Xmpp::Presence.subscribe(r.jid)]
270
+ end
271
+ end
272
+
273
+ #.........................................................................................................
274
+ def did_receive_update_roster_item_result(pipe, result)
275
+ AgentXmpp.logger.info "UPDATE ROSTER ITEM ACKNOWLEDEGED FROM: #{result.from.to_s}"
276
+ end
277
+
278
+ #.........................................................................................................
279
+ def did_receive_update_roster_item_error(pipe, roster_item_jid)
280
+ AgentXmpp.logger.info "UPDATE ROSTER ITEM RECEIVED ERROR REMOVING: #{roster_item_jid}"
281
+ AgentXmpp.roster.destroy_by_jid(Xmpp::Jid.new(roster_item_jid))
282
+ end
283
+
284
+ #.........................................................................................................
285
+ def did_receive_remove_roster_item_result(pipe, result)
286
+ AgentXmpp.logger.info "REMOVE ROSTER ITEM ACKNOWLEDEGED FROM: #{result.from.to_s}"
287
+ end
288
+
289
+ #.........................................................................................................
290
+ def did_receive_remove_roster_item_error(pipe, roster_item_jid)
291
+ AgentXmpp.logger.info "REMOVE ROSTER ITEM RECEIVED ERROR REMOVING: #{roster_item_jid}"
292
+ AgentXmpp.roster.destroy_by_jid(Xmpp::Jid.new(roster_item_jid))
293
+ end
294
+
295
+ #.........................................................................................................
296
+ # service discovery management
297
+ #.........................................................................................................
298
+ def did_receive_version_result(pipe, version)
299
+ version_jid = version.from
300
+ if AgentXmpp.roster.has_jid?(version_jid)
301
+ query = version.query
302
+ AgentXmpp.logger.info "RECEIVED VERSION RESULT: #{version_jid.to_s}, #{query.iname}, #{query.version}"
303
+ AgentXmpp.roster.update_resource_version(version)
304
+ else
305
+ AgentXmpp.logger.warn "RECEIVED VERSION RESULT FROM JID NOT IN ROSTER: #{from.to_s}"
306
+ end
307
+ end
308
+
309
+ #.........................................................................................................
310
+ def did_receive_version_get(pipe, request)
311
+ if AgentXmpp.roster.has_jid?(request.from)
312
+ AgentXmpp.logger.info "RECEIVED VERSION REQUEST: #{request.from.to_s}"
313
+ Xmpp::IqVersion.result(pipe, request)
314
+ else
315
+ AgentXmpp.logger.warn "RECEIVED VERSION REQUEST FROM JID NOT IN ROSTER: #{request.from.to_s}"
316
+ end
317
+ end
318
+
319
+ #.........................................................................................................
320
+ def did_receive_version_error(pipe, result)
321
+ from_jid = result.from
322
+ AgentXmpp.logger.warn "RECEIVED VERSION ERROR FROM: #{from_jid.to_s}"
323
+ end
324
+
325
+ #.........................................................................................................
326
+ def did_receive_discoinfo_get(pipe, request)
327
+ from_jid = request.from
328
+ if AgentXmpp.roster.has_jid?(from_jid)
329
+ if request.query.node.nil?
330
+ AgentXmpp.logger.info "RECEIVED DISCO INFO REQUEST FROM: #{from_jid.to_s}"
331
+ Xmpp::IqDiscoInfo.result(pipe, request)
332
+ else
333
+ AgentXmpp.logger.info "RECEIVED DISCO INFO REQUEST FOR UNSUPPORTED NODE FROM: #{from_jid.to_s}"
334
+ Xmpp::ErrorResponse.service_unavailable(request)
335
+ end
336
+ else
337
+ AgentXmpp.logger.warn "RECEIVED DISCO INFO REQUEST FROM JID NOT IN ROSTER: #{from_jid.to_s}"
338
+ end
339
+ end
340
+
341
+ #.........................................................................................................
342
+ def did_receive_discoinfo_result(pipe, discoinfo)
343
+ from_jid = discoinfo.from
344
+ do_discoitems = true
345
+ request = []
346
+ if AgentXmpp.roster.has_jid?(from_jid) or AgentXmpp.services.has_jid?(from_jid)
347
+ q = discoinfo.query
348
+ AgentXmpp.logger.info "RECEIVED DISCO INFO RESULT FROM: #{from_jid.to_s}" + (q.node.nil? ? '' : ", NODE: #{q.node}")
349
+ AgentXmpp.services.update_with_discoinfo(discoinfo)
350
+ q.identities.each do |i|
351
+ AgentXmpp.logger.info " IDENTITY: NAME:#{i.iname}, CATEGORY:#{i.category}, TYPE:#{i.type}"
352
+ request << case i.category
353
+ when 'server' then Xmpp::IqDiscoItems.get(pipe, from_jid.to_s, q.node)
354
+ when 'pubsub' then process_pubsub_discoinfo(i.type, pipe, from_jid, q.node)
355
+ when 'conference'
356
+ when 'proxy'
357
+ when 'directory'
358
+ when 'client'
359
+ when 'automation'
360
+ when 'auth'
361
+ when 'collaboration'
362
+ when 'componenet'
363
+ when 'gateway'
364
+ when 'hierarchy'
365
+ when 'headline'
366
+ when 'store'
367
+ end
368
+ end
369
+ q.features.each do |f|
370
+ AgentXmpp.logger.info " FEATURE: #{f}"
371
+ end
372
+ request.smash
373
+ else
374
+ AgentXmpp.logger.warn "RECEIVED DISCO INFO RESULT FROM JID NOT A ROSTER ITEM OR SERVICE: #{from_jid.to_s}"
375
+ end
376
+ end
377
+
378
+ #.........................................................................................................
379
+ def did_receive_discoinfo_error(pipe, result)
380
+ from_jid = result.from
381
+ AgentXmpp.logger.warn "RECEIVED DISCO INFO ERROR FROM: #{from_jid.to_s}, #{result.query.node}"
382
+ end
383
+
384
+ #.........................................................................................................
385
+ def did_receive_discoitems_get(pipe, request)
386
+ from_jid = request.from
387
+ if AgentXmpp.roster.has_jid?(from_jid)
388
+ if request.query.node.eql?('http://jabber.org/protocol/commands')
389
+ AgentXmpp.logger.info "RECEIVED COMMAND NODE DISCO ITEMS REQUEST FROM: #{from_jid.to_s}"
390
+ Xmpp::IqDiscoItems.result_command_nodes(pipe, request)
391
+ elsif request.query.node.nil?
392
+ AgentXmpp.logger.info "RECEIVED DISCO ITEMS REQUEST FROM: #{from_jid.to_s}"
393
+ Xmpp::IqDiscoItems.result(pipe, request)
394
+ else
395
+ AgentXmpp.logger.info "RECEIVED DISCO INFO REQUEST FOR UNSUPPORTED NODE FROM: #{from_jid.to_s}"
396
+ Xmpp::ErrorResponse.item_not_found(request)
397
+ end
398
+ else
399
+ AgentXmpp.logger.warn "RECEIVED DISCO ITEMS REQUEST FROM JID NOT IN ROSTER: #{from_jid.to_s}"
400
+ end
401
+ end
402
+
403
+ #.........................................................................................................
404
+ def did_receive_discoitems_result(pipe, discoitems)
405
+ from_jid = discoitems.from
406
+ if AgentXmpp.roster.has_jid?(from_jid) or AgentXmpp.services.has_jid?(from_jid)
407
+ q = discoitems.query
408
+ AgentXmpp.logger.info "RECEIVED DISCO ITEMS RESULT FROM: #{from_jid.to_s}" + (q.node.nil? ? '' : ", NODE: #{q.node}")
409
+ AgentXmpp.services.update_with_discoitems(discoitems)
410
+ case q.node
411
+ when 'http://jabber.org/protocol/commands'
412
+ Boot.call_if_implemented(:call_discovered_command_nodes, from_jid.to_s, q.items.map{|i| i.node}) unless q.items.empty?
413
+ else
414
+ msgs = if from_jid.to_s.eql?(pubsub_service.to_s) and q.node.eql?(AgentXmpp.pubsub_root)
415
+ create_user_pubsub_root(pipe, from_jid, q.items)
416
+ else ; []; end
417
+ if from_jid.to_s.eql?(pubsub_service.to_s) and q.node.eql?(AgentXmpp.user_pubsub_root)
418
+ msgs += update_publish_nodes(pipe, from_jid, q.items)
419
+ end
420
+ q.items.inject(msgs) do |r,i|
421
+ AgentXmpp.logger.info " ITEM JID: #{i.jid}" + (i.node.nil? ? '' : ", NODE: #{i.node}")
422
+ AgentXmpp.services.create(i.jid)
423
+ r << Xmpp::IqDiscoInfo.get(pipe, i.jid, i.node)
424
+ end
425
+ end
426
+ else
427
+ AgentXmpp.logger.warn "RECEIVED DISCO INFO RESULT FROM JID NOT A ROSTER ITEM OR SERVICE: #{from_jid.to_s}"
428
+ end
429
+ end
430
+
431
+ #.........................................................................................................
432
+ def did_receive_discoitems_error(pipe, result)
433
+ from_jid = result.from
434
+ AgentXmpp.logger.warn "RECEIVED DISCO ITEMS ERROR FROM: #{from_jid.to_s}, #{result.query.node}"
435
+ end
436
+
437
+ #.........................................................................................................
438
+ # pubsub
439
+ #.........................................................................................................
440
+ def did_receive_publish_result(pipe, result, node)
441
+ AgentXmpp.logger.info "PUBLISH TO NODE ACKNOWLEDEGED: #{node}, #{result.from.to_s}"
442
+ end
443
+
444
+ #.........................................................................................................
445
+ def did_receive_publish_error(pipe, result, node)
446
+ AgentXmpp.logger.info "ERROR PUBLISING TO NODE: #{node}, #{result.from.to_s}"
447
+ end
448
+
449
+ #.........................................................................................................
450
+ def did_discover_pupsub_service(pipe, jid)
451
+ AgentXmpp.logger.info "DISCOVERED PUBSUB SERVICE: #{jid}"
452
+ req = [Xmpp::IqPubSub.subscriptions(pipe, jid.to_s)]
453
+ unless pubsub_service
454
+ add_publish_methods(pipe, jid)
455
+ @pubsub_service = jid
456
+ req += [Xmpp::IqDiscoItems.get(pipe, jid.to_s)] + init_remote_services(pipe)
457
+ end; req
458
+ end
459
+
460
+ #.........................................................................................................
461
+ def did_discover_pupsub_collection(pipe, jid, node)
462
+ AgentXmpp.logger.info "DISCOVERED PUBSUB COLLECTION: #{jid}, #{node}"
463
+ Xmpp::IqDiscoItems.get(pipe, jid, node) if pubsub_service.eql?(jid)
464
+ end
465
+
466
+ #.........................................................................................................
467
+ def did_discover_pupsub_leaf(pipe, jid, node)
468
+ AgentXmpp.logger.info "DISCOVERED PUBSUB LEAF: #{jid}, #{node}"
469
+ if node.eql?(AgentXmpp.pubsub_root) or node.eql?(AgentXmpp.user_pubsub_root)
470
+ Xmpp::IqDiscoItems.get(pipe, jid, node)
471
+ else
472
+ Boot.call_if_implemented(:call_discovered_pubsub_node, jid, node)
473
+ end
474
+ end
475
+
476
+ #.........................................................................................................
477
+ def did_discover_user_pubsub_root(pipe, pubsub, node)
478
+ AgentXmpp.logger.info "DISCOVERED USER PUBSUB ROOT: #{pubsub.to_s}, #{node}"
479
+ end
480
+
481
+ #.........................................................................................................
482
+ def did_receive_pubsub_subscriptions_result(pipe, result)
483
+ from_jid = result.from.to_s
484
+ AgentXmpp.logger.info "RECEIVED SUBSCRIPTIONS FROM: #{from_jid}"
485
+ app_subs = BaseController.subscriptions(result.from.domain)
486
+ srvr_subs = result.pubsub.subscriptions.map do |s|
487
+ AgentXmpp.logger.info "SUBSCRIBED TO NODE: #{from_jid}, #{s.node}"
488
+ s.node
489
+ end
490
+ reqs = app_subs.inject([]) do |r,s|
491
+ unless srvr_subs.include?(s)
492
+ AgentXmpp.logger.info "SUBSCRIBING TO NODE: #{from_jid}, #{s}"
493
+ r << Xmpp::IqPubSub.subscribe(pipe, from_jid, s)
494
+ end; r
495
+ end
496
+ srvr_subs.inject(reqs) do |r,s|
497
+ unless app_subs.include?(s)
498
+ AgentXmpp.logger.warn "UNSUBSCRIBING TO NODE: #{from_jid}, #{s}"
499
+ r << Xmpp::IqPubSub.unsubscribe(pipe, from_jid, s)
500
+ end; r
501
+ end
502
+ end
503
+
504
+ #.........................................................................................................
505
+ def did_receive_pubsub_subscriptions_error(pipe, result)
506
+ from_jid = result.from
507
+ AgentXmpp.logger.warn "RECEIVED ERROR ON SUBSCRIPTION REQUEST FROM: #{from_jid}"
508
+ end
509
+
510
+ #.........................................................................................................
511
+ def did_receive_pubsub_affiliations_result(pipe, result)
512
+ from_jid = result.from
513
+ AgentXmpp.logger.info "RECEIVED AFFILIATIONS FROM: #{from_jid}"
514
+ end
515
+
516
+ #.........................................................................................................
517
+ def did_receive_pubsub_affiliations_error(pipe, result)
518
+ from_jid = result.from
519
+ AgentXmpp.logger.info "RECEIVED ERROR ON AFFILIATIONS REQUEST FROM: #{from_jid}"
520
+ end
521
+
522
+ #.........................................................................................................
523
+ def did_receive_pubsub_create_node_result(pipe, result, node)
524
+ from_jid = result.from
525
+ AgentXmpp.logger.info "RECEIVED CREATE NODE RESULT FROM: #{from_jid.to_s}, #{node}"
526
+ if node.eql?(AgentXmpp.user_pubsub_root)
527
+ [did_discover_user_pubsub_root(pipe, from_jid, node), Xmpp::IqDiscoInfo.get(pipe, from_jid.to_s, node)]
528
+ end
529
+ end
530
+
531
+ #.........................................................................................................
532
+ def did_receive_pubsub_create_node_error(pipe, result, node)
533
+ from_jid = result.from
534
+ AgentXmpp.logger.info "RECEIVED CREATE NODE ERROR FROM: #{from_jid.to_s}, #{node}"
535
+ end
536
+
537
+ #.........................................................................................................
538
+ def did_receive_pubsub_delete_node_result(pipe, result, node)
539
+ from_jid = result.from
540
+ AgentXmpp.logger.info "RECEIVED DELETE NODE RESULT FROM: #{from_jid.to_s}, #{node}"
541
+ end
542
+
543
+ #.........................................................................................................
544
+ def did_receive_pubsub_delete_node_error(pipe, result, node)
545
+ from_jid = result.from
546
+ AgentXmpp.logger.info "RECEIVED DELETE NODE ERROR FROM: #{from_jid.to_s}, #{node}"
547
+ end
548
+
549
+ #.........................................................................................................
550
+ def did_receive_pubsub_subscribe_result(pipe, result, node)
551
+ from_jid = result.from
552
+ AgentXmpp.logger.info "RECEIVED SUBSCRIBE RESULT FROM: #{from_jid.to_s}, #{node}"
553
+ end
554
+
555
+ #.........................................................................................................
556
+ def did_receive_pubsub_subscribe_error(pipe, result, node)
557
+ from_jid = result.from
558
+ AgentXmpp.logger.warn "RECEIVED SUBSCRIBE ERROR FROM: #{from_jid.to_s}, #{node}"
559
+ did_receive_pubsub_subscribe_error_item_not_found(pipe, result, node) if result.error.error.eql?('item-not-found')
560
+ end
561
+
562
+ #.........................................................................................................
563
+ def did_receive_pubsub_subscribe_error_item_not_found(pipe, result, node)
564
+ from_jid = result.from
565
+ AgentXmpp.logger.warn "RECEIVED SUBSCRIBE ERROR ITEM-NOT-FOUND FROM: #{from_jid.to_s}, #{node}; " +
566
+ "RETRYING SUBSCRIPTION IN #{AgentXmpp::SUBSCRIBE_RETRY_PERIOD}s"
567
+ EventMachine::Timer.new(AgentXmpp::SUBSCRIBE_RETRY_PERIOD) do
568
+ pipe.send_resp(Xmpp::IqPubSub.subscribe(pipe, from_jid.to_s, node))
569
+ end
570
+ end
571
+
572
+ #.........................................................................................................
573
+ def did_receive_pubsub_unsubscribe_result(pipe, result, node)
574
+ from_jid = result.from
575
+ AgentXmpp.logger.info "RECEIVED UNSUBSCRIBE RESULT FROM: #{from_jid.to_s}, #{node}"
576
+ end
577
+
578
+ #.........................................................................................................
579
+ def did_receive_pubsub_unsubscribe_error(pipe, result, node)
580
+ from_jid = result.from
581
+ AgentXmpp.logger.info "RECEIVED UNSUBSCRIBE ERROR FROM: #{from_jid.to_s}, #{node}"
582
+ end
583
+
584
+ private
585
+
586
+ #.........................................................................................................
587
+ def check_roster_item_group(pipe, roster_item)
588
+ roster_item_jid = roster_item.jid
589
+ config_roster_item = AgentXmpp.roster.find_by_jid(roster_item_jid)
590
+ unless roster_item.groups.sort.eql?(config_roster_item.groups.sort)
591
+ AgentXmpp.logger.info "CHANGE IN ROSTER ITEM GROUP FOUND UPDATING: #{roster_item_jid.to_s} to '#{config_roster_item.groups.join(', ')}'"
592
+ Xmpp::IqRoster.update(pipe, roster_item_jid.to_s, config_roster_item.groups)
593
+ end
594
+ end
595
+
596
+ #.........................................................................................................
597
+ def process_pubsub_discoinfo(type, pipe, from, node)
598
+ case type
599
+ when 'service' then pipe.broadcast_to_delegates(:did_discover_pupsub_service, pipe, from)
600
+ when 'collection' then pipe.broadcast_to_delegates(:did_discover_pupsub_collection, pipe, from, node)
601
+ when 'leaf' then pipe.broadcast_to_delegates(:did_discover_pupsub_leaf, pipe, from, node)
602
+ end
603
+ end
604
+
605
+ #.........................................................................................................
606
+ def process_roster_items(pipe, stanza)
607
+ [stanza.query.inject([]) do |r, i|
608
+ method = i.subscription.eql?(:remove) ? :did_remove_roster_item : :did_receive_roster_item
609
+ r.push(pipe.broadcast_to_delegates(method, pipe, i))
610
+ end, pipe.broadcast_to_delegates(:did_receive_all_roster_items, pipe)].smash
611
+ end
612
+
613
+ #.........................................................................................................
614
+ def add_publish_methods(pipe, pubsub)
615
+ AgentXmpp.published.find_all.each do |p|
616
+ if p.node
617
+ meth = ("publish_" + p.node.gsub(/-/,'_')).to_sym
618
+ unless AgentXmpp.respond_to?(meth)
619
+ AgentXmpp.define_meta_class_method(meth) do |payload|
620
+ pipe.send_resp(Xmpp::IqPublish.set(pipe, :node => p.node, :to => pubsub, :payload => payload.to_x_data))
621
+ end
622
+ AgentXmpp.logger.info "ADDED PUBLISH METHOD FOR NODE: #{p.node}, #{pubsub}"
623
+ Delegator.delegate(AgentXmpp, meth)
624
+ else
625
+ AgentXmpp.logger.warn "PUBLISH METHOD FOR NODE EXISTS: #{p.node}, #{pubsub}"
626
+ end
627
+ else
628
+ AgentXmpp.logger.warn "NODE NOT SPECIFIED FOR PUBSUB PUBLISH CONFIGURATION"
629
+ end
630
+ end
631
+ end
632
+
633
+ #.........................................................................................................
634
+ def add_command_method(pipe)
635
+ AgentXmpp.define_meta_class_method(:command) do |args, &blk|
636
+ raise ArgmentError ':to and :node are required' unless args[:to] and args[:node]
637
+ iq = Xmpp::Iq.new(:set, args[:to])
638
+ iq.command = Xmpp::IqCommand.new(args[:node])
639
+ iq.command.action = args[:action] || :execute
640
+ iq.command << args[:params].to_x_data(:submit) if args[:params]
641
+ pipe.send_resp(Send(iq) do |r|
642
+ AgentXmpp.logger.info "RECEIVED RESPONSE: #{r.type}, #{r.id}"
643
+ blk.call(r.type, (r.type.eql?(:result) and r.command and r.command.x) ? r.command.x.to_native : nil) if blk
644
+ end)
645
+ end
646
+ Delegator.delegate(AgentXmpp, :command)
647
+ AgentXmpp.logger.info "ADDED COMMAND METHOD"
648
+ end
649
+
650
+ #.........................................................................................................
651
+ def add_message_method(pipe)
652
+ AgentXmpp.define_meta_class_method(:message) do |args|
653
+ raise ArgmentError ':to and :body are required' unless args[:to] and args[:body]
654
+ message = Xmpp::Message.new(args[:to], args[:body])
655
+ message.type = args[:type] || :chat
656
+ pipe.send_resp(Send(message))
657
+ end
658
+ Delegator.delegate(AgentXmpp, :message)
659
+ AgentXmpp.logger.info "ADDED MESSAGE METHOD"
660
+ end
661
+
662
+ #.........................................................................................................
663
+ def create_user_pubsub_root(pipe, pubsub, items)
664
+ if (roots = items.select{|i| i.node.eql?(AgentXmpp.user_pubsub_root)}).empty?
665
+ AgentXmpp.logger.info "USER PUBSUB ROOT NOT FOUND CREATING NODE: #{pubsub.to_s}, #{AgentXmpp.user_pubsub_root}"
666
+ [Xmpp::IqPubSub.create_node(pipe, pubsub.to_s, AgentXmpp.user_pubsub_root)]
667
+ else
668
+ AgentXmpp.logger.info "USER PUBSUB ROOT FOUND: #{pubsub.to_s}, #{AgentXmpp.user_pubsub_root}"
669
+ did_discover_user_pubsub_root(pipe, pubsub, AgentXmpp.user_pubsub_root); []
670
+ end
671
+ end
672
+
673
+ #.........................................................................................................
674
+ def update_publish_nodes(pipe, pubsub, items)
675
+ disco_nodes = items.map{|i| i.node}
676
+ config_nodes = AgentXmpp.published.find_all.map{|p| "#{AgentXmpp.user_pubsub_root}/#{p.node}"}
677
+ updates = disco_nodes.inject([]) do |u,n|
678
+ unless config_nodes.include?(n)
679
+ AgentXmpp.logger.warn "DELETING PUBSUB NODE: #{pubsub.to_s}, #{n}"
680
+ u << Xmpp::IqPubSubOwner.delete_node(pipe, pubsub.to_s, n)
681
+ end; u
682
+ end
683
+ config_nodes.inject(updates) do |u,n|
684
+ unless disco_nodes.include?(n)
685
+ AgentXmpp.logger.warn "ADDING PUBSUB NODE: #{pubsub.to_s}, #{n}"
686
+ u << Xmpp::IqPubSub.create_node(pipe, pubsub.to_s, n)
687
+ end; u
688
+ end
689
+ end
690
+
691
+ #.........................................................................................................
692
+ def init_remote_services(pipe)
693
+ (BaseController.event_domains-[AgentXmpp.jid.domain]).map do |d|
694
+ AgentXmpp.services.create(d)
695
+ Xmpp::IqDiscoInfo.get(pipe, d)
696
+ end
697
+ end
698
+
699
+ #### self
700
+ end
701
+
702
+ #### MessagePipe
703
+ end
704
+
705
+ #### AgentXmpp
706
+ end