cancer 0.1.0.a1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|