Class Skates::ComponentConnection
In: lib/skates/component_connection.rb
Parent: XmppConnection

ComponentConnection is in charge of the XMPP connection itself. Upon stanza reception, and depending on the status (connected… etc), this component will handle or forward the stanzas.

Methods

Public Class methods

[Source]

    # File lib/skates/component_connection.rb, line 7
 7:     def self.connect(params, handler)
 8:       params["host"] ||= params["jid"]
 9:       super(params, handler)
10:     end

Creates a new ComponentConnection and waits for data in the stream

[Source]

    # File lib/skates/component_connection.rb, line 14
14:     def initialize(params)
15:       super(params)
16:       @state = :wait_for_stream
17:     end

Resolution for Components, based on SRV records

[Source]

     # File lib/skates/component_connection.rb, line 82
 82:     def self.resolve(host, &block)
 83:       Resolv::DNS.open { |dns|
 84:         # If ruby version is too old and SRV is unknown, this will raise a NameError
 85:         # which is caught below
 86:         Skates.logger.debug {
 87:           "RESOLVING: #{host} "
 88:         }
 89:         found = false
 90:         records = dns.getresources(host, Resolv::DNS::Resource::IN::A)
 91:         records.each do |record|
 92:           ip = record.address.to_s
 93:           if block.call({"host" => ip}) 
 94:             found = true
 95:             break
 96:           end
 97:         end
 98:         block.call(false) unless found # bleh, we couldn't resolve to any valid. Too bad.
 99:       }
100:     end

Public Instance methods

Connection_completed is called when the connection (socket) has been established and is in charge of "building" the XML stream to establish the XMPP connection itself. We use a "tweak" here to send only the starting tag of stream:stream

[Source]

    # File lib/skates/component_connection.rb, line 23
23:     def connection_completed
24:       super
25:       doc = Nokogiri::XML::Document.new 
26:       stream = Nokogiri::XML::Node.new("stream:stream", doc)
27:       stream["xmlns"] = stream_namespace
28:       stream["xmlns:stream"] = "http://etherx.jabber.org/streams"
29:       stream["to"] = jid
30:       doc.add_child(stream)
31:       paste_content_here= Nokogiri::XML::Node.new("paste_content_here", doc)
32:       stream.add_child(paste_content_here)
33:       start, stop = doc.to_xml.split('<paste_content_here/>')
34:       send_xml(start)
35:     end

XMPP Component handshake as defined in XEP-0114: xmpp.org/extensions/xep-0114.html

[Source]

    # File lib/skates/component_connection.rb, line 40
40:     def receive_stanza(stanza)
41:       case @state
42:       when :connected # Most frequent case
43:           super(stanza) # Can be dispatched
44:           
45:       when :wait_for_stream
46:         if stanza.name == "stream:stream" && stanza.attributes['id']
47:           # This means the XMPP session started!
48:           # We must send the handshake now.
49:           send_xml(handshake(stanza))
50:           @state = :wait_for_handshake
51:         else
52:           raise
53:         end
54: 
55:       when :wait_for_handshake
56:         if stanza.name == "handshake"
57:           begin
58:             @handler.on_connected(self) if @handler and @handler.respond_to?("on_connected")
59:           rescue
60:             Skates.logger.error {
61:               "on_connected failed : #{$!}\n#{$!.backtrace.join("\n")}"
62:             }
63:           end
64:           @state = :connected
65:         elsif stanza.name == "stream:error"
66:           raise AuthenticationError
67:         else
68:           raise
69:         end
70: 
71:       end
72:     end

Namespace of the component

[Source]

    # File lib/skates/component_connection.rb, line 76
76:     def stream_namespace
77:       'jabber:component:accept'
78:     end

[Validate]