There are additional operations that can be applied to message objects, as summarized below:
void msgConstructEmpty(Msg *message)
void msgConstructBuffer(Msg *message, char *buffer, int length)
char *msgConstructAllocate(Msg *message, int length)
void msgAssign(Msg *message_1, Msg *message_2)
int msgLength(Msg *message)
The first three operations are used to create messages. Each is used under a different set of circumstances. msgConstuctEmpty creates an empty message. It is used in conjunction with msgAssign to save a reference to a message. For example, if a given protocol wants to send a particular message m out over the network, but at the same time save a copy of m in case it needs to retransmit it in the future, it might use msgConstructEmpty to create an empty message n, and then do msgAssign(m, n). At this point both m and n represent the same message (the same byte string).
The other two message constructors create messages with an associated data component. msgConstructBuffer builds a message from the existing byte string referenced by buffer. This operation is used, for example, by an application program that already possesses a buffer of data it wants to transmit; it uses msgConstructBuffer to encapsulate this buffer in a message object. In contrast, msgConstructAllocate is used when a protocol knows it is going to need a message to hold length bytes of data, but it does not yet have the data to place in the message. This operation is used, for example, in a device driver that knows it will eventually receive a packet from the network of some size. It invokes msgConstructAllocate to create the message, and gets a pointer to a memory buffer that is free to hold data in return. The device driver would then program the network adaptor to receive the next packet into this buffer.