cancer 0.1.0.a1

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