New York
University
Computer
Science Department
Courant
Institute of Mathematical Sciences
Interoperability and the
CORBA Specification
Course Title: Application Servers Course
Number: g22.3033-011
Instructor: Jean-Claude Franchitti Session: 4
1. Overview of Universal Networked Objects (UNO)
The Object Management Group (OMG) adopted a specification called Universal Networked Objects (UNO) that supports interoperation among ORBs, that is, the ability of a client in one ORB to invoke an operation on an object in another ORB. UNO defines the following:
·
An
ORB Interoperability Architecture
that provides a conceptual and architectural framework within which ORB
components relevant to interoperability are positioned.
·
A
General Inter-ORB Protocol (GIOP)
that can be mapped onto multiple transport layers. The GIOP consists of:
·
A
Common Data Representation (CDR) for all data types
·
An
Interoperable Object Reference (IOR) format
·
Interoperable
TypeCodes for all data types
·
Inter-ORB
Protocol (IOP) message contents, formats, and semantics, independent of the
method of message conveyance
The intention is for
standard mappings to be developed from GIOP to alternative transport domains
(OSI, SNA, IPX, etc.), enabling out-of-the-box interoperability among ORBs that
share a common transport protocol.
·
The
Internet Inter-ORB Protocol (IIOP),
which is the first transport mapping for the GIOP. The Internet IOP maps the
GIOP to TCP/IP. It is mandatory for CORBA 2.0 (and above) networked ORBs and
guarantees out-of-the-box interoperability among them.
·
CORBA extensions that support the
construction of inter-ORB bridges. These extensions are mandatory for all CORBA
2.0-compliant ORBs, since they are more generally useful than simply for
building bridges. For example, they support the construction of distributed
debugging tools. The primary new CORBA component specified by UNO is a Dynamic Skeleton Interface (DSI), which
is the server-side analog of the client-side DII. The DSI provides a way to
deliver requests from an ORB to a Dynamic Implementation Routine (DIR) in a
server without compile-time knowledge of the type of object it implements. For
example, the DSI can be used to deliver an inter-ORB request to a bridge for
transmission to another ORB.
·
The
DCE Common Inter-ORB Protocol (DCE-CIOP),
the first Environment-Specific Inter-ORB Protocol (ESIOP). ESIOPs are IOPs that
do not comply with the GIOP specification. Instead, they are specialized for
particular operating environments and support out-of-the-box interoperation at
sites where a particular networking or distributed computing infrastructure is
already in general use.
UNO
organizes the various components of the CORBA specification into the following
categories for future compliance testing and branding purposes:
CORBA2/Core
Basically, the CORBA 1.2 specification, minus the
IDL C language mapping, plus extensions and modifications resulting from the
CORBA 2.0 RFPs (including UNO's bridging support) and requirements of COSS 2
Object Services.
CORBA2/C
CORBA2/C++
CORBA2/Smalltalk
IDL
language mappings that can be supported selectively by vendors on top of the
basic CORBA2/Core capability.
CORBA2/Java
CORBA2/Internet IOP
CORBA2/DCE IOP
UNO's IIOP and DCE-CIOP
UNO also defines a CORBA2 networked ORB as an ORB that supports the CORBA2/Core and
some set of CORBA2 language mappings; provides multinode operation using either
the IIOP, an ESIOP, or a proprietary protocol; and interoperates with other
networked ORBs via IIOP, supported either natively or via a half-bridge.
To show how the mechanisms defined by UNO support
interoperation among ORBs, Section 2 considers one possible implementation of
an IIOP half-bridge. Section 3 contains concluding remarks and our expectations
of how OMG's adoption of the UNO specification affects ORB vendors and users.
2. Example Implementation of an IIOP Bridge
2.1
Introduction
Suppose we have two ORBs -- ORB A and ORB B (Figure
1). Suppose further that a client in ORB A wishes to invoke an operation on an
object -- John -- in ORB B. Before
describing how this can be accomplished, let us consider how the client might
come to possess a reference to an object in another ORB. In the discussion that
follows, we refer to any ORB other than the client's as a foreign ORB and any object in a foreign ORB as a foreign object.
Figure 1. A client in ORB A wishes to invoke an
operation on an object in ORB B.
Object references are ORB-specific. UNO defines an
IOR format (described below) that contains sufficient information for any ORB
to determine how to direct requests to the ORB with the object in question. UNO
specifies how an IOR can be CDR-encoded and converted to string format. The
resulting string can be made available to ORBs in a variety of ways. An agent
(a bridge, for example) in any ORB can unstring the IOR, create a proxy for it
(as discussed below), and distribute references to the proxy among clients in
the same ORB. Clients can use a reference to the proxy to invoke operations on
the foreign object. Requests to the proxy are delivered to the bridge, and the
bridge forwards them to the foreign ORB. The proxy server may deliver requests
to the bridge or the bridge may be the proxy server itself. The scenario that
follows assumes the bridge is the proxy server.
Once a client possesses a reference to a foreign object, operations on that object may return references to additional foreign objects as result values or output parameters. Thus, for example, distributing a stringified IOR for a Naming Service makes the transitive closure of all the objects defined in the Naming Service available to other ORBs.
Figure 2 shows the proxy for John -- Gian -- in ORB A. The proxy is shown in
bridge A because bridge A is the proxy's server. The bridges are labeled
half-bridges because a full bridge
spans two ORBs and can receive requests from clients in one and invoke them on
objects in the other. A half-bridge
receives requests from clients in one ORB and transmits them in an agreed-upon format
using an agreed-upon protocol to the half-bridge in another ORB. One way we
expect vendors to comply with the UNO specification is by delivering a
half-bridge to IIOP with their ORBs. Figure 2 also shows the Proxy Table in each bridge. The Proxy
Table is used to store the association between a proxy and the IOR of the
foreign object it represents.
Figure 2. The client in ORB A has a proxy for the
object in ORB B.
2.2
Dynamic Skeleton Interface (DSI)
Now suppose the client invokes an operation on John
through its reference to the proxy Gian, passing a reference to an object Maria in ORB A as an in parameter
(Figure 3). ORB A delivers the request, through the DSI, to a DIR in bridge A,
which is Gian's server.
Figure 3. The
client in ORB A invokes a request through the proxy.
The DSI defines a new interface between the ORB and
an object's methods. In the original common ORB architecture, the ORB delivers a
request to a server through an IDL-generated skeleton. Precisely what
constitutes a skeleton is ORB-dependent. For example, in one ORB, it might be a
function that the ORB invokes when it delivers a request for the corresponding
operation. By fleshing out such a skeleton with actual method code and linking
it with whatever other code and libraries a particular ORB requires, the object
developer generates a server in which the ORB can invoke methods properly.
The DSI defines a new way for an ORB to deliver
requests to a server through a so-called dynamic
skeleton. The ORB delivers a request packaged as a ServerRequest pseudo-object to a DIR, which is a single function
that takes an arbitrary object reference and a ServerRequest as arguments. The
bridge developer can follow a particular ORB's rules for writing a DIR and then
link the DIR with whatever other code and libraries the ORB requires to create
a server (the bridge) in which the ORB delivers requests to the DIR using the
DSI.
The DIR in bridge A is invoked with a ServerRequest
pseudo-object that contains the name of the requested operation, its
OperationDef, a Context pseudo-object (if required by the requested operation's
IDL definition), an NVList with parameters (including the reference to Maria),
and a NamedValue to return the result (Figure 4).
Figure 4.
ServerRequest pseudo-object definition.
module CORBA
{
pseudo interface ServerRequest
{
Identifier op_name ();
OperationDef op_def ();
Context ctx ();
void params (inout NVList parms);
NamedValue result ();
};
};
2.3 IIOP
Request Message
Bridge A uses the identity of the object on which
the request was invoked -- Gian -- to retrieve John's IOR from its Proxy Table
(Figure 5). The type_id field in the
IOR identifies John's type, and the profiles
field contains a sequence of one TaggedProfile. The tag field in this TaggedProfile has the value TAG_INTERNET_IOP, and
the profile_data field contains an
instance of IIOP::ProfileBody (Figure 6) that has been CDR-encoded into what
UNO calls an encapsulation octet stream.
Figure 5. IOR
definition.
module IOR
{
typedef unsigned long ProfileId;
const ProfileId TAG_INTERNET_IOP = 0;
struct TaggedProfile
{
ProfileId tag;
sequence <octet> profile_data;
};
struct IOR
{
string type_id;
sequence <TaggedProfile> profiles;
};
};
Figure 6.
IIOP::ProfileBody definition.
module IIOP
{
struct Version
{
char major;
char minor;
};
struct ProfileBody
{
Version iiop_version;
string host;
unsigned short port;
sequence <octet> object_key;
};
};
The host
and port fields in the
IIOP::ProfileBody identify the host and port on which bridge B is listening for
inter-ORB requests. The object_key
field contains a value that identifies John to bridge B (it may be an object
reference for John in ORB B or some value that bridge B associates with a
reference to John). Bridge A has everything it needs to construct and send an
IIOP Request message. This consists
of an IIOP MessageHeader (Figure 7),
an IIOP RequestHeader (Figure 8), and
an IIOP Request body. The Request body includes all in and inout parameters
(including an IOR for Maria) and a Context pseudo-object (if required).
Figure 7.
IIOP::MessageHeader definition.
module IIOP
{
enum MsgType
{
Request, Reply, CancelRequest, LocateRequest,
LocateReply, CloseConnection, MessageError
};
struct MessageHeader
{
char magic [4];
Version iiop_version;
boolean byte_order;
octet message_type;
unsigned long message_size;
};
};
Figure 8.
IIOP::RequestHeader definition.
module IIOP
{
typedef unsigned long ServiceID;
struct ServiceContext
{
ServiceID context_id;
sequence <octet> context_data;
};
typedef sequence <ServiceContext> ServiceContextList;
const ServiceID TransactionService = 0;
struct RequestHeader
{
ServiceContextList service_context;
unsigned long request_id;
boolean response_expected;
sequence <octet> object_key;
string operation;
Principal requesting_principal;
};
};
The IIOP MessageHeader contents are as follows:
·
magic contains the four
characters "IIOP."
·
iiop_version identifies the major and
minor IIOP version (the version defined by UNO is major version 1, minor
version 0).
·
byte_order identifies the byte ordering
(big-endian or little-endian) in which the message is encoded.
·
message_type contains the CDR-encoded
value IIOP::Request.
·
message_size contains the number of
bytes following the message header.
The IIOP RequestHeader contents are as follows:
·
service_context contains service context
information that may need to accompany the request. The Transaction Service
defines a TSInteroperation::PropagationContext for this purpose and is the
first Object Service to do so. Thus, the only ServiceID currently defined is
IIOP:TransactionService.
·
request_id contains a unique request
ID that bridge A generates to allow it to identify the corresponding reply.
·
response_expected identifies whether the
client (and, therefore, bridge A) expects to receive a response. No response is
expected if the operation's IDL definition includes the oneway keyword or if the client invokes the operation using the DII
and specifies the INV_NO_RESPONSE flag.
·
object_key contains a CDR-encoded
version of a value that identifies John to bridge B (as discussed above). This
is obtained from the IOR in bridge A's Proxy Table as described previously.
·
operation contains the name of the
requested operation.
·
requesting_principal identifies the user
requesting the operation and is completely ORB-dependent at this time (pending
OMG specification of a Security Service).
Bridge
A must place a reference to Maria in the Request body of the message, since it
is an in parameter of the request. Rather than pass a real reference to Maria,
which would most likely be useless to ORB B, bridge A constructs an IOR for
Maria and places the IOR in the Request body. When bridge A has finished
constructing the Request message, it opens a TCP/IP connection to bridge B
using the host and port information in the IOR for John (Figure 9).
Figure 9.
Bridge A transmits the request to bridge B.
When bridge B receives the message from bridge A,
the IIOP MessageHeader identifies it as an IIOP Request message and enables bridge
B to unpack the RequestHeader and Request body. The RequestHeader yields a
reference to John as the target of the request; it also yields the name of the
operation to be invoked on John. While unpacking parameters in the Request
body, bridge B encounters the IOR for Maria. Bridge B creates a proxy for Maria
(Mary), places an entry in its Proxy
Table that associates the new proxy with the IOR for Maria, and uses a
reference to the new proxy as the in parameter when it invokes the request on
John (Figure 10).
Figure 10.
Bridge B invokes the request on the target object.
2.4 IIOP
Reply Message
If the client (and, therefore, bridge A) expects a
response, bridge B constructs an IIOP Reply
message when the invocation is completed and transmits the reply to bridge A.
The IIOP Reply message consists of an IIOP MessageHeader (Figure 10), an IIOP ReplyHeader (Figure 11), and an IIOP
Reply body.
Figure 11.
IIOP::ReplyHeader definition.
module IIOP
{
enum ReplyStatusType { NO_EXCEPTION,
USER_EXCEPTION,
SYSTEM_EXCEPTION,
LOCATION_FORWARD };
struct ReplyHeader
{
ServiceContextList service_context;
unsigned long request_id;
ReplyStatusType reply_status;
};
};
The IIOP MessageHeader contents are described above.
In this case, however, message_type
contains the CDR-encoded value IIOP::Reply. The IIOP ReplyHeader contents are
as follows:
·
service_context contains service context
information that may need to be returned to the client (see above).
·
request_id contains the same unique ID
as in the request received by bridge B.
·
reply_status indicates the completion
status of the request and determines the contents of the Reply body. Two
possible values are:
·
NO_EXCEPTION,
in which case the Reply body contains the operation's return value followed by
all inout and out parameters.
·
USER_EXCEPTION
or SYSTEM_EXCEPTION, in which case the Reply body contains the exception that
was raised by the operation.
There is a third possible value for reply_status -- LOCATION_FORWARD -- in
which case the Reply body contains an IOR. The client's bridge is expected to
reinvoke the request using the new IOR, and this redirection is expected to be
transparent to the client. This supports object migration. For example, if John
moves to a location that requires the use of a different IOR between the time
Gian is created and the time the client invokes an operation through Gian, the
LOCATION_FORWARD reply gives bridge A a new IOR it can use to send the request
to a bridge appropriate for John's new location. This mechanism also supports
ORB-wide location services; for example, an ORB may provide a location server
for all of the object references it exports to the external world and then
simply publish the address of that server in all of the IORs it exports.
2.5 IIOP
LocateRequest and LocateReply Messages
If a bridge does not want to receive a
LOCATION_FORWARD response and have to retransmit a request, it may use an IIOP LocateRequest message to determine
whether the reference it has for the target of the request is valid, whether
the receiver is prepared to accept requests to that reference, and if not, to
what address it should send requests to the target object. The IIOP
LocateRequest message consists of an IIOP MessageHeader (Figure 7) and an IIOP LocateRequestHeader (Figure 12).
Figure 12.
IIOP::LocateRequestHeader definition.
module IIOP
{
struct LocateRequestHeader
{
unsigned long request_id;
sequence <octet> object_key;
};
};
The IIOP MessageHeader contents are described above.
In this case, however, message_type
contains the CDR-encoded value IIOP::LocateRequest. The IIOP LocateRequestHeader
contents are as follows:
·
request_id contains a unique request
ID the sending bridge generates to allow it to identify the corresponding
reply.
·
object_key contains a CDR-encoded
version of the key value extracted from the IOR associated with the proxy on
which the client invoked the request.
When a bridge receives an IIOP LocateRequest
message, it responds with an IIOP LocateReply
message. An IIOP LocateReply message consists of an IIOP MessageHeader (Figure
7), an IIOP LocateReplyHeader (Figure
13), and an IIOP LocateReply body.
Figure 13.
IIOP::LocateReplyHeader definition.
module IIOP
{
enum LocateStatusType { UNKNOWN_OBJECT,
OBJECT_HERE,
OBJECT_FORWARD };
struct LocateReplyHeader
{
unsigned long request_id;
LocateStatusType locate_status;
};
};
The IIOP MessageHeader contents are described above.
In this case, however, message_type
contains the CDR-encoded value IIOP::LocateReply. The IIOP LocateReplyHeader contents
are as follows:
·
request_id contains the same unique ID
as in the corresponding LocateRequest message.
·
locate_status determines whether the
message includes a LocateReply body. The possible values for locate_status are as follows:
·
UNKNOWN_OBJECT,
which means the object specified in the LocateRequest message is unknown to the
bridge, and no LocateReply body exists.
·
OBJECT_HERE,
which means the bridge sending the LocateReply message is prepared to accept
requests to the specified object, and no LocateReply body exists.
·
OBJECT_FORWARD,
which means a LocateReply body exists and contains an IOR that may be used as
the target for requests to the object specified in the LocateRequest message.
2.6
Observations
The scenario in Section 2 shows how the bridging
support specified in UNO can be used to implement a half-bridge to IIOP. The
bridge can be implemented at the application level by end-user developers and
requires no proprietary information about the ORB or modifications to the ORB.
In fact, if and when all of the server-side ambiguities in the CORBA
specification are removed, the technique described here can be used to build a
portable half-bridge to IIOP that can run on any ORB (that is, whose source
code can be compiled and linked to run on any ORB).
While
some vendors will satisfy the IIOP requirement for a CORBA networked ORB by
providing a half-bridge similar to that described here, other vendors will
support IIOP directly in their ORBs. When a client invokes a request on a
foreign object, an IIOP-aware ORB could marshal the request directly into an
IIOP Request message, open a TCP/IP connection to the server indicated in the
IOR, if necessary, and transmit the Request message to the foreign server. This
is more efficient than using a bridge, but requires modifications to the ORB
itself and would increase the size of clients and servers somewhat.
3. Concluding Remarks
The UNO specification defines three significant
components:
·
The
Internet Inter-ORB Protocol (IIOP), which supports out-of-the-box
interoperability in the ubiquitous transport domain of TCP/IP.
·
The
DCE-CIOP, which supports out-of-the-box interoperability among DCE-based ORBs.
·
The
General Inter-ORB Protocol (GIOP) and CORBA extensions that support the
construction of bridges to non-compliant ORBs and ORBs in different transport
domains.
CORBA
compliance for networked ORBs requires IIOP, which may be supported via
half-bridges. We noted previously (in Section 2.6) that half-bridges can be
developed by end- users or third parties without proprietary information about
an ORB or modifications to the ORB. Mappings have been developed from GIOP to
additional transport domains. ICL has developed an OSI mapping, and Novell has
developed a mapping to IPX.
Glossary
CDR - Common Data Representation
CIOP - Common Inter-ORB Protocol
COM - DEC's and Microsoft's Common
Object Model
CORBA - Common Object Request Broker
Architecture
COSS - Common Object Services
Specification
DCE - OSF's Distributed Computing
Environment
DII - Dynamic Invocation Interface
DIR - Dynamic Implementation Routine
DSI - Dynamic Skeleton Interface
ESIOP - Environment-Specific
Inter-ORB Protocol
GIOP - General Inter-ORB Protocol
IDL - Interface Definition Language
IIOP - Internet Inter-ORB Protocol
IOP - Inter-ORB Protocol
IOR - Interoperable Object Reference
IPX - Novell's Internet Packet
Exchange
ISO - International Standards
Organization
OLE - Microsoft's Object Linking and
Embedding
OMG - Object Management Group
ORB - Object Request Broker
OSF - Open Software Foundation
OSI - ISO's Open Systems
Interconnection
RFP - Request For Proposals
SNA - IBM's System Network
Architecture
TCP/IP - Transmission Control
Protocol/Internet Protocol
UNO - Universal Networked Objects