Module: RocketAMF

Defined in:
lib/rocketamf.rb,
lib/rocketamf/pure.rb,
lib/rocketamf/remoting.rb,
lib/rocketamf/constants.rb,
lib/rocketamf/class_mapping.rb,
lib/rocketamf/pure/remoting.rb,
lib/rocketamf/pure/io_helpers.rb,
lib/rocketamf/pure/serializer.rb,
lib/rocketamf/values/messages.rb,
lib/rocketamf/pure/deserializer.rb,
lib/rocketamf/values/typed_hash.rb,
lib/rocketamf/values/array_collection.rb

Overview

RocketAMF is a full featured AMF0/3 serializer and deserializer with support for Flash -> Ruby and Ruby -> Flash class mapping, custom serializers, remoting gateway helpers that follow AMF0/3 messaging specs, and a suite of specs to ensure adherence to the specification documents put out by Adobe.

Serialization & Deserialization

RocketAMF provides two main methods - RocketAMF.serialize(obj, amf_version=0) and RocketAMF.deserialize(source, amf_version=0). To use, simple pass in the string to deserialize and the version if different from the default. To serialize an object, simply call RocketAMF.serialize with the object and the proper version. If you’re working only with AS3, it is more effiecient to use the version 3 encoding, as it caches duplicate string to reduce serialized size. However for greater compatibility the default, AMF version 0, should work fine.

Mapping Classes Between Flash and Ruby

RocketAMF provides a simple class mapping tool to facilitate serialization and deserialization of typed objects. Refer to the documentation of RocketAMF::ClassMapping for more details. If the provided class mapping tool is not sufficient for your needs, you also have the option to replace it with a class mapper of your own devising that matches the documented API.

Remoting

You can use RocketAMF bare to write an AMF gateway using the following code. In addition, you can use rack-amf (github.com/warhammerkid/rack-amf) which simplifies the code necessary to set up a functioning AMF gateway.

# helloworld.ru
require 'rocketamf'

class HelloWorldApp
  APPLICATION_AMF = 'application/x-amf'.freeze

  def call env
    if is_amf?(env)
      # Wrap request and response
      env['rack.input'].rewind
      request = RocketAMF::Envelope.new.populate_from_stream(env['rack.input'].read)
      response = RocketAMF::Envelope.new

      # Handle request
      response.each_method_call request do |method, args|
        raise "Service #{method} does not exists" unless method == 'App.helloWorld'
        'Hello world'
      end

      # Pass back response
      response_str = response.serialize
      return [200, {'Content-Type' => APPLICATION_AMF, 'Content-Length' => response_str.length.to_s}, [response_str]]
    else
      return [200, {'Content-Type' => 'text/plain', 'Content-Length' => '16' }, ["Rack AMF gateway"]]
    end
  end

  private
  def is_amf? env
    return false unless env['CONTENT_TYPE'] == APPLICATION_AMF
    return false unless env['PATH_INFO'] == '/amf'
    return true
  end
end

run HelloWorldApp.new

Defined Under Namespace

Modules: Pure, Values Classes: AMFError, ClassMapping, Envelope, Header, Message, Request, Response

Constant Summary collapse

Deserializer =

:stopdoc: Import deserializer

RocketAMF::Pure::Deserializer
AMF3Deserializer =
RocketAMF::Pure::AMF3Deserializer
Serializer =

Import serializer

RocketAMF::Pure::Serializer
AMF3Serializer =
RocketAMF::Pure::AMF3Serializer
AMF0_NUMBER_MARKER =

AMF0 Type Markers

0x00
AMF0_BOOLEAN_MARKER =

“000”

0x01
AMF0_STRING_MARKER =

“001”

0x02
AMF0_OBJECT_MARKER =

“002”

0x03
AMF0_MOVIE_CLIP_MARKER =

“003”

0x04
AMF0_NULL_MARKER =

“004” # Unused

0x05
AMF0_UNDEFINED_MARKER =

“005”

0x06
AMF0_REFERENCE_MARKER =

“006”

0x07
AMF0_HASH_MARKER =

“a”

0x08
AMF0_OBJECT_END_MARKER =

“b”

0x09
AMF0_STRICT_ARRAY_MARKER =

“t”

0x0A
AMF0_DATE_MARKER =

“n”

0x0B
AMF0_LONG_STRING_MARKER =

“v”

0x0C
AMF0_UNSUPPORTED_MARKER =

“f”

0x0D
AMF0_RECORDSET_MARKER =

“r”

0x0E
AMF0_XML_MARKER =

“016” # Unused

0x0F
AMF0_TYPED_OBJECT_MARKER =

“017”

0x10
AMF0_AMF3_MARKER =

“020”

0x11
AMF3_UNDEFINED_MARKER =

AMF3 Type Markers

0x00
AMF3_NULL_MARKER =

“000”

0x01
AMF3_FALSE_MARKER =

“001”

0x02
AMF3_TRUE_MARKER =

“002”

0x03
AMF3_INTEGER_MARKER =

“003”

0x04
AMF3_DOUBLE_MARKER =

“004”

0x05
AMF3_STRING_MARKER =

“005”

0x06
AMF3_XML_DOC_MARKER =

“006”

0x07
AMF3_DATE_MARKER =

“a”

0x08
AMF3_ARRAY_MARKER =

“b”

0x09
AMF3_OBJECT_MARKER =

“t”

0x0A
AMF3_XML_MARKER =

“n”

0x0B
AMF3_BYTE_ARRAY_MARKER =

“v”

0x0C
AMF3_DICT_MARKER =

“f”

0x11
AMF3_EMPTY_STRING =

Other AMF3 Markers

0x01
AMF3_CLOSE_DYNAMIC_OBJECT =
0x01
AMF3_CLOSE_DYNAMIC_ARRAY =
0x01
MAX_INTEGER =

Other Constants

268435455
MIN_INTEGER =
-268435456

Class Method Summary collapse

Class Method Details

.const_missing(const) ⇒ Object

We use const_missing to define the active ClassMapper at runtime. This way, heavy modification of class mapping functionality is still possible without forcing extenders to redefine the constant.



118
119
120
121
122
123
124
# File 'lib/rocketamf.rb', line 118

def self.const_missing const #:nodoc:
  if const == :ClassMapper
    RocketAMF.const_set(:ClassMapper, RocketAMF::ClassMapping.new)
  else
    super(const)
  end
end

.deserialize(source, amf_version = 0) ⇒ Object

Deserialize the AMF string source of the given AMF version into a Ruby data structure and return it



93
94
95
96
97
98
99
100
101
# File 'lib/rocketamf.rb', line 93

def self.deserialize source, amf_version = 0
  if amf_version == 0
    RocketAMF::Deserializer.new.deserialize(source)
  elsif amf_version == 3
    RocketAMF::AMF3Deserializer.new.deserialize(source)
  else
    raise AMFError, "unsupported version #{amf_version}"
  end
end

.serialize(obj, amf_version = 0) ⇒ Object

Serialize the given Ruby data structure obj into an AMF stream using the given AMF version



105
106
107
108
109
110
111
112
113
# File 'lib/rocketamf.rb', line 105

def self.serialize obj, amf_version = 0
  if amf_version == 0
    RocketAMF::Serializer.new.serialize(obj)
  elsif amf_version == 3
    RocketAMF::AMF3Serializer.new.serialize(obj)
  else
    raise AMFError, "unsupported version #{amf_version}"
  end
end