[Top] [Prev] [Next] [Bottom]

General Inter-ORB Protocol

12


This chapter specifies a General Inter-ORB Protocol (GIOP) for ORB interoperability, which can be mapped onto any connection-oriented transport protocol that meets a minimal set of assumptions. This chapter also defines a specific mapping of the GIOP which runs directly over TCP/IP connections, called the Internet Inter-ORB Protocol (IIOP). The IIOP must be supported by conforming networked ORB products regardless of other aspects of their implementation. Such support does not require using it internally; conforming ORBs may also provide bridges to this protocol.

12.1 Goals of the General Inter-ORB Protocol

The GIOP and IIOP support protocol-level ORB interoperability in a general, low-cost manner. The following objectives were pursued vigorously in the GIOP design:

The approach a particular ORB takes to providing support for the GIOP/IIOP is undefined. For example, an ORB could choose to use the IIOP as its internal protocol, it could choose to externalize IIOP as much as possible by implementing it in a half-bridge, or it could choose a strategy between these two extremes. All that is required of a conforming ORB is that some entity or entities in or associated with the ORB be able to send and receive IIOP messages.

12.2 General Inter-ORB Protocol Overview

The GIOP specification consists of the following elements:

The IIOP specification adds the following element to the GIOP specification:

The IIOP is not a separate specification; it is a specialization, or mapping, of the GIOP to a specific transport (TCP/IP). The GIOP specification (without the transport-specific IIOP element) may be considered as a separate conformance point for future mappings to other transport layers.

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:

12.2.2 GIOP Message Overview

The GIOP specifies formats for messages that are exchanged between inter- operating ORBs. GIOP message formats have the following features:

GIOP also supports passing service-specific context, such as the transaction context defined by the Transaction Service (the Transaction Service is described in CORBAservices). This mechanism is designed to support any service that requires service related context to be implicitly passed with requests.

12.2.3 GIOP Message Transfer

The GIOP specification is designed to operate over any connection-oriented transport protocol that meets a minimal set of assumptions (described in "GIOP Message Transport" on page 12-23). GIOP uses underlying transport connections in the following ways:

12.3 CDR Transfer Syntax

The Common Data Representation (CDR) transfer syntax is the format in which the GIOP represents OMG IDL data types in an octet stream.

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.

Where necessary, an alignment gap precedes the representation of a primitive datum. The value of octets in alignment gaps is undefined. A gap must be the minimum size necessary to align the following primitive. Table 12-1 gives alignment boundaries for CDR/OMG-IDL primitive types.
Table 12-1 Alignment requirements for OMG IDL primitive data types

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:

The figure illustrates bit ordering and size. Signed types (short and long) are represented as two's complement numbers; unsigned versions of these types are represented as unsigned binary numbers.

Figure 12-1 Sizes and bit ordering in big-endian and little-endian encodings of OMG IDL integer data types, both signed and unsigned.

Floating Point Data Types

Figure 12-2 on page 7 illustrates the representation of floating point numbers. These exactly follow the IEEE standard formats for floating point numbers1, selected parts of which are abstracted here for explanatory purposes. The diagram shows three different components for floating points numbers, the sign bit (s), the exponent (e) and the fractional part (f) of the mantissa. The sign bit has values of 0 or 1, representing positive and negative numbers, respectively.

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:

For double-precision values the exponent is 11 bits long, comprising e1 and e2 in the figure, where the 7 bits in e1 are most significant. The exponent is represented as excess 1023. The fractional mantissa (f1 - f7) is a 52-bit value m where 1.0 <= m < 2.0, f1 being most significant and f7 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).

Figure 12-2 Sizes and bit ordering in big-endian and little-endian representations of OMG IDL single and double precision floating point numbers.

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.

The GIOP and IIOP explicitly use encapsulations in three places: TypeCodes (see "TypeCode" on page 12-10), the IIOP protocol profile inside an IOR (see "Object References" on page 12-15), and in service-specific context (see "Object Service Context" on page 10-18). In addition, some ORBs may use choose to use an encapsulation to hold Principal identification information (see "Principal" on page 12-14), the object_key (see "IIOP IOR Profiles" on page 12-27), or in other places that a sequence<octet> data type is in use.

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:

The third column of Table 12-2 shows whether each parameter list is empty, simple, or complex. Also, note that an internal indirection facility is needed to represent some kinds of typecodes; this is explained in "Indirection: Recursive and Repeated TypeCodes" on page 12-13. This indirection does not need to be exposed to application programmers.

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.

Note that the tuples identifying struct, exception and enum members must be in the order defined in the OMG IDL definition text. Also, that the types of discriminant values in encoded 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.
Table 12-2 TypeCode enum values, parameter list types, and parameters

TCKind

Integer Value

Type

Parameters

tk_null

0

empty

- none -

tk_void

1

empty

- none -

tk_short

2

empty

- none -

tk_long

3

empty

- none -

tk_ushort

4

empty

- none -

tk_ulong

5

empty

- none -

tk_float

6

empty

- none -

tk_double

7

empty

- none -

tk_boolean

8

empty

- none -

tk_char

9

empty

- none -

tk_octet

10

empty

- none -

tk_any

11

empty

- none -

tk_TypeCode

12

empty

- none -

tk_Principal

13

empty

- none -

tk_objref

14

complex

string (repository ID), string(name)

tk_struct

15

complex

string (repository ID), string (name), ulong (count) {string (member name), TypeCode (member type)}

tk_union

16

complex

string (repository ID), string(name), TypeCode (discriminant type), long (default used), ulong (count) {discriminant type1 (label value), string (member name), TypeCode (member type)}

tk_enum

17

complex

string (repository ID), string (name), ulong (count) {string (member name)}

tk_string

18

simple

ulong (max length2)

tk_sequence

19

complex

TypeCode (element type), ulong (max length3)

tk_array

20

complex

TypeCode (element type), ulong (length)

tk_alias

21

complex

string (repository ID), string (name), TypeCode

tk_except

22

complex

string (repository ID), string (name), ulong (count) {string (member name), TypeCode (member type)}

- none -

0xffffffff

simple

long (indirection4)

1 The type of union label values is determined by the second parameter, discriminant type.

2 For unbounded strings, this value is zero.

3 For unbounded sequences, this value is zero.

4 See "Indirection: Recursive and Repeated TypeCodes" on page 12-13.

3

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.

The name parameters in tk_objref, tk_struct, tk_union, tk_enum, tk_alias, and tk_except TypeCodes and the member name parameters in tk_struct, tk_union, tk_enum and tk_except TypeCodes are not specified by (or significant in) GIOP. Agents should not make assumptions about type equivalence based on these name values; only the structural information (including RepositoryId values, if provided) is significant. If provided, the strings should be the simple, unscoped names supplied in the OMG IDL definition text. If omitted, they are encoded as empty strings.

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.

CDR provides a constrained indirection to resolve this problem:

The indirection is a numeric octet offset within the scope of the "top level" TypeCode and points to the TCKind value for the typecode. (Note that the byte order of the TCKind value can be determined by its encoded value.) This indirection may well cross encapsulation boundaries, but this is not problematic because of first constraint identified above. Because of the second constraint, the value of the offset will always be negative.

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.)

Any

Any values are encoded as a TypeCode (encoded as described above) followed by the encoded value.

Principal

Principal pseudo objects are encoded as sequence<octet>. In the absence of a Security service specification, Principal values have no standard format or interpretation, beyond (as described in the CORBA CORE) serving to identify callers (and potential callers). This specification does not define any inter-ORB security mechanisms, or prescribe any usage of Principal values.

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.

Context

Context pseudo objects are encoded as sequence<string>. The strings occur in pairs. The first string in each pair is the context property name, and the second string in each pair is the associated value.

Exception

Exceptions are encoded as a string followed by exception members, if any. The string contains the RepositoryId for the exception, as defined in the Interface Repository chapter. Exception members (if any) are encoded in the same manner as a struct.4

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:

12.4 GIOP Message Formats

In describing GIOP messages, it is necessary to define client and server roles. For the purpose of this discussion, a client is the agent that opens a connection (see more details in "Connection Management" on page 12-24) and originates requests. A server is an agent that accepts connections and receives requests.

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.
Table 12-3 GIOP Message Types and originators

Message Type

Originator

Value

Request

Client

0

Reply

Server

1

CancelRequest

Client

2

LocateRequest

Client

3

LocateReply

Server

4

CloseConnection

Server

5

MessageError

Both

6

12.4.1 GIOP Message Header

All GIOP messages begin with the following header, defined in OMG IDL:

module GIOP {

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;
};
};

The message header clearly identifies GIOP messages, but is defined to be byte-ordering independent, since the header itself defines the byte ordering of subsequent message elements. The members of the header are:

Request Message

Request messages encode CORBA object invocations, including attribute accessor operations, and CORBA::Object operations get_interface and get_implementation. Requests flow from client to server.

Request messages have three elements, encoded in this order:

Request Header

The request header is specified as follows:

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:

Request Body

The request body includes the following items encoded in this order:

For example, the request body for the following OMG IDL operation

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
};

12.4.2 Reply Message

Reply messages are sent in response to Request messages. Replies include inout and out parameters, operation results, and may include exception values. In addition, Reply messages may provide object location information. Replies flow from server to client.

Reply messages have three elements, encoded in this order:

Reply Header

The reply header is defined as follows:

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:

Reply Body

The reply body format is controlled by the value of reply_status. There are three types of reply body:

For example, the reply body for a successful response (the value of reply_status is NO_EXCEPTION) to the Request example shown on page 12-18 would be equivalent to the following structure:

struct example_reply {

double return_value; // return value
string str; // leftmost inout or out parameter
Principal p; // ... to the rightmost
};

Note that the object_key field in any specific GIOP profile is server-relative, not absolute. Specifically, when a new object reference is received in a LOCATION_FORWARD Reply or in a LocateReply message, the object_key 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.

CancelRequest messages have two elements, encoded in this order:

Cancel Request Header

The cancel request header is defined as follows:

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.

12.4.4 LocateRequest Message

LocateRequest messages may be sent from a client to a server to determine the following regarding a specified object reference: (a) whether the object reference is valid, (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:

LocateRequest Header.

The LocateRequest header is defined as follows:

module GIOP { // IDL

struct LocateRequestHeader {
unsigned long request_id;
sequence <octet> object_key;
};
};

The members are defined as follows:

See "Object Location" on page 12-25 for details on the use of LocateRequest.

12.4.5 LocateReply Message

LocateReply messages are sent from servers to clients in response to LocateRequest messages.

A LocateReply message has three elements, encoded in this order:

Locate Reply Header

The locate reply header is defined as follows:

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:

LocateReply Body

The body is empty unless the LocateStatus value is OBJECT_FORWARD, in which case the body contains an object reference (IOR) that may be used as the target for requests to the object specified in the LocateRequest message.

12.4.6 CloseConnection Message

CloseConnection messages are sent only by servers. They inform clients that the server intends to close the connection and must not be expected to provide further responses. Moreover, clients know that any requests for which they awaiting replies will never be processed, and may safely be reissued (on another connection).

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.

The MessageError message consists only of the GIOP message header, identifying the message type.

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:

The server does not actively initiate connections, but is prepared to accept requests to connect (i.e., it listens for connections in TCP/IP terms). Another agent that knows the address (called a client) can attempt to initiate connections by sending connect requests to the address. The listening server may accept the request, forming a new, unique connection with the client, or it may reject the request (e.g., due to lack of resources). Once a connection is open, either side may close the connection. (However, see "Connection Management" on page 12-24 for semantic issues related to connection closure.) A candidate transport might not directly support this specific connection model; it is only necessary that the transport's model can be mapped onto this view.

12.5.1 Connection Management

For the purposes of this discussion, the roles client and server are defined as follows:

These terms only denote roles with respect to a connection. They do not have any implications for ORB or application architectures.

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.

Connection Closure

Connections can be closed in two ways: orderly shutdown, or abortive disconnect. Orderly shutdown is initiated by servers reliably sending a CloseConnection message, or by clients just closing down a connection. Orderly shutdown may be initiated by the client at any time. If there are pending requests when a client shuts down a connection, the server should consider all such requests canceled. A server may not initiate shutdown if it has begun processing any requests for which it has not either received a CancelRequest or sent a corresponding reply.

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.

Multiplexing Connections

A client, if it chooses, may send requests to multiple target objects over the same connection, provided that the connection's server side is capable of responding to requests for the objects. It is the responsibility of the client to optimize resource usage by re-using connections, if it wishes. If not, the client may open a new connection for each active object supported by the server, although this behavior should be avoided.

12.5.2 Message Ordering

Only the client (connection originator) may send Request, LocateRequest, and CancelRequest messages. Connections are not fully symmetrical.

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.

12.6 Object Location

The GIOP is defined to support object migration and location services without dictating the existence of specific ORB architectures or features. The protocol features are based on the following observations:

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:

Agents are not required to implement location forwarding mechanisms. An agent can be implemented with the policy that a connection either supports direct access to an object, or returns exceptions. Such an ORB (or inter-ORB bridge) always return LocateReply messages with either OBJECT_HERE or UNKNOWN_OBJECT status, and never OBJECT_FORWARD status.

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 Internet Inter-ORB Protocol (IIOP)

The baseline transport specified for GIOP is TCP/IP6. Specific APIs for libraries supporting TCP/IP may vary, so this discussion is limited to an abstract view of TCP/IP and management of its connections. The mapping of GIOP message transfer to TCP/IP connections is called the Internet Inter-ORB Protocol (IIOP).

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.

The listening server may accept or reject the connection. In general, servers should accept connection requests if possible, but ORBs are free to establish any desired policy for connection acceptance (e.g., to enforce fairness or optimize resource usage).

Once a connection is accepted, the client may send Request, LocateRequest, or CancelRequest messages by writing to the TCP/IP socket it owns for the connection. The server may send Reply, LocateReply, and CloseConnection messages by writing to its TCP/IP connection.

After sending (or receiving) a CloseConnection message, both client or server must close the TCP/IP connection.

Given TCP/IP's flow control mechanism, it is possible to create deadlock situations between clients and servers if both sides of a connection send large amounts of data on a connection (or two different connections between the same processes) and do not read incoming data. Both processes may block on write operations, and never resume. It is the responsibility of both clients and servers to avoid creating deadlock by reading incoming messages and avoiding blocking when writing messages, by providing separate threads for reading and writing, or any other workable approach. ORBs are free to adopt any desired implementation strategy, but should provide robust behavior.

12.7.2 IIOP IOR Profiles

IIOP profiles, identifying individual objects accessible through the Internet Inter_ORB Protocol, have the following form:

module IIOP { // IDL

struct Version {
char major;
char minor;
};
struct ProfileBody {
Version iiop_version;
string host;
unsigned short port;
sequence <octet> object_key;
};
};

An instance of the IIOP::ProfileBody type is marshaled into an encapsulation octet stream. This encapsulation (a sequence<octet>) becomes the profile_data member of the IOR::TaggedProfile structure representing the IIOP profile in an IOR, and the tag has the value TAG_INTERNET_IOP (as defined earlier).

The members of IIOP::ProfileBody are defined as follows:

Note that host addresses are restricted in this version of IIOP to be Class A, B, or C Internet addresses. That is, Class D (multi-cast) addresses are not allowed. Such addresses are reserved for use in future versions of IIOP.

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.

12.8 OMG IDL for the GIOP and IIOP Specifications

This section contains the OMG IDL for the GIOP and IIOP modules.

12.8.1 GIOP Module

module GIOP { // 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;
};
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;
};
};

12.8.2 IIOP Module

module IIOP { \\ IDL

struct Version {
char major;
char minor;
};
struct ProfileBody {
Version iiop_version;
string host;
unsigned short port;
sequence <octet> object_key;
};
};



[Top] [Prev] [Next] [Bottom]

1 "IEEE Standard for Binary Floating-Point Arithmetic", ANSI/IEEE Standard 754-1985, Institute of Electrical and Electronics Engineers, August 1985.

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.