cancer 0.1.0.a1
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/.autotest +3 -0
- data/.gitignore +5 -0
- data/LICENSE.txt +22 -0
- data/Rakefile +46 -0
- data/VERSION +1 -0
- data/cancer.gemspec +156 -0
- data/documentation/STREAM_INITIATION.markdown +18 -0
- data/examples/example.rb +80 -0
- data/examples/example_2.rb +20 -0
- data/examples/example_em.rb +11 -0
- data/examples/example_em_helper.rb +23 -0
- data/examples/example_im_roster.rb +26 -0
- data/examples/example_xep_0004.rb +124 -0
- data/examples/example_xep_0047.rb +35 -0
- data/examples/example_xep_0050.rb +78 -0
- data/examples/example_xep_0065.rb +66 -0
- data/examples/example_xep_0096.dup.rb +40 -0
- data/examples/example_xep_0096_xep_0047.rb +42 -0
- data/examples/example_xep_0096_xep_0065.rb +40 -0
- data/lib/cancer.rb +122 -0
- data/lib/cancer/adapter.rb +33 -0
- data/lib/cancer/adapters/em.rb +88 -0
- data/lib/cancer/adapters/socket.rb +122 -0
- data/lib/cancer/builder.rb +28 -0
- data/lib/cancer/controller.rb +32 -0
- data/lib/cancer/dependencies.rb +187 -0
- data/lib/cancer/events/abstract_event.rb +10 -0
- data/lib/cancer/events/base_matchers.rb +63 -0
- data/lib/cancer/events/binary_matchers.rb +30 -0
- data/lib/cancer/events/eventable.rb +92 -0
- data/lib/cancer/events/exception_events.rb +28 -0
- data/lib/cancer/events/handler.rb +33 -0
- data/lib/cancer/events/manager.rb +130 -0
- data/lib/cancer/events/named_events.rb +25 -0
- data/lib/cancer/events/proc_matcher.rb +16 -0
- data/lib/cancer/events/xml_events.rb +44 -0
- data/lib/cancer/exceptions.rb +53 -0
- data/lib/cancer/jid.rb +215 -0
- data/lib/cancer/lock.rb +32 -0
- data/lib/cancer/spec.rb +35 -0
- data/lib/cancer/spec/error.rb +18 -0
- data/lib/cancer/spec/extentions.rb +79 -0
- data/lib/cancer/spec/matcher.rb +30 -0
- data/lib/cancer/spec/mock_adapter.rb +139 -0
- data/lib/cancer/spec/mock_stream.rb +15 -0
- data/lib/cancer/spec/transcript.rb +107 -0
- data/lib/cancer/stream.rb +182 -0
- data/lib/cancer/stream/builder.rb +20 -0
- data/lib/cancer/stream/controller.rb +36 -0
- data/lib/cancer/stream/event_helper.rb +12 -0
- data/lib/cancer/stream/xep.rb +52 -0
- data/lib/cancer/stream_parser.rb +144 -0
- data/lib/cancer/support.rb +27 -0
- data/lib/cancer/support/hash.rb +32 -0
- data/lib/cancer/support/string.rb +22 -0
- data/lib/cancer/synchronized_stanza.rb +79 -0
- data/lib/cancer/thread_pool.rb +118 -0
- data/lib/cancer/xep.rb +43 -0
- data/lib/cancer/xeps/core.rb +109 -0
- data/lib/cancer/xeps/core/bind.rb +33 -0
- data/lib/cancer/xeps/core/sasl.rb +113 -0
- data/lib/cancer/xeps/core/session.rb +22 -0
- data/lib/cancer/xeps/core/stream.rb +18 -0
- data/lib/cancer/xeps/core/terminator.rb +21 -0
- data/lib/cancer/xeps/core/tls.rb +34 -0
- data/lib/cancer/xeps/im.rb +323 -0
- data/lib/cancer/xeps/xep_0004_x_data.rb +692 -0
- data/lib/cancer/xeps/xep_0020_feature_neg.rb +35 -0
- data/lib/cancer/xeps/xep_0030_disco.rb +167 -0
- data/lib/cancer/xeps/xep_0047_ibb.rb +322 -0
- data/lib/cancer/xeps/xep_0050_commands.rb +256 -0
- data/lib/cancer/xeps/xep_0065_bytestreams.rb +306 -0
- data/lib/cancer/xeps/xep_0066_oob.rb +69 -0
- data/lib/cancer/xeps/xep_0095_si.rb +211 -0
- data/lib/cancer/xeps/xep_0096_si_filetransfer.rb +173 -0
- data/lib/cancer/xeps/xep_0114_component.rb +73 -0
- data/lib/cancer/xeps/xep_0115_caps.rb +180 -0
- data/lib/cancer/xeps/xep_0138_compress.rb +134 -0
- data/lib/cancer/xeps/xep_0144_rosterx.rb +250 -0
- data/lib/cancer/xeps/xep_0184_receipts.rb +40 -0
- data/lib/cancer/xeps/xep_0199_ping.rb +41 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/stream/stanza_errors_spec.rb +47 -0
- data/spec/stream/stream_errors_spec.rb +38 -0
- data/spec/stream/stream_initialization_spec.rb +160 -0
- data/spec/xep_0050/local_spec.rb +165 -0
- data/spec/xep_0050/remote_spec.rb +44 -0
- metadata +200 -0
@@ -0,0 +1,35 @@
|
|
1
|
+
|
2
|
+
module Cancer
|
3
|
+
# Feature Negotiation
|
4
|
+
# http://xmpp.org/extensions/xep-0020.html
|
5
|
+
module XEP_0020
|
6
|
+
include Cancer::XEP
|
7
|
+
|
8
|
+
dependency 'core'
|
9
|
+
dependency 'xep-0004'
|
10
|
+
|
11
|
+
NS = 'http://jabber.org/protocol/feature-neg'
|
12
|
+
|
13
|
+
def self.enhance_stream(stream)
|
14
|
+
stream.extend_builder do
|
15
|
+
include Cancer::XEP_0020::BuilderHelper
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module BuilderHelper
|
20
|
+
|
21
|
+
# type can bet :get and :set
|
22
|
+
def negotiate_features(type=:get, form=nil, &proc)
|
23
|
+
self.feature(:xmlns => Cancer::XEP_0020::NS) do
|
24
|
+
if form
|
25
|
+
self.x(form, :type => (type == :get ? :form : :submit), :verbose => (type == :get))
|
26
|
+
else
|
27
|
+
self.x(:type => (type == :get ? :form : :submit), :verbose => (type == :get), &proc)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
|
2
|
+
module Cancer
|
3
|
+
# Service Discovery
|
4
|
+
# http://xmpp.org/extensions/xep-0030.html
|
5
|
+
module XEP_0030
|
6
|
+
include Cancer::XEP
|
7
|
+
|
8
|
+
ITEMS_NS = "http://jabber.org/protocol/disco#items"
|
9
|
+
INFO_NS = "http://jabber.org/protocol/disco#info"
|
10
|
+
|
11
|
+
dependency 'core'
|
12
|
+
|
13
|
+
def self.enhance_stream(stream)
|
14
|
+
stream.extend_stream do
|
15
|
+
include Cancer::XEP_0030::StreamHelpers
|
16
|
+
end
|
17
|
+
stream.install_controller(Cancer::XEP_0030::Controller)
|
18
|
+
stream.disco.identity(:category => 'client', :type => 'pc', :name => 'Cancer')
|
19
|
+
stream.disco.feature INFO_NS
|
20
|
+
stream.disco.feature ITEMS_NS
|
21
|
+
end
|
22
|
+
|
23
|
+
class Item
|
24
|
+
|
25
|
+
attr_reader :jid, :node, :name
|
26
|
+
attr_reader :features, :identities, :items
|
27
|
+
|
28
|
+
def initialize(stream, options={})
|
29
|
+
@stream = stream
|
30
|
+
|
31
|
+
@jid = options[:jid].to_jid if options[:jid]
|
32
|
+
@node = options[:node]
|
33
|
+
@name = options[:name]
|
34
|
+
|
35
|
+
@items = {}
|
36
|
+
@features = []
|
37
|
+
@identities = []
|
38
|
+
end
|
39
|
+
|
40
|
+
def items
|
41
|
+
@items.values
|
42
|
+
end
|
43
|
+
|
44
|
+
def [](node)
|
45
|
+
@items[node.to_s]
|
46
|
+
end
|
47
|
+
|
48
|
+
def identity(options={})
|
49
|
+
self.identities.push({
|
50
|
+
:name => (options[:name] ? options[:name].to_s : nil),
|
51
|
+
:type => (options[:type] ? options[:type].to_s : nil),
|
52
|
+
:category => (options[:category] ? options[:category].to_s : nil)
|
53
|
+
})
|
54
|
+
end
|
55
|
+
|
56
|
+
def feature(var)
|
57
|
+
self.features.push(var.to_s)
|
58
|
+
end
|
59
|
+
|
60
|
+
def item(options={})
|
61
|
+
item = self[options[:node].to_s] || Item.new(@stream, options)
|
62
|
+
yield(item) if block_given?
|
63
|
+
@stream.disco_items[options[:node].to_s] = item
|
64
|
+
@items[options[:node].to_s] = item
|
65
|
+
item
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
class Controller < Cancer::Controller
|
71
|
+
|
72
|
+
on { |e| e.xpath('/c:iq[@type="get"]/d:query', 'c' => CLIENT_NS, 'd' => INFO_NS) }
|
73
|
+
def respond_with_info(e)
|
74
|
+
query_node = e.xml.first('/c:iq/d:query', 'c' => CLIENT_NS, 'd' => INFO_NS)
|
75
|
+
node = (query_node[:node] ? query_node[:node].to_s : nil)
|
76
|
+
item = (node ? disco_items[node] : disco)
|
77
|
+
|
78
|
+
return unless item
|
79
|
+
|
80
|
+
send_iq(e.sender, :result, e.id, e.receiver) do |x|
|
81
|
+
x.query((node ? {:node => node} : {}).merge(:xmlns => INFO_NS)) do
|
82
|
+
item.identities.each do |identity|
|
83
|
+
x.identity(identity)
|
84
|
+
end
|
85
|
+
item.features.each do |var|
|
86
|
+
x.feature(:var => var)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
on { |e| e.xpath("/c:iq[@type='get']/d:query", 'c' => CLIENT_NS, 'd' => ITEMS_NS) }
|
94
|
+
def respond_with_items(e)
|
95
|
+
query_node = e.xml.first('/c:iq/d:query', 'c' => CLIENT_NS, 'd' => ITEMS_NS)
|
96
|
+
node = (query_node[:node] ? query_node[:node].to_s : nil)
|
97
|
+
item = (node ? disco_items[node] : disco)
|
98
|
+
|
99
|
+
return unless item
|
100
|
+
|
101
|
+
send_iq(e.sender, :result, e.id, e.receiver) do |x|
|
102
|
+
x.query((node ? {:node => node} : {}).merge(:xmlns => ITEMS_NS)) do
|
103
|
+
item.items.each do |i|
|
104
|
+
attributes = {}
|
105
|
+
attributes[:node] = i.node if i.node
|
106
|
+
attributes[:name] = i.name if i.name
|
107
|
+
attributes[:jid] = i.jid if i.jid
|
108
|
+
x.item(attributes)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
module StreamHelpers
|
118
|
+
|
119
|
+
def disco
|
120
|
+
@disco_root ||= Cancer::XEP_0030::Item.new(self)
|
121
|
+
end
|
122
|
+
|
123
|
+
def disco_items
|
124
|
+
@disco_items ||= {}
|
125
|
+
end
|
126
|
+
|
127
|
+
def disco_items_for(jid, node=nil)
|
128
|
+
result = send_iq(jid) do |x|
|
129
|
+
attibutes = { :xmlns => Cancer::XEP_0030::ITEMS_NS }
|
130
|
+
attibutes[:node] = node if node
|
131
|
+
x.query attibutes
|
132
|
+
end
|
133
|
+
|
134
|
+
return nil unless result[:type] == 'result'
|
135
|
+
|
136
|
+
result = result.all('n:query/n:item', 'n' => Cancer::XEP_0030::ITEMS_NS)
|
137
|
+
result.collect do |item|
|
138
|
+
item.attributes
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def disco_info_for(jid, node=nil)
|
143
|
+
result = send_iq(jid) do |x|
|
144
|
+
attibutes = { :xmlns => Cancer::XEP_0030::INFO_NS }
|
145
|
+
attibutes[:node] = node if node
|
146
|
+
x.query attibutes
|
147
|
+
end
|
148
|
+
|
149
|
+
return nil unless result[:type] == 'result'
|
150
|
+
|
151
|
+
return_value = Item.new(:jid => jid, :node => node)
|
152
|
+
|
153
|
+
result.all('n:query/n:identity', 'n' => Cancer::XEP_0030::INFO_NS) do |e|
|
154
|
+
return_value.identity e
|
155
|
+
end
|
156
|
+
|
157
|
+
result.all('n:query/n:feature', 'n' => Cancer::XEP_0030::INFO_NS) do |e|
|
158
|
+
return_value.feature e[:var]
|
159
|
+
end
|
160
|
+
|
161
|
+
return_value
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
end
|
@@ -0,0 +1,322 @@
|
|
1
|
+
|
2
|
+
module Cancer
|
3
|
+
# In-Band Bytestreams
|
4
|
+
# http://xmpp.org/extensions/xep-0047.html
|
5
|
+
module XEP_0047
|
6
|
+
include Cancer::XEP
|
7
|
+
|
8
|
+
dependency 'core'
|
9
|
+
dependency 'xep-0095', :weak => true
|
10
|
+
|
11
|
+
NS = 'http://jabber.org/protocol/ibb'
|
12
|
+
|
13
|
+
def self.enhance_stream(stream)
|
14
|
+
stream.extend_stream do
|
15
|
+
include Cancer::XEP_0047::StreamHelpers
|
16
|
+
end
|
17
|
+
stream.install_controller Cancer::XEP_0047::Controller
|
18
|
+
stream.install_event_helper Cancer::XEP_0047::EventDSL
|
19
|
+
if stream.respond_to?(:register_stream_method)
|
20
|
+
stream.register_stream_method(Cancer::XEP_0047::StreamMethod, Cancer::XEP_0047::NS)
|
21
|
+
stream.install_controller Cancer::XEP_0047::IBBController
|
22
|
+
end
|
23
|
+
stream.disco.feature NS
|
24
|
+
end
|
25
|
+
|
26
|
+
class Controller < Cancer::Controller
|
27
|
+
|
28
|
+
NAMESPACES = { 'c' => CLIENT_NS, 'ibb' => NS }
|
29
|
+
|
30
|
+
on { |e| e.xpath('/c:iq/ibb:open', NAMESPACES) }
|
31
|
+
def open_bytestream(e)
|
32
|
+
open_element = e.xml.first('/c:iq/ibb:open', NAMESPACES)
|
33
|
+
bytestream = Bytestream.new(
|
34
|
+
self,
|
35
|
+
e.sender,
|
36
|
+
open_element['block-size'].to_i,
|
37
|
+
open_element['sid'],
|
38
|
+
open_element['stanza'] || 'iq')
|
39
|
+
fire! Event, self, bytestream, e.id
|
40
|
+
end
|
41
|
+
|
42
|
+
on { |e| e.xpath('/c:iq[@type="set"]/ibb:data', NAMESPACES) }
|
43
|
+
def receive_data(e)
|
44
|
+
data_element = e.xml.first('ibb:data', NAMESPACES)
|
45
|
+
bytestream = nil
|
46
|
+
|
47
|
+
if data_element[:sid]
|
48
|
+
bytestream = active_bytestreams[data_element[:sid]]
|
49
|
+
else
|
50
|
+
respond_with_error(:missing_session, e.sender, e.id)
|
51
|
+
end
|
52
|
+
|
53
|
+
if bytestream
|
54
|
+
bytestream.received_packet(
|
55
|
+
data_element[:seq].to_i,
|
56
|
+
Base64.decode64(data_element.text))
|
57
|
+
acknowledge_data(e.xml)
|
58
|
+
else
|
59
|
+
respond_with_error(:missing_session, e.sender, e.id)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
on { |e| e.xpath('/c:iq[@type="set"]/ibb:close', NAMESPACES) }
|
64
|
+
def close_bytestream(e)
|
65
|
+
close_element = e.xml.first('ibb:close', NAMESPACES)
|
66
|
+
bytestream = nil
|
67
|
+
|
68
|
+
if close_element[:sid]
|
69
|
+
bytestream = active_bytestreams[close_element[:sid]]
|
70
|
+
else
|
71
|
+
respond_with_error(:missing_session, e.sender, e.id)
|
72
|
+
end
|
73
|
+
|
74
|
+
if bytestream
|
75
|
+
bytestream.internal.close unless bytestream.internal.closed?
|
76
|
+
acknowledge_data(e.xml)
|
77
|
+
else
|
78
|
+
respond_with_error(:missing_session, e.sender, e.id)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def active_bytestreams
|
83
|
+
@active_bytestreams ||= {}
|
84
|
+
end
|
85
|
+
|
86
|
+
def accept_bytestream(event)
|
87
|
+
active_bytestreams[event.bytestream.stream_id] = event.bytestream
|
88
|
+
send_iq(event.bytestream.peer, :result, event.iq_id)
|
89
|
+
end
|
90
|
+
|
91
|
+
def reject_bytestream(event)
|
92
|
+
send_iq(event.bytestream.peer, :error, event.iq_id) do |x|
|
93
|
+
x.error(:type => 'cancel') do
|
94
|
+
x.send('not-acceptable', :xmlns => 'urn:ietf:params:xml:ns:xmpp-stanzas')
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def acknowledge_data(iq)
|
100
|
+
send_iq(iq[:from], :result, iq[:id])
|
101
|
+
end
|
102
|
+
|
103
|
+
def respond_with_error(error_type, to, id)
|
104
|
+
case error_type
|
105
|
+
when :missing_session
|
106
|
+
send_iq(to, :error, id) do |x|
|
107
|
+
x.error(:type => 'cancel') do
|
108
|
+
x.send('item-not-found', :xmlns => 'urn:ietf:params:xml:ns:xmpp-stanzas')
|
109
|
+
end
|
110
|
+
end
|
111
|
+
throw :halt
|
112
|
+
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
module StreamHelpers
|
119
|
+
|
120
|
+
def open_ibb(to, options={}, &proc)
|
121
|
+
controller = self.controllers_by_name['Cancer::XEP_0047::Controller']
|
122
|
+
|
123
|
+
bytestream = Bytestream.new(
|
124
|
+
controller,
|
125
|
+
to, options[:block_size], options[:stream_id])
|
126
|
+
|
127
|
+
controller.active_bytestreams[bytestream.stream_id] = bytestream
|
128
|
+
result = send_iq(to, :set) do |x|
|
129
|
+
x.open(
|
130
|
+
:xmlns => Cancer::XEP_0047::NS,
|
131
|
+
:'block-size' => bytestream.block_size,
|
132
|
+
:sid => bytestream.stream_id,
|
133
|
+
:stanza => bytestream.stanza
|
134
|
+
)
|
135
|
+
end
|
136
|
+
|
137
|
+
if result[:type] == 'result'
|
138
|
+
yield(bytestream)
|
139
|
+
bytestream.close
|
140
|
+
else
|
141
|
+
nil
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
|
147
|
+
module Bytestream
|
148
|
+
|
149
|
+
def self.new(controller, peer, block_size=nil, stream_id=nil, stanza=nil)
|
150
|
+
internal, external = * Socket.pair(Socket::AF_LOCAL, Socket::SOCK_STREAM, 0)
|
151
|
+
|
152
|
+
external.extend self
|
153
|
+
external.setup(controller, internal, peer, block_size, stream_id.to_s, stanza)
|
154
|
+
|
155
|
+
internal.extend Internal
|
156
|
+
internal.setup(controller, external)
|
157
|
+
internal.read_packets!
|
158
|
+
|
159
|
+
def external.close
|
160
|
+
sleep 0.1
|
161
|
+
@controller.send_iq(@peer, :set) do |x|
|
162
|
+
x.close(:xmlns => NS, :sid => @stream_id)
|
163
|
+
end
|
164
|
+
self.remove_from_controller
|
165
|
+
super
|
166
|
+
end
|
167
|
+
|
168
|
+
external
|
169
|
+
end
|
170
|
+
|
171
|
+
module Internal
|
172
|
+
|
173
|
+
attr_reader :packets, :controller, :external
|
174
|
+
attr_accessor :read_sec, :write_sec
|
175
|
+
|
176
|
+
def peer
|
177
|
+
@external.peer
|
178
|
+
end
|
179
|
+
|
180
|
+
def block_size
|
181
|
+
@external.block_size
|
182
|
+
end
|
183
|
+
|
184
|
+
def stream_id
|
185
|
+
@external.stream_id
|
186
|
+
end
|
187
|
+
|
188
|
+
def stanza
|
189
|
+
@external.stanza
|
190
|
+
end
|
191
|
+
|
192
|
+
def setup(controller, external)
|
193
|
+
@controller, @external = controller, external
|
194
|
+
@read_sec = @write_sec = 0
|
195
|
+
@packets = {}
|
196
|
+
end
|
197
|
+
|
198
|
+
def received_packet(sec, packet)
|
199
|
+
self.packets[sec.to_i] = packet
|
200
|
+
while bufferd_packet = self.packets.delete(self.read_sec)
|
201
|
+
begin
|
202
|
+
self.write(bufferd_packet)
|
203
|
+
self.flush
|
204
|
+
self.read_sec += 1
|
205
|
+
rescue IOError
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def read_packets!
|
211
|
+
@controller.deferred(self) do |ibb|
|
212
|
+
loop do
|
213
|
+
|
214
|
+
begin
|
215
|
+
packet = ibb.recv_nonblock(4096)
|
216
|
+
if packet and !packet.empty?
|
217
|
+
ibb.send_packet(ibb.write_sec, packet)
|
218
|
+
ibb.write_sec += 1
|
219
|
+
end
|
220
|
+
rescue Errno::EAGAIN, OpenSSL::SSL::ReadAgain
|
221
|
+
IO.select([ibb], nil, nil, 0.5) rescue nil
|
222
|
+
retry
|
223
|
+
rescue IOError
|
224
|
+
break
|
225
|
+
rescue OpenSSL::SSL::SSLError
|
226
|
+
break
|
227
|
+
end
|
228
|
+
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
def send_packet(sec, packet)
|
234
|
+
@controller.send_iq(self.peer, :set) do |x|
|
235
|
+
x.data(:xmlns => NS, :seq => sec, :sid => self.stream_id) do
|
236
|
+
x.text Base64.encode64(packet)
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
end
|
242
|
+
|
243
|
+
attr_reader :controller, :internal, :peer, :block_size, :stream_id, :stanza
|
244
|
+
|
245
|
+
def setup(controller, internal, peer, block_size=nil, stream_id=nil, stanza=nil)
|
246
|
+
@controller, @internal = controller, internal
|
247
|
+
@peer, @block_size, @stream_id, @stanza =
|
248
|
+
peer, block_size, stream_id, stanza
|
249
|
+
|
250
|
+
@stanza ||= 'iq'
|
251
|
+
@stream_id ||= rand(1<<100).to_s
|
252
|
+
@block_size ||= 4096
|
253
|
+
end
|
254
|
+
|
255
|
+
def received_packet(sec, packet)
|
256
|
+
self.internal.received_packet(sec, packet)
|
257
|
+
end
|
258
|
+
|
259
|
+
def remove_from_controller
|
260
|
+
self.controller.active_bytestreams.delete(self.stream_id)
|
261
|
+
end
|
262
|
+
|
263
|
+
end
|
264
|
+
|
265
|
+
class Event < Cancer::Events::AbstractEvent
|
266
|
+
attr_reader :bytestream, :iq_id
|
267
|
+
def initialize(controller, bytestream, iq_id)
|
268
|
+
@controller, @bytestream, @iq_id = controller, bytestream, iq_id
|
269
|
+
end
|
270
|
+
|
271
|
+
def accept!(&proc)
|
272
|
+
@controller.accept_bytestream(self)
|
273
|
+
if block_given?
|
274
|
+
@controller.enqueue(@bytestream, proc) do |bs, proc|
|
275
|
+
proc.call(bs)
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
def reject!
|
281
|
+
@controller.reject_bytestream(self)
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
class EventMatcher < Cancer::Events::Matcher
|
286
|
+
|
287
|
+
def initialize
|
288
|
+
end
|
289
|
+
|
290
|
+
def match?(event)
|
291
|
+
Event === event
|
292
|
+
end
|
293
|
+
|
294
|
+
end
|
295
|
+
|
296
|
+
module EventDSL
|
297
|
+
|
298
|
+
def ibb
|
299
|
+
Cancer::XEP_0047::EventMatcher.new
|
300
|
+
end
|
301
|
+
|
302
|
+
end
|
303
|
+
|
304
|
+
class StreamMethod < Cancer::XEP_0095::StreamMethod
|
305
|
+
def handle(to, id, &proc)
|
306
|
+
@stream.open_ibb(to, :stream_id => id, &proc)
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
class IBBController < Cancer::Controller
|
311
|
+
on { |e| e.ibb }
|
312
|
+
def catch_ibb(e)
|
313
|
+
controller = self.controllers_by_name['Cancer::XEP_0095::Controller']
|
314
|
+
si_event = controller.pending_streams[e.bytestream.stream_id.to_s]
|
315
|
+
if si_event
|
316
|
+
si_event.caught_stream!(e)
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
end
|
322
|
+
end
|