1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
|
# =XMPP4R - XMPP Library for Ruby
# License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
# Website::http://xmpp4r.github.io
require 'xmpp4r/iq'
require 'xmpp4r/discovery/iq/discoinfo'
require 'xmpp4r/discovery/iq/discoitems'
require 'xmpp4r/caps/helper/generator'
module Jabber
module Discovery
##
# Responds to Service Discovery queries on a given node
#
# Modify returned elements by these attributes:
# * Responder#identities
# * Responder#features (Responder#add_features is a short-cut accepting an Array of Strings, too)
# * Responder#forms
# * Responder#items
class Responder
##
# Service Discovery node this Responder is responsible for
# (will not answer queries for other nodes)
attr_reader :node
##
# Identities returned on Discovery Info query
#
# Array of [Discovery::Identity]
attr_accessor :identities
##
# Features returned on Discovery Info query,
#
# Array of [Discovery::Feature]
attr_accessor :features
##
# Forms returned on Discovery Info query
# (such as Software Information)
#
# Array of [Dataforms::XData]
attr_accessor :forms
##
# Children returned on Discovery Item query
#
# May contain other Discovery::Responder instances
# which will generate an item dynamically from their
# first identity
#
# Array of [Discovery::Item] or [Discovery::Responder] (mixed)
attr_accessor :items
##
# Set the JID this helper feels responsible for
# (default: nil, responsible for any JID)
attr_accessor :my_jid
CALLBACK_PRIORITY = 180
##
# Initialize responder for a specific node
# stream:: [Jabber::Stream]
# node:: [nil] or [String]
def initialize(stream, node=nil, identities=[], features=[], items=[])
@stream = stream
@my_jid = nil
@node = node
@identities = identities
@features = []
add_features(features)
@forms = []
@items = items
@stream.add_iq_callback(CALLBACK_PRIORITY, self) do |iq|
my_nodes = [@node, "#{@node}##{generate_ver}"]
if iq.type == :get and
iq.query.kind_of? IqQueryDiscoInfo and
my_nodes.include?(iq.query.node)
answer = iq.answer(false)
answer.type = :result
query = answer.add(IqQueryDiscoInfo.new)
query.node = iq.query.node
(@identities + @features + @forms).each do |element|
query.add(element)
end
@stream.send(answer)
true # handled
elsif iq.type == :get and
iq.query.kind_of? IqQueryDiscoItems and
my_nodes.include?(iq.query.node)
answer = iq.answer(false)
answer.type = :result
query = answer.add(IqQueryDiscoItems.new)
query.node = iq.query.node
@items.each do |item|
if item.kind_of? Responder
query.add(item.generate_item)
else
query.add(item)
end
end
@stream.send(answer)
true # handled
else
false # not handled
end
end
end
##
# Add a feature
# feature:: [Jabber::Discovery::Feature] or [String]
def add_feature(feature)
if feature.kind_of? Feature
@features << feature
else
@features << Feature.new(feature.to_s)
end
end
##
# Add a series of features
# features:: Array of [Jabber::Discovery::Feature] or [String]
def add_features(features)
features.each { |feature|
add_feature(feature)
}
end
##
# Generate a XEP-0115: Entity Capabilities <c/> element
# for inclusion in Presence stanzas. This enables efficient
# caching of Service Discovery information.
def generate_caps
Caps::C.new(@node, generate_ver)
end
##
# Generate an item for inclusion in items discovery in other
# responders
# return:: [Discovery::Item] or nil
def generate_item
i = @identities.first
if i
Item.new(@my_jid || @stream.jid, i.iname, @node)
else
nil
end
end
private
def generate_ver
Caps::generate_ver(@identities, @features, @forms)
end
end
end
end
|