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.)
117 lines
No EOL
3.9 KiB
Ruby
117 lines
No EOL
3.9 KiB
Ruby
require 'rocketamf/pure/io_helpers'
|
|
|
|
module RocketAMF
|
|
module Pure
|
|
# Included into RocketAMF::Envelope, this module replaces the
|
|
# populate_from_stream and serialize methods with actual working versions
|
|
module Envelope
|
|
# Included into RocketAMF::Envelope, this method handles deserializing an
|
|
# AMF request/response into the envelope
|
|
def populate_from_stream stream, class_mapper=nil
|
|
stream = StringIO.new(stream) unless StringIO === stream
|
|
des = Deserializer.new(class_mapper || RocketAMF::ClassMapper.new)
|
|
des.source = stream
|
|
|
|
# Initialize
|
|
@amf_version = 0
|
|
@headers = {}
|
|
@messages = []
|
|
|
|
# Read AMF version
|
|
@amf_version = read_word16_network stream
|
|
|
|
# Read in headers
|
|
header_count = read_word16_network stream
|
|
0.upto(header_count-1) do
|
|
name = stream.read(read_word16_network(stream))
|
|
name.force_encoding("UTF-8") if name.respond_to?(:force_encoding)
|
|
|
|
must_understand = read_int8(stream) != 0
|
|
|
|
length = read_word32_network stream
|
|
data = des.deserialize(0, nil)
|
|
|
|
@headers[name] = RocketAMF::Header.new(name, must_understand, data)
|
|
end
|
|
|
|
# Read in messages
|
|
message_count = read_word16_network stream
|
|
0.upto(message_count-1) do
|
|
target_uri = stream.read(read_word16_network(stream))
|
|
target_uri.force_encoding("UTF-8") if target_uri.respond_to?(:force_encoding)
|
|
|
|
response_uri = stream.read(read_word16_network(stream))
|
|
response_uri.force_encoding("UTF-8") if response_uri.respond_to?(:force_encoding)
|
|
|
|
length = read_word32_network stream
|
|
data = des.deserialize(0, nil)
|
|
if data.is_a?(Array) && data.length == 1 && data[0].is_a?(::RocketAMF::Values::AbstractMessage)
|
|
data = data[0]
|
|
end
|
|
|
|
@messages << RocketAMF::Message.new(target_uri, response_uri, data)
|
|
end
|
|
|
|
self
|
|
end
|
|
|
|
# Included into RocketAMF::Envelope, this method handles serializing an
|
|
# AMF request/response into a string
|
|
def serialize class_mapper=nil
|
|
ser = Serializer.new(class_mapper || RocketAMF::ClassMapper.new)
|
|
stream = ser.stream
|
|
|
|
# Write version
|
|
stream << pack_int16_network(@amf_version)
|
|
|
|
# Write headers
|
|
stream << pack_int16_network(@headers.length) # Header count
|
|
@headers.each_value do |h|
|
|
# Write header name
|
|
name_str = h.name
|
|
name_str.encode!("UTF-8").force_encoding("ASCII-8BIT") if name_str.respond_to?(:encode)
|
|
stream << pack_int16_network(name_str.bytesize)
|
|
stream << name_str
|
|
|
|
# Write must understand flag
|
|
stream << pack_int8(h.must_understand ? 1 : 0)
|
|
|
|
# Serialize data
|
|
stream << pack_word32_network(-1) # length of data - -1 if you don't know
|
|
ser.serialize(0, h.data)
|
|
end
|
|
|
|
# Write messages
|
|
stream << pack_int16_network(@messages.length) # Message count
|
|
@messages.each do |m|
|
|
# Write target_uri
|
|
uri_str = m.target_uri
|
|
uri_str.encode!("UTF-8").force_encoding("ASCII-8BIT") if uri_str.respond_to?(:encode)
|
|
stream << pack_int16_network(uri_str.bytesize)
|
|
stream << uri_str
|
|
|
|
# Write response_uri
|
|
uri_str = m.response_uri
|
|
uri_str.encode!("UTF-8").force_encoding("ASCII-8BIT") if uri_str.respond_to?(:encode)
|
|
stream << pack_int16_network(uri_str.bytesize)
|
|
stream << uri_str
|
|
|
|
# Serialize data
|
|
stream << pack_word32_network(-1) # length of data - -1 if you don't know
|
|
if @amf_version == 3
|
|
stream << AMF0_AMF3_MARKER
|
|
ser.serialize(3, m.data)
|
|
else
|
|
ser.serialize(0, m.data)
|
|
end
|
|
end
|
|
|
|
stream
|
|
end
|
|
|
|
private
|
|
include RocketAMF::Pure::ReadIOHelpers
|
|
include RocketAMF::Pure::WriteIOHelpers
|
|
end
|
|
end
|
|
end |