Envelopes

The envelope contains all the data fields required for delivering the messages.

Constructors

First we would like to introduce the constructors here:

// An empty envelope.
CEnvelope();

// A copy of an envelope is made here.
CEnvelope(final CEnvelope aTemplate);

// In this envelope, the recipient address is set to a local namespace.
// This constructor is used for messages to local services.
// The record ID is then the service ID.
CEnvelope(final IId aNID);

// Here the recipient address is set to a remote namespace.
// This constructor is used for messages to remote services.
// The record ID is then the service ID.
CEnvelope(final IId aNID,
          final INodeID aNodeID);

// The recipient address is set to the address of a target.
// The message then goes directly to the target.
CEnvelope(final IId aTID,
          final IId aNID,
          final INodeID aNodeID);

// The recipient address is set to the address of a target.
// The message then goes directly to the target.
CEnvelope(final ITargetAddress aReceiver);

There is a factory method for reading an envelope from a stream:

static CEnvelope createFromStream(final DataInputStream aStream) throws IOException;

The method takes into account different versions of the envelope. At the moment there is only version 0.

Recipient and Sender Address

The recipient address is the address of the target that is to receive the message. If only the namespace part of the address is filled in (NID+NODEID), a service is addressed, which is registered in exactly this namespace. The service ID (SID) is the same as the record ID of the message:

// Get the receiver
ITargetAddress getReceiver();

// Set the receiver
void setReceiver(final ITargetAddress aReceiver);

Since the: ref: target addresses <TARGETADRESSE> is immutable, it cannot be changed. This means that a new address must be created with the change. There are a few convenience methods for doing this:

// Creates a new receiver address with changed TID and sets it.
void setReceiverTID(final IId aTID);

// Creates and sets a new receiver address with changed NID
void setReceiverNID(final IId aNID);

// Creates and sets a new receiver address with changed NodeID
void setReceiverNodeID(final INodeID aNodeID);

If the recipient NID is omitted, the kernel assumes that it is the same NID as the sender’s NID. This also applies to the NodeID.

Similarly, there are similar methods for the sender:

void setSender(final ITargetAddress aSender);

ITargetAddress getSender();

void setSenderTID(final IId aTID);
void setSenderNID(final IId aNID);
void setSenderHID(final IHid aHID);

If the sending methods of the target are used, the sender is set by the system..

Answers

When the system sends a message back, the addresses are swapped (receiver <—> sender). Support methods are available for this purpose:

// Returns SUCCESS if the sender is set and the message is not an answer.
CResult canSwap();

// Swaps sender and receiver.
CResult swap();

At the same time, when exchanging addresses, a bit is set which indicates that the message is an answer.:

void setIsAnswer(final boolean aIsAnswer);

boolean isAnswer();

Since replies are only sent automatically in the event of an error, there is still one bit missing that the sender wants a response.:

boolean wantAnswer();

void setWantAnswer(final boolean aWantAnswer);

This bit is set in the corresponding send methods (request(...)). The bit is not set in the `notification(...) and send(...) methods.

Result

The result code for responses is also stored in the envelope and not in the record. One reason for this is the fact that records can also be used outside of messages. In addition, only one record at a time is always passed to a message handler, even if the message has several records. So only a single result code comes into the answer.

The results of a message are accessed as follows:

void setResult(final CResult aResult);

void setResult(final int aCode,
               final String aText);

CResult getResult();

int getResultCode();

String getResultText();

A message has an internal boolean mHasBeenHandled. A message handler returns a boolean in the handleMessage () method.: True means that the message has been handled. If false is returned, mHasBeenHandled is set to false, and the result code is set to CResultCode. NOT_HANDLED.

If the reply comes back and this result code is set, the sender should assume that the message has not been handled for some reason. This may also be due to the fact that the state machine of the receiver target does not handle this message in the current state.

The following methods are used internally for this purpose:

boolean hasBeenHandled();

void setHandled();

Blocked Messages

Since messages that leave the receiver’s message handler are sent back as replies by the framework, there must be a way to prevent this. For example, if a request cannot be completed immediately, the message must be saved and sent back manually after the work is done. For example, the recipient may have to send and receive messages in order to process the request.

The target blocks the message:

mag.setBlocked(true);

The getter for the state is called:

boolean isBlocked();

The message is saved by the receiver target (!). After the work is done he sends it back with one of the sendBack (...) methods of Target, Namespace or Kernel.:

msg.setBlocked(false);
sendBack(msg);

Blocked messages can (and should) be saved. Unblocked messages should not be saved under any circumstances, as they have already been sent and changed!

Services

To enable the receiver to check whether the received message came via a service or directly, there is an additional method:

boolean isServiceMessage();

Transport

There are a number of methods that facilitate the message transport between the NODES.

The following method prevents a message from leaving the system (for example, in the LOG):

void setOnlyLocal();

boolean isOnlyLocal();

In a new message, the bit is set to false.

Another bit prevents messages from being compressed or encrypted (Default: false):

void setRawTransport();

boolean isRawTransport();

The priority of messages is only taken into account if they are transported from NODE to NODE. A message with a higher priority is always transported first if several messages are to be transported.

void setPriority(final EPriority aPrio);

EPriority getPriority();

The framework in this version knows the priorities LOW, STREAM, NORMAL and HIGH`. Default is NORMAL. Log messages are set to LOW, answers are always set to HIGH.

Further Fields

To protect LOG messages from being logged, there are other methods. Without them, the system would be flooded with messages:

boolean isLogEnabled();

void disableLog();

A number that is incremented with each instance of a message may be helpful for debugging.:

int getInstanceId();

The following methods are also available for debugging:

long getTimeSend(); long getTimeDeliver(); long getTimeSendBack(); long getTimeDeliverAnswer();

void setTimeSend(final long aTimeSend); void setTimeDeliver(final long aTimeDeliver); void setTimeSendBack(final long aTimeSendBack); void setTimeDeliverAnswer(final long aTimeDeliverAnswer);

These times are assigned System.currentTimeMillis() by the framework.

The version of a message class is obtained by the following method:

byte getVersion();

At the moment version 0 is the current version.

Envelopes can be copied, either using the copy constructor or this method:

CEnvelope getCopy();

Transaction IDs as UUIDs can be set and fetched using these methods:

UUID getTransactionId();

void setTransactionId(final UUID aId);