Skip to content
This repository
Browse code

amf0 and amf3 implementation

  • Loading branch information...
commit a3db284e83622643e5c59f8d6fb8898265876a18 1 parent 6882faa
Nguyen Kien Trung authored
28 temp/server/action_message.hrl
... ... @@ -0,0 +1,28 @@
  1 +%% define amf0
  2 +-define(VERSION_1, 1).
  3 +%% not used anymore but just there
  4 +-define(VERSION_2, 2).
  5 +%% define amf3
  6 +-define(VERSION_3, 3).
  7 +
  8 +-define(STATUS_METHOD, "/onStatus").
  9 +-define(RESULT_METHOD, "/onResult").
  10 +
  11 +-define(AMF_CONTENT_TYPE, "application/x-amf").
  12 +-define(XML_CONTENT_TYPE, "application/xml").
  13 +
  14 +-record(header, {headerName = "", mustUnderstand = false, data = <<>>}).
  15 +-record(body, {targetUri = "", responseUri = "", data = <<>> }).
  16 +
  17 +-record(action_message, {
  18 + version = ?VERSION_1,
  19 + headers = [], %% list of 'header'
  20 + bodies = [] %% list of 'body'
  21 + }).
  22 +
  23 +-record(trait, {
  24 + className = "",
  25 + externalizable = false,
  26 + dynamic = false,
  27 + properties = []
  28 + }).
76 temp/server/amf0.erl
... ... @@ -0,0 +1,76 @@
  1 +-module(amf0).
  2 +-author("trung@mdkt.org").
  3 +
  4 +-export([read_object/1, read_u8/1, read_u16/1, read_u32/1, read_string/1]).
  5 +
  6 +-include("action_message.hrl").
  7 +
  8 +-define(number_marker, 16#00).
  9 +-define(boolean_marker, 16#01).
  10 +-define(string_marker, 16#02).
  11 +-define(object_marker, 16#03).
  12 +-define(movieclip_marker, 16#04). %% reserved, not supported
  13 +-define(null_marker, 16#05).
  14 +-define(undefined_marker, 16#06).
  15 +-define(reference_marker, 16#07).
  16 +-define(ecma_array_marker, 16#08).
  17 +-define(object_end_marker, 16#09).
  18 +-define(strict_array_marker, 16#0A).
  19 +-define(date_marker, 16#0B).
  20 +-define(long_string_marker, 16#0C).
  21 +-define(unsupported_marker, 16#0D).
  22 +-define(recordset_marker, 16#0E). %% reserved, not supported
  23 +-define(xml_document_marker, 16#0F).
  24 +-define(typed_object_marker, 16#10).
  25 +-define(avm_plus_object_marker, 16#11).
  26 +
  27 +read_u8(<<Value:8, Rest/binary>>) ->
  28 + {ok, Value, Rest}.
  29 +
  30 +read_u16(<<Value:16, Rest/binary>>) ->
  31 + {ok, Value, Rest}.
  32 +
  33 +read_u32(<<Value:32, Rest/binary>>) ->
  34 + {ok, Value, Rest}.
  35 +
  36 +read_string(Bin) ->
  37 + {ok, StringLen, Rest} = read_u16(Bin),
  38 + {StringBin, Rest1} = split_binary(Rest, StringLen),
  39 + {ok, String} = utf8:from_binary(StringBin),
  40 + {ok, String, Rest1}.
  41 +
  42 +read_number(<<Value/float, Rest/binary>>) ->
  43 + {ok, Value, Rest};
  44 +read_number(Something) ->
  45 + {bad, {"Can't read number", Something}}.
  46 +
  47 +read_boolean(<<Value:8, Rest/binary>>) ->
  48 + case Value of
  49 + 0 ->
  50 + {ok, false, Rest};
  51 + _ ->
  52 + {ok, true, Rest}
  53 + end;
  54 +read_boolean(Something) ->
  55 + {bad, {"Can't read boolean", Something}}.
  56 +
  57 +%% return {ok, value/Value, Rest} or {bad, Reason}
  58 +read_object(<<?number_marker:8, Rest/binary>>) -> read_number(Rest);
  59 +read_object(<<?boolean_marker:8, Rest/binary>>) -> read_boolean(Rest);
  60 +read_object(<<?string_marker:8, Rest/binary>>) -> read_string(Rest);
  61 +read_object(<<?object_marker:8, Rest/binary>>) -> {bad, {"Not supported", Rest}};
  62 +read_object(<<?movieclip_marker:8, Rest/binary>>) -> {bad, {"Reserved, not supported", Rest}};
  63 +read_object(<<?null_marker:8, Rest/binary>>) -> {ok, null, Rest};
  64 +read_object(<<?undefined_marker:8, Rest/binary>>) -> {bad, {"Not supported", Rest}};
  65 +read_object(<<?reference_marker:8, Rest/binary>>) -> {bad, {"Not supported", Rest}};
  66 +read_object(<<?ecma_array_marker:8, Rest/binary>>) -> {bad, {"Not supported", Rest}};
  67 +read_object(<<?object_end_marker:8, Rest/binary>>) -> {bad, {"Not supported", Rest}};
  68 +read_object(<<?strict_array_marker:8, Rest/binary>>) -> {bad, {"Not supported", Rest}};
  69 +read_object(<<?date_marker:8, Rest/binary>>) -> {bad, {"Not supported", Rest}};
  70 +read_object(<<?long_string_marker:8, Rest/binary>>) -> {bad, {"Not supported", Rest}};
  71 +read_object(<<?unsupported_marker:8, Rest/binary>>) -> {bad, {"Not supported", Rest}};
  72 +read_object(<<?recordset_marker:8, Rest/binary>>) -> {bad, {"Reserved, not supported", Rest}};
  73 +read_object(<<?xml_document_marker:8, Rest/binary>>) -> {bad, {"Not supported", Rest}};
  74 +read_object(<<?typed_object_marker:8, Rest/binary>>) -> {bad, {"Not supported", Rest}};
  75 +%% switch to AMF3
  76 +read_object(<<?avm_plus_object_marker:8, Rest/binary>>) -> amf3:read_object(Rest).
59 temp/server/deserializer.erl
... ... @@ -0,0 +1,59 @@
  1 +-module(deserializer).
  2 +-author("trung@mdkt.org").
  3 +
  4 +-export([read/1]).
  5 +
  6 +-include("action_message.hrl").
  7 +
  8 +read_header(Bin) ->
  9 + io:fwrite("Bin = ~n~p~n", [Bin]),
  10 + {ok, HeaderName, BinAfterHeaderName} = amf0:read_string(Bin),
  11 + {ok, MustUnderstand, BinAfterMustUnderstand} = amf0:read_u8(BinAfterHeaderName),
  12 + {ok, _DataLen, DataBin} = amf0:read_u32(BinAfterMustUnderstand),
  13 + %% Don't care about DataLen, just read
  14 + %% {DataBin, NextBin} = split_binary(Rest2, DataLen),
  15 + {ok, Data, NextBin} = amf0:read_object(DataBin),
  16 + Header = #header{headerName = HeaderName, mustUnderstand = case MustUnderstand of 0 -> false; _Other -> true end, data = Data},
  17 + {ok, Header, NextBin}.
  18 +
  19 +read_headers(Bin, Count, Total, Acc) when Count == Total ->
  20 + {ok, Acc, Bin};
  21 +read_headers(Bin, Count, Total, Acc) ->
  22 + {ok, Header, NextBin} = read_header(Bin),
  23 + io:fwrite("Parsed header ~p : ~p~n", [Count + 1, Header]),
  24 + read_headers(NextBin, Count + 1, Total, Acc ++ [Header]).
  25 +
  26 +read_body(Bin) ->
  27 + {ok, TargetUri, BinAfterTargetUri} = amf0:read_string(Bin),
  28 + {ok, ResponseUri, BinAfterResponseUri} = amf0:read_string(BinAfterTargetUri),
  29 + {ok, _DataLen, DataBin} = amf0:read_u32(BinAfterResponseUri),
  30 + %% Don't care about DataLen, just read
  31 + %% {DataBin, NextBin} = split_binary(Rest2, DataLen),
  32 + {ok, Data, NextBin} = amf0:read_object(DataBin),
  33 + Body = #body{targetUri = TargetUri, responseUri = ResponseUri, data=Data},
  34 + {ok, Body, NextBin}.
  35 +
  36 +read_bodies(Bin, Count, Total, Acc) when Count == Total ->
  37 + {ok, Acc, Bin};
  38 +read_bodies(Bin, Count, Total, Acc) ->
  39 + {ok, Body, NextBin} = read_body(Bin),
  40 + read_bodies(NextBin, Count + 1, Total, Acc ++ [Body]).
  41 +
  42 +%% Read binary and translate to action_message record
  43 +%% Msg = #action_message
  44 +%% return {ok, Msg, Rest} or {bad, Reason}
  45 +%% ideally, Rest must be <<>>
  46 +read(<<?VERSION_1:16, Rest/binary>>) -> read_now(?VERSION_1, Rest);
  47 +read(<<?VERSION_3:16, Rest/binary>>) -> read_now(?VERSION_3, Rest);
  48 +read(_) ->
  49 + {bad, "Not a valid binary or version not supported"}.
  50 +
  51 +read_now(Version, Bin) ->
  52 + {ok, HeaderCount, BinAfterHeaderCount} = amf0:read_u16(Bin),
  53 + io:fwrite("There are ~p header(s)~n", [HeaderCount]),
  54 + {ok, Headers, BinAfterHeaders} = read_headers(BinAfterHeaderCount, 0, HeaderCount, []),
  55 + {ok, BodyCount, BinAfterBodyCount} = amf0:read_u16(BinAfterHeaders),
  56 + io:fwrite("There are ~p body(s)~n", [BodyCount]),
  57 + {ok, Bodies, BinAfterBodies} = read_bodies(BinAfterBodyCount, 0, BodyCount, []),
  58 + Msg = #action_message{version = Version, headers = Headers, bodies = Bodies},
  59 + {ok, Msg, BinAfterBodies}.

0 comments on commit a3db284

Please sign in to comment.
Something went wrong with that request. Please try again.