module AMF
module Messages #:nodoc:
# Base class for all special AS3 response messages. Maps to
# flex.messaging.messages.AbstractMessage
class AbstractMessage
attr_accessor :client_id
attr_accessor :destination
attr_accessor :message_id
attr_accessor :timestamp
attr_accessor :time_to_live
attr_accessor :headers
attr_accessor :body
def to_amf(options = {})
options[:amf_version] ||= 3
options[:serializable_names] = (self.public_methods - Object.new.public_methods).delete_if { |elm| elm =~ /to_amf|body|.*=/ }
AMF.serialize(self, options) do |s|
if body
s.write_utf8_vr("body")
s.stream << body
end
end
end
protected
def rand_uuid
[8,4,4,4,12].map {|n| rand_hex_3(n)}.join('-').to_s
end
def rand_hex_3(l)
"%0#{l}x" % rand(1 << l*4)
end
end
# Maps to flex.messaging.messages.RemotingMessage
class RemotingMessage < AbstractMessage
# The name of the service to be called including package name
attr_accessor :source
# The name of the method to be called
attr_accessor :operation
# The arguments to call the method with
attr_accessor :parameters
def initialize
@client_id = rand_uuid
@destination = nil
@message_id = rand_uuid
@timestamp = Time.new.to_i*100
@time_to_live = 0
@headers = {}
@body = nil
end
end
# Maps to flex.messaging.messages.AsyncMessage
class AsyncMessage < AbstractMessage
attr_accessor :correlation_id
end
# Maps to flex.messaging.messages.CommandMessage
class CommandMessage < AsyncMessage
SUBSCRIBE_OPERATION = 0
UNSUSBSCRIBE_OPERATION = 1
POLL_OPERATION = 2
CLIENT_SYNC_OPERATION = 4
CLIENT_PING_OPERATION = 5
CLUSTER_REQUEST_OPERATION = 7
LOGIN_OPERATION = 8
LOGOUT_OPERATION = 9
SESSION_INVALIDATE_OPERATION = 10
MULTI_SUBSCRIBE_OPERATION = 11
DISCONNECT_OPERATION = 12
UNKNOWN_OPERATION = 10000
attr_accessor :operation
def initialize
@operation = UNKNOWN_OPERATION
end
end
# Maps to flex.messaging.messages.AcknowledgeMessage
class AcknowledgeMessage < AsyncMessage
def initialize(message = nil)
@client_id = rand_uuid
@destination = nil
@message_id = rand_uuid
@timestamp = Time.new.to_i*100
@time_to_live = 0
@headers = {}
@body = nil
if message.is_a?(AbstractMessage)
@correlation_id = message.message_id
end
end
end
# Maps to flex.messaging.messages.ErrorMessage in AMF3 mode
class ErrorMessage < AcknowledgeMessage
# Extended data that will facilitate custom error processing on the client
attr_accessor :extended_data
# The fault code for the error, which defaults to the class name of the
# causing exception
attr_accessor :fault_code
# Detailed description of what caused the error
attr_accessor :fault_detail
# A simple description of the error
attr_accessor :fault_string
# Optional "root cause" of the error
attr_accessor :root_cause
def initialize message, exception
super message
@e = exception
@fault_code = @e.class.name
@fault_detail = @e.backtrace.join("\n")
@fault_string = @e.message
end
def to_amf serializer
stream = ""
# if serializer.version == 0
# data = {
# :faultCode => @faultCode,
# :faultDetail => @faultDetail,
# :faultString => @faultString
# }
# serializer.write_hash(data, stream)
# else
# serializer.write_object(self, stream)
# end
stream
end
end
end
end