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.
Files changed (89) hide show
  1. data/.autotest +3 -0
  2. data/.gitignore +5 -0
  3. data/LICENSE.txt +22 -0
  4. data/Rakefile +46 -0
  5. data/VERSION +1 -0
  6. data/cancer.gemspec +156 -0
  7. data/documentation/STREAM_INITIATION.markdown +18 -0
  8. data/examples/example.rb +80 -0
  9. data/examples/example_2.rb +20 -0
  10. data/examples/example_em.rb +11 -0
  11. data/examples/example_em_helper.rb +23 -0
  12. data/examples/example_im_roster.rb +26 -0
  13. data/examples/example_xep_0004.rb +124 -0
  14. data/examples/example_xep_0047.rb +35 -0
  15. data/examples/example_xep_0050.rb +78 -0
  16. data/examples/example_xep_0065.rb +66 -0
  17. data/examples/example_xep_0096.dup.rb +40 -0
  18. data/examples/example_xep_0096_xep_0047.rb +42 -0
  19. data/examples/example_xep_0096_xep_0065.rb +40 -0
  20. data/lib/cancer.rb +122 -0
  21. data/lib/cancer/adapter.rb +33 -0
  22. data/lib/cancer/adapters/em.rb +88 -0
  23. data/lib/cancer/adapters/socket.rb +122 -0
  24. data/lib/cancer/builder.rb +28 -0
  25. data/lib/cancer/controller.rb +32 -0
  26. data/lib/cancer/dependencies.rb +187 -0
  27. data/lib/cancer/events/abstract_event.rb +10 -0
  28. data/lib/cancer/events/base_matchers.rb +63 -0
  29. data/lib/cancer/events/binary_matchers.rb +30 -0
  30. data/lib/cancer/events/eventable.rb +92 -0
  31. data/lib/cancer/events/exception_events.rb +28 -0
  32. data/lib/cancer/events/handler.rb +33 -0
  33. data/lib/cancer/events/manager.rb +130 -0
  34. data/lib/cancer/events/named_events.rb +25 -0
  35. data/lib/cancer/events/proc_matcher.rb +16 -0
  36. data/lib/cancer/events/xml_events.rb +44 -0
  37. data/lib/cancer/exceptions.rb +53 -0
  38. data/lib/cancer/jid.rb +215 -0
  39. data/lib/cancer/lock.rb +32 -0
  40. data/lib/cancer/spec.rb +35 -0
  41. data/lib/cancer/spec/error.rb +18 -0
  42. data/lib/cancer/spec/extentions.rb +79 -0
  43. data/lib/cancer/spec/matcher.rb +30 -0
  44. data/lib/cancer/spec/mock_adapter.rb +139 -0
  45. data/lib/cancer/spec/mock_stream.rb +15 -0
  46. data/lib/cancer/spec/transcript.rb +107 -0
  47. data/lib/cancer/stream.rb +182 -0
  48. data/lib/cancer/stream/builder.rb +20 -0
  49. data/lib/cancer/stream/controller.rb +36 -0
  50. data/lib/cancer/stream/event_helper.rb +12 -0
  51. data/lib/cancer/stream/xep.rb +52 -0
  52. data/lib/cancer/stream_parser.rb +144 -0
  53. data/lib/cancer/support.rb +27 -0
  54. data/lib/cancer/support/hash.rb +32 -0
  55. data/lib/cancer/support/string.rb +22 -0
  56. data/lib/cancer/synchronized_stanza.rb +79 -0
  57. data/lib/cancer/thread_pool.rb +118 -0
  58. data/lib/cancer/xep.rb +43 -0
  59. data/lib/cancer/xeps/core.rb +109 -0
  60. data/lib/cancer/xeps/core/bind.rb +33 -0
  61. data/lib/cancer/xeps/core/sasl.rb +113 -0
  62. data/lib/cancer/xeps/core/session.rb +22 -0
  63. data/lib/cancer/xeps/core/stream.rb +18 -0
  64. data/lib/cancer/xeps/core/terminator.rb +21 -0
  65. data/lib/cancer/xeps/core/tls.rb +34 -0
  66. data/lib/cancer/xeps/im.rb +323 -0
  67. data/lib/cancer/xeps/xep_0004_x_data.rb +692 -0
  68. data/lib/cancer/xeps/xep_0020_feature_neg.rb +35 -0
  69. data/lib/cancer/xeps/xep_0030_disco.rb +167 -0
  70. data/lib/cancer/xeps/xep_0047_ibb.rb +322 -0
  71. data/lib/cancer/xeps/xep_0050_commands.rb +256 -0
  72. data/lib/cancer/xeps/xep_0065_bytestreams.rb +306 -0
  73. data/lib/cancer/xeps/xep_0066_oob.rb +69 -0
  74. data/lib/cancer/xeps/xep_0095_si.rb +211 -0
  75. data/lib/cancer/xeps/xep_0096_si_filetransfer.rb +173 -0
  76. data/lib/cancer/xeps/xep_0114_component.rb +73 -0
  77. data/lib/cancer/xeps/xep_0115_caps.rb +180 -0
  78. data/lib/cancer/xeps/xep_0138_compress.rb +134 -0
  79. data/lib/cancer/xeps/xep_0144_rosterx.rb +250 -0
  80. data/lib/cancer/xeps/xep_0184_receipts.rb +40 -0
  81. data/lib/cancer/xeps/xep_0199_ping.rb +41 -0
  82. data/spec/spec.opts +2 -0
  83. data/spec/spec_helper.rb +14 -0
  84. data/spec/stream/stanza_errors_spec.rb +47 -0
  85. data/spec/stream/stream_errors_spec.rb +38 -0
  86. data/spec/stream/stream_initialization_spec.rb +160 -0
  87. data/spec/xep_0050/local_spec.rb +165 -0
  88. data/spec/xep_0050/remote_spec.rb +44 -0
  89. metadata +200 -0
@@ -0,0 +1,10 @@
1
+
2
+ module Cancer
3
+ module Events
4
+
5
+ # The abstract base class for all events.
6
+ class AbstractEvent
7
+ end
8
+
9
+ end
10
+ end
@@ -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,16 @@
1
+
2
+ module Cancer
3
+ module Events
4
+ class ProcMatcher < Cancer::Events::Matcher
5
+
6
+ def initialize(proc=nil, &block)
7
+ @proc = proc || block
8
+ end
9
+
10
+ def match?(event)
11
+ !!@proc.call(event)
12
+ end
13
+
14
+ end
15
+ end
16
+ 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