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.
- data/.document +5 -0
- data/.gitignore +11 -0
- data/LICENSE +20 -0
- data/README.rdoc +417 -0
- data/Rakefile +75 -0
- data/VERSION +1 -0
- data/agent_xmpp.gemspec +144 -0
- data/lib/agent_xmpp.rb +22 -0
- data/lib/agent_xmpp/admin.rb +113 -0
- data/lib/agent_xmpp/client.rb +7 -0
- data/lib/agent_xmpp/client/boot.rb +83 -0
- data/lib/agent_xmpp/client/client.rb +64 -0
- data/lib/agent_xmpp/client/connection.rb +108 -0
- data/lib/agent_xmpp/client/controller.rb +394 -0
- data/lib/agent_xmpp/client/message_delegate.rb +720 -0
- data/lib/agent_xmpp/client/message_pipe.rb +193 -0
- data/lib/agent_xmpp/client/response.rb +102 -0
- data/lib/agent_xmpp/config.rb +48 -0
- data/lib/agent_xmpp/main.rb +175 -0
- data/lib/agent_xmpp/models.rb +7 -0
- data/lib/agent_xmpp/models/contact.rb +85 -0
- data/lib/agent_xmpp/models/message.rb +152 -0
- data/lib/agent_xmpp/models/publication.rb +53 -0
- data/lib/agent_xmpp/models/roster.rb +107 -0
- data/lib/agent_xmpp/models/service.rb +91 -0
- data/lib/agent_xmpp/models/subscription.rb +61 -0
- data/lib/agent_xmpp/models/table_definitions.rb +107 -0
- data/lib/agent_xmpp/patches.rb +7 -0
- data/lib/agent_xmpp/patches/array.rb +32 -0
- data/lib/agent_xmpp/patches/float.rb +10 -0
- data/lib/agent_xmpp/patches/hash.rb +13 -0
- data/lib/agent_xmpp/patches/object.rb +15 -0
- data/lib/agent_xmpp/patches/rexml.rb +69 -0
- data/lib/agent_xmpp/patches/string.rb +15 -0
- data/lib/agent_xmpp/xmpp.rb +18 -0
- data/lib/agent_xmpp/xmpp/element.rb +158 -0
- data/lib/agent_xmpp/xmpp/entry.rb +36 -0
- data/lib/agent_xmpp/xmpp/error_response.rb +189 -0
- data/lib/agent_xmpp/xmpp/iq.rb +90 -0
- data/lib/agent_xmpp/xmpp/iq_command.rb +54 -0
- data/lib/agent_xmpp/xmpp/iq_disco.rb +206 -0
- data/lib/agent_xmpp/xmpp/iq_pubsub.rb +270 -0
- data/lib/agent_xmpp/xmpp/iq_roster.rb +183 -0
- data/lib/agent_xmpp/xmpp/iq_version.rb +89 -0
- data/lib/agent_xmpp/xmpp/jid.rb +150 -0
- data/lib/agent_xmpp/xmpp/message.rb +82 -0
- data/lib/agent_xmpp/xmpp/presence.rb +127 -0
- data/lib/agent_xmpp/xmpp/sasl.rb +241 -0
- data/lib/agent_xmpp/xmpp/stanza.rb +107 -0
- data/lib/agent_xmpp/xmpp/x_data.rb +357 -0
- data/test/app/app.rb +339 -0
- data/test/cases/test_application_message_processing.rb +65 -0
- data/test/cases/test_errors.rb +24 -0
- data/test/cases/test_presence_management.rb +139 -0
- data/test/cases/test_roster_management.rb +214 -0
- data/test/cases/test_service_discovery.rb +168 -0
- data/test/cases/test_session_management.rb +120 -0
- data/test/cases/test_version_discovery.rb +67 -0
- data/test/helpers/matchers.rb +23 -0
- data/test/helpers/mocks.rb +82 -0
- data/test/helpers/test_case_extensions.rb +45 -0
- data/test/helpers/test_client.rb +44 -0
- data/test/helpers/test_delegate.rb +60 -0
- data/test/helpers/test_helper.rb +91 -0
- data/test/messages/application_messages.rb +206 -0
- data/test/messages/error_messages.rb +35 -0
- data/test/messages/presence_messages.rb +66 -0
- data/test/messages/roster_messages.rb +126 -0
- data/test/messages/service_discovery_messages.rb +201 -0
- data/test/messages/session_messages.rb +158 -0
- data/test/messages/version_discovery_messages.rb +69 -0
- data/test/peer/peer.rb +21 -0
- metadata +187 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Troy Stribling
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,417 @@
|
|
1
|
+
= Agent XMPP
|
2
|
+
|
3
|
+
Agent XMPP is a simple DSL for writing automated XMPP clients that support Messaging, Ad-Hoc Commands and Publish Subscribe
|
4
|
+
Events. An application that responds to an Ad-Hoc command can be written with few lines of code.
|
5
|
+
|
6
|
+
# myapp.rb
|
7
|
+
require 'rubygems'
|
8
|
+
require 'agent_xmpp'
|
9
|
+
|
10
|
+
command 'hello' do
|
11
|
+
'Hello World'
|
12
|
+
end
|
13
|
+
|
14
|
+
Specify the application Jabber ID (JID), password and roster in <tt>agent_xmpp.yml</tt>.
|
15
|
+
|
16
|
+
jid: myapp@nowhere.com
|
17
|
+
password: none
|
18
|
+
roster:
|
19
|
+
-
|
20
|
+
jid:you@home.com
|
21
|
+
groups: [admin]
|
22
|
+
|
23
|
+
Be sure libxml2 headers are available and that libsqlite3-ruby1.9.1 is installed,
|
24
|
+
|
25
|
+
sudo apt-get install libxml2-dev
|
26
|
+
sudo apt-get install libsqlite3-ruby1.9.1
|
27
|
+
|
28
|
+
Install the gem,
|
29
|
+
|
30
|
+
sudo gem install troystribling-agent_xmpp --source=http://gems.github.com
|
31
|
+
|
32
|
+
Install the Gajim XMPP Client version 0.12.3 or higher, http://www.gajim.org, and connect to <i>you@home.com</i>.
|
33
|
+
|
34
|
+
Run the application,
|
35
|
+
|
36
|
+
ruby myapp.rb
|
37
|
+
|
38
|
+
When started for the first time <tt>myapp.rb</tt> will automatically send buddy requests to all contacts specified
|
39
|
+
in <tt>agent_xmpp.yml</tt>. Accept the buddy request and _myapp_ will appear as a contact in the Gajim roster. Right click on _myapp_
|
40
|
+
and select _execute_ _commands_ from the drop down menu. A list of Ad-Hoc Commands will be displayed containing _hello_.
|
41
|
+
Select it and click the _forward_ _button_ to execute.
|
42
|
+
|
43
|
+
== Supported Environment
|
44
|
+
|
45
|
+
The following versions of ruby are supported
|
46
|
+
|
47
|
+
ruby 1.9.1
|
48
|
+
|
49
|
+
The following Operating Systems are supported
|
50
|
+
|
51
|
+
Ubuntu 10.4
|
52
|
+
|
53
|
+
== Ad-Hoc Command Response Payload
|
54
|
+
|
55
|
+
Agent XMPP will map native ruby scalars, arrays and hashes returned by <tt>execute</tt> blocks to jabber:x:data command
|
56
|
+
response payloads (see XEP-0004 http://xmpp.org/extensions/xep-0004.html for a description of jabber:x:data).
|
57
|
+
|
58
|
+
command 'scalar' do
|
59
|
+
'scalar'
|
60
|
+
end
|
61
|
+
|
62
|
+
command 'hash' do
|
63
|
+
{:a1 => 'v1', :a2 => 'v2'}
|
64
|
+
end
|
65
|
+
|
66
|
+
command 'scalar_array' do
|
67
|
+
['v1', 'v2','v3', 'v4']
|
68
|
+
end
|
69
|
+
|
70
|
+
command 'hash_array' do
|
71
|
+
{:a1 => ['v11', 'v11'], :a2 => 'v12'}
|
72
|
+
end
|
73
|
+
|
74
|
+
command 'array_hash' do
|
75
|
+
[{:a1 => 'v11', :a2 => 'v12'},
|
76
|
+
{:a1 => 'v21', :a2 => 'v22'},
|
77
|
+
{:a1 => 'v31', :a2 => 'v32'}]
|
78
|
+
end
|
79
|
+
|
80
|
+
command 'array_hash_array' do
|
81
|
+
[{:a1 => ['v11', 'v11'], :a2 => 'v12'},
|
82
|
+
{:a1 => ['v21', 'v21'], :a2 => 'v22'},
|
83
|
+
{:a1 => ['v31', 'v31'], :a2 => 'v32'}]
|
84
|
+
end
|
85
|
+
|
86
|
+
a <tt>params</tt> structure is available within the <tt>execute</tt> block containing routing information.
|
87
|
+
|
88
|
+
== Ad-Hoc Command Forms
|
89
|
+
|
90
|
+
Agent XMPP supports
|
91
|
+
== Send Commands
|
92
|
+
|
93
|
+
Commands may be sent with or without a response callback,
|
94
|
+
|
95
|
+
send_command(:to=>'thatapp@a-place.com/ahost', :node=> 'hello') do |status, data|
|
96
|
+
puts "COMMAND RESPONSE: #{status}, #{data.inspect}"
|
97
|
+
end
|
98
|
+
|
99
|
+
send_command(:to=>'thatapp@a-place.com/ahost', :node=> 'bye')
|
100
|
+
|
101
|
+
and within <tt>command</tt> blocks.
|
102
|
+
|
103
|
+
command 'hash_hello' do
|
104
|
+
send_command(:to=>params[:from], :node=> 'hello') do |status, data|
|
105
|
+
puts "COMMAND RESPONSE: #{status}, #{data.inspect}"
|
106
|
+
end
|
107
|
+
{:a1 => 'v1', :a2 => 'v2'}
|
108
|
+
end
|
109
|
+
|
110
|
+
== Publish
|
111
|
+
|
112
|
+
Publish nodes are configured in <tt>agent_xmpp.yml</tt>.
|
113
|
+
|
114
|
+
jid: myapp@nowhere.com
|
115
|
+
password: none
|
116
|
+
roster:
|
117
|
+
-
|
118
|
+
jid:you@home.com
|
119
|
+
publish:
|
120
|
+
-
|
121
|
+
node: time
|
122
|
+
title: "Curent Time"
|
123
|
+
-
|
124
|
+
node: alarm
|
125
|
+
title: "Alarms"
|
126
|
+
|
127
|
+
The nodes are created if they do not exist and publish methods are generated for each node.
|
128
|
+
|
129
|
+
publish_time('The time is:' + Time.now.to_s)
|
130
|
+
|
131
|
+
publish_alarm({:severity => :major, :description => "A really bad failure"})
|
132
|
+
|
133
|
+
Publish nodes discovered that are not in <tt>agent_xmpp.yml</tt> will be deleted.
|
134
|
+
|
135
|
+
== Publish Options
|
136
|
+
|
137
|
+
The following publish options are available with the indicated default values. The options may be changed in
|
138
|
+
<tt>agent_xmpp.yml</tt>.
|
139
|
+
|
140
|
+
:title => 'event',
|
141
|
+
:access_model => 'presence',
|
142
|
+
:max_items => 20,
|
143
|
+
:deliver_notifications => 1,
|
144
|
+
:deliver_payloads => 1,
|
145
|
+
:persist_items => 1,
|
146
|
+
:subscribe => 1,
|
147
|
+
:notify_config => 0,
|
148
|
+
:notify_delete => 0,
|
149
|
+
:notify_retract => 0,
|
150
|
+
|
151
|
+
See http://xmpp.org/extensions/xep-0060.html#registrar-formtypes-config for a detailed description.
|
152
|
+
|
153
|
+
== Subscribe
|
154
|
+
|
155
|
+
Declare <tt>event</tt> blocks in <tt>myapp.rb</tt> to subscribe to published events.
|
156
|
+
|
157
|
+
# myapp.rb
|
158
|
+
require 'rubygems'
|
159
|
+
require 'agent_xmpp'
|
160
|
+
|
161
|
+
event 'someone@somewhere.com', 'time' do
|
162
|
+
message(:to=>'someone@somewhere.com', :body=>"Got the event at: " + Time.now.to_s)
|
163
|
+
end
|
164
|
+
|
165
|
+
Agent XMPP will verify subscription to the event and subscribe if required. Subscriptions
|
166
|
+
discovered that are not declared by an event block will be deleted.
|
167
|
+
|
168
|
+
== Receive Chat Messages
|
169
|
+
|
170
|
+
Declare <tt>chat</tt> blocks in <tt>myapp.rb</tt> to receive and respond to chat messages.
|
171
|
+
|
172
|
+
# myapp.rb
|
173
|
+
require 'rubygems'
|
174
|
+
require 'agent_xmpp'
|
175
|
+
|
176
|
+
chat do
|
177
|
+
params[:body].reverse
|
178
|
+
end
|
179
|
+
|
180
|
+
If the <tt>chat</tt> block returns a <tt>String</tt> a response will be sent to the message sender.
|
181
|
+
|
182
|
+
== Send Chat Messages
|
183
|
+
|
184
|
+
send_chat(:to=>'thatapp@a-place.com/onahost', :body=>"Hello from #{AgentXmpp.jid.to_s} at " + Time.now.to_s)
|
185
|
+
|
186
|
+
== Roster
|
187
|
+
|
188
|
+
Roster groups may be specified in <tt>agent_xmpp.yml</tt>.
|
189
|
+
|
190
|
+
jid: myapp@nowhere.com
|
191
|
+
password: none
|
192
|
+
roster:
|
193
|
+
-
|
194
|
+
jid:you@home.com
|
195
|
+
groups: [good group, owners]
|
196
|
+
|
197
|
+
-
|
198
|
+
jid: someone@somewhere.com
|
199
|
+
groups: [bad group]
|
200
|
+
|
201
|
+
Agent XMPP will update the roster maintained on the XMPP server to be consistent with to the roster specified in <tt>agent_xmpp.yml</tt>.
|
202
|
+
|
203
|
+
== Routing Priority
|
204
|
+
|
205
|
+
The routing priority may be configured in <tt>agent_xmpp.yml</tt>. The default value is 1. Valid values are between -127 and 128.
|
206
|
+
See http://xmpp.org/rfcs/rfc3921.html for a details.
|
207
|
+
|
208
|
+
jid: myapp@nowhere.com
|
209
|
+
password: none
|
210
|
+
priority: 128
|
211
|
+
roster:
|
212
|
+
-
|
213
|
+
jid:you@home.com
|
214
|
+
groups: [good group, owners]
|
215
|
+
|
216
|
+
== Major Event Callbacks
|
217
|
+
|
218
|
+
Agent XMPP provides callbacks for applications to respond to major events that occur during execution.
|
219
|
+
|
220
|
+
# application starting
|
221
|
+
before_start{}
|
222
|
+
|
223
|
+
# connected to server
|
224
|
+
after_connected{|connection|}
|
225
|
+
|
226
|
+
# client restarts when disconnected form server
|
227
|
+
restarting_client{|connection|}
|
228
|
+
|
229
|
+
# a pubsub node was discovered at service
|
230
|
+
discovered_pubsub_node{|service, node|}
|
231
|
+
|
232
|
+
# command nodes were discovered at jid
|
233
|
+
discovered_command_nodes{|jid, nodes|}
|
234
|
+
|
235
|
+
# a presence message of status :available or :unavailable was received from jid
|
236
|
+
received_presence{|from, status|}
|
237
|
+
|
238
|
+
== Authentication
|
239
|
+
|
240
|
+
* Basic SASL
|
241
|
+
|
242
|
+
== Development with XMPP Clients
|
243
|
+
|
244
|
+
Ad-Hoc Commands, jabber:x:data Forms nor Service Discovery are widely supported by XMPP clients and I have not found
|
245
|
+
a client that supports Publish-Subscribe. Gajim http://www.gajim.org provides support for Ad-Hoc Commands and jabber:x:data Forms. Service Discovery,
|
246
|
+
which is useful for Publish-Subscibe development, is supported by Gajim, but Psi http://psi-im.org provides a much better
|
247
|
+
implementation. Both Gajim and Psi provide an interface for manual entry of XML messages. Since Publish-Subscribe is not supported on
|
248
|
+
the user interface manual entry of messages is required for development. Example messages can be found at http://gist.github.com/160344
|
249
|
+
|
250
|
+
== Logging
|
251
|
+
|
252
|
+
By default log messages are written to STDOUT. A log file can be specified with the -l option.
|
253
|
+
|
254
|
+
ruby mybot.rb -l file.log
|
255
|
+
|
256
|
+
The logger can be accessed and configured.
|
257
|
+
|
258
|
+
before_start do
|
259
|
+
AgentXmpp.logger.level = Logger::WARN
|
260
|
+
end
|
261
|
+
|
262
|
+
== More Examples
|
263
|
+
|
264
|
+
More examples can be found at http://gist.github.com/160338
|
265
|
+
|
266
|
+
== Supported XEPs
|
267
|
+
|
268
|
+
XEP-0004 jabber:x:data Forms http://xmpp.org/extensions/xep-0004.html
|
269
|
+
XEP-0030 Service Discovery http://xmpp.org/extensions/xep-0030.html
|
270
|
+
XEP-0050 Ad-Hoc Commands http://xmpp.org/extensions/xep-0050.html
|
271
|
+
XEP-0060 Publish Subscribe http://xmpp.org/extensions/xep-0060.html
|
272
|
+
XEP-0092 Software Version http://xmpp.org/extensions/xep-0092.html
|
273
|
+
|
274
|
+
== Message Processing Callbacks
|
275
|
+
|
276
|
+
Message processing callbacks are available to applications to extend the message processing work flow. To receive
|
277
|
+
callbacks a delegate object must be provided that implements the callbacks of interest.
|
278
|
+
|
279
|
+
after_connected do |connection|
|
280
|
+
connection.add_delegate(YourDelegate)
|
281
|
+
end
|
282
|
+
|
283
|
+
=== Connection
|
284
|
+
|
285
|
+
on_connect(connection)
|
286
|
+
|
287
|
+
on_disconnect(connection)
|
288
|
+
|
289
|
+
on_did_not_connect(connection)
|
290
|
+
|
291
|
+
=== Authentication
|
292
|
+
|
293
|
+
on_bind(connection)
|
294
|
+
|
295
|
+
on_preauthenticate_features(connection)
|
296
|
+
|
297
|
+
on_authenticate(connection)
|
298
|
+
|
299
|
+
on_did_not_authenticate(connection)
|
300
|
+
|
301
|
+
on_postauthenticate_features(connection)
|
302
|
+
|
303
|
+
on_start_session(connection)
|
304
|
+
|
305
|
+
=== Presence
|
306
|
+
|
307
|
+
on_presence(connection, presence)
|
308
|
+
|
309
|
+
on_presence_subscribe(connection, presence)
|
310
|
+
|
311
|
+
on_presence_subscribed(connection, presence)
|
312
|
+
|
313
|
+
on_presence_unavailable(connection, presence)
|
314
|
+
|
315
|
+
on_presence_unsubscribed(connection, presence)
|
316
|
+
|
317
|
+
on_presence_error(pipe, presence)
|
318
|
+
|
319
|
+
=== Roster
|
320
|
+
|
321
|
+
on_roster_result(connection, stanza)
|
322
|
+
|
323
|
+
on_roster_set(connection, stanza)
|
324
|
+
|
325
|
+
on_roster_item(connection, roster_item)
|
326
|
+
|
327
|
+
on_remove_roster_item(connection, roster_item)
|
328
|
+
|
329
|
+
on_all_roster_items(connection)
|
330
|
+
|
331
|
+
on_update_roster_item_result(connection, item_jid)
|
332
|
+
|
333
|
+
on_update_roster_item_error(connection, item_jid)
|
334
|
+
|
335
|
+
on_remove_roster_item(connection, item_jid)
|
336
|
+
|
337
|
+
on_remove_roster_item_error(connection, item_jid)
|
338
|
+
|
339
|
+
=== Service Discovery
|
340
|
+
|
341
|
+
on_version_result(connection, version)
|
342
|
+
|
343
|
+
on_version_get(connection, request)
|
344
|
+
|
345
|
+
on_version_error(connection, error)
|
346
|
+
|
347
|
+
on_discoinfo_get(connection, request)
|
348
|
+
|
349
|
+
on_discoinfo_result(connection, discoinfo)
|
350
|
+
|
351
|
+
on_discoinfo_error(connection, error)
|
352
|
+
|
353
|
+
on_discoitems_result(connection, discoitems)
|
354
|
+
|
355
|
+
on_discoitems_get(connection, request)
|
356
|
+
|
357
|
+
on_discoitems_error(connection, result)
|
358
|
+
|
359
|
+
=== Applications
|
360
|
+
|
361
|
+
on_command_set(connection, stanza)
|
362
|
+
|
363
|
+
on_message_chat(connection, stanza)
|
364
|
+
|
365
|
+
on_message_normal(connection, stanza)
|
366
|
+
|
367
|
+
on_pubsub_event(connection, event, to, from)
|
368
|
+
|
369
|
+
=== PubSub
|
370
|
+
|
371
|
+
on_publish_result(connection, result, node)
|
372
|
+
|
373
|
+
on_publish_error(connection, result, node)
|
374
|
+
|
375
|
+
on_discovery_of_pubsub_service(connection, jid, ident)
|
376
|
+
|
377
|
+
on_discovery_of_pubsub_collection(connection, jid, node)
|
378
|
+
|
379
|
+
on_discovery_of_pubsub_leaf(connection, jid, node)
|
380
|
+
|
381
|
+
on_discovery_of_user_pubsub_root(pipe, pubsub, node)
|
382
|
+
|
383
|
+
on_pubsub_subscriptions_result(connection, result)
|
384
|
+
|
385
|
+
on_pubsub_subscriptions_error(connection, result)
|
386
|
+
|
387
|
+
on_pubsub_affiliations_result(connection, result)
|
388
|
+
|
389
|
+
on_pubsub_affiliations_error(connection, result)
|
390
|
+
|
391
|
+
on_discovery_of_user_pubsub_root(connection, result)
|
392
|
+
|
393
|
+
on_create_node_result(connection, node, result)
|
394
|
+
|
395
|
+
on_create_node_error(connection, node, result)
|
396
|
+
|
397
|
+
on_delete_node_result(connection, node, result)
|
398
|
+
|
399
|
+
on_delete_node_error(connection, node, result)
|
400
|
+
|
401
|
+
on_pubsub_subscribe_result(connection, result, node)
|
402
|
+
|
403
|
+
on_pubsub_subscribe_error(connection, result, node)
|
404
|
+
|
405
|
+
on_pubsub_subscribe_error_item_not_found(connection, result, node)
|
406
|
+
|
407
|
+
on_pubsub_unsubscribe_result(connection, result, node)
|
408
|
+
|
409
|
+
on_pubsub_unsubscribe_error(connection, result, node)
|
410
|
+
|
411
|
+
=== ERRORS
|
412
|
+
|
413
|
+
on_unsupported_message(connection, stanza)
|
414
|
+
|
415
|
+
== Copyright
|
416
|
+
|
417
|
+
Copyright (c) 2009 Troy Stribling. See LICENSE for details.
|