12
The complete OMG IDL specifications for the GIOP and IOP are shown in Section 12.8, "OMG IDL for the GIOP and IIOP Specifications," on page 12-29 . Fragments of the specification are used throughout this chapter as necessary.
12.2.1 Common Data Representation (CDR)
CDR is a transfer syntax, mapping from data types defined in OMG IDL to a bicanonical, low-level representation for transfer between agents. CDR has the following features:
An octet stream is an abstract notion that typically corresponds to a memory buffer that is to be sent to another process or machine over some IPC mechanism or network transport. For the purposes of this discussion, an octet stream is an arbitrarily long (but finite) sequence of eight-bit values (octets) with a well-defined beginning. The octets in the stream are numbered from 0 to n-1, where n is the size of the stream. The numeric position of an octet in the stream is called its index. Octet indices are used to calculate alignment boundaries, as described in "Alignment" on page 12-5.
GIOP defines two distinct kinds of octet streams, messages and encapsulations. Messages are the basic units of information exchange in GIOP, described in detail in "GIOP Message Formats" on page 12-15.
Encapsulations are octet streams into which OMG IDL data structures may be marshaled independently, apart from any particular message context. Once a data structure has been encapsulated, the octet stream can be represented as the OMG IDL opaque data type sequence<octet>, which can subsequently marshaled into a message or another encapsulation. Encapsulations allow complex constants (such as TypeCodes) to be pre-marshaled; they also allow certain message components to be handled without requiring full unmarshaling. Whenever encapsulations are used in CDR or the GIOP, they are clearly noted.
12.3.1 Primitive Types
Primitive data types are specified for both big-endian and little-endian orderings. The message formats (see "GIOP Message Formats" on page 12-15) include tags in message headers that indicate the byte ordering in the message. Encapsulations include an initial flag that indicates the byte ordering within the encapsulation, described in "Encapsulation" on page 12-9. The byte ordering of any encapsulation may be different from the message or encapsulation within which it is nested. It is the responsibility of the message recipient to translate byte ordering if necessary.
Primitive data types are encoded in multiples of octets. An octet is an 8-bit value.
Alignment
In order to allow primitive data to be moved into and out of octet streams with instructions specifically designed for those primitive data types, in CDR all primitive data types must be aligned on their natural boundaries; i.e., the alignment boundary of a primitive datum is equal to the size of the datum in octets. Any primitive of size n octets must start at an octet stream index that is a multiple of n. In CDR, n is one of 1, 2, 4, or 8.
TYPE
|
OCTET ALIGNMENT
|
---|---|
char
|
1
|
octet
|
1
|
short
|
2
|
unsigned short
|
2
|
long
|
4
|
unsigned long
|
4
|
float
|
4
|
double
|
8
|
boolean
|
1
|
enum
|
4
|
Alignment is defined above as being relative to the beginning of an octet stream. The first octet of the stream is octet index zero (0); any data type may be stored starting at this index. Such octet streams begin at the start of an GIOP message header (see "GIOP Message Header" on page 12-15) and at the beginning of an encapsulation, even if the encapsulation itself is nested in another encapsulation. (See "Encapsulation" on page 12-9).
Integer Data Types
Figure 12-1 illustrates the representations for OMG IDL integer data types, including the following data types:
Figure 12-1 Sizes and bit ordering in big-endian and little-endian encodings of OMG IDL integer data types, both signed and unsigned.
For single-precision float values the exponent is 8 bits long, comprising e1 and e2 in the figure, where the 7 bits in e1 are most significant. The exponent is represented as excess 127. The fractional mantissa (f1 - f3) is a 23-bit value f where 1.0 <= f < 2.0, f1 being most significant and f3 being least significant. The value of a normalized number is described by:
Octet
Octets are uninterpreted 8-bit values whose contents are guaranteed not to undergo any conversion during transmission. For the purposes of describing possible octet values in this specification, octets may be considered as unsigned 8-bit integer values. Boolean
Boolean values are encoded as single octets, where TRUE is the value 1, and FALSE as 0. Character Types
OMG IDL characters are represented single octets, encoded as defined by ISO Latin-1 (8859.1). 12.3.2 OMG IDL Constructed Types
Constructed types are built from OMG IDL's data types using facilities defined by the OMG IDL language. Alignment
Constructed type have no alignment restrictions beyond those of their primitive components; the alignment of those primitive types is not intended to support use of marshaling buffers as equivalent to the implementation of constructed data types within any particular language environment. GIOP assumes that agents will usually construct structured data types by copying primitive data between the marshaled buffer and the appropriate in-memory data structure layout for the language mapping implementation involved. Struct
The components of a structure are encoded in their order of their declaration in the structure. Each component is encoded as defined for its data type. Union
Unions are encoded as the discriminant tag of the type specified in the union declaration, followed by the representation of any selected member, encoded as its type indicates. Array
Arrays are encoded as the array elements in sequence. As the array length is fixed, no length values are encoded. Each element is encoded as defined for the type of the array. In multidimensional arrays, the elements are ordered so the index of the first dimension varies most slowly, and the index of the last dimension varies most quickly. Sequence
Sequences are encoded as an unsigned long value, followed by the elements of the sequence. The initial unsigned long contains the number of elements in the sequence. The elements of the sequence are encoded as specified for their type. String
Strings are encoded as an unsigned long containing the length of the string, followed by the individual characters in the string, encoded in ISO Latin-1 (8859.1). The length (initial unsigned long) and string representation include a terminating null character, so that conventional C-string handling library routines (e.g., strcpy
) may be used in the encoded message buffer. Enum
Enum values are encoded as unsigned longs. The numeric values associated with enum identifiers are determined by the order in which the identifiers appear in the enum declaration. The first enum identifier has the numeric value zero (0). Successive enum identifiers are take ascending numeric values, in order of declaration from left to right. 12.3.3 Encapsulation
As described above, OMG IDL data types may be independently marshaled into encapsulation octet streams. The octet stream is represented as the OMG IDL type sequence<octet>, which may be subsequently included in a GIOP message or nested in another encapsulation.
When encapsulating OMG IDL data types, the first octet in the stream (index 0) contains a boolean value indicating the byte ordering of the encapsulated data. If the value is FALSE (0), the encapsulated data is encoded in big-endian order; if TRUE (1), the data is encoded in little-endian order, exactly like the byte order flag in GIOP message headers (see "GIOP Message Header" on page 12-15). This value is not part of the data being encapsulated, but is part of the octet stream holding the encapsulation. Following the byte order flag, the data to be encapsulated is marshaled into the buffer as defined by CDR encoding rules. Marshaled data are aligned relative to the beginning of the octet stream (the first octet of which is occupied by the byte order flag).
When the encapsulation is encoded as type sequence<octet> for subsequent marshaling, an unsigned long value containing the sequence length is prefixed to the octet stream, as prescribed for sequences (see "Sequence" on page 12-8). The length value is not part of the encapsulation's octet stream, and does not affect alignment of data within the encapsulation. Note that this guarantees a four octet alignment of the start of all encapsulated data within GIOP messages and nested encapsulations.2
12.3.4 Pseudo-Object Types
CORBA defines some kinds of entities that are neither primitive types (integral or floating point) nor constructed ones. TypeCode
In general, TypeCodes are encoded as the TCKind enum value, potentially followed by values that represent the TypeCode parameters. Unfortunately, TypeCodes cannot be expressed simply in OMG IDL, since their definitions are recursive. The basic TypeCode representations are given in Table 12-2. The enum value column this table gives the TCKind enum value corresponding to the given TypeCode, and lists the parameters associated with such a TypeCode. The rest of this section presents the details of the encoding.
Basic TypeCode Encoding Framework
The encoding of a TypeCode is the TCKind enum value (encoded, like all enum values, using four octets), followed by zero or more parameter values. The encodings of the parameter lists fall into three general categories, and differ in order to conserve space and to support efficient traversal of the binary representation:
TypeCode Parameter Notation
TypeCode parameters are specified in the fourth column of Table 12-2. The ordering and meaning of parameters is a superset of those given in the Interface Repository specification (Chapter 6); more information is needed by CDR's representation in order to provide the full semantics of TypeCodes as shown by the API.
unsigned
long
, and then each parameter in each tuple (using the noted type), is encoded in the CDR representation of the typecode. Each tuple is encoded, first parameter followed by second etc., before the next tuple is encoded (first, then second, etc.).
tk_union
TypeCodes are established by the second encoded parameter (discriminant type), and cannot be specified except with reference to a specific OMG IDL definition.
Encoded Identifiers and Names
The Repository ID parameters in tk_objref, tk_struct, tk_union, tk_enum, tk_alias, and tk_except TypeCodes are Interface Repository RepositoryId
values, whose format is described in the specification of of the Interface Repository. RepositoryId values are required for tk_objref and tk_except TypeCodes; for other TypeCodes they are optional and are encoded as empty strings if omitted. Encoding the tk_union Default Case
In tk_union TypeCodes, the long default used value is used to indicate which tuple in the sequence describes the union's default
case. If this value is less than zero, then the union contains no default case. Otherwise, the value contains the zero based index of the default case in the sequence of tuples describing union members. TypeCodes for Multi-Dimensional Arrays
The tk_array TypeCode only describes a single dimension of any array. TypeCodes for multi-dimensional arrays are constructed by nesting tk_array TypeCodes within other tk_array TypeCodes, one per array dimension. The outermost (or top-level) tk_array TypeCode describes the leftmost array index of the array as defined in IDL; the innermost nested tk_array TypeCode describes the rightmost index. Indirection: Recursive and Repeated TypeCodes
The typecode representation of OMG IDL data types that can indirectly contain instances of themselves (e.g struct foo {sequence <foo> bar;}) must also contain an indirection. Such an indirection is also useful to reduce the size of encodings; for example, unions with many cases sharing the same value.
The encoding of such an indirection is as a TypeCode with an "TCKind value" that has the special value 232-1 (0xffffffff, all ones). Such typecodes have a single (simple) parameter, which is the
long
offset (in units of octets) from the simple parameter. (As an example, that this means offset of negative four (-4) is illegal, because it be self-indirecting.)
By representing Principal values as sequence<octet>, GIOP guarantees that ORBs may use domain-specific principal identification schemes; such values undergo no translation or interpretation during transmission. This allows bridges to translate or interpret these identifiers as needed when forwarding requests between different security domains.
Note ¯ A catalog of minor codes for CORBA's System Exceptions will be provided, based on implementers' agreements. Such an agreement is needed to support complete interoperability, since otherwise applications could distinguish ORBs based on the diagnostics they report, and could not reliably assign meanings to system exceptions reported to them.
12.3.5 Object References
Object references are encoded in OMG IDL as described in "Object Addressing" on page 10-11. IOR profiles contain transport-specific addressing information, so there is no general-purpose IOR profile format defined for GIOP. Instead, this specification describes the general information model for GIOP profiles and provides a specific format for the IIOP (see "IIOP IOR Profiles" on page 12-27).
In general, GIOP profiles shall include at least these three elements:
GIOP message types are summarized in Table 12-3, which lists the message type names, whether the message is originated by client, server, or both, and the value used to identify the message type in GIOP message headers.
12.4.1 GIOP Message Header
All GIOP messages begin with the following header, defined in OMG IDL: enum MsgType {
Request, Reply, CancelRequest,
LocateRequest, LocateReply,
CloseConnection, MessageError
};
struct MessageHeader {
char magic [4];
Version GIOP_version;
boolean byte_order;
octet message_type;
unsigned long message_size;
};
};
Request messages have three elements, encoded in this order:
module GIOP { // IDL
struct RequestHeader {
IOP::ServiceContextList service_context;
unsigned long request_id;
boolean response_expected;
sequence <octet> object_key;
string operation;
Principal requesting_principal;
};};
The members have the following definitions:
TRUE
if the request is expected to have an associated reply. The value is FALSE
if the operation is defined as oneway, or if the operation is invoked with the DII and the invocation flags include the INV_NO_RESPONSE
flag.
_get_<attribute>
and _set_<attribute>
. The case of the operation or attribute name must match the case of the operation name specified in the OMG IDL source for the interface being used.
CORBA::Object
operations that are defined in the CORBA Core ("Object Reference Operations" on page 7-2) and that correspond to GIOP request messages, the operation names are _interface
, _implementation5
, _is_a
and _not_existent
.
double example (in short m, out string str, inout Principal p);would be equivalent to this structure:
struct example_body {
short m; // leftmost in or inout parameter
Principal p; // ... to the rightmost};
Reply messages have three elements, encoded in this order:
module GIOP { // IDL
enum ReplyStatusType {
NO_EXCEPTION,
USER_EXCEPTION,
SYSTEM_EXCEPTION,
LOCATION_FORWARD
};
struct ReplyHeader {
IOP::ServiceContextList service_context;
unsigned long request_id;
ReplyStatusType reply_status;
};};
The members have the following definitions:
inout
and out
parameters in the order in which they appear in the operation's OMG IDL definition, from left to right. (That structure could be empty.)
struct example_reply {
double return_value; // return value
string str; // leftmost inout or out parameter
Principal p; // ... to the rightmost
};
field embedded in the new object reference's GIOP profile may not have the same value as the object_key in the GIOP profile of the original object reference. For details on location forwarding, see "Object Location" on page 12-25.
12.4.3 CancelRequest Message
CancelRequest messages may be sent from clients to servers. CancelRequest messages notify a server that the client is no longer expecting a reply for a specified pending Request or LocateRequest message.
module GIOP { // IDL
struct CancelRequestHeader {
unsigned long request_id;
};};
The request_id member identifies the Request or LocateRequest message to which the cancel applies. This value is the same as the request_id value specified in the original Request or LocateRequest message.
When a client issues a cancel request message, it serves in an advisory capacity only. The server is not required to acknowledge the cancellation, and may subsequently send the corresponding reply. The client should have no expectation about whether a reply (including an exceptional one) arrives.
(b)
whether the current server is capable of directly receiving requests for the object reference, and if not, (c) to what address requests for the object reference should be sent.Note that this information is also provided through the Request message, but that some clients might prefer not to support retransmission of potentially large messages that might be implied by a LOCATION_FORWARD status in a Reply message. That is, client use of this represents a potential optimization.
LocateRequest messages have two elements, encoded in this order:
module GIOP { // IDL
struct LocateRequestHeader {
unsigned long request_id;
sequence <octet> object_key;
};};
The members are defined as follows:
12.4.5 LocateReply Message
LocateReply messages are sent from servers to clients in response to LocateRequest messages.
module GIOP { // IDL
enum LocateStatusType {
UNKNOWN_OBJECT,
OBJECT_HERE,
OBJECT_FORWARD
};
struct LocateReplyHeader {
unsigned long request_id;
LocateStatusType locate_status;
};};
The members have the following definitions:
same
request_id
value as the corresponding LocateRequest message.
The CloseConnection message consists only of the GIOP message header, identifying the message type.
For details on the usage of CloseConnection messages, see "Connection Management" on page 12-24.
12.4.7 MessageError Message
The MessageError message is sent in response to any GIOP message whose version number or message type is unknown to the recipient, or any message is received whose header is not properly formed (e.g., has the wrong magic value). Error handling is context-specific. 12.5 GIOP Message Transport
The GIOP is designed to be implementable on a wide range of transport protocols. The GIOP definition makes the following assumptions regarding transport behavior:
12.5.1 Connection Management
For the purposes of this discussion, the roles client and server are defined as follows:
Connections are not symmetrical. Only clients can send Request, LocateRequest, and CancelRequest messages over a connection. Only a server can send Reply, LocateReply and CloseConnection messages over a connection. Either client or server can send MessageError messages.
Only GIOP messages are sent over GIOP connections.
Request IDs must unambiguously associate replies with requests within the scope and lifetime of a connection. Request IDs may be re-used if there is no possibility that the previous request using the ID may still have a pending reply. Note that cancellation does not guarantee no reply will be sent. It is the responsibility of the client to generate and assign request IDs. Request IDs must be unique among both Request and LocateRequest messages.
If a client receives an CloseConnection message from the server, it should assume that any outstanding messages (i.e., without replies) were received after the server sent the CloseConnection message, were not processed, and may be safely resent on a new connection.
After reliably issuing a CloseConnection message, the server may close the connection. Some transport protocols (not including TCP) do not provide an "orderly disconnect" capability, guaranteeing reliable delivery of the last message sent. When GIOP is used with such protocols an additional handshake needs to be provided to guarantee that both ends of the connection understand the disposition of any outstanding GIOP requests.
If a client detects connection closure without receiving a CloseConnection message, it should assume an abortive disconnect has occurred, and treat the condition as an error. Specifically, it should report COMM_FAILURE exceptions for all pending requests on the connection, with completion_status values set to COMPLETED_MAYBE.
Clients may have multiple pending requests. A client need not wait for a reply from a previous request before sending another request.
Servers may reply to pending requests in any order. Reply messages are not required to be in the same order as the corresponding Requests.
The ordering restrictions regarding connection closure mentioned in Connection Management, above, are also noted here. Servers may only issue CloseConnection messages when Reply messages have been sent in response to all received Request messages that require replies.
A given transport address does not necessarily correspond to any specific ORB architectural component (such as an object adapter, object server process, Inter-ORB bridge, and so forth). It merely implies the existence of some agent with which a connection may be opened, and to which requests may be sent.
The "agent" (owner of the server side of a connection) may have one of the following roles with respect to a particular object reference:
Clients must, however, be able to accept and process Reply messages with
LOCATION_FORWARD
status, since any ORB may choose to implement a location service. Whether a client chooses to send LocationRequest messages is at the discretion of the client. For example, if the client routinely expected to see LOCATION_FORWARD
replies when using the address in an object reference, it might always send LocateRequest messages to objects for which it has no recorded forwarding address. If a client sends LocateRequest messages, it should (obviously) be prepared to accept LocateReply messages.A client should not make any assumptions about the longevity of object addresses returned by location forwarding mechanisms. Once a connection based on location forwarding information is closed, subsequent attempts to send requests to the same object should start with the original address specified in the initial object reference.
Even after performing successful invocations using an address, a client should be prepared to be forwarded. The only object address that a client should expect to continue working reliably is the one in the initial object reference. If an invocation using that address returns UNKNOWN_OBJECT, the object should be deemed non-existent.
In general, the implementation of location forwarding mechanisms is at the discretion of ORBs, available to be used for optimization and to support flexible object location and migration behaviors.
12.7.1 TCP/IP Connection Usage
Agents that are capable of accepting object requests or providing locations for objects (i.e., servers) publish TCP/IP addresses in IORs, as described in "IIOP IOR Profiles" on page 12-27. A TCP/IP address consists of an IP host address, typically represented by a host name, and a TCP port number. Servers must listen for connection requests.
A client needing a object's services must initiate a connection with the address specified in the IOR, with a connect request.
12.7.2 IIOP IOR Profiles
IIOP profiles, identifying individual objects accessible through the Internet Inter_ORB Protocol, have the following form: struct Version {
char major;
char minor;
};
struct ProfileBody {
Version iiop_version;
string host;
unsigned short port;
sequence <octet> object_key;
};
};tag
has the value TAG_INTERNET_IOP (as defined earlier).
Also, note that at this time no "well known" port number has been allocated, so individual agents will need to assign previously unused ports as part of their installation procedures. IIOP supports multiple such agents per host.
enum MsgType {
Request, Reply, CancelRequest,
LocateRequest, LocateReply,
CloseConnection, MessageError
};
struct MessageHeader {
char magic [4];
Version GIOP_version;
boolean byte_order;
octet message_type;
unsigned long message_size;
};
struct RequestHeader {
IOP::ServiceContextList service_context;
unsigned long request_id;
boolean response_expected;
sequence <octet> object_key;
string operation;
Principal requesting_principal;
};
enum ReplyStatusType {
NO_EXCEPTION,
USER_EXCEPTION,
SYSTEM_EXCEPTION,
LOCATION_FORWARD
};
struct ReplyHeader {
IOP::ServiceContextList service_context;
unsigned long request_id;
ReplyStatusType reply_status;
};
struct CancelRequestHeader {
unsigned long request_id;
};
struct LocateRequestHeader {
unsigned long request_id;
sequence <octet> object_key;
};
enum LocateStatusType {
UNKNOWN_OBJECT,
OBJECT_HERE,
OBJECT_FORWARD
};
struct LocateReplyHeader {
unsigned long request_id;
LocateStatusType locate_status;
};};
struct Version {
char major;
char minor;
};
struct ProfileBody {
Version iiop_version;
string host;
unsigned short port;
sequence <octet> object_key;
};};
2 Accordingly, in cases where encapsulated data holds data with natural alignment of greater than four octets, some processors may need to copy the octet data before removing it from the encapsulation. The GIOP protocol itself does not require encapsulation of such data.
3 This means that, for example, two OMG IDL unions that are textually equivalent, except that one uses a "char" discriminant, and the other uses a "long" one, would have different size encoded TypeCodes.
4 Compiled stubs are guaranteed to know how to unmarshal all exceptions. As of this writing, there are recognized problems with the language mappings for the DII in that they can not provide the ORB core with the same amount of information that can be provided to it by compiled stubs, unless an implementation of the DII consults an Interface Repository. Those mappings are being revised to address this issue.
5 Since CORBA::Object::get_implementation is a null interface, clients must narrow the object reference they get to some ORB-specific kind of ImplementationDef.
6 Postel, J., "Transmission Control Protocol - DARPA Internet Program Protocol Specification", RFC-793, Information Sciences Institute, September 1981
pubs@omg.org Copyright © 1995, Object Management Group. All rights reserved.