Tutorials/cppHowTo

Introduction
This page will show you how to use the Firebase C++ API to encode and decode packets.

Firebase Packet Format
The Firebase packet format consists of a header followed by the actual packet data. Header contains total packet length plus an identifier (classId). The length is a 32 bit integer in network format (big endian). The identifier is an unsigned 8 bit value (1-255) that identifies each packet

See this blog for more details on the packet format

Usage
The following examples use this structure definition for generating an example packet:    Which will produce the following code: (TestPacket.h)

// I AM AUTO-GENERATED, DON'T CHECK ME INTO SUBVERSION (or else...)


 * 1) ifndef TESTPACKET_H_41C707DB_INCLUDE
 * 2) define TESTPACKET_H_41C707DB_INCLUDE


 * 1) include "styx_support.h"
 * 2) include "PacketInputStream.h"
 * 3) include "PacketOutputStream.h"
 * 4) include "ProtocolEnums.h"
 * 5) include "ProtocolObject.h"

namespace org_cubeia_test_io_protocol {

class TestPacket : public styx::ProtocolObject {

public:

static const uint8_t CLASSID = 1;

virtual uint8_t classId { return CLASSID; }

uint32_t id; std::string name;

TestPacket {}

TestPacket(uint32_t id, std::string name) { this->id = id; this->name = name; }

friend styx::PacketOutputStream& operator<<(styx::PacketOutputStream &packetOutputStream, const TestPacket &testPacket) {           packetOutputStream << testPacket.id; packetOutputStream << testPacket.name; packetOutputStream.finish; return packetOutputStream; }

friend styx::PacketInputStream & operator>>(styx::PacketInputStream &packetInputStream, TestPacket &testPacket) {           packetInputStream >> testPacket.id; packetInputStream >> testPacket.name; return packetInputStream; }

virtual void load(const styx::StyxBuffer &buffer) {           styx::PacketInputStream packetInputStream(buffer); packetInputStream >> *this; }

virtual styx::StyxBuffer save(void) const {           styx::PacketOutputStream packetOutputStream(CLASSID); packetOutputStream << *this; return packetOutputStream.packet; }   }; }

As you can see above, all generated packets derive from ProtocolObject which has three virtual functions (classId, load & save)
 * 1) endif

Encoding
To serialize this packet into a buffer, all we have to do is:

// packet namespace using namespace org_cubeia_test_io_protocol;
 * 1) include "styx_support.h"
 * 2) include "ProtocolObject.h"
 * 3) include "ProtocolObjectFactory.h"
 * 4) include "TestPacket.h"

int main(int argc, char *argv[]) {   // create an instance of TestPacket TestPacket testPacket(10, "test");

// Get the buffer (StyxBuffer lives in namespace styx) styx::StyxBuffer styxBuffer = testPacket.save;

// continues further down.........................

StyxBuffer is defined as a std::vector

Decode
When the packets are generated, a matching ProtocolObjectFactory is created as well. It contains a static function that creates a packet object from a buffer.

// create a ProtocolObject instance (ProtocolObject lives in namespace styx) styx::ProtocolObject *protocolObject = ProtocolObjectFactory::create(styxBuffer);

// call the virtual load function to deserialize protocolObject->load(styxBuffer);

// the packet has now been serialized, we can now do this switch (protocolObject->classId) { case TestPacket::CLASSID: TestPacket *tp = dynamic_cast (protocolObject); //do something with tp here printf("name=%s, id=%d\n", tp->name.c_str, tp->id); break; }

// delete protocolObject when done with it   delete protocolObject;

return 0;

} // int main(int argc, char *argv)