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