em-xmpp 0.0.11 → 0.0.12
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/bin/xmig +40 -37
- data/em-xmpp.gemspec +1 -0
- data/lib/em-xmpp.rb +0 -2
- data/lib/em-xmpp/component.rb +18 -0
- data/lib/em-xmpp/connection.rb +35 -103
- data/lib/em-xmpp/context.rb +37 -19
- data/lib/em-xmpp/entity.rb +219 -223
- data/lib/em-xmpp/evented.rb +183 -0
- data/lib/em-xmpp/handler.rb +89 -86
- data/lib/em-xmpp/helpers.rb +39 -38
- data/lib/em-xmpp/namespaces.rb +1 -0
- data/lib/em-xmpp/non-em.rb +95 -0
- data/lib/em-xmpp/version.rb +1 -1
- data/lib/em-xmpp/xml_builder.rb +160 -0
- data/lib/em-xmpp/xml_parser.rb +344 -0
- data/samples/hello.rb +6 -3
- data/samples/non-em-hello.rb +90 -0
- metadata +25 -9
- data/lib/em-xmpp/connector.rb +0 -244
data/bin/xmig
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
$LOAD_PATH.unshift './lib'
|
2
|
-
require 'em-xmpp'
|
2
|
+
require 'em-xmpp/connection'
|
3
3
|
require 'em-xmpp/helpers'
|
4
4
|
require 'em-xmpp/conversation'
|
5
5
|
|
@@ -46,7 +46,7 @@ module Command extend self
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def print_context_dataforms(ctx)
|
49
|
-
df = ctx.bit
|
49
|
+
df = ctx.bit(:dataforms)
|
50
50
|
df.x_forms.each do |form|
|
51
51
|
print_dataform form
|
52
52
|
end
|
@@ -116,7 +116,7 @@ module Command extend self
|
|
116
116
|
lambda do |client|
|
117
117
|
puts "=== PubSub Subscriptions on #{jid} (#{node}) ==="
|
118
118
|
ctx = client.entity(jid).pubsub(node).service_subscriptions
|
119
|
-
ctx.bit
|
119
|
+
ctx.bit(:pubsub).subscriptions.each do |s|
|
120
120
|
puts "#{s.node} -- #{s.subscription} (#{s.sub_id})"
|
121
121
|
end
|
122
122
|
end
|
@@ -125,7 +125,7 @@ module Command extend self
|
|
125
125
|
lambda do |client|
|
126
126
|
puts "=== PubSub Affiliations on #{jid} (#{node}) ==="
|
127
127
|
ctx = client.entity(jid).pubsub(node).service_affiliations
|
128
|
-
ctx.bit
|
128
|
+
ctx.bit(:pubsub).affiliations.each do |s|
|
129
129
|
puts "#{s.node} (#{s.affiliation})"
|
130
130
|
end
|
131
131
|
end
|
@@ -182,7 +182,7 @@ module Command extend self
|
|
182
182
|
lambda do |client|
|
183
183
|
puts "publishing #{payload.size} bytes to #{jid} (#{node})"
|
184
184
|
ctx = client.entity(jid).pubsub(node).publish(payload)
|
185
|
-
ctx.bit
|
185
|
+
ctx.bit(:pubsub).items.each do |item|
|
186
186
|
puts "published: #{item.item_id} at #{item.node}"
|
187
187
|
end
|
188
188
|
end
|
@@ -215,7 +215,7 @@ module Command extend self
|
|
215
215
|
lambda do |client|
|
216
216
|
puts "=== PubSub Subscriptions on #{jid} ==="
|
217
217
|
ctx = client.entity(jid).pubsub(node).subscriptions
|
218
|
-
ctx.bit
|
218
|
+
ctx.bit(:pubsubowner).subscriptions.each do |s|
|
219
219
|
puts "#{s.jid} -- #{s.subscription} (#{s.sub_id})"
|
220
220
|
end
|
221
221
|
end
|
@@ -224,7 +224,7 @@ module Command extend self
|
|
224
224
|
lambda do |client|
|
225
225
|
puts "=== PubSub Affiliations on #{jid} ==="
|
226
226
|
ctx = client.entity(jid).pubsub(node).affiliations
|
227
|
-
ctx.bit
|
227
|
+
ctx.bit(:pubsubowner).affiliations.each do |s|
|
228
228
|
puts "#{s.jid} (#{s.affiliation})"
|
229
229
|
end
|
230
230
|
end
|
@@ -366,13 +366,15 @@ module Command extend self
|
|
366
366
|
|
367
367
|
client.entity(dst).say("",'chat', xmlproc)
|
368
368
|
client.on_iq do |ctx|
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
369
|
+
if ctx.bit?(:bob)
|
370
|
+
bob = ctx.bit(:bob)
|
371
|
+
if (bob.cid == item.cid)
|
372
|
+
puts "sending bob"
|
373
|
+
iq = bob.reply(item)
|
374
|
+
client.send_stanza iq
|
375
|
+
ctx.delete_xpath_handler!
|
376
|
+
ctx.done!
|
377
|
+
end
|
376
378
|
end
|
377
379
|
ctx
|
378
380
|
end
|
@@ -484,11 +486,11 @@ module Command extend self
|
|
484
486
|
disco = client.entity(dst).discover_infos(node)
|
485
487
|
|
486
488
|
puts "=== Identities ==="
|
487
|
-
disco.bit
|
489
|
+
disco.bit(:discoinfos).identities.each do |i|
|
488
490
|
puts "#{i.category}/#{i.type}: #{i.name || "_"}"
|
489
491
|
end
|
490
492
|
puts "=== Features ==="
|
491
|
-
disco.bit
|
493
|
+
disco.bit(:discoinfos).features.each do |f|
|
492
494
|
puts "#{f.var}"
|
493
495
|
end
|
494
496
|
end
|
@@ -500,7 +502,7 @@ module Command extend self
|
|
500
502
|
disco = client.entity(dst).discover_items(node)
|
501
503
|
|
502
504
|
puts "=== Items ==="
|
503
|
-
disco.bit
|
505
|
+
disco.bit(:discoitems).items.each do |i|
|
504
506
|
puts "#{i.entity} (#{i.node}) -- #{i.name || i.entity}"
|
505
507
|
end
|
506
508
|
end
|
@@ -594,6 +596,8 @@ module RosterClient
|
|
594
596
|
attr_reader :queue
|
595
597
|
|
596
598
|
def ready
|
599
|
+
@handler.enable_default_stack_decorators!
|
600
|
+
|
597
601
|
@show_xml = false
|
598
602
|
puts "***** #{@jid} ready"
|
599
603
|
user_data.each{|c| handle_command c}
|
@@ -607,7 +611,7 @@ module RosterClient
|
|
607
611
|
|
608
612
|
# Signal presence subscriptions
|
609
613
|
on_presence do |ctx|
|
610
|
-
pre = ctx.bit
|
614
|
+
pre = ctx.bit(:presence)
|
611
615
|
if pre.subscription_request?
|
612
616
|
puts "=== Presence subscription request from: #{pre.from.bare}"
|
613
617
|
ctx.done!
|
@@ -617,15 +621,15 @@ module RosterClient
|
|
617
621
|
|
618
622
|
# Signal people arriving and leaving
|
619
623
|
on_presence do |ctx|
|
620
|
-
pre = ctx.bit
|
624
|
+
pre = ctx.bit(:presence)
|
621
625
|
puts "=== Presence #{pre.from}: #{pre.type}"
|
622
626
|
ctx.done!
|
623
627
|
end
|
624
628
|
|
625
629
|
# Acknowledge roster change
|
626
630
|
on_iq do |ctx|
|
627
|
-
|
628
|
-
|
631
|
+
if ctx.bit?(:roster)
|
632
|
+
roster = ctx.bit(:roster)
|
629
633
|
if roster.type == 'set'
|
630
634
|
puts "=== Roster change ==="
|
631
635
|
roster.items.each do |item|
|
@@ -640,8 +644,8 @@ module RosterClient
|
|
640
644
|
|
641
645
|
# Replies to item queries
|
642
646
|
on_iq do |ctx|
|
643
|
-
|
644
|
-
|
647
|
+
if ctx.bit?(:discoitems)
|
648
|
+
query = ctx.bit(:discoitems)
|
645
649
|
list = items(query.to,query.node)
|
646
650
|
puts "==== #{query.from} discovers #{list.size} items at node #{query.node} ==="
|
647
651
|
reply = query.reply do |iq|
|
@@ -661,9 +665,8 @@ module RosterClient
|
|
661
665
|
|
662
666
|
# Replies to command queries
|
663
667
|
on_iq do |ctx|
|
664
|
-
|
665
|
-
|
666
|
-
if query
|
668
|
+
if ctx.bit?(:command)
|
669
|
+
query = ctx.bit(:command)
|
667
670
|
if query.sessionid
|
668
671
|
key = "command:#{query.from}:#{query.node}:#{query.sessionid}"
|
669
672
|
conv = conversation(key)
|
@@ -720,10 +723,10 @@ module RosterClient
|
|
720
723
|
|
721
724
|
# Prints Pubsub event
|
722
725
|
on_message do |ctx|
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
726
|
+
if ctx.bit?(:pubsubevent)
|
727
|
+
event = ctx.bit(:pubsubevent)
|
728
|
+
delay = ctx.bit(:delay)
|
729
|
+
stamp = delay.stamp
|
727
730
|
puts "=== PubSub event #{event.service} #{stamp} ==="
|
728
731
|
if event.items_node #oddly enough, retractions fall in items_node
|
729
732
|
items = event.items
|
@@ -763,8 +766,8 @@ module RosterClient
|
|
763
766
|
ctx.done!
|
764
767
|
end
|
765
768
|
|
766
|
-
|
767
|
-
|
769
|
+
if ctx.bit?(:pubsub)
|
770
|
+
event = ctx.bit(:pubsub)
|
768
771
|
puts "=== PubSub #{event.service} ==="
|
769
772
|
event.subscriptions.each do |sub|
|
770
773
|
puts "subscription of #{sub.jid} (#{sub.sub_id}) status is now #{sub.subscription} for #{sub.node}"
|
@@ -776,8 +779,8 @@ module RosterClient
|
|
776
779
|
end
|
777
780
|
|
778
781
|
on_iq do |ctx|
|
779
|
-
|
780
|
-
|
782
|
+
if ctx.bit?(:streaminitiation)
|
783
|
+
si = ctx.bit(:streaminitiation)
|
781
784
|
puts "=== FileTransfer request from #{si.from}:#{si.id} ==="
|
782
785
|
puts "file details: #{si.file_name} (#{si.file_size} bytes) (mime:#{si.mime_type})"
|
783
786
|
puts "description: #{si.description}" if si.description
|
@@ -796,8 +799,8 @@ module RosterClient
|
|
796
799
|
end
|
797
800
|
|
798
801
|
on_iq do |ctx|
|
799
|
-
|
800
|
-
|
802
|
+
if ctx.bit?(:ibb)
|
803
|
+
ibb = ctx.bit(:ibb)
|
801
804
|
key = ibb_conversation_key(ibb)
|
802
805
|
|
803
806
|
if ibb.open_node
|
@@ -954,7 +957,7 @@ module RosterClient
|
|
954
957
|
end
|
955
958
|
|
956
959
|
def default_dataform_conversation(ctx, banner, &action)
|
957
|
-
ctx.env['dataform'] = ctx.bit
|
960
|
+
ctx.env['dataform'] = ctx.bit(:dataforms).form
|
958
961
|
dataform_conversation(ctx) do |step|
|
959
962
|
step.on(:start) do
|
960
963
|
puts banner
|
data/em-xmpp.gemspec
CHANGED
data/lib/em-xmpp.rb
CHANGED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'em-xmpp/namespaces'
|
2
|
+
|
3
|
+
module EM::Xmpp
|
4
|
+
module Component
|
5
|
+
def stream_start(node)
|
6
|
+
send_raw("<handshake>#{Digest::SHA1.hexdigest(node['id']+@pass)}</handshake>")
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
def open_xml_stream_tag
|
11
|
+
"<stream:stream
|
12
|
+
to='#{@jid}'
|
13
|
+
xmlns='#{Namespaces::Component}:accept'
|
14
|
+
xmlns:stream='#{Namespaces::Stream}'
|
15
|
+
>"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/em-xmpp/connection.rb
CHANGED
@@ -1,22 +1,39 @@
|
|
1
1
|
|
2
|
+
require 'eventmachine'
|
3
|
+
|
2
4
|
require 'em-xmpp/namespaces'
|
3
|
-
require 'em-xmpp/
|
4
|
-
require 'em-xmpp/handler'
|
5
|
+
require 'em-xmpp/evented'
|
5
6
|
require 'em-xmpp/jid'
|
6
|
-
require 'em-xmpp/
|
7
|
-
require 'em-xmpp/
|
8
|
-
|
9
|
-
require 'fiber'
|
7
|
+
require 'em-xmpp/component'
|
8
|
+
require 'em-xmpp/resolver'
|
9
|
+
|
10
10
|
|
11
11
|
module EM::Xmpp
|
12
12
|
class Connection < EM::Connection
|
13
13
|
include Namespaces
|
14
|
-
include
|
14
|
+
include Evented
|
15
15
|
|
16
16
|
attr_reader :jid, :pass, :user_data
|
17
17
|
|
18
|
+
def self.start(jid, pass=nil, mod=nil, cfg={}, server=nil, port=5222, &blk)
|
19
|
+
jid = JID.parse jid
|
20
|
+
if server.nil?
|
21
|
+
record = Resolver.resolve jid.domain
|
22
|
+
if record
|
23
|
+
server = record.target.to_s
|
24
|
+
port = record.port
|
25
|
+
else
|
26
|
+
server = jid.domain
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
EM.connect(server, port, self, jid, pass, mod, cfg, &blk)
|
31
|
+
end
|
32
|
+
|
18
33
|
def initialize(jid, pass, mod=nil, cfg={})
|
19
34
|
@jid = jid
|
35
|
+
@component = jid.node.nil?
|
36
|
+
self.extend Component if component?
|
20
37
|
@pass = pass.dup.freeze
|
21
38
|
self.extend mod if mod
|
22
39
|
certdir = cfg[:certificates]
|
@@ -30,112 +47,27 @@ module EM::Xmpp
|
|
30
47
|
|
31
48
|
def post_init
|
32
49
|
super
|
33
|
-
|
50
|
+
prepare_parser!
|
51
|
+
set_negotiation_handler!
|
34
52
|
end
|
35
53
|
|
36
|
-
def
|
54
|
+
def send_raw(data)
|
55
|
+
puts ">> out\n#{data}\n" if $DEBUG
|
56
|
+
send_data data
|
37
57
|
end
|
38
58
|
|
39
|
-
def
|
40
|
-
|
59
|
+
def receive_data(dat)
|
60
|
+
puts "<< in\n#{dat}\n" if $DEBUG
|
61
|
+
receive_raw(dat)
|
41
62
|
end
|
42
63
|
|
43
|
-
def
|
44
|
-
|
64
|
+
def unbind
|
65
|
+
puts "**** unbound ****" if $DEBUG
|
45
66
|
end
|
46
67
|
|
47
|
-
def
|
48
|
-
@jid = entity jid
|
49
|
-
end
|
50
|
-
|
51
|
-
def entity(jid)
|
52
|
-
Entity.new(self, jid)
|
53
|
-
end
|
54
|
-
|
55
|
-
def negotiation_finished
|
56
|
-
@pass = nil
|
57
|
-
@handler = Routine.new self
|
58
|
-
send_stanza presence_stanza()
|
59
|
-
framework_ready if respond_to? :framework_ready
|
60
|
-
ready
|
61
|
-
end
|
62
|
-
|
63
|
-
def negotiation_failed(node)
|
64
|
-
raise RuntimeError, "could not negotiate a stream:\n#{node}"
|
65
|
-
end
|
66
|
-
|
67
|
-
OutgoingStanza = Struct.new(:xml, :params)
|
68
|
-
|
69
|
-
def default_presence_params
|
70
|
-
{}
|
71
|
-
end
|
72
|
-
|
73
|
-
def default_message_params
|
74
|
-
{'to' => @jid.domain, 'id' => "em-xmpp.#{rand(65535)}"}
|
75
|
-
end
|
76
|
-
|
77
|
-
def default_iq_params
|
78
|
-
{'type' => 'get', 'id' => "em-xmpp.#{rand(65535)}"}
|
79
|
-
end
|
80
|
-
|
81
|
-
def presence_stanza(params={}, &blk)
|
82
|
-
params = default_presence_params.merge(params)
|
83
|
-
xml = build_xml do |x|
|
84
|
-
x.presence(params, &blk)
|
85
|
-
end
|
86
|
-
OutgoingStanza.new xml, params
|
87
|
-
end
|
88
|
-
|
89
|
-
def message_stanza(params={}, &blk)
|
90
|
-
params = default_message_params.merge(params)
|
91
|
-
xml = build_xml do |x|
|
92
|
-
x.message(params, &blk)
|
93
|
-
end
|
94
|
-
OutgoingStanza.new xml, params
|
95
|
-
end
|
96
|
-
|
97
|
-
def iq_stanza(params={}, &blk)
|
98
|
-
params = default_iq_params.merge(params)
|
99
|
-
xml = build_xml do |x|
|
100
|
-
x.iq(params, &blk)
|
101
|
-
end
|
102
|
-
OutgoingStanza.new xml, params
|
103
|
-
end
|
104
|
-
|
105
|
-
def send_stanza(stanza)
|
106
|
-
send_raw stanza.xml
|
107
|
-
if block_given?
|
108
|
-
upon(:anything) do |ctx|
|
109
|
-
if ctx.bit!(:stanza).id == stanza.params['id']
|
110
|
-
yield ctx
|
111
|
-
ctx.delete_xpath_handler!
|
112
|
-
else
|
113
|
-
ctx
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
%w{upon on on_exception on_presence on_iq on_message on_decorator on_iq_decorator on_presence_decorator on_message_decorator}.each do |meth|
|
120
|
-
define_method(meth) do |*args,&blk|
|
121
|
-
@handler.send meth, *args, &blk
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
def ready
|
126
|
-
end
|
127
|
-
|
128
|
-
def start_using_tls_and_reset_stream
|
68
|
+
def initiate_tls
|
129
69
|
bool = !! @certstore
|
130
70
|
start_tls(:verify_peer => bool)
|
131
|
-
restart_xml_stream
|
132
71
|
end
|
133
|
-
|
134
|
-
def ssl_verify_peer(pem)
|
135
|
-
@certstore.trusted?(pem).tap do |trusted|
|
136
|
-
close_connection unless trusted
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
72
|
end
|
141
73
|
end
|
data/lib/em-xmpp/context.rb
CHANGED
@@ -89,11 +89,7 @@ module EM::Xmpp
|
|
89
89
|
end
|
90
90
|
|
91
91
|
def bit(klassname)
|
92
|
-
bits[bit_klass_name(klassname)]
|
93
|
-
end
|
94
|
-
|
95
|
-
def bit!(klassname)
|
96
|
-
ret = bit klassname
|
92
|
+
ret = bits[bit_klass_name(klassname)]
|
97
93
|
unless ret
|
98
94
|
klass = if klassname.is_a?(Class)
|
99
95
|
klassname
|
@@ -105,6 +101,16 @@ module EM::Xmpp
|
|
105
101
|
ret
|
106
102
|
end
|
107
103
|
|
104
|
+
def bit!(klassname)
|
105
|
+
if $DEBUG
|
106
|
+
$stderr.puts "EM::Xmpp::Context#bit! is outdated, please use bit (without bang)"
|
107
|
+
line = caller.first
|
108
|
+
$stderr.puts " caller is here> #{line}"
|
109
|
+
end
|
110
|
+
bit klassname
|
111
|
+
end
|
112
|
+
|
113
|
+
|
108
114
|
def bit?(klassname)
|
109
115
|
bits.has_key? bit_klass_name(klassname)
|
110
116
|
end
|
@@ -177,9 +183,8 @@ module EM::Xmpp
|
|
177
183
|
jid = connection.jid.full
|
178
184
|
{'from' => jid, 'to' => from, 'id' => id}
|
179
185
|
end
|
180
|
-
def reply(args
|
181
|
-
|
182
|
-
connection.presence_stanza(args,&blk)
|
186
|
+
def reply(*args)
|
187
|
+
connection.presence_stanza(reply_default_params,*args)
|
183
188
|
end
|
184
189
|
def priority_node
|
185
190
|
xpath('//xmlns:priority',{'xmlns' => Client}).first
|
@@ -236,9 +241,8 @@ module EM::Xmpp
|
|
236
241
|
h
|
237
242
|
end
|
238
243
|
|
239
|
-
def reply(args
|
240
|
-
|
241
|
-
connection.message_stanza(args,&blk)
|
244
|
+
def reply(*args)
|
245
|
+
connection.message_stanza(reply_default_params,*args)
|
242
246
|
end
|
243
247
|
|
244
248
|
def groupchat?
|
@@ -261,9 +265,8 @@ module EM::Xmpp
|
|
261
265
|
{'from' => jid, 'to' => from, 'type' => 'result', 'id' => id}
|
262
266
|
end
|
263
267
|
|
264
|
-
def reply(args
|
265
|
-
|
266
|
-
connection.iq_stanza(args,&blk)
|
268
|
+
def reply(*args)
|
269
|
+
connection.iq_stanza(reply_default_params,*args)
|
267
270
|
end
|
268
271
|
end
|
269
272
|
|
@@ -748,15 +751,15 @@ module EM::Xmpp
|
|
748
751
|
Base64.strict_encode64 data
|
749
752
|
end
|
750
753
|
end
|
751
|
-
|
754
|
+
|
752
755
|
def reply(item,*args)
|
753
756
|
ref = "cid:#{item.cid}"
|
754
757
|
params = {}
|
755
758
|
params['max-age'] = item.max_age if item.max_age
|
756
|
-
super(
|
757
|
-
|
758
|
-
|
759
|
-
|
759
|
+
super(
|
760
|
+
x('data',{:xmlns => EM::Xmpp::Namespaces::BoB, :cid => ref, :type => item.mime}.merge(params), item.b64),
|
761
|
+
*args
|
762
|
+
)
|
760
763
|
end
|
761
764
|
|
762
765
|
def data_node
|
@@ -1096,6 +1099,18 @@ module EM::Xmpp
|
|
1096
1099
|
read_attr(n, 'role') if n
|
1097
1100
|
end
|
1098
1101
|
end
|
1102
|
+
|
1103
|
+
module Ping
|
1104
|
+
include Iq
|
1105
|
+
|
1106
|
+
def ping?
|
1107
|
+
stanza.child && stanza.child.name == 'ping'
|
1108
|
+
end
|
1109
|
+
|
1110
|
+
def pong
|
1111
|
+
reply
|
1112
|
+
end
|
1113
|
+
end
|
1099
1114
|
end
|
1100
1115
|
|
1101
1116
|
class Bit
|
@@ -1206,6 +1221,9 @@ module EM::Xmpp
|
|
1206
1221
|
class Mucuser < Bit
|
1207
1222
|
include Contexts::Mucuser
|
1208
1223
|
end
|
1224
|
+
class Ping < Bit
|
1225
|
+
include Contexts::Ping
|
1226
|
+
end
|
1209
1227
|
end
|
1210
1228
|
|
1211
1229
|
end
|