Class: Vines::Stanza

Inherits:
Object
  • Object
show all
Includes:
Nokogiri::XML
Defined in:
lib/vines/stanza.rb,
lib/vines/stanza/iq.rb,
lib/vines/stanza/pubsub.rb,
lib/vines/stanza/iq/auth.rb,
lib/vines/stanza/iq/ping.rb,
lib/vines/stanza/message.rb,
lib/vines/stanza/iq/error.rb,
lib/vines/stanza/iq/query.rb,
lib/vines/stanza/iq/vcard.rb,
lib/vines/stanza/presence.rb,
lib/vines/stanza/iq/result.rb,
lib/vines/stanza/iq/roster.rb,
lib/vines/stanza/iq/session.rb,
lib/vines/stanza/iq/version.rb,
lib/vines/stanza/iq/disco_info.rb,
lib/vines/stanza/pubsub/create.rb,
lib/vines/stanza/pubsub/delete.rb,
lib/vines/stanza/iq/disco_items.rb,
lib/vines/stanza/presence/error.rb,
lib/vines/stanza/presence/probe.rb,
lib/vines/stanza/pubsub/publish.rb,
lib/vines/stanza/pubsub/subscribe.rb,
lib/vines/stanza/iq/private_storage.rb,
lib/vines/stanza/presence/subscribe.rb,
lib/vines/stanza/pubsub/unsubscribe.rb,
lib/vines/stanza/presence/subscribed.rb,
lib/vines/stanza/presence/unavailable.rb,
lib/vines/stanza/presence/unsubscribe.rb,
lib/vines/stanza/presence/unsubscribed.rb

Direct Known Subclasses

Iq, Message, Presence

Defined Under Namespace

Classes: Iq, Message, Presence, PubSub

Constant Summary collapse

EMPTY =
''.freeze
ROUTABLE_STANZAS =
%w[message iq presence].freeze
@@types =
{}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(node, stream) ⇒ Stanza

Returns a new instance of Stanza.



27
28
29
# File 'lib/vines/stanza.rb', line 27

def initialize(node, stream)
  @node, @stream = node, stream
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object



109
110
111
# File 'lib/vines/stanza.rb', line 109

def method_missing(method, *args, &block)
  @node.send(method, *args, &block)
end

Instance Attribute Details

#streamObject (readonly)

Returns the value of attribute stream.



7
8
9
# File 'lib/vines/stanza.rb', line 7

def stream
  @stream
end

Class Method Details

.from_node(node, stream) ⇒ Object



19
20
21
22
23
24
25
# File 'lib/vines/stanza.rb', line 19

def self.from_node(node, stream)
  # optimize common case
  return Message.new(node, stream) if node.name == MESSAGE
  found = @@types.select {|pair, v| node.xpath(*pair).any? }
    .sort {|a, b| b[0][0].length - a[0][0].length }.first
  found ? found[1].new(node, stream) : nil
end

.register(xpath, ns = {}) ⇒ Object



15
16
17
# File 'lib/vines/stanza.rb', line 15

def self.register(xpath, ns={})
  @@types[[xpath, ns]] = self
end

Instance Method Details

#broadcast(recipients) ⇒ Object

Send the stanza to all recipients, stamping it with from and to addresses first.



33
34
35
36
37
38
39
# File 'lib/vines/stanza.rb', line 33

def broadcast(recipients)
  @node[FROM] = stream.user.jid.to_s
  recipients.each do |recipient|
    @node[TO] = recipient.user.jid.to_s
    recipient.write(@node)
  end
end

#local?Boolean

Returns true if this stanza should be processed locally. Returns false if it’s destined for a remote domain or external component.

Returns:

  • (Boolean)


43
44
45
46
47
# File 'lib/vines/stanza.rb', line 43

def local?
  return true unless ROUTABLE_STANZAS.include?(@node.name)
  to = JID.new(@node[TO])
  to.empty? || local_jid?(to)
end

#local_jid?(*jids) ⇒ Boolean

Returns:

  • (Boolean)


49
50
51
# File 'lib/vines/stanza.rb', line 49

def local_jid?(*jids)
  stream.config.local_jid?(*jids)
end

#processObject



73
74
75
# File 'lib/vines/stanza.rb', line 73

def process
  raise 'subclass must implement'
end

#routeObject



61
62
63
# File 'lib/vines/stanza.rb', line 61

def route
  stream.router.route(@node)
end

#routerObject



65
66
67
# File 'lib/vines/stanza.rb', line 65

def router
  stream.router
end

#send_unavailable(from, to) ⇒ Object

Broadcast unavailable presence from the user’s available resources to the recipient’s available resources. Route the stanza to a remote server if the recipient isn’t hosted locally.



80
81
82
83
84
# File 'lib/vines/stanza.rb', line 80

def send_unavailable(from, to)
  available = router.available_resources(from, to)
  stanzas = available.map {|stream| unavailable(stream.user.jid) }
  broadcast_to_available_resources(stanzas, to)
end

#storage(domain = stream.domain) ⇒ Object



69
70
71
# File 'lib/vines/stanza.rb', line 69

def storage(domain=stream.domain)
  stream.storage(domain)
end

#to_pubsub_domain?Boolean

Return true if this stanza is addressed to a pubsub subdomain hosted at this server. This helps differentiate between IQ stanzas addressed to the server and stanzas addressed to pubsub domains, both of which must be handled locally and not routed.

Returns:

  • (Boolean)


57
58
59
# File 'lib/vines/stanza.rb', line 57

def to_pubsub_domain?
  stream.config.pubsub?(validate_to)
end

#unavailable(from) ⇒ Object

Return an unavailable presence stanza addressed from the given JID.



87
88
89
90
91
92
93
# File 'lib/vines/stanza.rb', line 87

def unavailable(from)
  doc = Document.new
  doc.create_element('presence',
    'from' => from.to_s,
    'id'   => Kit.uuid,
    'type' => 'unavailable')
end

#validate_fromObject

Return nil if this stanza has no ‘from’ attribute. Return a Vines::JID if it contains a valid ‘from’ attribute. Raise a JidMalformed error if the JID is invalid.



105
106
107
# File 'lib/vines/stanza.rb', line 105

def validate_from
  validate_address(FROM)
end

#validate_toObject

Return nil if this stanza has no ‘to’ attribute. Return a Vines::JID if it contains a valid ‘to’ attribute. Raise a JidMalformed error if the JID is invalid.



98
99
100
# File 'lib/vines/stanza.rb', line 98

def validate_to
  validate_address(TO)
end