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,63 @@
|
|
1
|
+
|
2
|
+
module Cancer
|
3
|
+
module Events
|
4
|
+
|
5
|
+
# The abstract base class for all event matchers.
|
6
|
+
class Matcher
|
7
|
+
|
8
|
+
# test if an event macthes the matcher.
|
9
|
+
# @param [Cancer::Events::AbstractEvent] event the event to test
|
10
|
+
# @return [true, false] returns true if the event matches self. otherwise it returns false.
|
11
|
+
def match?(event)
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
# matches any events which exclusivly match self or other.
|
16
|
+
# @param [Cancer::Events::Matcher] other the other macther
|
17
|
+
# @return [Cancer::Events::XorMatcher] the new matcher
|
18
|
+
def ^(other)
|
19
|
+
Cancer::Events::XorMatcher.new(self, other)
|
20
|
+
end
|
21
|
+
|
22
|
+
# matches any events which match self or other.
|
23
|
+
# @param [Cancer::Events::Matcher] other the other macther
|
24
|
+
# @return [Cancer::Events::OrMatcher] the new matcher
|
25
|
+
def |(other)
|
26
|
+
Cancer::Events::OrMatcher.new(self, other)
|
27
|
+
end
|
28
|
+
|
29
|
+
# matches any events which match self and other.
|
30
|
+
# @param [Cancer::Events::Matcher] other the other macther
|
31
|
+
# @return [Cancer::Events::AndMatcher] the new matcher
|
32
|
+
def &(other)
|
33
|
+
Cancer::Events::AndMatcher.new(self, other)
|
34
|
+
end
|
35
|
+
|
36
|
+
# matches any events which match not self
|
37
|
+
# @return [Cancer::Events::NotMatcher] the new matcher
|
38
|
+
def invert!
|
39
|
+
Cancer::Events::NotMatcher.new(self)
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
class UnaryMatcher < Cancer::Events::Matcher
|
45
|
+
def initialize(a)
|
46
|
+
@a = a
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class BinaryMatcher < Cancer::Events::Matcher
|
51
|
+
def initialize(a, b)
|
52
|
+
@a, @b = a, b
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class AnyMatcher < Cancer::Events::Matcher
|
57
|
+
def match?(event)
|
58
|
+
true
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
|
2
|
+
module Cancer
|
3
|
+
module Events
|
4
|
+
|
5
|
+
class OrMatcher < Cancer::Events::BinaryMatcher
|
6
|
+
def match?(event)
|
7
|
+
@a.match?(event) or @b.match?(event)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class XorMatcher < Cancer::Events::BinaryMatcher
|
12
|
+
def match?(event)
|
13
|
+
@a.match?(event) ^ @b.match?(event)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class AndMatcher < Cancer::Events::BinaryMatcher
|
18
|
+
def match?(event)
|
19
|
+
@a.match?(event) and @b.match?(event)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class NotMatcher < Cancer::Events::UnaryMatcher
|
24
|
+
def match?(event)
|
25
|
+
!@a.match?(event)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
|
2
|
+
module Cancer
|
3
|
+
module Events
|
4
|
+
module Eventable
|
5
|
+
|
6
|
+
def self.included(base)
|
7
|
+
base.extend Cancer::Events::Eventable::ClassMethods
|
8
|
+
end
|
9
|
+
|
10
|
+
def event_manager
|
11
|
+
@manager
|
12
|
+
end
|
13
|
+
|
14
|
+
def on(method, *args, &proc)
|
15
|
+
matcher, options = *args
|
16
|
+
if Hash === matcher and options.nil?
|
17
|
+
matcher, options = options, matcher
|
18
|
+
end
|
19
|
+
matcher = (matcher || proc)
|
20
|
+
handler = @manager.on(matcher, method(method.to_sym), options)
|
21
|
+
registered_handlers.push(handler)
|
22
|
+
end
|
23
|
+
|
24
|
+
def fire!(*args)
|
25
|
+
@manager.fire!(*args)
|
26
|
+
end
|
27
|
+
|
28
|
+
def register_with(manager)
|
29
|
+
raise "can only register with a single manager!" if @manager
|
30
|
+
@manager = manager
|
31
|
+
self.class.send(:evented_methods).each do |(m, condition, options)|
|
32
|
+
m = m.bind(self)
|
33
|
+
handler = @manager.on(condition, m, options)
|
34
|
+
registered_handlers.push(handler)
|
35
|
+
end
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
def unregister!
|
40
|
+
registered_handlers.each do |handler|
|
41
|
+
@manager.unregister_handler(handler)
|
42
|
+
end
|
43
|
+
@manager = nil
|
44
|
+
end
|
45
|
+
|
46
|
+
def registered_handlers
|
47
|
+
@registered_handlers ||= []
|
48
|
+
end
|
49
|
+
|
50
|
+
module ClassMethods
|
51
|
+
def register_new_instance_with(manager, *args, &proc)
|
52
|
+
register_instance_with new(*args, &proc)
|
53
|
+
end
|
54
|
+
|
55
|
+
def register_instance_with(manager, instance)
|
56
|
+
instance.register_with manager
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def evented_methods
|
62
|
+
@evented_methods ||= (super rescue [])
|
63
|
+
end
|
64
|
+
|
65
|
+
def method_added(m)
|
66
|
+
if @event_options
|
67
|
+
private m
|
68
|
+
@event_options[:priority] ||= @default_handler_priority if @default_handler_priority
|
69
|
+
evented_methods.push([instance_method(m), @event_condition, @event_options])
|
70
|
+
@event_condition = nil
|
71
|
+
@event_options = nil
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def priority(priority)
|
76
|
+
@default_handler_priority = priority.to_i
|
77
|
+
end
|
78
|
+
|
79
|
+
def on(*args, &proc)
|
80
|
+
matcher, options = *args
|
81
|
+
if Hash === matcher and options.nil?
|
82
|
+
matcher, options = options, matcher
|
83
|
+
end
|
84
|
+
matcher = (matcher || proc)
|
85
|
+
@event_condition = matcher
|
86
|
+
@event_options = options || {}
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
|
2
|
+
module Cancer
|
3
|
+
module Events
|
4
|
+
|
5
|
+
class ExceptionMatcher < Cancer::Events::Matcher
|
6
|
+
|
7
|
+
def initialize(klass, message=nil)
|
8
|
+
@klass = klass
|
9
|
+
@message = message
|
10
|
+
end
|
11
|
+
|
12
|
+
def match?(event)
|
13
|
+
((ExceptionEvent === event) and
|
14
|
+
(@klass === event.exception) and
|
15
|
+
(@message ? (@message === event.exception.message) : true))
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
class ExceptionEvent < Cancer::Events::AbstractEvent
|
21
|
+
attr_reader :exception
|
22
|
+
def initialize(exception)
|
23
|
+
@exception = exception
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
|
2
|
+
module Cancer
|
3
|
+
module Events
|
4
|
+
class Handler
|
5
|
+
|
6
|
+
attr_reader :proc, :options
|
7
|
+
|
8
|
+
def initialize(proc, options={})
|
9
|
+
@options = { :mode => :inline, :priority => 200 }.merge(options || {})
|
10
|
+
@proc = proc
|
11
|
+
@mutex = Mutex.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def run(manager, event)
|
15
|
+
case @proc.arity
|
16
|
+
when 0 then @proc.call()
|
17
|
+
when 1 then @proc.call(event)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def <=>(other)
|
22
|
+
raise TypeError, 'no an EventHandler' unless Cancer::Events::Handler === other
|
23
|
+
cmp = @options[:priority] <=> other.options[:priority]
|
24
|
+
(cmp == 0 ? (@options[:sequence] <=> other.options[:sequence]) : cmp)
|
25
|
+
end
|
26
|
+
|
27
|
+
def single_use?
|
28
|
+
!!@options[:single_use]
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
|
2
|
+
module Cancer
|
3
|
+
module Events
|
4
|
+
class Manager
|
5
|
+
|
6
|
+
# Build a new event manager
|
7
|
+
# @option options [Fixnum] :size the size of the thread pool
|
8
|
+
def initialize(options={})
|
9
|
+
@matchers = []
|
10
|
+
@queue = Cancer::ThreadPool.new(options[:size] || 10) do |event|
|
11
|
+
handle_event(event)
|
12
|
+
end
|
13
|
+
@queue.on_exception do |e|
|
14
|
+
fire!(Cancer::Events::ExceptionEvent, e)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def use(app, *args, &proc)
|
19
|
+
raise TypeError unless app.included_modules.include?(Cancer::Events::Eventable)
|
20
|
+
app.register_new_instance_with(self, *args, &proc)
|
21
|
+
end
|
22
|
+
|
23
|
+
def on(matcher, proc=nil, options={}, &block)
|
24
|
+
options ||= {}
|
25
|
+
|
26
|
+
options = options.merge(:sequence => @matchers.size)
|
27
|
+
handler = Cancer::Events::Handler.new(proc || block, options)
|
28
|
+
@matchers.push([matcher, handler])
|
29
|
+
@matchers.sort! { |(ma, ha), (mb, hb)| ha <=> hb }
|
30
|
+
handler
|
31
|
+
end
|
32
|
+
|
33
|
+
def resolve_martchers!
|
34
|
+
@matchers.each do |pair|
|
35
|
+
pair[0] = case pair[0]
|
36
|
+
when Cancer::Events::Matcher then pair[0]
|
37
|
+
when Proc then pair[0].call(DSL.new)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def unregister_handler(handler)
|
43
|
+
@matchers.delete_if do |m,h|
|
44
|
+
h == handler
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def fire!(event_or_class, *args)
|
49
|
+
event = (Class === event_or_class ? event_or_class.new(*args) : event_or_class)
|
50
|
+
@queue.push(event)
|
51
|
+
end
|
52
|
+
|
53
|
+
def deferred(*args, &proc)
|
54
|
+
@queue.defer(*args, &proc)
|
55
|
+
end
|
56
|
+
|
57
|
+
def start!
|
58
|
+
@queue.start!
|
59
|
+
end
|
60
|
+
|
61
|
+
def stop!
|
62
|
+
@queue.stop!
|
63
|
+
end
|
64
|
+
|
65
|
+
def handle_event(event)
|
66
|
+
Thread.current[:event] = event
|
67
|
+
@matchers.dup.each do |pair|
|
68
|
+
matcher, handler = *pair
|
69
|
+
next if matcher.nil?
|
70
|
+
Thread.current[:event_matcher] = matcher
|
71
|
+
Thread.current[:event_handler] = handler
|
72
|
+
if matcher.match?(event)
|
73
|
+
should_break = !no_break? do
|
74
|
+
handler.run(self, event)
|
75
|
+
end
|
76
|
+
|
77
|
+
if Thread.current[:remove_current_handler] or handler.single_use?
|
78
|
+
@matchers.delete(pair)
|
79
|
+
Thread.current[:remove_current_handler] = false
|
80
|
+
end
|
81
|
+
|
82
|
+
if should_break
|
83
|
+
break
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def no_break?
|
90
|
+
!!catch(:halt) do
|
91
|
+
catch(:skip) do
|
92
|
+
yield
|
93
|
+
end
|
94
|
+
true
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.remove_current_handler!
|
99
|
+
Thread.current[:remove_current_handler] = true
|
100
|
+
end
|
101
|
+
|
102
|
+
class DSL
|
103
|
+
def xpath(xpath, ns=nil)
|
104
|
+
Cancer::Events::XPathMatcher.new(xpath, ns)
|
105
|
+
end
|
106
|
+
|
107
|
+
def name(name)
|
108
|
+
Cancer::Events::NamedMatcher.new(name)
|
109
|
+
end
|
110
|
+
|
111
|
+
def exception(klass, message=nil)
|
112
|
+
Cancer::Events::ExceptionMatcher.new(klass, message)
|
113
|
+
end
|
114
|
+
|
115
|
+
def not(matcher)
|
116
|
+
matcher.invert!
|
117
|
+
end
|
118
|
+
|
119
|
+
def any
|
120
|
+
Cancer::Events::AnyMatcher.new()
|
121
|
+
end
|
122
|
+
|
123
|
+
def proc(proc=nil, &block)
|
124
|
+
Cancer::Events::ProcMatcher.new(proc || block)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
|
2
|
+
module Cancer
|
3
|
+
module Events
|
4
|
+
|
5
|
+
class NamedMatcher < Cancer::Events::Matcher
|
6
|
+
|
7
|
+
def initialize(name)
|
8
|
+
@name = name.to_sym
|
9
|
+
end
|
10
|
+
|
11
|
+
def match?(event)
|
12
|
+
NamedEvent === event and @name === event.name
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
class NamedEvent < Cancer::Events::AbstractEvent
|
18
|
+
attr_reader :name
|
19
|
+
def initialize(name)
|
20
|
+
@name = name.to_sym
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
|
2
|
+
module Cancer
|
3
|
+
module Events
|
4
|
+
class XPathMatcher < Cancer::Events::Matcher
|
5
|
+
|
6
|
+
def initialize(xpath, ns=nil)
|
7
|
+
@xpath, @ns = xpath, ns
|
8
|
+
end
|
9
|
+
|
10
|
+
def match?(event)
|
11
|
+
Cancer::Events::XMLEvent === event and !event.xml.xpath(@xpath, @ns).empty?
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
class XMLEvent < Cancer::Events::AbstractEvent
|
17
|
+
attr_reader :xml
|
18
|
+
def initialize(xml)
|
19
|
+
@xml = xml
|
20
|
+
end
|
21
|
+
|
22
|
+
def sender
|
23
|
+
@xml[:from].to_jid if @xml[:from]
|
24
|
+
end
|
25
|
+
|
26
|
+
def receiver
|
27
|
+
@xml[:to].to_jid if @xml[:to]
|
28
|
+
end
|
29
|
+
|
30
|
+
def id
|
31
|
+
@xml[:id].to_s if @xml[:id]
|
32
|
+
end
|
33
|
+
|
34
|
+
def type
|
35
|
+
@xml[:type].to_s if @xml[:type]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class StanzaEvent < Cancer::Events::XMLEvent
|
40
|
+
alias_method :stanza, :xml
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|