c++apache-flexamf

Trying to make AMF3 Packet


I'm trying to make AMF Packet. I'm using https://github.com/Ventero/amf-cpp C++ implementation of AMF3, but it doesn't contains all needed variables. AMF0 documentation is describing how is built AMF packet (http://download.macromedia.com/pub/labs/amf/amf0_spec_121207.pdf) First two bytes specify packet version:

version = U16 It could be 0 or 3

U16 is an unsigned 16-bit integer in big endian (network) byte order

So i created

typedef unsigned int u16;

In amf.hpp I'm trying now to add all header information to single std::vector variable. I wrote:

std::vector<u16> buf = std::vector<u16>{3};  //packet version
std::vector<u16> buf2 = std::vector<u16>{0}; //header-count
std::vector<u16> buf3 = std::vector<u16>{1}; //message count

std::vector<u16> data;

buffermain.insert(data.end(), buf.begin(), buf.end());
buffermain.insert(data.end(), buf2.begin(), buf2.end());
buffermain.insert(data.end(), buf3.begin(), buf3.end());

In result in data i just have first inserted vector(buf).

//edit I made some progress.

Serializer serializer;
QByteArray outArray; //to insert amf bytes, and send it later

AmfArray Content;
AmfObject Object;

Object.addSealedProperty("Source", AmfNull());
Object.addSealedProperty("operation", AmfNull());
Object.addSealedProperty("clientId", AmfNull());
Object.addSealedProperty("destination", AmfNull());
Object.addSealedProperty("messageId", AmfNull());
Object.addSealedProperty("timestamp", AmfNull());
Object.addSealedProperty("timeToLive", AmfNull());
Object.addSealedProperty("timeToLive", AmfNull());
Object.addSealedProperty("body", AmfNull());
Object.addSealedProperty("headers", AmfNull());

Content.push_back(Object);
serializer << Content;

std::vector<uint8_t> data2 = serializer.data();

char* datas = reinterpret_cast<char*>(data2.data());//

std::vector<unsigned __int32> v;
v.reserve(data.size());

char* sizes = reinterpret_cast<char*>(v.data()); //teoretical size of message in U32

char null = 0;
outArray.append(null); //version first byte
outArray.append(3); //version second byte
outArray.append(null); //header count first byte
outArray.append(null); //header count second byte
outArray.append(null); //messages count first byte
outArray.append(1); //messages count second byte

outArray.append(null); //"Target" lenght first byte 
outArray.append(4); //"Target" lenght second byte 

outArray.append(QByteArray::fromHex("6e756c6c")); // "Target" value

outArray.append(null); // "Response" length first byte
outArray.append(2); // "Response" length second byte

outArray.append(QByteArray::fromHex("2f31"));

outArray.append(sizes); //insert theoretical length of message
outArray.append(datas); //insert message

Solution

  • (I'm the author of amf-cpp)

    I've just added AMF3 packet support to amf-cpp. To use it, you have to create an AmfPacket object, add headers (PacketHeader) or messages (PacketMessage) and then serialize the AmfPacket. Here's a quick example (which assumes something like using namespace amf; for brevity):

    AmfPacket packet;
    // first, we construct a simple header in-place
    packet.headers.emplace_back(
        "SomeHeader", // header name
        false, // must understand?
        AmfString("Value") // header value
    );
    
    // set up the message value
    AmfObject object;
    // add some properties
    object.addSealedProperty("prop", AmfString("val"));
    AmfArray content;
    content.push_back(object);
    // now construct the message in-place
    packet.messages.emplace_back(
        "com/example/Object.method", // target uri
        "/1/onResult", // response-uri
        content // value
    );
    
    // amf::v8 is a typedef for std::vector<uint8_t>
    v8 data = packet.serialize();
    

    The resulting data object can then be used with your QDataStream.

    In the future, if you notice that amf-cpp is missing a feature you would like to use, feel free to open a bug report on the GitHub issue tracker.