Message Envelopes is a concept that make it easy to extend and influence the on-the-wire format of data on top of what the SDK's Messages provide out of the box.
There are two areas where Message Envelopes provide benefits to developers using RO:
- through existing message envelopes shipped in the box with RO
- the ability to easily write custom message envelopes
Message Envelopes are supported on all platforms.
Using Message Envelopes
Existing and pre-defined message envelopes make it easy to apply functionality such as encryption, signing or other well-defined operations to data before it is send out over the wire, and undo/decode those operations on data that is received, where necessary.
To configure one more more message envelopes, simply drop the appropriate components on your form (or instantiate them in code) and hook them up with the message's Envelopes collection property. In addition to options provided by particular envelope implementations, two properties are relevant for message envelope operation:
Envelope marker: This property uniquely identifies the envelope and its configuration for en- and decoding.
Enabled: Controls whether this envelope will be used for
Individual envelopes can be marked as enabled or disabled. Disabled envelopes will not be applied when sending out, but are available to process incoming messages. This can be used to have different envelope configurations on client and server. The message's envelope lists persist the order of registered envelopes.
The receiving system will use the
Envelope marker to identify the envelope type to be used for processing the envelope. This name will be determined by the envelope configuration on the Message component. Envelope implementations will provide a "default" marker, which can be overridden by the user of the envelope component. This will allow, in theory, the same envelope type to be used in different configurations. Envelope names on client and server systems must match.
Existing Message Envelopes
We are shipping one concrete message envelope implementation: the
AES Encryption Envelope. This has been one of the most sought-after features (cross-platform compatible encryption) and will also serve as a sample implementation for those wanting to implement custom message envelopes.
Writing Custom Message Envelopes
Custom message envelopes can easily be implemented by creating a descendant from the
TROMessageEnvelope class and implementing
intProcessIncoming methods according to whatever functionality your envelope wants to provide.
Envelopes can change or replace the original message data (as is the case for the encryption envelope provided), but can also decide to simply append - as for example an envelope signing a message with a public key might do.
The envelope implementations will get passed in the inner message body (which might or might not already be wrapped by other envelopes, and return the wrapped body (for writing to the network) or get passed in the wrapped message body and return the inner message (for reading from the network). Handling of the preamble and detection of envelopes (see below) will be handled by the RO framework, and does not affect the envelope implementation.
Since envelopes can be nested arbitrarily, it is important that envelopes make no assumptions about the content of the message body they are enveloping.
Individual properties (for example encryption keys) might be provided on the component itself.
Custom envelope implementations should also override the read-only
DefaultEnvelopeMarker property to provide a "unique enough" default name that will identify the envelope. A Blowfish implementation might merely return
BLOWFISH, for example.
Message Envelope Features
Envelopes will work with any message type, although they will not conform with
XML-RPCstandards, so usage with anything but
BinMessagewould be purely academic.
Envelopes can be combined arbitrarily, and the messaging stack in Remoting SDK will handle the processing of all configured envelopes, transparently.
Envelopes can modify the contents of a message, by adding data before or after the original message, or by replacing the entire message.
Envelopes work cross-platform, although cross-platform usability of course relies on matching implementations of the used envelopes being available on both sides. The message envelopes shipped with RO itself are cross-platform.
Each envelope will add the following preamble to messages as they are enveloped:
- 5 ASCII characters
ROENVas a marker.
- The envelope marker, as 1-byte binary length, followed by the UTF-8-encoded envelope name (maximum of 255 characters). The length bytes indicates the number of bytes, not UTF-8 characters.
This preamble is followed by the enveloped (wrapped) message body, which reaches until the end of the stream or data packet.
It is up to the envelope implementation to define the format and handle the processing of this message body. Envelopes might simply add data at the end (for checksums), rewrite the entire body (for encryption or encoding), they might also leave the message body untouched entirely. The RO stack will at no time try to interpret the data of the wrapped/enveloped message body.
ROENV marker will be used by the receiving system to determine the presence of envelopes. Since envelopes can be nested, the receiving system will continue unpacking and processing envelopes until no (further) envelope marker is found, and then proceed with handling the result as a plain RO message.