Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

165 lines (131 sloc) 3.841 kb
module Sails
# Represents a server, remote or local, and tracks certificates, waves, and the
# queue of packets to send to a server once a connection is established.
class Server
attr_accessor :provider, :certificates, :certificate_hash, :domain, :jids, :jid, :waves, :queue, :state, :users, :record
# Create a new server.
def initialize(provider, domain, jid=nil, init=true)
@provider = provider
@domain = domain
@jid = jid
@jids = []
@waves = {}
@users = {}
@queue = []
@state = :uninited
@certificates = []
@record = ::Server.find_by_domain domain
@record ||= ::Server.find_by_jid jid || domain
@record ||= ::Server.create :domain => domain, :jid => jid
@certificate_hash = Utils.decode64 @record.signer_id if @record.signer_id
@jid = @record.jid if @record.jid && @jid.nil?
provider.servers << self
disco 'items' if init
load_waves
end
def load_waves
return unless @record
@record.waves.each do |wave_rec|
wave = @provider.find_or_create_wave wave_rec.conv_root_path
wave_rec.deltas.each do |delta_rec|
Delta.from_record wave, delta_rec
end
end
end
def certificate= cert
self.certificates = [cert]
end
# Sets the certificate and generates a SHA2 hash in ASN.1/DER format, ready
# to send to remote servers.
def certificates= certs
@certificates = certs.map do |cert|
if cert.is_a? String
cert = OpenSSL::X509::Certificate.new Utils.format_x509(cert)
end
cert
end
sequence = OpenSSL::ASN1::Sequence.new(@certificates.reverse)
@certificate_hash = Utils::sha2 sequence.to_der
@record.signer_id = Utils.encode64 @certificate_hash
@record.save if @record.changed?
@certificate_hash
end
# Returns Base64-encoded certificates, ready for sending in XML packets.
def certificates64
@certificates.map {|cert| Utils::encode64 cert.to_der }
end
def certificate_xml
certificates64.map do |cert|
"<certificate><![CDATA[#{cert}]]></certificate>"
end.join ''
end
# Sets the server name.
def jid= jid
@provider.servers.delete @jid unless !@jid || @jid == @domain
@provider.servers[jid] = self
@record.jid = jid
@record.save if @record.changed?
@jid = jid
return unless @state == :listing
@state = :details
ping
@jid
end
# Look up a wave.
#
# Must be passed only the name, i.e. you must pass "meep" to get meep. No
# domains will be handled.
def [](name)
@waves[name]
end
# Add a wave to the server's listing -or- queue/send a packet.
def << item
if item.is_a? Array # packet
if @state == :ready
@provider.send item[0], item[1], @jid, item[2], item[3]
else
@queue << item
end
elsif item.is_a? Wave
@waves[item.name] = item
elsif item.is_a? WaveUser
@users[item.username] = item
else
raise ArgumentError, 'expected an Array (packet) or Wave'
end
end
# Send the queue out (state must be :ready)
def flush
p queue
return false unless @state == :ready && @provider.ready?
return nil unless @queue && @queue.any?
p :MEEEP
@queue.each do |packet|
@provider.send packet[0], packet[1], @jid, packet[2], packet[3]
end
@queue = nil
end
def ready!
@state = :ready
flush
end
# Create a unique wave name, accross all waves known to this server
def random_wave_name(length=12)
name = Utils.random_string(length)
name = Utils.random_string(length) while self[name]
name
end
def disco dance, jid=nil
target = jid || (dance == 'items' ? @domain : @jid)
@provider.disco target, dance
end
def ping
@provider.queue 'message', 'normal', @jid || @domain, '<ping xmlns="http://waveprotocol.org/protocol/0.2/waveserver"/><request xmlns="urn:xmpp:receipts"/>'
end
def disco_jids
p @state
@state = :listing
@jids.each {|jid| disco 'info', jid }
end
end # class
end # module
Jump to Line
Something went wrong with that request. Please try again.