Class: Vines::Router
- Inherits:
-
Object
- Object
- Vines::Router
- Defined in:
- lib/vines/router.rb
Overview
The router tracks all stream connections to the server for all clients, servers, and components. It sends stanzas to the correct stream based on the ‘to’ attribute. Router is a singleton, shared by all streams, that must be accessed with Router.instance
, not Router.new
.
Constant Summary collapse
- ROUTABLE_STANZAS =
%w[message iq presence].freeze
- STREAM_TYPES =
[:client, :server, :component].freeze
- @@instance =
nil
Class Method Summary collapse
Instance Method Summary collapse
-
#<<(connection) ⇒ Object
Add the connection to the routing table.
-
#available_resources(*jid) ⇒ Object
Returns streams for all available resources for this JID.
-
#connected_resources(jid) ⇒ Object
Returns streams for all connected resources for this JID.
-
#delete(connection) ⇒ Object
Remove the connection from the routing table.
-
#initialize ⇒ Router
constructor
A new instance of Router.
-
#interested_resources(*jid) ⇒ Object
Returns streams for all interested resources for this JID.
-
#local?(stanza) ⇒ Boolean
Returns true if this stanza should be processed locally.
- #local_jid?(jid) ⇒ Boolean
-
#route(stanza) ⇒ Object
Send the stanza to the appropriate remote server-to-server stream or an external component stream.
-
#size ⇒ Object
Returns the total number of streams connected to the server.
Constructor Details
#initialize ⇒ Router
Returns a new instance of Router.
23 24 25 26 27 |
# File 'lib/vines/router.rb', line 23 def initialize @config = nil @streams = Hash.new {|h,k| h[k] = [] } @pending = Hash.new {|h,k| h[k] = [] } end |
Class Method Details
.instance ⇒ Object
19 20 21 |
# File 'lib/vines/router.rb', line 19 def self.instance @@instance ||= self.new end |
Instance Method Details
#<<(connection) ⇒ Object
Add the connection to the routing table. The connection must return :client, :server, or :component from its stream_type
method so the router can properly route stanzas to the stream.
62 63 64 65 66 |
# File 'lib/vines/router.rb', line 62 def <<(connection) type = stream_type(connection) @config ||= connection.config @streams[type] << connection end |
#available_resources(*jid) ⇒ Object
Returns streams for all available resources for this JID. A resource is marked available after it sends initial presence. This method accepts a single JID or a list of JIDs.
42 43 44 45 46 47 |
# File 'lib/vines/router.rb', line 42 def available_resources(*jid) ids = jid.flatten.map {|jid| JID.new(jid). } clients.select do |stream| stream.available? && ids.include?(stream.user.jid.) end end |
#connected_resources(jid) ⇒ Object
Returns streams for all connected resources for this JID. A resource is considered connected after it has completed authentication and resource binding.
32 33 34 35 36 37 |
# File 'lib/vines/router.rb', line 32 def connected_resources(jid) jid = JID.new(jid) clients.select do |stream| stream.connected? && jid == (jid. ? stream.user.jid. : stream.user.jid) end end |
#delete(connection) ⇒ Object
Remove the connection from the routing table.
69 70 71 72 |
# File 'lib/vines/router.rb', line 69 def delete(connection) type = stream_type(connection) @streams[type].delete(connection) end |
#interested_resources(*jid) ⇒ Object
Returns streams for all interested resources for this JID. A resource is marked interested after it requests the roster. This method accepts a single JID or a list of JIDs.
52 53 54 55 56 57 |
# File 'lib/vines/router.rb', line 52 def interested_resources(*jid) ids = jid.flatten.map {|jid| JID.new(jid). } clients.select do |stream| stream.interested? && ids.include?(stream.user.jid.) end end |
#local?(stanza) ⇒ Boolean
Returns true if this stanza should be processed locally. Returns false if it’s destined for a remote domain or external component.
102 103 104 105 106 |
# File 'lib/vines/router.rb', line 102 def local?(stanza) return true unless ROUTABLE_STANZAS.include?(stanza.name) to = (stanza['to'] || '').strip to.empty? || local_jid?(to) end |
#local_jid?(jid) ⇒ Boolean
108 109 110 |
# File 'lib/vines/router.rb', line 108 def local_jid?(jid) @config.vhost?(JID.new(jid).domain) end |
#route(stanza) ⇒ Object
Send the stanza to the appropriate remote server-to-server stream or an external component stream.
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/vines/router.rb', line 76 def route(stanza) to, from = %w[to from].map {|attr| JID.new(stanza[attr]) } if stream = connection_to(to.domain) stream.write(stanza) elsif @pending.key?(to.domain) @pending[to.domain] << stanza elsif @config.s2s?(to.domain) @pending[to.domain] << stanza Vines::Stream::Server.start(@config, to.domain, from.domain) do |stream| if stream @pending[to.domain].each {|s| stream.write(s) } else @pending[to.domain].each do |s| xml = StanzaErrors::RemoteServerNotFound.new(s, 'cancel').to_xml connected_resources(s['from']).each {|c| c.write(xml) } end end @pending.delete(to.domain) end else raise StanzaErrors::RemoteServerNotFound.new(stanza, 'cancel') end end |
#size ⇒ Object
Returns the total number of streams connected to the server.
113 114 115 |
# File 'lib/vines/router.rb', line 113 def size @streams.values.inject(0) {|sum, arr| sum + arr.size } end |