RFC 5444 handler library
Copyright (c) 2010 Henning Rogge <hrogge@googlemail.com>

The rfc 5444 library is a combined parser and generator for the
'Generalized Mobile Ad Hoc Network (MANET) Packet/Message Format'.
The library is split into a separate reader and writer part, both
of them use a generic avl-tree and double-linked list implementation.

The reader and writer allow multiple independent code blocks to read
overlapping parts of a RFC 5444 data stream and assemble packets and
messages together. This allow API users to separate different sub-
protocol in their codebase (e.g. NHDP and OLSRv2).


=======================
    RFC 5444 writer
=======================

1) general information
1.1) using the writer
1.2) packet sending
1.3) interfaces
1.4) maximum transmission unit
2) packets
2.1) packet creator
2.2) packet content provider
2.3) callback order for packets
3) messages
3.1) message creator
3.2) message content provider 
3.3) message fragmentation
3.4) callback order for messages


1) general information
**********************

The rfc5444 writer can be used on two different levels of rfc5444,
packets and messages. Other than the reader, it has no third independant
category for addresses in messages.

For each type of message there has to be ONE (and only one) registered
user responsible for the fixed message header. Only this user of
the writer can manipulate the message header fields (hopcount, hoplimit,
originator and sequence number) and set the address length for the
message.

Because there are no 'types' of packets, there is only ONE user
responsible for the packet header. The only thing he can do is set a
sequence number for the packet header.

There can be multiple content providers for each packet header and for
each message type. Each content provider has a priority and the parser
will call them in the right order. 

Packet content providers can add TLVs to the packet header.

Message content providers can add TLVs to their message header, can add
addresses to it and add TLVs to this addresses. Each TLV type that should
be added to an address has to be registered with the rfc5444 writer
in advance.


1.1) using the writer
*********************

Before using the writer you have to allocate a writer context by calling
rfc5444_writer_init(). All functions of the writer need a pointer to this
context as a parameter.
If you don't need the writer anymore, call rfc5444_writer_cleanup() to
free all allocated memory of the writer including the writer context
itself.

After allocating the context you can register and unregister all
necessary callbacks to the writer, as long as you do this outside
of the writer callbacks itself!

To start a message call the rfc5444_writer_create_message() function. The
writer will begin to call all callbacks associated with the message
type. The message will then be stored in the packet buffer. 

The function rfc5444_writer_forward_msg() can be used to forward a
received binary rfc5444 message by appending it to the current package.

rfc5444_writer_flush() will clear the current packet buffer and send the
packet. A parameter controls if this will generate an 'empty' packet
if no messages are currently inside the packet buffer.


1.2) packet sending
*******************

The rfc5444 writer cannot know how your protocol sends the finished
packets. Because of this you have to set the sendPacket() callback
in the writer context before generating messages and packet. The writer
will call the callback once for each outgoing packet.


1.3) interfaces
***************

The rfc5444 writer has support for multiple outgoing interfaces.
Each interface have to be created with the rfc5444_writer_register_interface()
function. When creating or forwarding a message the caller has to
support a callback to a function that decides, if a certain interface is
used for this message. This way a message going out on multiple interfaces
does not need to be created/compressed multiple times.


1.4) maximum transmission unit
******************************

The writer has to deal with the problem of MTU size of interfaces to
fragment the messages correctly. Each outgoing interface might have its
own MTU, but even making sure that all generated messages will fit into
the smallest interface MTU used for the message might not enough. If there
are interfaces somewhere in the MANET with a smaller maximum message size
(either because of a small MTU of the link or a large amount of packet
TLVs for this link), all messages in the whole MANET must be small enough
to fit through this bottleneck.

Because of this you have to specify a maximum message size (in bytes)
when initializing the writer AND specify a MTU for each registered
interface.


2) packets
**********

There are no distinct types of packets and packets cannot contain
addresses, so the options for registering callbacks are more primitive
than the callbacks for messages.

All packet specific callbacks are interface specific.


2.1) packet creator
*******************

There is no register/unregister function for a packet creator, there are
just two callback pointers in the rfc5444_writer object.

The first callback addPacketHeader() allows the packet creator to define
if the packet should contain the sequence number.
Both this and the second callback finishPacketHeader() can set the
sequence number of the packet, if it was activated by the first callback.

The addPacketHeader() callback will be the first called when a new
packet is started. finishPacketHeader() is the last one called before
the new packet is send.


2.2) packet content provider
****************************

There can be multiple packet content providers registered to a rfc5444
writer. Each of them has a pair of callbacks to add TLVs to the message.

The addPacketTLVs() callback allows a content provider to either add a
TLV directly to the packet header or allocate memory for adding one
later.
The finishPacketTLVs() callback can use the allocated memory from the
first callback to add TLVs after all messages have been created.

The addPacketTLVs() callbacks will be called in the right order defined
by their priority right after the addPacketHeader() callback. The
finishPacketTLVs() callbacks will be called in reverse order after all
messages have been created right before the finishPacketHeader() one.


2.3) callback order for packets
*******************************

The order of callbacks for packets can be described as:

New packet is started
 * addPacketHeader()
 * addPacketTLVs() (provider 1)
   ...
 * addPacketTLVs() (provider n)

Message creation starts
Message creation (fragment 1) finishes
 * finishPacketTLVs() (provider n)
   ...
 * finishPacketTLVs() (provider 1)
 * finishPacketHeader()

...

Message creation (fragment n) finishes
 * finishPacketTLVs() (provider n)
   ...
 * finishPacketTLVs() (provider 1)
 * finishPacketHeader()


3) messages
***********

Each message type registered to the rfc5444 writer has a single
message creator and may have multiple content providers. Without a
registered message creator even multiple content provider will be
useless, because the writer will not create a message of this type.

Message fragmentation is a special case when the all of the output
of the message content providers does not fit into a single packet.
Chapter 3.3 will explain the stategy of the writer fragmenting the
message and how this will interact with the callbacks.

Some messages are unique for each interface. If the if_specific
parameter of rfc5444_writer_register_message() is true, the writer
will call the message creation process once for each interface
instead of generating a common message for interfaces in one step.


3.1) message creator
********************

The message creators are a pair of callbacks for a registered message
similar to the packet creator.

The first callback addMessageHeader() allows the message creator to
define which header elements (hopcount, hoplimit, originator, sequence
number) the message header will have. It can also set an address length for
the message.
Both this and the second callback finishMessageHeader() can set all
four message header fields, if they were activated by the first
callback.

The addMessageHeader() callback will be the first called when the
message is generated. finishMessageHeader() is the last one called
before the binary message content is appended to the packet buffer.


3.2) message content provider
*****************************

There can be multiple message content providers registered for each
message type. Each of them has a pair of callbacks to add TLVs and
one callback to add addresses and address-tlvs to the message.

The addMessageTLVs() callback allows a content provider to either add a
TLV directly to the message header or allocate memory for adding one
later.

The addAddresses() callback allows adding new addresses and TLVs for
them to the message. Each tlvtype has to be registered with the
rfc5444 writer. If multiple content providers add the same address,
their tlvs will be merged together.

The finishMessageTLVs() callback can use the allocated memory from the
first callback to add TLVs after all addresses and addresstlvs have
been added.

The addMessageTLVs() callbacks will be called in the defined order
after the addMessageHeader() callback.  After this the addAddresses()
callback of each provider is called in the same order, followed by
the finishMessageTLVs() callback in reverse order.


3.3) message fragmentation
**************************

RFC 5444 message fragmentation is a problem for a generic writer with
multiple input sources. Because it's impossible for any of the content
providers to calculate the necessary borders to split a message, the
writer has to assist them.

The strategy of this rfc5444 writer is simple, but will hopefully
be sufficient for most usecases.

The writer will begin to allocate space for both the message header,
the message TLVs and the TLVs allocated by the addMessageTLVs()
callback. It then starts to add one address at a time including it's
tlvs. If the message gets too large the parser stops, calls all
involved finishMessageTLVs() callbacks and the finishMessageHeader()
callback. At this point, the first fragment will added to the packet
and the packet will be sent in order to clear the packet buffer.
Then the writer clears it's message buffer from all optional TLVs
allocated by addMessageTLVs() and all addresses including their TLVs
and begins to add the next address including its tlvs.
This will continue until the last fragment has been finalized by
calling the finishMessageTLVs() and finishMessageHeader() callback.

If there is a single address with TLVs which do not fit into a
message an error will be thrown and the message generation will stop.
It's the job of the user to make sure that even with reserved
packet TLVs and message TLVs there is enough MTU left to put at
least any single address including its tlvs inside.


3.4) callback order for messages
********************************

The order of callbacks for messages can be described as:

Message generation starts
 * addMessageHeader()
 * addMessageTLVs() (provider 1)
   ...
 * addMessageTLVs() (provider n)
 * addAddresses() (provider 1)
   ...
 * addAddresses() (provider n)

Message fragment 1
 * finishMessageTLVs() (provider n)
   ...
 * finishMessageTLVs() (provider 1)
 * finishMessageHeader()

...

Message fragment n
 * finishMessageTLVs() (provider n)
   ...
 * finishMessageTLVs() (provider 1)
 * finishMessageHeader()
