omf_common 6.0.0.pre.10 → 6.0.0.pre.11
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/monitor_topic.rb +80 -0
- data/bin/send_create.rb +94 -0
- data/bin/send_request.rb +58 -0
- data/example/engine_alt.rb +136 -0
- data/example/vm_alt.rb +65 -0
- data/lib/omf_common.rb +224 -3
- data/lib/omf_common/comm.rb +113 -46
- data/lib/omf_common/comm/amqp/amqp_communicator.rb +76 -0
- data/lib/omf_common/comm/amqp/amqp_topic.rb +91 -0
- data/lib/omf_common/comm/local/local_communicator.rb +64 -0
- data/lib/omf_common/comm/local/local_topic.rb +42 -0
- data/lib/omf_common/comm/topic.rb +190 -0
- data/lib/omf_common/{dsl/xmpp.rb → comm/xmpp/communicator.rb} +93 -53
- data/lib/omf_common/comm/xmpp/topic.rb +147 -0
- data/lib/omf_common/{dsl → comm/xmpp}/xmpp_mp.rb +2 -0
- data/lib/omf_common/eventloop.rb +94 -0
- data/lib/omf_common/eventloop/em.rb +57 -0
- data/lib/omf_common/eventloop/local_evl.rb +78 -0
- data/lib/omf_common/message.rb +112 -229
- data/lib/omf_common/message/json/json_message.rb +129 -0
- data/lib/omf_common/message/xml/message.rb +410 -0
- data/lib/omf_common/message/xml/relaxng_schema.rb +17 -0
- data/lib/omf_common/message/xml/topic_message.rb +20 -0
- data/lib/omf_common/protocol/6.0.rnc +11 -21
- data/lib/omf_common/protocol/6.0.rng +52 -119
- data/lib/omf_common/version.rb +1 -1
- data/omf_common.gemspec +4 -2
- data/test/fixture/pubsub.rb +19 -19
- data/test/omf_common/{dsl/xmpp_spec.rb → comm/xmpp/communicator_spec.rb} +47 -111
- data/test/omf_common/comm/xmpp/topic_spec.rb +113 -0
- data/test/omf_common/comm_spec.rb +1 -0
- data/test/omf_common/message/xml/message_spec.rb +136 -0
- data/test/omf_common/message_spec.rb +37 -131
- data/test/test_helper.rb +4 -1
- metadata +38 -28
- data/lib/omf_common/core_ext/object.rb +0 -21
- data/lib/omf_common/relaxng_schema.rb +0 -17
- data/lib/omf_common/topic.rb +0 -34
- data/lib/omf_common/topic_message.rb +0 -20
- data/test/omf_common/topic_message_spec.rb +0 -114
- data/test/omf_common/topic_spec.rb +0 -75
@@ -0,0 +1,190 @@
|
|
1
|
+
require 'monitor'
|
2
|
+
require 'securerandom'
|
3
|
+
|
4
|
+
module OmfCommon
|
5
|
+
class Comm
|
6
|
+
class Topic
|
7
|
+
|
8
|
+
@@name2inst = {}
|
9
|
+
@@lock = Monitor.new
|
10
|
+
|
11
|
+
def self.create(name, opts = {}, &block)
|
12
|
+
# Force string conversion as 'name' can be an ExperimentProperty
|
13
|
+
name = name.to_s.to_sym
|
14
|
+
@@lock.synchronize do
|
15
|
+
unless @@name2inst[name]
|
16
|
+
debug "New topic: #{name}"
|
17
|
+
#opts[:address] ||= address_for(name)
|
18
|
+
@@name2inst[name] = self.new(name, opts, &block)
|
19
|
+
else
|
20
|
+
debug "Existing topic: #{name}"
|
21
|
+
block.call(@@name2inst[name]) if block
|
22
|
+
end
|
23
|
+
@@name2inst[name]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.[](name)
|
28
|
+
@@name2inst[name]
|
29
|
+
end
|
30
|
+
|
31
|
+
attr_reader :id
|
32
|
+
|
33
|
+
# Request the creation of a new resource. Returns itself
|
34
|
+
#
|
35
|
+
def create(res_type, config_props = {}, core_props = {}, &block)
|
36
|
+
# new_res = nil
|
37
|
+
#res_name = res_name.to_sym
|
38
|
+
#config_props[:name] ||= res_name
|
39
|
+
config_props[:type] ||= res_type
|
40
|
+
debug "Create resource of type '#{res_type}'"
|
41
|
+
create_message_and_publish(:create, config_props, core_props, block)
|
42
|
+
self
|
43
|
+
end
|
44
|
+
|
45
|
+
def configure(props = {}, core_props = {}, &block)
|
46
|
+
create_message_and_publish(:configure, props, core_props, block)
|
47
|
+
self
|
48
|
+
end
|
49
|
+
|
50
|
+
def request(select = [], core_props = {}, &block)
|
51
|
+
# TODO: What are the parameters to the request method really?
|
52
|
+
create_message_and_publish(:request, select, core_props, block)
|
53
|
+
self
|
54
|
+
end
|
55
|
+
|
56
|
+
def inform(type, props = {}, core_props = {}, &block)
|
57
|
+
msg = OmfCommon::Message.create(:inform, props, core_props.merge(itype: type))
|
58
|
+
publish(msg, &block)
|
59
|
+
self
|
60
|
+
end
|
61
|
+
|
62
|
+
# def inform(type, props = {}, &block)
|
63
|
+
# msg = OmfCommon::Message.create(:inform, props)
|
64
|
+
# msg.itype = type
|
65
|
+
# publish(msg, &block)
|
66
|
+
# self
|
67
|
+
# end
|
68
|
+
|
69
|
+
def release(resource, core_props = {}, &block)
|
70
|
+
unless resource.is_a? self.class
|
71
|
+
raise "Expected '#{self.class}', but got '#{resource.class}'"
|
72
|
+
end
|
73
|
+
msg = OmfCommon::Message.create(:release, {}, core_props.merge(res_id: resource.id))
|
74
|
+
publish(msg, &block)
|
75
|
+
self
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
def create_message_and_publish(type, props = {}, core_props = {}, block = nil)
|
80
|
+
debug "(#{id}) create_message_and_publish '#{type}': #{props.inspect}"
|
81
|
+
msg = OmfCommon::Message.create(type, props, core_props)
|
82
|
+
publish(msg, &block)
|
83
|
+
end
|
84
|
+
|
85
|
+
def publish(msg, &block)
|
86
|
+
# TODO should it be _send_message(msg, &block) ?
|
87
|
+
#raise "Expected message but got '#{msg.class}" unless msg.is_a?(OmfCommon::Message)
|
88
|
+
_send_message(msg, block)
|
89
|
+
end
|
90
|
+
|
91
|
+
[:created,
|
92
|
+
:create_succeeded, :create_failed,
|
93
|
+
:inform_status, :inform_failed,
|
94
|
+
:released, :failed,
|
95
|
+
:message
|
96
|
+
].each do |itype|
|
97
|
+
mname = "on_#{itype}"
|
98
|
+
define_method(mname) do |*args, &message_block|
|
99
|
+
debug "(#{id}) register handler for '#{mname}'"
|
100
|
+
@lock.synchronize do
|
101
|
+
(@handlers[itype] ||= []) << message_block
|
102
|
+
end
|
103
|
+
self
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Unsubscribe from the underlying comms layer
|
108
|
+
#
|
109
|
+
def unsubscribe()
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
def on_subscribed(&block)
|
114
|
+
raise "Not implemented"
|
115
|
+
end
|
116
|
+
|
117
|
+
# For detecting message publishing error, means if callback indeed yield a Topic object, there is no publishing error, thus always false
|
118
|
+
def error?
|
119
|
+
false
|
120
|
+
end
|
121
|
+
|
122
|
+
def address
|
123
|
+
raise "Not implemented"
|
124
|
+
end
|
125
|
+
|
126
|
+
def after(delay_sec, &block)
|
127
|
+
return unless block
|
128
|
+
OmfCommon.eventloop.after(delay_sec) do
|
129
|
+
block.arity == 1 ? block.call(self) : block.call
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
private
|
134
|
+
|
135
|
+
def initialize(id, opts = {})
|
136
|
+
@id = id
|
137
|
+
#@address = opts[:address]
|
138
|
+
@handlers = {}
|
139
|
+
@lock = Monitor.new
|
140
|
+
@context2cbk = {}
|
141
|
+
end
|
142
|
+
|
143
|
+
|
144
|
+
def _send_message(msg, block = nil)
|
145
|
+
if (block)
|
146
|
+
# register callback for responses to 'mid'
|
147
|
+
@context2cbk[msg.mid.to_s] = {block: block, created_at: Time.now}
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def on_incoming_message(msg)
|
152
|
+
type = msg.operation
|
153
|
+
debug "(#{id}) Deliver message '#{type}': #{msg.inspect}"
|
154
|
+
htypes = [type, :message]
|
155
|
+
if type == :inform
|
156
|
+
if it = msg.itype.to_s.downcase
|
157
|
+
#puts "TTT> #{it}"
|
158
|
+
case it
|
159
|
+
when "creation_ok"
|
160
|
+
htypes << :create_succeeded
|
161
|
+
when 'status'
|
162
|
+
htypes << :inform_status
|
163
|
+
else
|
164
|
+
htypes << it.to_sym
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
debug "(#{id}) Message type '#{htypes.inspect}' (#{msg.class}:#{msg.cid})"
|
170
|
+
hs = htypes.map do |ht| @handlers[ht] end.compact.flatten
|
171
|
+
debug "(#{id}) Distributing message to '#{hs.inspect}'"
|
172
|
+
hs.each do |block|
|
173
|
+
block.call msg
|
174
|
+
end
|
175
|
+
if cbk = @context2cbk[msg.cid.to_s]
|
176
|
+
debug "(#{id}) Distributing message to '#{cbk.inspect}'"
|
177
|
+
cbk[:last_used] = Time.now
|
178
|
+
cbk[:block].call(msg)
|
179
|
+
# else
|
180
|
+
# if msg.cid
|
181
|
+
# puts "====NOOOO for #{msg.cid} - #{@context2cbk.keys.inspect}"
|
182
|
+
# end
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
186
|
+
|
187
|
+
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
@@ -1,10 +1,18 @@
|
|
1
1
|
require 'blather/client/dsl'
|
2
2
|
|
3
|
+
require 'omf_common/comm/xmpp/xmpp_mp'
|
4
|
+
require 'omf_common/comm/xmpp/topic'
|
5
|
+
require 'uri'
|
6
|
+
require 'socket'
|
7
|
+
|
3
8
|
module OmfCommon
|
4
|
-
|
5
|
-
|
9
|
+
class Comm
|
10
|
+
class XMPP
|
11
|
+
class Communicator < OmfCommon::Comm
|
6
12
|
include Blather::DSL
|
7
13
|
|
14
|
+
attr_accessor :published_messages, :normal_shutdown_mode, :retry_counter
|
15
|
+
|
8
16
|
HOST_PREFIX = 'pubsub'
|
9
17
|
|
10
18
|
PUBSUB_CONFIGURE = Blather::Stanza::X.new({
|
@@ -17,9 +25,63 @@ module OmfCommon
|
|
17
25
|
{ :var => "pubsub#publish_model", :value => "open" }]
|
18
26
|
})
|
19
27
|
|
28
|
+
# Capture system :INT & :TERM signal
|
29
|
+
def on_interrupted(&block)
|
30
|
+
if block
|
31
|
+
trap(:INT) { block.call(self) }
|
32
|
+
trap(:TERM) { block.call(self) }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def on_connected(&block)
|
37
|
+
when_ready do
|
38
|
+
block.call(self)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Set up XMPP options and start the Eventmachine, connect to XMPP server
|
43
|
+
#
|
44
|
+
def init(opts = {})
|
45
|
+
@pubsub_host = opts[:pubsub_domain]
|
46
|
+
if opts[:url]
|
47
|
+
url = URI(opts[:url])
|
48
|
+
username, password, server = url.user, url.password, url.host
|
49
|
+
else
|
50
|
+
username, password, server = opts[:username], opts[:password], opts[:server]
|
51
|
+
end
|
52
|
+
|
53
|
+
random_name = "#{Socket.gethostname}-#{Process.pid}"
|
54
|
+
username ||= random_name
|
55
|
+
password ||= random_name
|
56
|
+
|
57
|
+
raise ArgumentError, "Username cannot be nil when connect to XMPP" if username.nil?
|
58
|
+
raise ArgumentError, "Password cannot be nil when connect to XMPP" if password.nil?
|
59
|
+
raise ArgumentError, "Server cannot be nil when connect to XMPP" if server.nil?
|
60
|
+
|
61
|
+
@retry_counter = 0
|
62
|
+
@normal_shutdown_mode = false
|
63
|
+
|
64
|
+
connect(username, password, server)
|
65
|
+
|
66
|
+
disconnected do
|
67
|
+
unless normal_shutdown_mode
|
68
|
+
unless retry_counter > 0
|
69
|
+
@retry_counter += 1
|
70
|
+
client.connect
|
71
|
+
else
|
72
|
+
error "Authentication failed."
|
73
|
+
OmfCommon.eventloop.stop
|
74
|
+
end
|
75
|
+
else
|
76
|
+
shutdown
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
20
81
|
# Set up XMPP options and start the Eventmachine, connect to XMPP server
|
21
82
|
#
|
22
83
|
def connect(username, password, server)
|
84
|
+
info "Connecting to '#{server}' ..."
|
23
85
|
jid = "#{username}@#{server}"
|
24
86
|
client.setup(jid, password)
|
25
87
|
client.run
|
@@ -28,38 +90,18 @@ module OmfCommon
|
|
28
90
|
|
29
91
|
# Shut down XMPP connection
|
30
92
|
def disconnect(opts = {})
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
# none means... topics subscribed to
|
36
|
-
none_topics = a[:none] ? a[:none].size : 0
|
37
|
-
|
38
|
-
if none_topics > 0
|
39
|
-
info "Unsubscribing #{none_topics} pubsub topic(s)"
|
40
|
-
unsubscribe
|
41
|
-
end
|
42
|
-
|
43
|
-
if owner_topics > 0
|
44
|
-
info "Deleting #{owner_topics} pubsub topic(s) in 2 seconds"
|
45
|
-
EM.add_timer(2) do
|
46
|
-
a[:owner].each { |topic| delete_topic(topic) }
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
shutdown if none_topics == 0 && owner_topics == 0
|
51
|
-
end
|
52
|
-
else
|
53
|
-
shutdown
|
54
|
-
end
|
93
|
+
# NOTE Do not clean up
|
94
|
+
info "Disconnecting ..."
|
95
|
+
@normal_shutdown_mode = true
|
96
|
+
shutdown
|
55
97
|
OmfCommon::DSL::Xmpp::MPConnection.inject(Time.now.to_f, jid, 'disconnect') if OmfCommon::Measure.enabled?
|
56
98
|
end
|
57
99
|
|
58
100
|
# Create a new pubsub topic with additional configuration
|
59
101
|
#
|
60
102
|
# @param [String] topic Pubsub topic name
|
61
|
-
def create_topic(topic,
|
62
|
-
|
103
|
+
def create_topic(topic, opts = {})
|
104
|
+
OmfCommon::Comm::XMPP::Topic.create(topic)
|
63
105
|
end
|
64
106
|
|
65
107
|
# Delete a pubsub topic
|
@@ -75,22 +117,19 @@ module OmfCommon
|
|
75
117
|
# @param [Hash] opts
|
76
118
|
# @option opts [Boolean] :create_if_non_existent create the topic if non-existent, use this option with caution
|
77
119
|
def subscribe(topic, opts = {}, &block)
|
78
|
-
if
|
79
|
-
|
80
|
-
if a[:owner] && a[:owner].include?(topic)
|
81
|
-
pubsub.subscribe(topic, nil, default_host, &callback_logging(__method__, topic, &block))
|
82
|
-
else
|
83
|
-
create_topic(topic) do
|
84
|
-
pubsub.subscribe(topic, nil, default_host, &callback_logging(__method__, topic, &block))
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
else
|
89
|
-
pubsub.subscribe(topic, nil, default_host, &callback_logging(__method__, topic, &block))
|
90
|
-
end
|
120
|
+
topic = topic.first if topic.is_a? Array
|
121
|
+
OmfCommon::Comm::XMPP::Topic.create(topic, &block)
|
91
122
|
MPSubscription.inject(Time.now.to_f, jid, 'join', topic) if OmfCommon::Measure.enabled?
|
92
123
|
end
|
93
124
|
|
125
|
+
def _subscribe(topic, &block)
|
126
|
+
pubsub.subscribe(topic, nil, default_host, &callback_logging(__method__, topic, &block))
|
127
|
+
end
|
128
|
+
|
129
|
+
def _create(topic, &block)
|
130
|
+
pubsub.create(topic, default_host, PUBSUB_CONFIGURE, &callback_logging(__method__, topic, &block))
|
131
|
+
end
|
132
|
+
|
94
133
|
# Un-subscribe all existing subscriptions from all pubsub topics.
|
95
134
|
def unsubscribe
|
96
135
|
pubsub.subscriptions(default_host) do |m|
|
@@ -108,10 +147,12 @@ module OmfCommon
|
|
108
147
|
# Publish to a pubsub topic
|
109
148
|
#
|
110
149
|
# @param [String] topic Pubsub topic name
|
111
|
-
# @param [
|
150
|
+
# @param [OmfCommon::Message] message Any XML fragment to be sent as payload
|
112
151
|
def publish(topic, message, &block)
|
113
152
|
raise StandardError, "Invalid message" unless message.valid?
|
114
153
|
|
154
|
+
message = message.xml unless message.kind_of? String
|
155
|
+
|
115
156
|
new_block = proc do |stanza|
|
116
157
|
published_messages << OpenSSL::Digest::SHA1.new(message.to_s)
|
117
158
|
block.call(stanza) if block
|
@@ -121,13 +162,6 @@ module OmfCommon
|
|
121
162
|
MPPublished.inject(Time.now.to_f, jid, topic, message.to_s.gsub("\n",'')) if OmfCommon::Measure.enabled?
|
122
163
|
end
|
123
164
|
|
124
|
-
# Event machine related method delegation
|
125
|
-
%w(add_timer add_periodic_timer).each do |m_name|
|
126
|
-
define_method(m_name) do |*args, &block|
|
127
|
-
EM.send(m_name, *args, &block)
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
165
|
# Event callback for pubsub topic event(item published)
|
132
166
|
#
|
133
167
|
def topic_event(additional_guard = nil, &block)
|
@@ -148,16 +182,21 @@ module OmfCommon
|
|
148
182
|
|
149
183
|
private
|
150
184
|
|
185
|
+
def initialize(opts = {})
|
186
|
+
self.published_messages = []
|
187
|
+
super
|
188
|
+
end
|
189
|
+
|
151
190
|
# Provide a new block wrap to automatically log errors
|
152
191
|
def callback_logging(*args, &block)
|
153
|
-
m = args.empty? ? "OPERATION" : args.
|
192
|
+
m = args.empty? ? "OPERATION" : args.join(" >> ")
|
154
193
|
proc do |stanza|
|
155
194
|
if stanza.respond_to?(:error?) && stanza.error?
|
156
195
|
e_stanza = Blather::StanzaError.import(stanza)
|
157
196
|
if [:unexpected_request].include? e_stanza.name
|
158
197
|
logger.debug e_stanza
|
159
|
-
elsif e_stanza.name == :conflict
|
160
|
-
logger.debug e_stanza
|
198
|
+
elsif e_stanza.name == :conflict
|
199
|
+
#logger.debug e_stanza
|
161
200
|
else
|
162
201
|
logger.warn "#{e_stanza} Original: #{e_stanza.original}"
|
163
202
|
end
|
@@ -168,8 +207,9 @@ module OmfCommon
|
|
168
207
|
end
|
169
208
|
|
170
209
|
def default_host
|
171
|
-
"#{HOST_PREFIX}.#{
|
210
|
+
@pubsub_host || "#{HOST_PREFIX}.#{jid.domain}"
|
172
211
|
end
|
173
212
|
end
|
174
213
|
end
|
175
214
|
end
|
215
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
module OmfCommon
|
2
|
+
class Comm
|
3
|
+
class XMPP
|
4
|
+
class Topic < OmfCommon::Comm::Topic
|
5
|
+
%w(creation.ok creation.failed status released error warn).each do |itype|
|
6
|
+
define_method("on_#{itype.gsub(/\./, '_')}") do |*args, &message_block|
|
7
|
+
mid = args[0].mid if args[0]
|
8
|
+
|
9
|
+
raise ArgumentError, 'Missing callback' if message_block.nil?
|
10
|
+
|
11
|
+
event_block = proc do |event|
|
12
|
+
message_block.call(OmfCommon::Message.parse(event.items.first.payload))
|
13
|
+
end
|
14
|
+
|
15
|
+
guard_block = proc do |event|
|
16
|
+
(event.items?) && (!event.delayed?) &&
|
17
|
+
event.items.first.payload &&
|
18
|
+
(omf_message = OmfCommon::Message.parse(event.items.first.payload)) &&
|
19
|
+
event.node == id.to_s &&
|
20
|
+
omf_message.operation == :inform &&
|
21
|
+
omf_message.read_content(:itype) == itype.upcase &&
|
22
|
+
(mid ? (omf_message.cid == mid) : true)
|
23
|
+
end
|
24
|
+
|
25
|
+
OmfCommon.comm.topic_event(guard_block, &event_block)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def on_message(message_guard_proc = nil, ref_id = 0, &message_block)
|
30
|
+
@lock.synchronize do
|
31
|
+
@on_message_cbks[ref_id] ||= []
|
32
|
+
@on_message_cbks[ref_id] << message_block
|
33
|
+
end
|
34
|
+
|
35
|
+
event_block = proc do |event|
|
36
|
+
@on_message_cbks.each do |id, cbks|
|
37
|
+
cbks.each do |cbk|
|
38
|
+
cbk.call(OmfCommon::Message.parse(event.items.first.payload))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
guard_block = proc do |event|
|
44
|
+
(event.items?) && (!event.delayed?) &&
|
45
|
+
event.items.first.payload &&
|
46
|
+
(omf_message = OmfCommon::Message.parse(event.items.first.payload)) &&
|
47
|
+
event.node == id.to_s &&
|
48
|
+
(valid_guard?(message_guard_proc) ? message_guard_proc.call(omf_message) : true)
|
49
|
+
end
|
50
|
+
OmfCommon.comm.topic_event(guard_block, &event_block)
|
51
|
+
end
|
52
|
+
|
53
|
+
def delete_on_message_cbk_by_id(id)
|
54
|
+
@lock.synchronize do
|
55
|
+
@on_message_cbks[id] && @on_message_cbks.reject! { |k| k == id.to_s }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def inform(type, props = {}, core_props = {}, &block)
|
60
|
+
msg = OmfCommon::Message.create(:inform, props, core_props.merge(itype: type))
|
61
|
+
publish(msg, &block)
|
62
|
+
self
|
63
|
+
end
|
64
|
+
|
65
|
+
def publish(msg, &block)
|
66
|
+
_send_message(msg, &block)
|
67
|
+
end
|
68
|
+
|
69
|
+
def address
|
70
|
+
"xmpp://#{id.to_s}@#{OmfCommon.comm.jid.domain}"
|
71
|
+
end
|
72
|
+
|
73
|
+
def on_subscribed(&block)
|
74
|
+
return unless block
|
75
|
+
|
76
|
+
@lock.synchronize do
|
77
|
+
@on_subscrided_handlers << block
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def initialize(id, opts = {}, &block)
|
84
|
+
@on_message_cbks = Hashie::Mash.new
|
85
|
+
|
86
|
+
id = $1 if id =~ /^xmpp:\/\/(.+)@.+$/
|
87
|
+
|
88
|
+
super
|
89
|
+
|
90
|
+
@on_subscrided_handlers = []
|
91
|
+
|
92
|
+
topic_block = proc do |stanza|
|
93
|
+
if stanza.error?
|
94
|
+
block.call(stanza) if block
|
95
|
+
else
|
96
|
+
block.call(self) if block
|
97
|
+
|
98
|
+
@lock.synchronize do
|
99
|
+
@on_subscrided_handlers.each do |handler|
|
100
|
+
handler.call
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
OmfCommon.comm._create(id.to_s) do |stanza|
|
107
|
+
if stanza.error?
|
108
|
+
e_stanza = Blather::StanzaError.import(stanza)
|
109
|
+
if e_stanza.name == :conflict
|
110
|
+
# Topic exists, just subscribe to it.
|
111
|
+
OmfCommon.comm._subscribe(id.to_s, &topic_block)
|
112
|
+
else
|
113
|
+
block.call(stanza) if block
|
114
|
+
end
|
115
|
+
else
|
116
|
+
OmfCommon.comm._subscribe(id.to_s, &topic_block)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def _send_message(msg, &block)
|
122
|
+
# while sending a message, need to setup handler for replying messages
|
123
|
+
OmfCommon.comm.publish(self.id, msg) do |stanza|
|
124
|
+
if !stanza.error? && !block.nil?
|
125
|
+
on_error(msg, &block)
|
126
|
+
on_warn(msg, &block)
|
127
|
+
case msg.operation
|
128
|
+
when :create
|
129
|
+
on_creation_ok(msg, &block)
|
130
|
+
on_creation_failed(msg, &block)
|
131
|
+
when :configure, :request
|
132
|
+
on_status(msg, &block)
|
133
|
+
when :release
|
134
|
+
on_released(msg, &block)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def valid_guard?(guard_proc)
|
141
|
+
guard_proc && guard_proc.class == Proc
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|