I'm not sure if this is a Mac-only problem or what, but we were getting incompatible-function-pointer errors when trying to build the RocketAMF C extensions. This fixes that! (Maybe it's like, Mac-only but as of Ruby 3.4 in specific? We're running RocketAMF in production on Ruby 3.4 right now without this. Shrug.)
214 lines
No EOL
5.6 KiB
Ruby
214 lines
No EOL
5.6 KiB
Ruby
module RocketAMF
|
|
module Values #:nodoc:
|
|
# Base class for all special AS3 response messages. Maps to
|
|
# <tt>flex.messaging.messages.AbstractMessage</tt>.
|
|
class AbstractMessage
|
|
EXTERNALIZABLE_FIELDS = [
|
|
%w[ body clientId destination headers messageId timestamp timeToLive ],
|
|
%w[ clientIdBytes messageIdBytes ]
|
|
]
|
|
attr_accessor :clientId
|
|
attr_accessor :destination
|
|
attr_accessor :messageId
|
|
attr_accessor :timestamp
|
|
attr_accessor :timeToLive
|
|
attr_accessor :headers
|
|
attr_accessor :body
|
|
|
|
def clientIdBytes= bytes
|
|
@clientId = pretty_uuid(bytes) unless bytes.nil?
|
|
end
|
|
|
|
def messageIdBytes= bytes
|
|
@messageId = pretty_uuid(bytes) unless bytes.nil?
|
|
end
|
|
|
|
def read_external des
|
|
read_external_fields des, EXTERNALIZABLE_FIELDS
|
|
end
|
|
|
|
private
|
|
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
|
|
|
|
def pretty_uuid bytes
|
|
"%08x-%04x-%04x-%04x-%08x%04x" % bytes.string.unpack("NnnnNn")
|
|
end
|
|
|
|
def read_external_fields des, fields
|
|
# Read flags
|
|
flags = []
|
|
loop do
|
|
flags << des.source.read(1).unpack('C').first
|
|
break if flags.last < 128
|
|
end
|
|
|
|
# Read fields and any remaining unmapped fields in a byte-set
|
|
fields.each_with_index do |list, i|
|
|
break if flags[i].nil?
|
|
|
|
list.each_with_index do |name, j|
|
|
if flags[i] & 2**j != 0
|
|
send("#{name}=", des.read_object)
|
|
end
|
|
end
|
|
|
|
# Read remaining flags even though we don't recognize them
|
|
# Zero out high bit, as it's the has-next-field marker
|
|
f = (flags[i] & ~128) >> list.length
|
|
while f > 0
|
|
des.read_object if (f & 1) != 0
|
|
f >>= 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
# Maps to <tt>flex.messaging.messages.RemotingMessage</tt>
|
|
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
|
|
|
|
def initialize
|
|
@clientId = nil
|
|
@destination = nil
|
|
@messageId = rand_uuid
|
|
@timestamp = Time.new.to_i*100
|
|
@timeToLive = 0
|
|
@headers = {}
|
|
@body = nil
|
|
end
|
|
end
|
|
|
|
# Maps to <tt>flex.messaging.messages.AsyncMessage</tt>
|
|
class AsyncMessage < AbstractMessage
|
|
EXTERNALIZABLE_FIELDS = [
|
|
%w[ correlationId correlationIdBytes]
|
|
]
|
|
attr_accessor :correlationId
|
|
|
|
def correlationIdBytes= bytes
|
|
@correlationId = pretty_uuid(bytes) unless bytes.nil?
|
|
end
|
|
|
|
def read_external des
|
|
super des
|
|
read_external_fields des, EXTERNALIZABLE_FIELDS
|
|
end
|
|
end
|
|
|
|
class AsyncMessageExt < AsyncMessage #:nodoc:
|
|
end
|
|
|
|
# Maps to <tt>flex.messaging.messages.CommandMessage</tt>
|
|
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
|
|
|
|
EXTERNALIZABLE_FIELDS = [
|
|
%w[ operation ]
|
|
]
|
|
attr_accessor :operation
|
|
|
|
def initialize
|
|
@operation = UNKNOWN_OPERATION
|
|
end
|
|
|
|
def read_external des
|
|
super des
|
|
read_external_fields des, EXTERNALIZABLE_FIELDS
|
|
end
|
|
end
|
|
|
|
class CommandMessageExt < CommandMessage #:nodoc:
|
|
end
|
|
|
|
# Maps to <tt>flex.messaging.messages.AcknowledgeMessage</tt>
|
|
class AcknowledgeMessage < AsyncMessage
|
|
EXTERNALIZABLE_FIELDS = [[]]
|
|
|
|
def initialize message=nil
|
|
@clientId = rand_uuid
|
|
@destination = nil
|
|
@messageId = rand_uuid
|
|
@timestamp = Time.new.to_i*100
|
|
@timeToLive = 0
|
|
@headers = {}
|
|
@body = nil
|
|
|
|
if message.is_a?(AbstractMessage)
|
|
@correlationId = message.messageId
|
|
end
|
|
end
|
|
|
|
def read_external des
|
|
super des
|
|
read_external_fields des, EXTERNALIZABLE_FIELDS
|
|
end
|
|
end
|
|
|
|
class AcknowledgeMessageExt < AcknowledgeMessage #:nodoc:
|
|
end
|
|
|
|
# Maps to <tt>flex.messaging.messages.ErrorMessage</tt> in AMF3 mode
|
|
class ErrorMessage < AcknowledgeMessage
|
|
# Extended data that will facilitate custom error processing on the client
|
|
attr_accessor :extendedData
|
|
|
|
# The fault code for the error, which defaults to the class name of the
|
|
# causing exception
|
|
attr_accessor :faultCode
|
|
|
|
# Detailed description of what caused the error
|
|
attr_accessor :faultDetail
|
|
|
|
# A simple description of the error
|
|
attr_accessor :faultString
|
|
|
|
# Optional "root cause" of the error
|
|
attr_accessor :rootCause
|
|
|
|
def initialize message=nil, exception=nil
|
|
super message
|
|
|
|
unless exception.nil?
|
|
@e = exception
|
|
@faultCode = @e.class.name
|
|
@faultDetail = @e.backtrace.join("\n")
|
|
@faultString = @e.message
|
|
end
|
|
end
|
|
|
|
def encode_amf serializer
|
|
if serializer.version == 0
|
|
data = {
|
|
:faultCode => @faultCode,
|
|
:faultDetail => @faultDetail,
|
|
:faultString => @faultString
|
|
}
|
|
serializer.write_object(data)
|
|
else
|
|
serializer.write_object(self)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end |