Skip to content

Commit

Permalink
Try features in our preferred order
Browse files Browse the repository at this point in the history
Instead of trying them in source order, which the RFC says is not meant
to be important. This prevents, for example, trying to register on a
server we already have an account and lets us always try authenticating first.
  • Loading branch information
singpolyma committed Jun 2, 2024
1 parent 03f9cda commit 8ede462
Showing 1 changed file with 14 additions and 9 deletions.
23 changes: 14 additions & 9 deletions lib/blather/stream/features.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,36 +16,41 @@ def initialize(stream, succeed, fail)
@stream, @succeed, @fail = stream, succeed, fail
end

# Fetures may appear in the XML in any order, but sometimes
# we might prefer to try some first if present
FEATURE_SCORES = {
"urn:ieft:params:xml:ns:xmpp-tls" => 0,
"urn:ieft:params:xml:ns:xmpp-bind" => 1,
"urn:ieft:params:xml:ns:xmpp-session" => 1,
"urn:ietf:params:xml:ns:xmpp-sasl" => 2
}.freeze

def receive_data(stanza)
if @feature
@feature.receive_data stanza
else
@features ||= stanza
@use_next =
@features.children
.map { |el| el.namespaces['xmlns'] }.compact
.sort { |x, y| FEATURE_SCORES.fetch(x, FEATURE_SCORES.length) <=> FEATURE_SCORES.fetch(y, FEATURE_SCORES.length) }
next!
end
end

def next!
if starttls = @features.at_xpath("tls:starttls",{"tls" => "urn:ietf:params:xml:ns:xmpp-tls"})
@feature = TLS.new(@stream, nil, @fail)
@feature.receive_data(starttls)
return
end

bind = @features.at_xpath('ns:bind', ns: 'urn:ietf:params:xml:ns:xmpp-bind')
session = @features.at_xpath('ns:session', ns: 'urn:ietf:params:xml:ns:xmpp-session')
if bind && session && @features.children.last != session
bind.after session
end

@idx = @idx ? @idx+1 : 0
if stanza = @features.children[@idx]
if (stanza = @features.at_xpath('ns:*', ns: @use_next.shift))
if stanza.namespaces['xmlns'] && (klass = self.class.from_namespace(stanza.namespaces['xmlns']))
@feature = klass.new(
@stream,
proc {
if (klass == Blather::Stream::Register && stanza = feature?(:mechanisms))
@idx = @features.children.index(stanza)
@feature = Blather::Stream::SASL.new @stream, proc { next! }, @fail
@feature.receive_data stanza
else
Expand Down

0 comments on commit 8ede462

Please sign in to comment.