agent_xmpp 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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,67 @@
1
+ ##############################################################################################################
2
+ require 'test_helper'
3
+
4
+ ##############################################################################################################
5
+ class TestClientVersionDiscovery < Test::Unit::TestCase
6
+
7
+ #.........................................................................................................
8
+ def setup
9
+ @troy = AgentXmpp::Xmpp::Jid.new('troy@nowhere.com/home')
10
+ @noone = AgentXmpp::Xmpp::Jid.new('noone@nowhere.com/nothing')
11
+ @config = {'jid' => 'test@nowhere.com', 'roster' =>[@troy.bare.to_s], 'password' => 'nopass'}
12
+ @client = TestClient.new(@config)
13
+ test_init_roster(@client)
14
+ @delegate = @client.new_delegate
15
+ end
16
+
17
+ ####-------------------------------------------------------------------------------------------------------
18
+ context "on receiving a presence message of type=available from a jid in configured roster" do
19
+
20
+ #.........................................................................................................
21
+ setup do
22
+ AgentXmpp::Xmpp::IdGenerator.set_gen_id([1,2])
23
+ @delegate.on_version_get_method.should_not be_called
24
+ @delegate.on_version_result_method.should_not be_called
25
+ AgentXmpp::Roster.find_by_jid(@troy).should be_nil
26
+ @client.receiving(PresenceMessages.recv_presence_available(@client, @troy.to_s)).should \
27
+ respond_with(VersionDiscoveryMessages.send_iq_get_query_version(@client, @troy.to_s))
28
+ AgentXmpp::Roster.find_by_jid(@troy).should_not be_nil
29
+ end
30
+
31
+ #.........................................................................................................
32
+ should "send a client version request to that jid and do nothing if the result is an error" do
33
+ @client.receiving(VersionDiscoveryMessages.recv_iq_result_query_version(@client, @troy.to_s)).should not_respond
34
+ AgentXmpp::Roster.has_version?(@troy).should be(true)
35
+ @delegate.on_version_result_method.should be_called
36
+ end
37
+
38
+ #.........................................................................................................
39
+ should "respond to client version requests from that jid" do
40
+ @client.receiving(VersionDiscoveryMessages.recv_iq_result_query_version(@client, @troy.to_s)).should not_respond
41
+ AgentXmpp::Roster.has_version?(@troy).should be(true)
42
+ @delegate.on_version_result_method.should be_called
43
+ @client.receiving(VersionDiscoveryMessages.recv_iq_get_query_version(@client, @troy.to_s)).should \
44
+ respond_with(VersionDiscoveryMessages.send_iq_result_query_version(@client, @troy.to_s))
45
+ @delegate.on_version_get_method.should be_called
46
+ end
47
+
48
+ #.........................................................................................................
49
+ should "send a client version request to that jid and update roster with result version information" do
50
+ @delegate.on_version_error_method.should_not be_called
51
+ @client.receiving(VersionDiscoveryMessages.recv_iq_error_query_version(@client, @troy.to_s)).should not_respond
52
+ AgentXmpp::Roster.has_version?(@troy).should be(false)
53
+ @delegate.on_version_error_method.should be_called
54
+ end
55
+
56
+ end
57
+
58
+ #.........................................................................................................
59
+ should "not respond to client version requests from jids not in configured roster" do
60
+ @delegate.on_version_get_method.should_not be_called
61
+ AgentXmpp::Contact.has_jid?(@noone).should be(false)
62
+ @client.receiving(VersionDiscoveryMessages.recv_iq_get_query_version(@client, @noone.to_s)).should not_respond
63
+ @delegate.on_version_get_method.should be_called
64
+ end
65
+
66
+ end
67
+
@@ -0,0 +1,23 @@
1
+ ####------------------------------------------------------------------------------------------------------
2
+ def_matcher :respond_with do |receiver, matcher, args|
3
+ prepare_msg = lambda{|msg| msg.collect{|i| i.split(/\n+/).inject("") {|p, m| p + m.strip.gsub(/id='\d+'/, '').gsub(/\s+/, " ")}}}
4
+ given = prepare_msg[[receiver].flatten].join
5
+ expected = prepare_msg[args].join
6
+ matcher.positive_msg = "Expected response message of \"#{expected}\" but was given message \"#{given}\""
7
+ matcher.negative_msg = "Expected response message \"#{expected}\" to not match given message \"#{given}\""
8
+ given.include?(expected)
9
+ end
10
+
11
+ ####------------------------------------------------------------------------------------------------------
12
+ def_matcher :not_respond do |receiver, matcher, args|
13
+ matcher.positive_msg = "Expected no responce"
14
+ matcher.negative_msg = "Expected a response"
15
+ receiver.nil? || receiver.empty?
16
+ end
17
+
18
+ ####------------------------------------------------------------------------------------------------------
19
+ def_matcher :be_called do |receiver, matcher, args|
20
+ matcher.positive_msg = "Expected client delgate method '#{receiver.last}' to be called"
21
+ matcher.negative_msg = "Expected client delgate method '#{receiver.last}' to not be called"
22
+ receiver.first
23
+ end
@@ -0,0 +1,82 @@
1
+ ##############################################################################################################
2
+ module AgentXmpp
3
+
4
+ #####-------------------------------------------------------------------------------------------------------
5
+ class Connection
6
+
7
+ #.........................................................................................................
8
+ def self.new(*args)
9
+ allocate.instance_eval do
10
+ initialize(*args)
11
+ connection_completed
12
+ self
13
+ end
14
+ end
15
+
16
+ #.........................................................................................................
17
+ def send_data(data)
18
+ data
19
+ end
20
+
21
+ def connection_completed
22
+ pipe.connection_completed
23
+ end
24
+
25
+ #.........................................................................................................
26
+ def error?
27
+ false
28
+ end
29
+
30
+ #.........................................................................................................
31
+ def reset_parser
32
+ end
33
+
34
+ #### Connection
35
+ end
36
+
37
+ #####-------------------------------------------------------------------------------------------------------
38
+ class Client
39
+
40
+ #.........................................................................................................
41
+ def connect
42
+ @connection = AgentXmpp::Connection.new(self)
43
+ end
44
+
45
+ #.........................................................................................................
46
+ def reconnect
47
+ true
48
+ end
49
+
50
+ #### Client
51
+ end
52
+
53
+ #####-------------------------------------------------------------------------------------------------------
54
+ class Controller
55
+ def handle_request
56
+ request_callback(request).collect{|m| Send(Xmpp::Stanza::import(REXML::Document.new(m).root))}
57
+ end
58
+ end
59
+
60
+ #####-------------------------------------------------------------------------------------------------------
61
+ class Boot
62
+ def self.boot
63
+ end
64
+ end
65
+
66
+ #### AgentXmpp
67
+ end
68
+
69
+
70
+ ##############################################################################################################
71
+ module AgentXmpp
72
+ module Xmpp
73
+ class IdGenerator
74
+ @gen_id;
75
+ class << self
76
+ def set_gen_id(val=1); @gen_id = val; end
77
+ def gen_id; @gen_id; end;
78
+ def generate_id; @gen_id.kind_of?(Array) ? @gen_id.shift : @gen_id; end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,45 @@
1
+ #####-------------------------------------------------------------------------------------------------------
2
+ class Test::Unit::TestCase
3
+
4
+ #.........................................................................................................
5
+ def bind_resource(client)
6
+ AgentXmpp::Xmpp::IdGenerator.set_gen_id
7
+ client.receiving(SessionMessages.recv_preauthentication_stream_features_with_plain_SASL(client))
8
+ client.receiving(SessionMessages.recv_auth_success(client))
9
+ client.receiving(SessionMessages.recv_postauthentication_stream_features(client))
10
+ client.receiving(SessionMessages.recv_iq_result_bind(client))
11
+ end
12
+
13
+ #.........................................................................................................
14
+ def test_send_roster_request(client)
15
+
16
+ #### client configured with two contacts in roster
17
+ delegate = client.new_delegate
18
+ bind_resource(client)
19
+
20
+ #### session starts and roster is requested
21
+ delegate.on_start_session_method.should_not be_called
22
+ AgentXmpp::Xmpp::IdGenerator.set_gen_id([1,2])
23
+ client.receiving(SessionMessages.recv_iq_result_session(client)).should \
24
+ respond_with(SessionMessages.send_presence_init(client), RosterMessages.send_iq_get_query_roster(client), \
25
+ ServiceDiscoveryMessages.send_iq_get_query_discoinfo(client, client.jid.domain))
26
+ delegate.on_start_session_method.should be_called
27
+ AgentXmpp::Xmpp::IdGenerator.set_gen_id
28
+ end
29
+
30
+ #.........................................................................................................
31
+ def test_init_roster(client)
32
+
33
+ #### client configured with two contacts in roster
34
+ test_send_roster_request(client)
35
+ delegate = client.new_delegate
36
+
37
+ #### receive roster request and verify that roster items are activated
38
+ delegate.on_all_roster_items_method.should_not be_called
39
+ AgentXmpp::Roster.find_all{|r| r[:status].should be(:inactive)}
40
+ client.receiving(RosterMessages.recv_iq_result_query_roster(client, AgentXmpp.config['roster'])).should not_respond
41
+ AgentXmpp::Roster.find_all{|r| r[:status].should be(:both)}
42
+ delegate.on_all_roster_items_method.should be_called
43
+ end
44
+
45
+ end
@@ -0,0 +1,44 @@
1
+ ##############################################################################################################
2
+ class TestClient
3
+
4
+ #.........................................................................................................
5
+ attr_reader :client, :config, :jid
6
+
7
+ #.........................................................................................................
8
+ def initialize(config = nil)
9
+ @config = config || File.open('test/helpers/agent_xmpp.yml') {|yf| YAML::load(yf)}
10
+ @client = AgentXmpp::Client.new(@config)
11
+ @jid = @client.jid
12
+ @client.connect
13
+ end
14
+
15
+ #.........................................................................................................
16
+ def connection
17
+ @client.connection
18
+ end
19
+
20
+ #.........................................................................................................
21
+ def responder_list
22
+ @client.pipe.responder_list
23
+ end
24
+
25
+ #.........................................................................................................
26
+ def new_delegate
27
+ @client.remove_delegate(@delegate) unless @delegate.nil?
28
+ @delegate = TestDelegate.new
29
+ @client.add_delegate(@delegate)
30
+ @delegate
31
+ end
32
+
33
+ #.........................................................................................................
34
+ def receiving(msg)
35
+ prepared_msg = msg.split(/\n/).inject("") {|p, m| p + m.strip}
36
+ doc = REXML::Document.new(prepared_msg).root
37
+ doc = doc.elements.first if doc.name.eql?('stream')
38
+ if ['presence', 'message', 'iq'].include?(doc.name)
39
+ doc = AgentXmpp::Xmpp::Stanza::import(doc)
40
+ end
41
+ client.connection.receive(doc)
42
+ end
43
+
44
+ end
@@ -0,0 +1,60 @@
1
+ ##############################################################################################################
2
+ class TestDelegate
3
+
4
+ ####------------------------------------------------------------------------------------------------------
5
+ class << self
6
+
7
+ #.........................................................................................................
8
+ @@callback_methods = []
9
+
10
+ #.........................................................................................................
11
+ def delegate_callbacks(*args)
12
+ args.each do |meth|
13
+ @@callback_methods.push(meth)
14
+ class_eval <<-do_eval
15
+ def #{meth}(*args)
16
+ AgentXmpp.logger.info "TEST_DELEGATE #{meth.to_s.upcase}"
17
+ @#{meth}_method = true
18
+ nil
19
+ end
20
+ def #{meth}_method
21
+ [@#{meth}_method, "#{meth.to_s}"]
22
+ end
23
+ attr_writer :#{meth}_method
24
+ do_eval
25
+ end
26
+ end
27
+
28
+ end
29
+
30
+ #---------------------------------------------------------------------------------------------------------
31
+ #### connection
32
+ delegate_callbacks :on_connect, :on_disconnect, :on_did_not_connect, :on_did_not_authenticate
33
+
34
+ #### authentication
35
+ delegate_callbacks :on_authenticate, :on_bind, :on_start_session, :on_preauthenticate_features,
36
+ :on_postauthenticate_features
37
+
38
+ #### presence
39
+ delegate_callbacks :on_presence, :on_presence_subscribe, :on_presence_unsubscribed, :on_presence_subscribed, :on_presence_unavailable
40
+
41
+ #### roster management
42
+ delegate_callbacks :on_roster_item, :on_all_roster_items, :on_acknowledge_add_roster_item,
43
+ :on_roster_result, :on_roster_set, :on_remove_roster_item, :on_acknowledge_remove_roster_item,
44
+ :on_remove_roster_item_error, :on_add_roster_item_error
45
+
46
+ #### service discovery management
47
+ delegate_callbacks :on_version_result, :on_version_get, :on_version_error, :on_discoinfo_result,
48
+ :on_discoinfo_get, :on_discoitems_get, :on_discoitems_result,
49
+ :on_discoinfo_error, :on_discoitems_error
50
+
51
+ #### errors
52
+ delegate_callbacks :on_unsupported_message
53
+
54
+ #---------------------------------------------------------------------------------------------------------
55
+ def initialize
56
+ @@callback_methods.each{|m| send("#{m.to_s}_method=".to_sym, false)}
57
+ end
58
+
59
+ #### TestDelegate
60
+ end
@@ -0,0 +1,91 @@
1
+ #####-------------------------------------------------------------------------------------------------------
2
+ require 'test/unit'
3
+ require 'rubygems'
4
+ begin
5
+ require 'shoulda'
6
+ rescue LoadError
7
+ abort "shoulda is not available. In order to run test, you must: sudo gem install thoughtbot-shoulda --source=http://gems.github.com"
8
+ end
9
+ begin
10
+ require 'matchy'
11
+ rescue LoadError
12
+ abort "matchy is not available. In order to run test, you must: sudo gem install mhennemeyer-matchy --source=http://gems.github.com"
13
+ end
14
+
15
+ #####-------------------------------------------------------------------------------------------------------
16
+ $:.unshift('lib')
17
+ require 'rubygems'
18
+ require 'agent_xmpp'
19
+
20
+ #####-------------------------------------------------------------------------------------------------------
21
+ require 'test_delegate'
22
+ require 'mocks'
23
+ require 'test_client'
24
+ require 'matchers'
25
+ require 'test_case_extensions'
26
+
27
+ #####-------------------------------------------------------------------------------------------------------
28
+ require 'application_messages'
29
+ require 'roster_messages'
30
+ require 'version_discovery_messages'
31
+ require 'service_discovery_messages'
32
+ require 'session_messages'
33
+ require 'presence_messages'
34
+ require 'error_messages'
35
+
36
+ #####-------------------------------------------------------------------------------------------------------
37
+ AgentXmpp.app_path = 'test/helpers'
38
+ AgentXmpp.logger.level = Logger::DEBUG
39
+
40
+ ####------------------------------------------------------------------------------------------------------
41
+ before_start do
42
+ AgentXmpp.logger.info "AgentXmpp::BootApp.before_start"
43
+ end
44
+
45
+ after_connected do |pipe|
46
+ AgentXmpp.logger.info "AgentXmpp::BootApp.after_connected"
47
+ end
48
+
49
+ restarting_client do |pipe|
50
+ AgentXmpp.logger.info "AgentXmpp::BootApp.restarting_client"
51
+ end
52
+
53
+ discovered_pubsub_service do |pipe|
54
+ AgentXmpp.logger.info "discovered_pubsub_service"
55
+ end
56
+
57
+ #####-------------------------------------------------------------------------------------------------------
58
+ execute 'scalar' do
59
+ AgentXmpp.logger.info "ACTION: scalar"
60
+ 'scalar'
61
+ end
62
+
63
+ #.........................................................................................................
64
+ execute 'hash' do
65
+ AgentXmpp.logger.info "ACTION: hash"
66
+ {:attr1 => 'val1', :attr2 => 'val2'}
67
+ end
68
+
69
+ #.........................................................................................................
70
+ execute 'scalar_array' do
71
+ AgentXmpp.logger.info "ACTION: array"
72
+ ['val1', 'val2','val3', 'val4']
73
+ end
74
+
75
+ #.........................................................................................................
76
+ execute 'hash_array' do
77
+ AgentXmpp.logger.info "ACTION: hash_array"
78
+ {:attr1 => ['val11', 'val11'], :attr2 => 'val12'}
79
+ end
80
+
81
+ #.........................................................................................................
82
+ execute 'array_hash' do
83
+ AgentXmpp.logger.info "ACTION: array_hash"
84
+ [{:attr1 => 'val11', :attr2 => 'val12'}, {:attr1 => 'val21', :attr2 => 'val22'}, {:attr1 => 'val31', :attr2 => 'val32'}]
85
+ end
86
+
87
+ #.........................................................................................................
88
+ execute 'array_hash_array' do
89
+ AgentXmpp.logger.info "ACTION: hash_array"
90
+ [{:attr1 => ['val11', 'val11'], :attr2 => 'val12'}, {:attr1 => ['val21', 'val21'], :attr2 => 'val22'}, {:attr1 => ['val31', 'val31'], :attr2 => 'val32'}]
91
+ end
@@ -0,0 +1,206 @@
1
+ ##############################################################################################################
2
+ module ApplicationMessages
3
+
4
+ #####-------------------------------------------------------------------------------------------------------
5
+ class << self
6
+
7
+ #### received messages
8
+ #.........................................................................................................
9
+ def recv_iq_set_command_execute(client, node, from)
10
+ <<-MSG
11
+ <iq from='#{from}' to='#{client.client.jid.to_s}' id='1' type='set' xmlns='jabber:client'>
12
+ <command node='#{node}' action='execute' xmlns='http://jabber.org/protocol/commands'/>
13
+ </iq>
14
+ MSG
15
+ end
16
+
17
+ #.........................................................................................................
18
+ def recv_message_chat(client, from)
19
+ <<-MSG
20
+ <message from='#{from}' to='#{client.client.jid.to_s}' type='chat' xmlns='jabber:client'>
21
+ <body>fuck you</body>
22
+ </message>
23
+ MSG
24
+ end
25
+
26
+ #### sent messages
27
+ #.........................................................................................................
28
+ def send_iq_result_command_x_data_scalar(client, to)
29
+ <<-MSG
30
+ <iq id='1' to='#{to}' type='result' xmlns='jabber:client'>
31
+ <command node='scalar' status='completed' xmlns='http://jabber.org/protocol/commands'>
32
+ <x type='result' xmlns='jabber:x:data'>
33
+ <field>
34
+ <value>scalar</value>
35
+ </field>
36
+ </x>
37
+ </command>
38
+ </iq>
39
+ MSG
40
+ end
41
+
42
+ #.........................................................................................................
43
+ def send_iq_result_command_x_data_hash(client, to)
44
+ <<-MSG
45
+ <iq id='1' to='#{to}' type='result' xmlns='jabber:client'>
46
+ <command node='hash' status='completed' xmlns='http://jabber.org/protocol/commands'>
47
+ <x type='result' xmlns='jabber:x:data'>
48
+ <field var='attr1'>
49
+ <value>val1</value>
50
+ </field>
51
+ <field var='attr2'>
52
+ <value>val2</value>
53
+ </field>
54
+ </x>
55
+ </command>
56
+ </iq>
57
+ MSG
58
+ end
59
+
60
+ #.........................................................................................................
61
+ def send_iq_result_command_x_data_scalar_array(client, to)
62
+ <<-MSG
63
+ <iq id='1' to='#{to}' type='result' xmlns='jabber:client'>
64
+ <command node='scalar_array' status='completed' xmlns='http://jabber.org/protocol/commands'>
65
+ <x type='result' xmlns='jabber:x:data'>
66
+ <field type='list-multi'>
67
+ <value>val1</value>
68
+ <value>val2</value>
69
+ <value>val3</value>
70
+ <value>val4</value>
71
+ </field>
72
+ </x>
73
+ </command>
74
+ </iq>
75
+ MSG
76
+ end
77
+
78
+ #.........................................................................................................
79
+ def send_iq_result_command_x_data_hash_array(client, to)
80
+ <<-MSG
81
+ <iq id='1' to='#{to}' type='result' xmlns='jabber:client'>
82
+ <command node='hash_array' status='completed' xmlns='http://jabber.org/protocol/commands'>
83
+ <x type='result' xmlns='jabber:x:data'>
84
+ <field type='list-multi' var='attr1'>
85
+ <value>val11</value>
86
+ <value>val11</value>
87
+ </field>
88
+ <field var='attr2'>
89
+ <value>val12</value>
90
+ </field>
91
+ </x>
92
+ </command>
93
+ </iq>
94
+ MSG
95
+ end
96
+
97
+ #.........................................................................................................
98
+ def send_iq_result_command_x_data_array_hash(client, to)
99
+ <<-MSG
100
+ <iq id='1' to='#{to}' type='result' xmlns='jabber:client'>
101
+ <command node='array_hash' status='completed' xmlns='http://jabber.org/protocol/commands'>
102
+ <x type='result' xmlns='jabber:x:data'>
103
+ <reported>
104
+ <field var='attr1'/>
105
+ <field var='attr2'/>
106
+ </reported>
107
+ <item>
108
+ <field var='attr1'>
109
+ <value>val11</value>
110
+ </field>
111
+ <field var='attr2'>
112
+ <value>val12</value>
113
+ </field>
114
+ </item>
115
+ <item>
116
+ <field var='attr1'>
117
+ <value>val21</value>
118
+ </field>
119
+ <field var='attr2'>
120
+ <value>val22</value>
121
+ </field>
122
+ </item>
123
+ <item>
124
+ <field var='attr1'>
125
+ <value>val31</value>
126
+ </field>
127
+ <field var='attr2'>
128
+ <value>val32</value>
129
+ </field>
130
+ </item>
131
+ </x>
132
+ </command>
133
+ </iq>
134
+ MSG
135
+ end
136
+
137
+ #.........................................................................................................
138
+ def send_iq_result_command_x_data_array_hash_array(client, to)
139
+ <<-MSG
140
+ <iq id='1' to='#{to}' type='result' xmlns='jabber:client'>
141
+ <command node='array_hash_array' status='completed' xmlns='http://jabber.org/protocol/commands'>
142
+ <x type='result' xmlns='jabber:x:data'>
143
+ <reported>
144
+ <field var='attr1'/>
145
+ <field var='attr2'/>
146
+ </reported>
147
+ <item>
148
+ <field type='list-multi' var='attr1'>
149
+ <value>val11</value>
150
+ <value>val11</value>
151
+ </field>
152
+ <field var='attr2'>
153
+ <value>val12</value>
154
+ </field>
155
+ </item>
156
+ <item>
157
+ <field type='list-multi' var='attr1'>
158
+ <value>val21</value>
159
+ <value>val21</value>
160
+ </field>
161
+ <field var='attr2'>
162
+ <value>val22</value>
163
+ </field>
164
+ </item>
165
+ <item>
166
+ <field type='list-multi' var='attr1'>
167
+ <value>val31</value>
168
+ <value>val31</value>
169
+ </field>
170
+ <field var='attr2'>
171
+ <value>val32</value>
172
+ </field>
173
+ </item>
174
+ </x>
175
+ </command>
176
+ </iq>
177
+ MSG
178
+ end
179
+
180
+ #.........................................................................................................
181
+ def send_error_command_routing(client, node, to)
182
+ <<-MSG
183
+ <iq id='1' to='#{to}' type='error' xmlns='jabber:client'>
184
+ <command node='#{node}' action='execute' xmlns='http://jabber.org/protocol/commands'/>
185
+ <error code='404' type='cancel'>
186
+ <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
187
+ <text xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'>no route for specified command node</text>
188
+ </error>
189
+ </iq>
190
+ MSG
191
+ end
192
+
193
+ #.........................................................................................................
194
+ def send_message_chat(client, to)
195
+ <<-MSG
196
+ <message to='#{to}' type='chat' xmlns='jabber:client'>
197
+ <body>#{AgentXmpp::AGENT_XMPP_NAME} #{AgentXmpp::VERSION}, #{AgentXmpp::OS_VERSION}</body>
198
+ </message>
199
+ MSG
200
+ end
201
+
202
+ ## self
203
+ end
204
+
205
+ #### ApplicationMessages
206
+ end