Jini Extensible Remote Invocation (Jini ERI) Multiplexing Protocol

This page defines the Jini extensible remote invocation (Jini ERI) multiplexing protocol, which is used by the following Jini ERI transport layer implementation classes:
net.jini.jeri.connection.ConnectionManager
net.jini.jeri.connection.ServerConnectionManager
net.jini.jeri.tcp.TcpEndpoint
net.jini.jeri.tcp.TcpServerEndpoint
net.jini.jeri.ssl.SslEndpoint
net.jini.jeri.ssl.SslServerEndpoint
net.jini.jeri.kerberos.KerberosEndpoint
net.jini.jeri.kerberos.KerberosServerEndpoint
The purpose of this protocol is to provide a wire format for implementing a binary request/response communication interface, such as that of the Jini ERI OutboundRequest and InboundRequest interfaces, on top of a bi-directional byte stream connection. The intended application of this protocol is to communicate Jini ERI remote method invocations over TCP and similar connection-oriented transport protocols, as well as over layered application-level protocols that can provide a connection-oriented byte stream interface.

Requirements

The design is intended to satisfy the following requirements: Note that it is explicitly not a goal of the design at this time to support bi-directional request initiation over a single connection, such as for making remote "callbacks" over an incoming connection, because of the endpoint identification, security, and connection life cycle issues that are consequences of such a goal. Also not a requirement is flexibility of byte order for multi-byte data items directly defined by this protocol.

Notation

The following notation is used for the remainder of this page:

Data Types and Encoding

The term byte on this page means the same as "octet": an 8-bit value. All integer values requiring more than one byte are represented in big-endian byte order. All integer values are unsigned.

Items in the protocol are of the following simple types:

flag:
1-bit value for which the value 0 indicates false, or that the flag is not set, and the value 1 indicates true, or that the flag is set.
n-bit integer:
n-bit value from 0 to (2^n)-1
sequence of n bytes:
sequence of n bytes of application data
A sequence of bytes that is to be interpreted as a string of characters is encoded in UTF-8 (see RFC 2279).

Connection Properties

The connection underlying this protocol connects two endpoints, a client and a server, with the apparent behavior of two independent streams of bytes, one stream from client to server and the other from server to client. The connection must make reasonable attempts to guarantee reliable delivery, such that when a sequence of bytes is sent by one endpoint, it will either be received by the other endpoint at most once, in correct order with other sequences sent, or else a failure will be detected within a reasonable period of time (such as when delivery acknowledgment has not been received). The connection must not impose granularity restrictions on the size of sequences of bytes that can be flushed over the streams.

The client may use the connection to send requests to the server and receive responses in reply. The server may use the connection to receive requests and send responses in reply. (Note that the terms "client" and "server" in this page are only used as convenient labels to distinguish the two endpoints of the asymmetric connection over which this protocol operates; they do not necessarily correspond to higher-level application concepts of "client" and "server".)

How the connection is established is outside the scope of this protocol. A typical model, however, is for the server to passively listen on a network address for incoming connections and to publish that address to clients, and for the client to actively attempt to connect to the server at the published address; if the server accepts the connection, this protocol may then commence over the established connection.

Message Structure

The contents of each of the connection's streams is an 8-byte connection header followed by a sequence of variable length messages of the types described below. The initial byte of a message directly follows the final byte of the previous message (there is no padding to cause a particular alignment of message boundaries).

A message comprises a four-byte header optionally followed by more data, depending on the type of the message. The first byte of the message header defines the type of the message. Message types fall into two general categories: messages that pertain to the connection as a whole, which begin with a byte in the range 0-0xF, and messages that pertain to a particular session, which begin with a byte in the range 0x10-0xFF.

The following table lists the allowed ranges of values for the first byte of a message header, and what message type each range corresponds to. The value ranges are listed as both bit patterns, in which x represents a bit that may be either 0 or 1 for the given message type, and in hexadecimal, in which two hyphen-separated values indicate an inclusive range. Some of the hexadecimal ranges include more values than are legally allowed for the given message type, but the bit pattern range specifies the allowed values exactly.

bit pattern hexadecimal range message type
00000000 00 NoOperation
00000010 02 Shutdown
00000100 04 Ping
00000110 06 PingAck
00001000 08 Error
0001xxx0 10-1F IncrementRation
001000x0 20-23 Abort
00110000 30 Close
01000000 40 Acknowledgment
100xxxx0 80-9F Data
It is a protocol violation to send a message with a first byte that does not match one of the above bit patterns.

Sessions

A request and its associated response are communicated over a session. An established session has an associated session identifier that is an integer between 0 and 127 (inclusive). Thus, there can be at most 128 sessions concurrently established over one connection. The session identifier is included in the header of every message related to the associated session. In the structure of all message types, a session identifier is stored in a single byte with the most significant bit set to zero (and reserved for future use).

A session may be either established or terminated with respect to either endpoint. A session established with respect to an endpoint may also be finished with respect to that endpoint, meaning that the endpoint is finished sending data for that session. These and other session state changes occur as a result of messages sent for the associated session identifier.

For any transmitted message that affects the state of a session, the state change is clearly known first to the sender of the message (when the message is sent), and later to the receiver (when the message is received). All restrictions on what messages may be sent relating to the current state of a session require that there is some interleaved order of messages received and messages sent by a given endpoint for which the restrictions are satisfied.

Session Establishment

Only the client can establish new sessions (and thus only the client can initiate requests over the connection). To establish a new session, the client sends a Data message with the open flag set.

A session is established with respect to both endpoints when the client sends a Data message with the open flag set. The newly established session is associated with the session identifier contained in the message header. A session remains established with respect to a given endpoint until it becomes terminated with respect to that endpoint.

An established session is finished with respect to a given endpoint after the endpoint has sent a Data message with the eof flag set for the associated session identifier. A session finished with respect to a given endpoint still remains established with respect to that endpoint (and data still can be received) until it becomes terminated with respect to the endpoint. Note that a session can become both established and finished from a single Data message sent from the client, if both the open and the eof flags are set.

Session Termination

An established session is terminated with respect to the server after the server has sent a Close or an Abort message with the associated session identifier, after which the server can no longer use the session identifier to refer to that session. A session is terminated with respect to the client after the client has sent an Abort message with the associated session identifier.

The client may re-use a session identifier for establishing a new session after the previous session associated with that session identifier is terminated with respect to the client and the server, or after it is terminated with respect to the server and the client has sent a Data message with the eof flag set with the session identifier (after which the previous session associated with the session identifier becomes implicitly terminated with respect to the client).

Flow Control

Because sessions must be assumed to have arbitrary processing dependencies among them, it is a requirement of this protocol that the processing of any one session must not interfere with (and thus possibly be an inverse, deadlocking dependency for) any other session. Even without explicit processing dependencies among sessions, it would be undesirable for one session with blocked processing to starve the processing of other sessions. Therefore, the implementation must always be able to read more messages from the connection in a timely fashion, so that regardless of a state of any one session, a message waiting to be read for another session is not ignored indefinitely. For example, if the buffers allocated for holding data from one session become full and more data arrives for the session, this fact must not indefinitely postpone transmission and processing of data for any other session. Without a flow control mechanism (and without the burden of arbitrary buffering), the only way to avoid such deadlock or starvation conditions is to abort sessions that would otherwise interfere with timely message processing. This protocol does support a flow control mechanism to throttle incoming session data to support finite session buffer capacities without the need to abort sessions unnecessarily.

Each endpoint has two state values associated with each session:

inbound ration
how many bytes of data may currently be received for the session
outbound ration
how many bytes of data may currently be sent for the session
Both ration values are integers in the range 0 to 0x7FFFFFFF, inclusive. The inbound ration is only meaningful while the session is established with respect to the endpoint and established but not finished with respect to the other endpoint. The outbound ration is only meaningful while the session is established but not finished with respect to the endpoint and established with respect to the other endpoint.

When a session is first established, the client's inbound ration is the value that the client sent in the ClientConnectionHeader for the connection, and the client's outbound ration is the value that the server sent in the ServerConnectionHeader for the connection (although it will likely be immediately decremented by the length value of the Data message used to establish the session). Also, the server's outbound ration is the value that the client sent in the ClientConnectionHeader for the connection, and the server's inbound ration is the value that the server sent in the ServerConnectionHeader for the connection (although it will likely be immediately decremented by the length value of the Data message used to establish the session).

An endpoint's outbound ration for a session is incremented when it receives an IncrementRation message for that session with a non-zero increment, and it is decremented when it sends a Data message for that session with a non-zero length. An endpoint's inbound ration for a session is incremented when it sends an IncrementRation message for that session with a non-zero increment, and it is decremented when it receives a Data message for that session with a non-zero length. It is a protocol violation for an endpoint to send a Data message with a length value greater than its current outbound ration.

Connection Establishment

When the protocol first commences over the connection, the client must first send a ClientConnectionHeader message to the server, and the server must wait to receive one. After receiving the ClientConnectionHeader, the server must then first send a ServerConnectionHeader message in response. After sending a ServerConnectionHeader message, the server can send other messages as otherwise permitted. After receiving a ServerConnectionHeader message, the client can send other messages as permitted, including a Data message with the open flag set in order to establish a session.

The sequence of messages sent by the server ends with a Shutdown message, an Error message, or closure of the connection's stream from the server. The sequence of messages sent by the client ends with an Error message or closure of the connection's stream from the client.

ClientConnectionHeader Message

A ClientConnectionHeader message contains the following variable items:
initialRation: 16-bit integer
A ClientConnectionHeader message must and must only be sent by the client, as the first message of this protocol over the connection.

For all newly established sessions, the client's initial inbound ration and the server's initial outbound ration will be (initialRation * 256) if initialRation is non-zero, or infinity if initialRation is zero.

(If the server receives an invalid ClientConnectionHeader message, the server should respond with an Error message following the ServerConnectionHeader message.)

The structure of a ClientConnectionHeader message is 8 bytes as follows:

offset bit pattern content
0 to 3 01001010
01101101
01110101
01111000
magic number (ASCII "Jmux")
4 00000001
version
5 to 6 xxxxxxxx
xxxxxxxx
initialRation
7 00000000
reserved

ServerConnectionHeader Message

A ServerConnectionHeader message contains the following variable items:
initialRation: 16-bit integer
A ServerConnectionHeader message must and must only be sent by the server, as the first message of this protocol over the connection.

For all newly established sessions, the server's initial inbound ration and the client's initial outbound ration will be (initialRation * 256) if initialRation is non-zero, or infinity if initialRation is zero.

The structure of a ServerConnectionHeader message is 8 bytes as follows:

offset bit pattern content
0 to 3 01001010
01101101
01110101
01111000
magic number (ASCII "Jmux")
4 00000001
version
5 to 6 xxxxxxxx
xxxxxxxx
initialRation
7 00000000
reserved

NoOperation Message

A NoOperation message contains the following variable items:
length: 16-bit integer
data: sequence of length bytes
A NoOperation message may be sent by the client or the server. A NoOperation message should be ignored by the receiver.

The structure of a NoOperation message is (4+length) bytes as follows:

offset bit pattern content
0 00000000
NoOperation message type identifier
1 00000000
reserved
2 to 3 xxxxxxxx
xxxxxxxx
length
4 to (4+length-1) n/a data

Shutdown Message

A Shutdown message contains the following variable items:

length: 16-bit integer
detail: sequence of length bytes
The Shutdown message is used to indicate that the server is shutting down the connection in a graceful fashion.

A Shutdown message must only be sent by the server.

By definition, a Shutdown message is the last message of the protocol sent by the server over the connection; after sending a Shutdown message, the server will typically close the connection.

When the client receives a Shutdown message, it should discard the connection and consider all established sessions that were not finished with respect to the server as if they have been aborted (as with an Abort message) with no partial processing-- thus the client can safely retry such sessions on another connection without violating at most once execution semantics. Therefore, the server must only send a Shutdown message if it can guarantee that no currently established sessions have been processed with any possible side effects.

The server can use the detail item to provide the client with more information explaining the reason for the Shutdown message. The content of the detail item, if any, is a UTF-8 encoded string of unspecified content.

The structure of a Shutdown message is (4+length) bytes as follows:

offset bit pattern content
0 00000010
Shutdown message type identifier
1 00000000
reserved
2 to 3 xxxxxxxx
xxxxxxxx
length
4 to (4+length-1) n/a detail

Ping Message

A Ping message contains the following variable items:

cookie: 16-bit integer
The Ping message is used to test the liveness of the receiver.

A Ping message may be sent by the client or the server.

The sender may choose any arbitrary value for cookie. After sending a Ping message, the sender can expect the receiver to respond with exactly one corresponding PingAck message containing the same cookie value. The sender may expect the corresponding PingAck within a reasonable timeout, and if it is not received, the sender may consider the receiver to have gone down or become unreachable (such as due to a network partition), in which case it should discard the connection and consider all open sessions aborted (with partial processing, if the sender is the client).

The structure of a Ping message is 4 bytes as follows:

offset bit pattern content
0 00000100
Ping message type identifier
1 00000000
reserved
2 to 3 xxxxxxxx
xxxxxxxx
cookie

PingAck Message

A PingAck message contains the following variable items:
cookie: 16-bit integer
The PingAck message is used to respond to a Ping message.

A PingAck message may be sent by the client or the server, and must only be sent in response to exactly one previous Ping message received by the sender.

After receiving a Ping message with a given cookie value, an endpoint should immediately respond with a PingAck message with the same cookie value.

The structure of a PingAck message is 4 bytes as follows:

offset bit pattern content
0 00000110
PingAck message type identifier
1 00000000
reserved
2 to 3 xxxxxxxx
xxxxxxxx
cookie

Error Message

An Error message contains the following variable items:
length: 16-bit integer
detail: sequence of length bytes
The Error message is used to indicate that the sender has detected a protocol violation somewhere in the messages that it has received.

An Error message may be sent by the client or the server.

By definition, an Error message is the last message of the protocol sent by the sender over the connection; after sending an Error message, the sender will typically close the connection.

When the client receives an Error message, it should discard the connection and consider all established sessions that were not finished with respect to the server as if they have been aborted (as with an Abort message) with possible partial processing-- thus the client cannot safely retry such sessions on another connection without violating at most once execution semantics.

When the server receives an Error message, it should discard the connection and consider all established sessions as if they have been aborted.

The sender can use the detail item to provide the receiver with more information explaining the reason for the Error message. The content of the detail item, if any, is a UTF-8 encoded string of unspecified content.

The structure of an Error message is (4+length) bytes as follows:

offset bit pattern content
0 00001000
Error message type identifier
1 00000000
reserved
2 to 3 xxxxxxxx
xxxxxxxx
length
4 to (4+length-1) n/a detail

IncrementRation Message

An IncrementRation message contains the following variable items:
shift: 3-bit integer
sessionID: 7-bit integer
increment: 16-bit integer
The IncrementRation message is used to indicate that more data can be received by the sender for a given session.

An IncrementRation message may be sent by the client or the server. The sessionID must identify a session established with respect to the sender. (In other words, the client must not send an IncrementRation message after sending an Abort message for the given session, and the server must not send an IncrementMessage after sending a Close or an Abort message for the given session.)

An IncrementRation message indicates that the sender is prepared to receive (increment<<(shift*2)) more bytes for the session beyond its current inbound ration for the session identified by sessionID. After sending an IncrementRation message, the sender's inbound ration for the session is incremented by (increment<<(shift*2)), and after receiving an IncrementRation message, the receiver's outbound ration is incremented by (increment<<(shift*2)). It is a protocol violation for an IncrementRation message to cause the sender's inbound ration to exceed 0x7FFFFFFF. (Therefore, if the receiver's outbound ration is caused to exceed 0x7FFFFFFF, the receiver should respond with an Error message.)

If the session is finished (or terminated) with respect to the receiver, this message should be ignored.

For a given session, if an endpoint is expecting more data from the other endpoint but its inbound ration is zero, then it must send an IncrementRation message (with a non-zero increment) for that session.

The structure of an IncrementRation message is 4 bytes as follows:

offset bit pattern content
0 0001----
IncrementRation message type identifier
0 ----xxx-
shift
0 -------0
reserved
1 0-------
reserved
1 -xxxxxxx
sessionID
2 to 3 xxxxxxxx
xxxxxxxx
increment

Abort Message

An Abort message contains the following variable items:
partial: flag
sessionID: 7-bit integer
length: 16-bit integer
detail: sequence of length bytes
The Abort message is used to terminate a session abruptly, usually before its expected exchange of data has completed.

An Abort message may be sent by the client or the server. The partial flag must only be set when the sender is the server. The sessionID must identify a session established with respect to the sender.

An Abort message causes the session to be terminated with respect to the sender; the sender must not send any further messages for the session.

If the session is not yet terminated with respect to the receiver, then the receiver should cease sending messages for the session, except to respond in a timely fashion with an Abort message for the session so that it will be terminated with respect to the receiver.

If the client receives an Abort message with the partial flag set, then it must assume that any data sent over the session has been at least partially processed with any possible side effects-- thus the client cannot safely retry the session again without violating at most once execution semantics. If the client receives an Abort message with the partial flag not set, then it may assume that no data sent over the session has been even partially executed with any possible side effects-- thus the client can safely retry the session again without violating at most once execution semantics. Therefore, the server must only send an Abort message with the partial flag not set if it can guarantee that no amount of the data received for the session has been processed with any possible side effects.

The sender can use the detail item to provide the receiver with more information explaining the reason for the Abort message. The content of the detail item, if any, is a UTF-8 encoded string of unspecified content.

The structure of an Abort message is (4+length) bytes as follows:

offset bit pattern content
0 001000--
Abort message type identifier
0 ------x-
partial
0 -------0
reserved
1 0-------
reserved
1 -xxxxxxx
sessionID
2 to 3 xxxxxxxx
xxxxxxxx
length
4 to (4+length-1) n/a detail

Close Message

A Close message contains the following variable items:
sessionID: 7-bit integer
The Close message is used to indicate that the server is done with a particular session in the normal fashion.

A Close message must only be sent by the server. The sessionID must identify a session finished (but established) with respect to the server.

A Close message causes the session to be terminated with respect to the server; the server must not send any further messages for the session.

The server should send a Close message in a timely fashion after the session is finished with respect to the server and either finished with respect to the client or the server is not interested in the remainder of the request data, so that the client may reuse the session identifier. When possible, the server should use the abbreviated form of the Close message: the close flag of the Data message.

If the session is finished (or terminated) with respect to the client, then after receipt of a Close message for the session, the client may reuse the session identifier.

If the session is not yet terminated with respect to the client, then the client should cease sending messages for the session, except to respond in a timely fashion with an Abort message for the session so that it will be terminated with respect to the client as well, and then the client may reuse the session identifier. Note that in this case, the client must not consider the session to have failed; instead, it must provide the data received as the complete response, and it should consider that the server is not interested in the remainder of the request data, so it should be silently discarded.

The structure of a Close message is 4 bytes as follows:

offset bit pattern content
0 00110000
Close message type identifier
1 0-------
reserved
1 -xxxxxxx
sessionID
2 to 3 00000000
00000000
reserved

Acknowledgment Message

An Acknowledgment message contains the following variable items:
sessionID: 7-bit integer
The Acknowledgment message is used to indicate that the client is done processing the complete response data for a particular session.

An Acknowledgment message must only be sent by the client. The sessionID must identify a session established with respect to the client. An Acknowledgment must only be sent after the server has sent a Data message with the ackRequired flag set for the session, and it must only be sent once for the session.

Upon receipt of an Acknowledgment message, the server may consider that the client has finished processing the response.

The structure of an Acknowledgment message is 4 bytes as follows:

offset bit pattern content
0 01000000
Acknowledgment message type identifier
1 0-------
reserved
1 -xxxxxxx
sessionID
2 to 3 00000000
00000000
reserved

Data Message

A Data message contains the following variable items:
open: flag
eof: flag
close: flag
ackRequired: flag
sessionID: 7-bit integer
length: 16-bit integer
data: sequence of length bytes
The Data message is used by the client to establish a session, by the client or the server to transmit fragments of data for a session and to signal the end of data for a session, and by the server to terminate the session and to request an acknowledgment for complete processing of the data sent.

A Data message may be sent by the client or the server. The open flag must only be set when the sender is the client, and the close and ackRequired flags must only be set when the sender is the server. The close and the ackRequired flags must only be set if the eof flag is also set.

If the open flag is not set, then sessionID must identify a session established and not finished with respect to the sender. If the open flag is set, then sessionID must not identify an established session, and a new session is established associated with the session identifier sessionID.

The data of the message represents the next fragment of data that constitutes the request data (if sent by the client) or the response data (if sent by the server) of the session. It is a protocol violation for an endpoint to send a Data message with a length value greater than its current outbound ration for the session. (Therefore, if the receiver's inbound ration is less than length, the receiver should respond with an Error message.) After sending a Data message, the sender's outbound ration is decremented by length, and after receiving a Data message, the receiver's inbound ration is decremented by length.

The eof flag marks this message as containing the last fragment of data for the session, and thus the request or response data has been completely transmitted and the session is finished with respect to the sender.

The meaning of the close flag being set is equivalent to the meaning of the same Data message sent without the close flag being set immediately followed by a Close message with the same sessionID.

The ackRequired flag indicates that the server is interested in being notified with a positive acknowledgment when the client is done processing the response data for the session. Such a positive acknowledgment takes the form of an Acknowledgment message received from the client with the same sessionID. If instead the server receives an Abort message with the same sessionID, or the server receives a Data message with the open flag set and the same sessionID, or the connection is closed, then that constitutes a negative acknowledgment (as a positive acknowledgment could never be received).

After the client has received a Data message with the ackRequired flag set, it should send an Acknowledgment message with the same sessionID in a timely fashion after it is done processing the response data.

The structure of a Data message is (4+length) bytes as follows:

offset bit pattern content
0 100-----
Data message type identifier
0 ---x----
open
0 ----x---
close
0 -----x--
eof
0 ------x-
ackRequired
0 -------0
reserved
1 0-------
reserved
1 -xxxxxxx
sessionID
2 to 3 xxxxxxxx
xxxxxxxx
length
4 to (4+length-1) n/a data


Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.