blather 0.2.1 → 0.2.2
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/LICENSE +2 -0
- data/README.rdoc +54 -29
- data/Rakefile +94 -13
- data/VERSION.yml +4 -0
- data/examples/drb_client.rb +2 -4
- data/examples/echo.rb +13 -8
- data/examples/pubsub/cli.rb +64 -0
- data/examples/pubsub/ping_pong.rb +18 -0
- data/examples/pubsub/pubsub_dsl.rb +52 -0
- data/examples/pubsub_client.rb +39 -0
- data/examples/rosterprint.rb +14 -0
- data/examples/xmpp4r/echo.rb +35 -0
- data/ext/extconf.rb +65 -0
- data/lib/blather.rb +18 -121
- data/lib/blather/client.rb +13 -0
- data/lib/blather/client/client.rb +165 -0
- data/lib/blather/client/dsl.rb +99 -0
- data/lib/blather/client/pubsub.rb +53 -0
- data/lib/blather/client/pubsub/node.rb +27 -0
- data/lib/blather/core_ext/active_support.rb +1 -0
- data/lib/blather/core_ext/libxml.rb +7 -1
- data/lib/blather/errors.rb +39 -18
- data/lib/blather/errors/sasl_error.rb +87 -0
- data/lib/blather/errors/stanza_error.rb +262 -0
- data/lib/blather/errors/stream_error.rb +253 -0
- data/lib/blather/jid.rb +9 -16
- data/lib/blather/roster.rb +9 -0
- data/lib/blather/roster_item.rb +7 -4
- data/lib/blather/stanza.rb +19 -25
- data/lib/blather/stanza/disco.rb +9 -0
- data/lib/blather/stanza/disco/disco_info.rb +84 -0
- data/lib/blather/stanza/disco/disco_items.rb +59 -0
- data/lib/blather/stanza/iq.rb +16 -4
- data/lib/blather/stanza/iq/query.rb +6 -4
- data/lib/blather/stanza/iq/roster.rb +38 -38
- data/lib/blather/stanza/pubsub.rb +33 -0
- data/lib/blather/stanza/pubsub/affiliations.rb +52 -0
- data/lib/blather/stanza/pubsub/errors.rb +9 -0
- data/lib/blather/stanza/pubsub/event.rb +21 -0
- data/lib/blather/stanza/pubsub/items.rb +59 -0
- data/lib/blather/stanza/pubsub/owner.rb +9 -0
- data/lib/blather/stanza/pubsub/subscriptions.rb +57 -0
- data/lib/blather/stream.rb +125 -57
- data/lib/blather/stream/client.rb +26 -0
- data/lib/blather/stream/component.rb +34 -0
- data/lib/blather/stream/parser.rb +17 -27
- data/lib/blather/stream/resource.rb +21 -24
- data/lib/blather/stream/sasl.rb +60 -37
- data/lib/blather/stream/session.rb +12 -19
- data/lib/blather/stream/stream_handler.rb +39 -0
- data/lib/blather/stream/tls.rb +22 -18
- data/lib/blather/xmpp_node.rb +91 -17
- data/spec/blather/core_ext/libxml_spec.rb +58 -0
- data/spec/blather/errors/sasl_error_spec.rb +56 -0
- data/spec/blather/errors/stanza_error_spec.rb +148 -0
- data/spec/blather/errors/stream_error_spec.rb +114 -0
- data/spec/blather/errors_spec.rb +40 -0
- data/spec/blather/jid_spec.rb +0 -7
- data/spec/blather/roster_item_spec.rb +5 -0
- data/spec/blather/roster_spec.rb +6 -6
- data/spec/blather/stanza/discos/disco_info_spec.rb +207 -0
- data/spec/blather/stanza/discos/disco_items_spec.rb +136 -0
- data/spec/blather/stanza/iq/query_spec.rb +9 -2
- data/spec/blather/stanza/iq/roster_spec.rb +117 -1
- data/spec/blather/stanza/iq_spec.rb +29 -0
- data/spec/blather/stanza/presence/subscription_spec.rb +12 -1
- data/spec/blather/stanza/presence_spec.rb +29 -0
- data/spec/blather/stanza/pubsub/affiliations_spec.rb +46 -0
- data/spec/blather/stanza/pubsub/items_spec.rb +59 -0
- data/spec/blather/stanza/pubsub/subscriptions_spec.rb +63 -0
- data/spec/blather/stanza/pubsub_spec.rb +26 -0
- data/spec/blather/stanza_spec.rb +13 -1
- data/spec/blather/stream/client_spec.rb +787 -0
- data/spec/blather/stream/component_spec.rb +86 -0
- data/spec/blather/xmpp_node_spec.rb +75 -22
- data/spec/fixtures/pubsub.rb +157 -0
- data/spec/spec_helper.rb +6 -14
- metadata +86 -74
- data/CHANGELOG +0 -5
- data/Manifest +0 -47
- data/blather.gemspec +0 -41
- data/lib/blather/stanza/error.rb +0 -31
- data/spec/blather/stream_spec.rb +0 -462
- data/spec/build_safe.rb +0 -20
data/lib/blather/stream.rb
CHANGED
@@ -1,8 +1,13 @@
|
|
1
1
|
module Blather
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
#
|
3
|
+
class Stream < EventMachine::Connection
|
4
|
+
##
|
5
|
+
# Start the stream between client and server
|
6
|
+
# [client] must be an object that will respond to #call and #jid=
|
7
|
+
# [jid] must be a valid argument for JID.new (see JID)
|
8
|
+
# [pass] must be the password
|
9
|
+
# [host] (optional) must be the hostname or IP to connect to. defaults to the domain of [jid]
|
10
|
+
# [port] (optional) must be the port to connect to. defaults to 5222
|
6
11
|
def self.start(client, jid, pass, host = nil, port = 5222)
|
7
12
|
jid = JID.new jid
|
8
13
|
host ||= jid.domain
|
@@ -10,43 +15,85 @@ module Blather
|
|
10
15
|
EM.connect host, port, self, client, jid, pass
|
11
16
|
end
|
12
17
|
|
18
|
+
##
|
19
|
+
# Send data over the wire
|
20
|
+
# The argument for this can be anything that
|
21
|
+
# responds to #to_s
|
22
|
+
def send(stanza)
|
23
|
+
#TODO Queue if not ready
|
24
|
+
LOG.debug "SENDING: (#{caller[1]}) #{stanza}"
|
25
|
+
send_data stanza.respond_to?(:to_xml) ? stanza.to_xml : stanza.to_s
|
26
|
+
end
|
27
|
+
|
28
|
+
##
|
29
|
+
# True if the stream is in the stopped state
|
30
|
+
def stopped?
|
31
|
+
@state == :stopped
|
32
|
+
end
|
33
|
+
|
34
|
+
##
|
35
|
+
# True when the stream is in the negotiation phase.
|
36
|
+
def negotiating?
|
37
|
+
![:stopped, :ready].include? @state
|
38
|
+
end
|
39
|
+
|
40
|
+
##
|
41
|
+
# True when the stream is ready
|
42
|
+
# The stream is ready immediately after receiving <stream:stream>
|
43
|
+
# and before any feature negotion. Once feature negoation starts
|
44
|
+
# the stream will not be ready until all negotations have completed
|
45
|
+
# successfully.
|
46
|
+
def ready?
|
47
|
+
@state == :ready
|
48
|
+
end
|
49
|
+
|
50
|
+
##
|
51
|
+
# Called by EM.connect to initialize stream variables
|
13
52
|
def initialize(client, jid, pass) # :nodoc:
|
14
53
|
super()
|
15
54
|
|
55
|
+
@error = nil
|
16
56
|
@client = client
|
17
57
|
|
18
58
|
self.jid = jid
|
19
59
|
@pass = pass
|
20
60
|
|
21
61
|
@to = @jid.domain
|
22
|
-
@id = nil
|
23
|
-
@lang = 'en'
|
24
|
-
@version = '1.0'
|
25
|
-
@namespace = 'jabber:client'
|
26
|
-
|
27
|
-
@parser = Parser.new self
|
28
62
|
end
|
29
63
|
|
64
|
+
##
|
65
|
+
# Called when EM completes the connection to the server
|
66
|
+
# this kicks off the starttls/authorize/bind process
|
30
67
|
def connection_completed # :nodoc:
|
31
68
|
# @keepalive = EM::Timer.new(60) { send_data ' ' }
|
32
69
|
@state = :stopped
|
33
70
|
dispatch
|
34
71
|
end
|
35
72
|
|
73
|
+
##
|
74
|
+
# Called by EM with data from the wire
|
36
75
|
def receive_data(data) # :nodoc:
|
37
|
-
|
76
|
+
LOG.debug "\n#{'-'*30}\n"
|
77
|
+
LOG.debug "<< #{data}"
|
78
|
+
@parser.receive_data data
|
38
79
|
|
39
|
-
rescue => e
|
40
|
-
@
|
80
|
+
rescue ParseError => e
|
81
|
+
@error = e
|
82
|
+
stop
|
41
83
|
end
|
42
84
|
|
85
|
+
##
|
86
|
+
# Called by EM when the connection is closed
|
43
87
|
def unbind # :nodoc:
|
44
88
|
# @keepalive.cancel
|
45
89
|
@state = :stopped
|
90
|
+
@client.call @error if @error
|
91
|
+
@client.stopped
|
46
92
|
end
|
47
93
|
|
94
|
+
##
|
95
|
+
# Called by the parser with parsed nodes
|
48
96
|
def receive(node) # :nodoc:
|
49
|
-
LOG.debug "\n"+('-'*30)+"\n"
|
50
97
|
LOG.debug "RECEIVING (#{node.element_name}) #{node}"
|
51
98
|
@node = node
|
52
99
|
|
@@ -55,7 +102,7 @@ module Blather
|
|
55
102
|
@state = :ready if @state == :stopped
|
56
103
|
|
57
104
|
when 'stream:end'
|
58
|
-
|
105
|
+
stop
|
59
106
|
|
60
107
|
when 'stream:features'
|
61
108
|
@features = @node.children
|
@@ -63,7 +110,9 @@ module Blather
|
|
63
110
|
dispatch
|
64
111
|
|
65
112
|
when 'stream:error'
|
66
|
-
|
113
|
+
@error = StreamError.import @node
|
114
|
+
stop
|
115
|
+
@state = :error
|
67
116
|
|
68
117
|
else
|
69
118
|
dispatch
|
@@ -72,61 +121,57 @@ module Blather
|
|
72
121
|
end
|
73
122
|
|
74
123
|
##
|
75
|
-
#
|
76
|
-
def send(stanza)
|
77
|
-
#TODO Queue if not ready
|
78
|
-
LOG.debug "SENDING: (#{caller[1]}) #{stanza}"
|
79
|
-
send_data stanza.to_s
|
80
|
-
end
|
81
|
-
|
82
|
-
def stopped?
|
83
|
-
@state == :stopped
|
84
|
-
end
|
85
|
-
|
86
|
-
def ready?
|
87
|
-
@state == :ready
|
88
|
-
end
|
89
|
-
|
124
|
+
# Ensure the JID gets attached to the client
|
90
125
|
def jid=(new_jid) # :nodoc:
|
91
126
|
LOG.debug "NEW JID: #{new_jid}"
|
92
|
-
|
93
|
-
@client.jid =
|
94
|
-
@jid = new_jid
|
127
|
+
@jid = JID.new new_jid
|
128
|
+
@client.jid = @jid
|
95
129
|
end
|
96
130
|
|
97
|
-
|
131
|
+
protected
|
132
|
+
##
|
133
|
+
# Dispatch based on current state
|
98
134
|
def dispatch
|
99
135
|
__send__ @state
|
100
136
|
end
|
101
137
|
|
138
|
+
##
|
139
|
+
# Start the stream
|
140
|
+
# Each time the stream is started or re-started we need to kill off the old
|
141
|
+
# parser so as not to confuse it
|
102
142
|
def start
|
103
|
-
send <<-STREAM
|
104
|
-
<stream:stream
|
105
|
-
to='#{@to}'
|
106
|
-
xmlns='#{@namespace}'
|
107
|
-
xmlns:stream='http://etherx.jabber.org/streams'
|
108
|
-
version='#{@version}'
|
109
|
-
xml:lang='#{@lang}'
|
110
|
-
>
|
111
|
-
STREAM
|
112
143
|
end
|
113
144
|
|
145
|
+
##
|
146
|
+
# Stop the stream
|
114
147
|
def stop
|
115
|
-
|
148
|
+
unless @state == :stopped
|
149
|
+
@state = :stopped
|
150
|
+
send '</stream:stream>'
|
151
|
+
end
|
116
152
|
end
|
117
153
|
|
154
|
+
##
|
155
|
+
# Called when @state == :stopped to start the stream
|
156
|
+
# Counter intuitive, I know
|
118
157
|
def stopped
|
119
158
|
start
|
120
159
|
end
|
121
160
|
|
161
|
+
##
|
162
|
+
# Called when @state == :ready
|
163
|
+
# Simply passes the stanza to the client
|
122
164
|
def ready
|
123
165
|
@client.call @node.to_stanza
|
124
166
|
end
|
125
167
|
|
168
|
+
##
|
169
|
+
# Called when @state == :features
|
170
|
+
# Runs through the list of features starting each one in turn
|
126
171
|
def features
|
127
172
|
feature = @features.first
|
128
173
|
LOG.debug "FEATURE: #{feature}"
|
129
|
-
@state = case feature ? feature
|
174
|
+
@state = case feature ? feature.namespaces.default.href : nil
|
130
175
|
when 'urn:ietf:params:xml:ns:xmpp-tls' then :establish_tls
|
131
176
|
when 'urn:ietf:params:xml:ns:xmpp-sasl' then :authenticate_sasl
|
132
177
|
when 'urn:ietf:params:xml:ns:xmpp-bind' then :bind_resource
|
@@ -134,47 +179,70 @@ module Blather
|
|
134
179
|
else :ready
|
135
180
|
end
|
136
181
|
|
182
|
+
# Dispatch to the individual feature methods unless
|
183
|
+
# feature negotiation is complete
|
137
184
|
dispatch unless ready?
|
138
185
|
end
|
139
186
|
|
187
|
+
##
|
188
|
+
# Start TLS
|
140
189
|
def establish_tls
|
141
190
|
unless @tls
|
142
191
|
@tls = TLS.new self
|
143
|
-
|
144
|
-
@tls.
|
192
|
+
# on success destroy the TLS object and restart the stream
|
193
|
+
@tls.on_success { LOG.debug "TLS: SUCCESS"; @tls = nil; start }
|
194
|
+
# on failure stop the stream
|
195
|
+
@tls.on_failure { |err| LOG.debug "TLS: FAILURE"; @error = err; stop }
|
196
|
+
|
145
197
|
@node = @features.shift
|
146
198
|
end
|
147
|
-
@tls.
|
199
|
+
@tls.handle @node
|
148
200
|
end
|
149
201
|
|
202
|
+
##
|
203
|
+
# Authenticate via SASL
|
150
204
|
def authenticate_sasl
|
151
205
|
unless @sasl
|
152
206
|
@sasl = SASL.new(self, @jid, @pass)
|
153
|
-
|
154
|
-
@sasl.
|
207
|
+
# on success destroy the SASL object and restart the stream
|
208
|
+
@sasl.on_success { LOG.debug "SASL SUCCESS"; @sasl = nil; start }
|
209
|
+
# on failure set the error and stop the stream
|
210
|
+
@sasl.on_failure { |err| LOG.debug "SASL FAIL"; @error = err; stop }
|
211
|
+
|
155
212
|
@node = @features.shift
|
156
213
|
end
|
157
|
-
@sasl.
|
214
|
+
@sasl.handle @node
|
158
215
|
end
|
159
216
|
|
217
|
+
##
|
218
|
+
# Bind to the resource provided by either the client or the server
|
160
219
|
def bind_resource
|
161
220
|
unless @resource
|
162
221
|
@resource = Resource.new self, @jid
|
163
|
-
|
164
|
-
@resource.
|
222
|
+
# on success destroy the Resource object, set the jid, continue along the features dispatch process
|
223
|
+
@resource.on_success { |jid| LOG.debug "RESOURCE: SUCCESS"; @resource = nil; self.jid = jid; @state = :features; dispatch }
|
224
|
+
# on failure end the stream
|
225
|
+
@resource.on_failure { |err| LOG.debug "RESOURCE: FAILURE"; @error = err; stop }
|
226
|
+
|
165
227
|
@node = @features.shift
|
166
228
|
end
|
167
|
-
@resource.
|
229
|
+
@resource.handle @node
|
168
230
|
end
|
169
231
|
|
232
|
+
##
|
233
|
+
# Establish the session between client and server
|
170
234
|
def establish_session
|
171
235
|
unless @session
|
172
236
|
@session = Session.new self, @to
|
173
|
-
|
174
|
-
|
237
|
+
# on success destroy the session object, let the client know the stream has been started
|
238
|
+
# then continue the features dispatch process
|
239
|
+
@session.on_success { LOG.debug "SESSION: SUCCESS"; @session = nil; @client.stream_started(self); @state = :features; dispatch }
|
240
|
+
# on failure end the stream
|
241
|
+
@session.on_failure { |err| LOG.debug "SESSION: FAILURE"; @error = err; stop }
|
242
|
+
|
175
243
|
@node = @features.shift
|
176
244
|
end
|
177
|
-
@session.
|
245
|
+
@session.handle @node
|
178
246
|
end
|
179
247
|
end
|
180
248
|
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Blather
|
2
|
+
class Stream
|
3
|
+
|
4
|
+
class Client < Stream
|
5
|
+
LANG = 'en'
|
6
|
+
VERSION = '1.0'
|
7
|
+
NAMESPACE = 'jabber:client'
|
8
|
+
|
9
|
+
protected
|
10
|
+
def start
|
11
|
+
@parser = Parser.new self
|
12
|
+
start_stream = <<-STREAM
|
13
|
+
<stream:stream
|
14
|
+
to='#{@to}'
|
15
|
+
xmlns='#{NAMESPACE}'
|
16
|
+
xmlns:stream='http://etherx.jabber.org/streams'
|
17
|
+
version='#{VERSION}'
|
18
|
+
xml:lang='#{LANG}'
|
19
|
+
>
|
20
|
+
STREAM
|
21
|
+
send start_stream.gsub(/\s+/, ' ')
|
22
|
+
end
|
23
|
+
end #Client
|
24
|
+
|
25
|
+
end #Stream
|
26
|
+
end #Blather
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Blather
|
2
|
+
class Stream
|
3
|
+
|
4
|
+
class Component < Stream
|
5
|
+
NAMESPACE = 'jabber:component:accept'
|
6
|
+
|
7
|
+
def receive(node) # :nodoc:
|
8
|
+
if node.element_name == 'handshake'
|
9
|
+
@client.stream_started(self)
|
10
|
+
else
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
if node.element_name == 'stream:stream'
|
15
|
+
send("<handshake>#{Digest::SHA1.hexdigest(@node['id']+@pass)}</handshake>")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
def start
|
21
|
+
@parser = Parser.new self
|
22
|
+
start_stream = <<-STREAM
|
23
|
+
<stream:stream
|
24
|
+
to='#{@jid}'
|
25
|
+
xmlns='#{NAMESPACE}'
|
26
|
+
xmlns:stream='http://etherx.jabber.org/streams'
|
27
|
+
>
|
28
|
+
STREAM
|
29
|
+
send start_stream.gsub(/\s+/, ' ')
|
30
|
+
end
|
31
|
+
end #Client
|
32
|
+
|
33
|
+
end #Stream
|
34
|
+
end #Blather
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module Blather # :nodoc:
|
2
|
-
|
2
|
+
class Stream # :nodoc:
|
3
3
|
|
4
4
|
class Parser # :nodoc:
|
5
5
|
STREAM_REGEX = %r{(/)?stream:stream}.freeze
|
6
6
|
ERROR_REGEX = /^<(stream:[a-z]+)/.freeze
|
7
7
|
|
8
|
-
@@debug = false
|
8
|
+
@@debug = !false
|
9
9
|
def self.debug; @@debug; end
|
10
10
|
def self.debug=(debug); @@debug = debug; end
|
11
11
|
|
@@ -14,31 +14,20 @@ module Stream # :nodoc:
|
|
14
14
|
def initialize(receiver)
|
15
15
|
@receiver = receiver
|
16
16
|
@current = nil
|
17
|
-
|
18
|
-
@parser = XML::SaxParser.new
|
19
|
-
@parser.io = StringIO.new
|
20
|
-
@parser.callbacks = self
|
17
|
+
@parser = XML::SaxPushParser.new self
|
21
18
|
end
|
22
19
|
|
23
|
-
def
|
24
|
-
LOG.debug "PARSING: #{string}" if @@debug
|
25
|
-
|
26
|
-
@receiver.receive XMPPNode.new('stream:end')
|
27
|
-
else
|
28
|
-
string << "</stream:stream>" if string =~ STREAM_REGEX && !$1
|
29
|
-
string.gsub!(ERROR_REGEX, "<\\1 xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'")
|
30
|
-
|
31
|
-
@parser.string = string
|
32
|
-
@parser.parse
|
33
|
-
end
|
20
|
+
def receive_data(string)
|
21
|
+
LOG.debug "PARSING: (#{string})" if @@debug
|
22
|
+
@parser.receive string
|
34
23
|
end
|
35
24
|
|
36
|
-
NON_ATTRS = [nil, 'stream'].freeze
|
37
25
|
def on_start_element_ns(elem, attrs, prefix, uri, namespaces)
|
38
|
-
LOG.debug "START ELEM: (#{{:elem => elem, :attrs => attrs, :prefix => prefix, :ns => namespaces}.inspect})" if @@debug
|
26
|
+
LOG.debug "START ELEM: (#{{:elem => elem, :attrs => attrs, :prefix => prefix, :uri => uri, :ns => namespaces}.inspect})" if @@debug
|
39
27
|
elem = "#{"#{prefix}:" if prefix}#{elem}"
|
40
28
|
e = XMPPNode.new elem
|
41
|
-
|
29
|
+
XML::Namespace.new(e, prefix, uri)
|
30
|
+
attrs.each { |k,v| e.attributes[k] = v if k }
|
42
31
|
|
43
32
|
if elem == 'stream:stream'
|
44
33
|
@receiver.receive e
|
@@ -56,23 +45,24 @@ module Stream # :nodoc:
|
|
56
45
|
end
|
57
46
|
|
58
47
|
def on_end_element_ns(elem, prefix, uri)
|
59
|
-
LOG.debug "END ELEM: #{{:elem => elem, :prefix => prefix, :uri => uri
|
48
|
+
LOG.debug "END ELEM: #{{:elem => elem, :prefix => prefix, :uri => uri}.inspect}" if @@debug
|
60
49
|
|
61
|
-
|
62
|
-
|
50
|
+
if !@current && "#{prefix}:#{elem}" =~ STREAM_REGEX
|
51
|
+
@receiver.receive XMPPNode.new('stream:end')
|
63
52
|
|
64
|
-
|
53
|
+
elsif @current.parent?
|
65
54
|
@current = @current.parent
|
66
55
|
|
67
56
|
else
|
68
57
|
c, @current = @current, nil
|
58
|
+
XML::Document.new.root = c
|
69
59
|
@receiver.receive c
|
70
60
|
|
71
61
|
end
|
62
|
+
end
|
72
63
|
|
73
|
-
|
74
|
-
|
75
|
-
end
|
64
|
+
def on_error(msg)
|
65
|
+
raise ParseError.new(msg.to_s)
|
76
66
|
end
|
77
67
|
end #Parser
|
78
68
|
|
@@ -1,49 +1,46 @@
|
|
1
1
|
module Blather # :nodoc:
|
2
|
-
|
2
|
+
class Stream # :nodoc:
|
3
3
|
|
4
|
-
class Resource # :nodoc:
|
4
|
+
class Resource < StreamHandler # :nodoc:
|
5
5
|
def initialize(stream, jid)
|
6
|
-
|
6
|
+
super stream
|
7
7
|
@jid = jid
|
8
|
-
@callbacks = {}
|
9
|
-
end
|
10
|
-
|
11
|
-
def success(&callback)
|
12
|
-
@callbacks[:success] = callback
|
13
|
-
end
|
14
|
-
|
15
|
-
def failure(&callback)
|
16
|
-
@callbacks[:failure] = callback
|
17
|
-
end
|
18
|
-
|
19
|
-
def receive(node)
|
20
|
-
@node = node
|
21
|
-
__send__(@node.element_name == 'iq' ? @node['type'] : @node.element_name)
|
22
8
|
end
|
23
9
|
|
10
|
+
private
|
11
|
+
##
|
12
|
+
# Respond to the bind request
|
13
|
+
# If @jid has a resource set already request it from the server
|
24
14
|
def bind
|
15
|
+
response = Stanza::Iq.new :set
|
16
|
+
@id = response.id
|
17
|
+
|
25
18
|
binder = XMPPNode.new('bind')
|
26
|
-
binder.
|
19
|
+
binder.namespace = 'urn:ietf:params:xml:ns:xmpp-bind'
|
27
20
|
|
28
21
|
binder << XMPPNode.new('resource', @jid.resource) if @jid.resource
|
29
22
|
|
30
|
-
response = Stanza::Iq.new :set
|
31
|
-
@id = response.id
|
32
23
|
response << binder
|
33
|
-
|
34
24
|
@stream.send response
|
35
25
|
end
|
36
26
|
|
27
|
+
##
|
28
|
+
# Process the result from the server
|
29
|
+
# Sets the sends the JID (now bound to a resource)
|
30
|
+
# back to the stream
|
37
31
|
def result
|
38
32
|
LOG.debug "RESOURE NODE #{@node}"
|
33
|
+
# ensure this is a response to our original request
|
39
34
|
if @id == @node['id']
|
40
|
-
@jid = JID.new @node.find_first('bind').
|
41
|
-
|
35
|
+
@jid = JID.new @node.find_first('bind/jid').content
|
36
|
+
success @jid
|
42
37
|
end
|
43
38
|
end
|
44
39
|
|
40
|
+
##
|
41
|
+
# Server returned an error
|
45
42
|
def error
|
46
|
-
|
43
|
+
failure StanzaError.import(@node)
|
47
44
|
end
|
48
45
|
end #Resource
|
49
46
|
|