the omniorbpy version 1.3 user’s guidedocs/external/python/omniorb/omniorb... · 2004. 7. 4. ·...

63
The omniORBpy version 1.3 User’s Guide Duncan Grisby (email: [email protected]) AT&T Laboratories Cambridge August 2000

Upload: others

Post on 11-Oct-2020

0 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

The omniORBpy version 1.3User’s Guide

Duncan Grisby(email: [email protected])

AT&T Laboratories Cambridge

August 2000

Page 2: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

Changes and Additions, August 2000

• New omniORB.maxTcpConnectionPerServer function.

Changes and Additions, August 2000

• New omniORB.LOCATION_FORWARDexception.

• New omniORB.traceLevel() function.

Changes and Additions, June 2000

• Brand new manual.

Page 3: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

Contents

1 Introduction 11.1 Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

1.1.1 CORBA 2.3 compliant . . . . . . . . . . . . . . . . . . . . . . . 11.1.2 Multithreading . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.1.3 Missing features . . . . . . . . . . . . . . . . . . . . . . . . . . 2

1.2 Setting up your environment . . . . . . . . . . . . . . . . . . . . . . . 21.2.1 Paths . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.2.2 Configuration file . . . . . . . . . . . . . . . . . . . . . . . . . . 3

1.2.2.1 omniORB 2.8 configuration file entries . . . . . . . . 3

2 The Basics 52.1 The Echo example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52.2 Generating the Python stubs . . . . . . . . . . . . . . . . . . . . . . . . 62.3 Object References and Servants . . . . . . . . . . . . . . . . . . . . . . 62.4 Example 1 — Colocated client and servant . . . . . . . . . . . . . . . 6

2.4.1 Imports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72.4.2 Servant class definition . . . . . . . . . . . . . . . . . . . . . . 72.4.3 ORB initialisation . . . . . . . . . . . . . . . . . . . . . . . . . . 82.4.4 Obtaining the Root POA . . . . . . . . . . . . . . . . . . . . . . 82.4.5 Object initialisation . . . . . . . . . . . . . . . . . . . . . . . . . 82.4.6 Activating the POA . . . . . . . . . . . . . . . . . . . . . . . . . 92.4.7 Performing a call . . . . . . . . . . . . . . . . . . . . . . . . . . 9

2.5 Example 2 — Different Address Spaces . . . . . . . . . . . . . . . . . 92.5.1 Object Implementation: Generating a Stringified Object Ref-

erence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92.5.2 Client: Using a Stringified Object Reference . . . . . . . . . . . 102.5.3 System exceptions . . . . . . . . . . . . . . . . . . . . . . . . . 112.5.4 Lifetime of a CORBA object . . . . . . . . . . . . . . . . . . . . 12

2.6 Example 3 — Using the Naming Service . . . . . . . . . . . . . . . . . 122.6.1 Obtaining the Root Context object reference . . . . . . . . . . 132.6.2 The Naming Service interface . . . . . . . . . . . . . . . . . . . 132.6.3 Server code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132.6.4 Client code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

iii

Page 4: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

2.7 Global IDL definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

3 Python language mapping issues 173.1 Narrowing object references . . . . . . . . . . . . . . . . . . . . . . . . 17

3.1.1 The gory details . . . . . . . . . . . . . . . . . . . . . . . . . . . 173.2 Support for Any values . . . . . . . . . . . . . . . . . . . . . . . . . . . 193.3 Interface Repository stubs . . . . . . . . . . . . . . . . . . . . . . . . . 213.4 Using omniORBpy with omniORB 2.8 . . . . . . . . . . . . . . . . . . 21

3.4.1 POA functions . . . . . . . . . . . . . . . . . . . . . . . . . . . 213.4.2 Local / remote transparency . . . . . . . . . . . . . . . . . . . 22

4 Interoperable Naming Service 234.1 Object URIs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

4.1.1 corbaloc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234.1.2 corbaname . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

4.2 Configuring resolve_initial_references . . . . . . . . . . . . . . . . . . 254.2.1 ORBInitRef . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254.2.2 ORBDefaultInitRef . . . . . . . . . . . . . . . . . . . . . . . . . 254.2.3 omniORB configuration file . . . . . . . . . . . . . . . . . . . . 264.2.4 Resolution order . . . . . . . . . . . . . . . . . . . . . . . . . . 26

4.3 omniNames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274.3.1 NamingContextExt . . . . . . . . . . . . . . . . . . . . . . . . . 274.3.2 Use with corbaname . . . . . . . . . . . . . . . . . . . . . . . . 28

4.4 omniMapper . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284.5 Creating objects with simple object keys . . . . . . . . . . . . . . . . . 29

5 The IDL compiler 315.1 Common options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

5.1.1 Preprocessor interactions . . . . . . . . . . . . . . . . . . . . . 325.1.1.1 Windows 9x . . . . . . . . . . . . . . . . . . . . . . . 32

5.1.2 Forward-declared interfaces . . . . . . . . . . . . . . . . . . . . 325.1.3 Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

5.2 Python back-end options . . . . . . . . . . . . . . . . . . . . . . . . . . 335.3 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

6 The omniORBpy API 356.1 ORB initialisation options . . . . . . . . . . . . . . . . . . . . . . . . . 356.2 Hostname and port . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 366.3 Run-time Tracing and Diagnostic Messages . . . . . . . . . . . . . . . 366.4 Server Name . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376.5 GIOP Message Size . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376.6 Object table size . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376.7 Obsolete Initial Object Reference Bootstrapping . . . . . . . . . . . . . 386.8 GIOP Lowest Common Denominator Mode . . . . . . . . . . . . . . . 39

Page 5: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

6.9 GIOP Requesting Principal field . . . . . . . . . . . . . . . . . . . . . . 406.10 System Exception Handlers . . . . . . . . . . . . . . . . . . . . . . . . 40

6.10.1 CORBA.TRANSIENT handlers . . . . . . . . . . . . . . . . . . 406.10.2 CORBA.COMM_FAILURE and CORBA.SystemException . . 41

6.11 Location forwarding . . . . . . . . . . . . . . . . . . . . . . . . . . . . 416.12 Dynamic importing of IDL . . . . . . . . . . . . . . . . . . . . . . . . . 42

7 Connection Management 457.1 Background . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 457.2 The Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 467.3 Idle Connection Shutdown and Remote Call Timeout . . . . . . . . . 467.4 Interoperability Considerations . . . . . . . . . . . . . . . . . . . . . . 477.5 Connection Acceptance . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

A hosts_access(5) 49

Page 6: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements
Page 7: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

Chapter 1

Introduction

omniORBpy is an Object Request Broker (ORB) that implements the CORBA 2.3Python mapping [OMG00b]. It is designed for use with omniORB 3, but it can alsobe used with omniORB 2.8. If you use omniORB 3.0, the full POA functionality isavailable; with omniORB 2.8 many POA functions are not supported.

This user guide tells you how to use omniORBpy to develop CORBA appli-cations using Python. It assumes a basic understanding of CORBA, and of thePython mapping. Unlike most CORBA standards, the Python mapping documentis small, and quite easy to follow.

This manual contains all you need to know about omniORB in order to useomniORBpy. Some sections are repeated from the omniORB manual.

In this chapter, we give an overview of the main features of omniORBpy andwhat you need to do to setup your environment to run it.

1.1 Features

1.1.1 CORBA 2.3 compliant

omniORB implements the Internet Inter-ORB Protocol (IIOP). This protocol pro-vides omniORB the means of achieving interoperability with the ORBs imple-mented by other vendors. In fact, this is the native protocol used by omniORBfor the communication amongst its objects residing in different address spaces.

Moreover, the IDL to Python language mapping provided by omniORBpy con-forms to the 2.3 Python mapping specification1.

1.1.2 Multithreading

omniORBpy is fully multithreaded2. To achieve low IIOP call overhead, unneces-sary call-multiplexing is eliminated. At any time, there is at most one call in-flight

1As detailed in section 1.1.3, a number of features are missing.2This means that your Python interpreter must have been built with thread support.

1

Page 8: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

2 CHAPTER 1. INTRODUCTION

in each communication channel between two address spaces. To do so without lim-iting the level of concurrency, new channels connecting the two address spaces arecreated on demand and cached when there are more concurrent calls in progress.Each channel is served by a dedicated thread. This arrangement provides maximalconcurrency and eliminates any thread switching in either of the address spaces toprocess a call. Furthermore, to maximise the throughput in processing large callarguments, large data elements are sent as soon as they are processed while theother arguments are being marshalled.

1.1.3 Missing features

omniORBpy is not a complete implementation of the CORBA 2.3 core. The follow-ing is a list of the missing features.

• omniORB does not have its own Interface Repository. However, it can act asa client to an IR3.

• The IDL types wchar, wstring, fixed, and valuetype are not supported in thisrelease.

• The PortableServer.Current interface is not yet supported.

• DII and DSI are not supported. However, since both Python code and IDLcan be generated and used at run-time, this is not a significant restriction.

These features may be implemented in the short to medium term. It is bestto check out the latest status on the omniORB home page (http://www.uk.research.att.com/omniORB/ ).

1.2 Setting up your environment

omniORBpy relies on the omniORB C++ libraries. If you are building from source,you must first build omniORB itself, as detailed in the omniORB documentation.After that, you can build the omniORBpy distribution, according to the instruc-tions in the release notes.

1.2.1 Paths

For Python to find omniORBpy, you must add two directories to the PYTHONPATHenvironment variable. The lib/python directory contains platform-independentPython code; the lib/$FARCH directory contains platform-specific binaries, whereFARCHis the name of your platform, such as i586_linux_glibc or x86_win32 .

On Unix platforms, set PYTHONPATHwith a command like:3See section 3.3 for a note about using an interface repository.

Page 9: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

1.2. SETTING UP YOUR ENVIRONMENT 3

export PYTHONPATH=$PYTHONPATH:$TOP/lib/python:$TOP/lib/$FARCH

On Windows, use

set PYTHONPATH=%PYTHONPATH%;%TOP%\lib\python;%TOP%\lib\x86_win32

(Where the TOPenvironment variable is the root of your omniORB tree.)You should also add the bin/$FARCH directory to your PATH, so you can

run the IDL compiler, omniidl. Finally, add the lib/$FARCH directory to LD_LIBRARY_PATH, so the omniORB core library can be found.

1.2.2 Configuration file

• On Unix platforms, the omniORB runtime looks for the environment variableOMNIORB_CONFIG. If this variable is defined, it contains the pathname of theomniORB configuration file. If the variable is not set, omniORB will use thecompiled-in pathname to locate the file.

• On Win32 platforms (Windows NT, 2000, 95, 98), omniORB first checks theenvironment variable OMNIORB_CONFIGto obtain the pathname of the con-figuration file. If this is not set, it then attempts to obtain configuration datain the system registry. It searches for the data under the key HKEY_LOCAL_MACHINE\SOFTWARE\ORL\omniORB\2.0.

The configuration file is used to obtain an object reference for the Naming Ser-vice, via either a stringified IOR or an Interoperable Naming Service URI. Whenusing omniORB 3, the entry in the configuration file should be specified in theform:

ORBInitRef NameService=<URI for the Naming Service>

The easiest way of specifying the Naming Service is with a corbaname: URI,as described in section 4.1.2.

Comments in the configuration file should be prefixed with a ‘#’ character.On Win32 platforms, the naming service reference can be placed in the system

registry, in the (string) value ORBInitRef , under the key HKEY_LOCAL_MACHINE\SOFTWARE\ORL\omniORB\2.0 .

1.2.2.1 omniORB 2.8 configuration file entries

ORBInitRef is new with omniORB 3. Under omniORB 2.8, you must use theolder format (which is still supported by omniORB 3):

NAMESERVICE <IOR for the Naming Service>

Two other entries are also supported, but with omniORB 3 are made obsoleteby the Interoperable Naming Service URIs:

Page 10: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

4 CHAPTER 1. INTRODUCTION

ORBInitialHost <hostname string>ORBInitialPort <port number (1-65535)>

The corresponding entries under the Win32 system registry are the keys namedORBInitialHost and ORBInitialPort .

The two entries provide information to the ORB to locate a (proprietary) boot-strap service at runtime. The bootstrap service is able to return the initial objectreference for the Naming Service and others.

Page 11: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

Chapter 2

The Basics

In this chapter, we go through three examples to illustrate the practical steps touse omniORBpy. By going through the source code of each example, the essentialconcepts and APIs are introduced. If you have no previous experience with us-ing CORBA, you should study this chapter in detail. There are pointers to otheressential documents you should be familiar with.

If you have experience with using other ORBs, you should still go through thischapter because it provides important information about the features and APIsthat are necessarily omniORB specific.

2.1 The Echo example

We use an example which is similar to the one used in the omniORB manual. Wedefine an interface, called Example::Echo , as follows:

// echo_example.idlmodule Example {

interface Echo {string echoString(in string mesg);

};};

The important difference from the omniORB Echo example is that our Echointerface is declared within an IDL module named Example . The reason for thiswill become clear in a moment.

If you are new to IDL, you can learn about its syntax in Chapter 3 of the CORBAspecification 2.3 [OMG99]. For the moment, you only need to know that the in-terface consists of a single operation, echoString() , which takes a string as anargument and returns a copy of the same string.

The interface is written in a file, called echo_example.idl . It is part of theCORBA standard that all IDL files should have the extension ‘.idl ’, althoughomniORB does not enforce this.

5

Page 12: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

6 CHAPTER 2. THE BASICS

2.2 Generating the Python stubs

From the IDL file, we use the IDL compiler, omniidl, to produce the Python stubsfor that IDL. The stubs contain Python declarations for all the interfaces and typesdeclared in the IDL, as required by the Python mapping. It is possible to generatestubs dynamically at run-time, as described in section 6.12, but it is more efficientto generate them statically.

To generate the stubs, we use a command line like

omniidl -bpython echo_example.idl

As required by the standard, that produces two Python packages derived from themodule name Example . Directory Example contains the client-side definitions(and also the type declarations if there were any); directory Example__POA con-tains the server-side skeletons. This explains the difficulty with declarations at IDLglobal scope; section 2.7 explains how to access global declarations.

If you look at the Python code in the two packages, you will see that they are al-most empty. They simply import the echo_example_idl.py file, which is whereboth the client and server side declarations actually live. This arrangement is sothat omniidl can easily extend the packages if other IDL files add declarations tothe same IDL modules.

2.3 Object References and Servants

We contact a CORBA object through an object reference. The actual implementationof a CORBA object is termed a servant.

Object references and servants are quite separate entities, and it is importantnot to confuse the two. Client code deals purely with object references, so there canbe no confusion; object implementation code must deal with both object referencesand servants. You will get a run-time error if you use a servant where an objectreference is expected, or vice-versa.

2.4 Example 1 — Colocated client and servant

In the first example, both the client and servant are in the same address space.The next sections show how the client and servant can be split between differentaddress spaces.

First, the code:

1 #!/usr/bin/env python2

3 import sys4 from omniORB import CORBA, PortableServer5 import Example, Example__POA

Page 13: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

2.4. EXAMPLE 1 — COLOCATED CLIENT AND SERVANT 7

6

7 class Echo_i (Example__POA.Echo):8 def echoString(self, mesg):9 print "echoString() called with message:", mesg

10 return mesg11

12 orb = CORBA.ORB_init(sys.argv, CORBA.ORB_ID)13 poa = orb.resolve_initial_references("RootPOA")14

15 ei = Echo_i()16 eo = ei._this()17

18 poaManager = poa._get_the_POAManager()19 poaManager.activate()20

21 message = "Hello"22 result = eo.echoString(message)23

24 print "I said ’%s’. The object said ’%s’." % (message,result)

The example illustrates several important interactions among the ORB, thePOA, the servant, and the client. Here are the details:

2.4.1 Imports

Line 3Import the sys module to access sys.argv .

Line 4Import omniORB’s implementations of the CORBAand PortableServermodules. The standard requires that these modules are available outside ofany package, so you can also do

import CORBA, PortableServer

Explicitly specifying omniORB is useful if you have more than one PythonORB installed.

Line 5Import the client-side stubs and server-side skeletons generated for IDL mod-ule Example .

2.4.2 Servant class definition

Lines 7–10For interface Example::Echo , omniidl produces a skeleton class namedExample__POA.Echo . Here we define an implementation class, Echo_i ,which derives from the skeleton class.

Page 14: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

8 CHAPTER 2. THE BASICS

There is little constraint on how you design your implementation class, ex-cept that it has to inherit from the skeleton class and must implement all ofthe operations declared in the IDL. Note that since Python is a dynamic lan-guage, errors due to missing operations and operations with incorrect typesignatures are only reported when someone tries to call those operations.

2.4.3 ORB initialisation

Line 12The ORB is initialised by calling the CORBA.ORB_init() function. ORB_init() is passed a list of command-line arguments, and an ORB identi-fier. The ORB identifier should be ‘omniORB3’ or ‘omniORB2’, depend-ing on which version of omniORB you are using. It is usually best to useCORBA.ORB_ID, which is initialised to a suitable string.

ORB_init() processes any command-line arguments which begin with thestring ‘-ORB’, and removes them from the argument list. See section 6.1for details. If any arguments are invalid, or other initialisation errors occur(such as errors in the configuration file), the CORBA.INITIALIZE exceptionis raised.

2.4.4 Obtaining the Root POA

Line 13To activate our servant object and make it available to clients, we must regis-ter it with a POA. In this example, we use the Root POA, rather than creatingany child POAs. The Root POA is found with orb.resolve_initial_references() .

A POA’s behaviour is governed by its policies. The Root POA has suitablepolicies for many simple servers. Chapter 11 of the CORBA 2.3 specification[OMG99] has details of all the POA policies which are available.

When omniORBpy is used with omniORB 2.8, only the Root POA is available(and is mapped to the omniORB BOA). You cannot create child POAs or alterpolicies.

2.4.5 Object initialisation

Line 15An instance of the Echo servant object is created.

Line 16The object is implicitly activated in the Root POA, and an object reference isreturned, using the _this() method.

One of the important characteristics of an object reference is that it is com-pletely location transparent. A client can invoke on the object using its object

Page 15: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

2.5. EXAMPLE 2 — DIFFERENT ADDRESS SPACES 9

reference without any need to know whether the servant object is colocatedin the same address space or is in a different address space.

In the case of colocated client and servant, omniORB is able to short-circuitthe client calls so they do not involve IIOP. The calls still go through thePOA, however, so the various POA policies affect local calls in the same wayas remote ones. This optimisation is applicable not only to object referencesreturned by _this() , but to any object references that are passed aroundwithin the same address space or received from other address spaces via IIOPcalls.

2.4.6 Activating the POA

Lines 18–19POAs are initially in the holding state, meaning that incoming requests areblocked. Lines 18 and 19 acquire a reference to the POA’s POA manager, anduse it to put the POA into the active state. Incoming requests are now served.

2.4.7 Performing a call

Line 22At long last, we can call the object’s echoString() operation. Even thoughthe object is local, the operation goes through the ORB and POA, so thetypes of the arguments can be checked, and any mutable arguments can becopied. This ensures that the semantics of local and remote calls are iden-tical. If any of the arguments (or return values) are of the wrong type, aCORBA.BAD_PARAMexception is raised.

2.5 Example 2 — Different Address Spaces

In this example, the client and the object implementation reside in two differentaddress spaces. The code of this example is almost the same as the previous exam-ple. The only difference is the extra work which needs to be done to pass the objectreference from the object implementation to the client.

The simplest (and quite primitive) way to pass an object reference between twoaddress spaces is to produce a stringified version of the object reference and to passthis string to the client as a command-line argument. The string is then convertedby the client into a proper object reference. This method is used in this example. Inthe next example, we shall introduce a better way of passing the object referenceusing the CORBA Naming Service.

2.5.1 Object Implementation: Generating a Stringified Object Reference

Page 16: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

10 CHAPTER 2. THE BASICS

1 #!/usr/bin/env python2

3 import sys4 from omniORB import CORBA, PortableServer5 import Example, Example__POA6

7 class Echo_i (Example__POA.Echo):8 def echoString(self, mesg):9 print "echoString() called with message:", mesg

10 return mesg11

12 orb = CORBA.ORB_init(sys.argv, CORBA.ORB_ID)13 poa = orb.resolve_initial_references("RootPOA")14

15 ei = Echo_i()16 eo = ei._this()17

18 print orb.object_to_string(eo)19

20 poaManager = poa._get_the_POAManager()21 poaManager.activate()22

23 orb.run()

Up until line 18, this example is identical to the colocated case. On line 18, theORB’s object_to_string() operation is called. This results in a string startingwith the signature ‘IOR:’ and followed by some hexadecimal digits. All CORBA2 compliant ORBs are able to convert the string into its internal representation ofa so-called Interoperable Object Reference (IOR). The IOR contains the locationinformation and a key to uniquely identify the object implementation in its ownaddress space1. From the IOR, an object reference can be constructed.

After the POA has been activated, orb.run() is called. Since omniORB isfully multi-threaded, it is not actually necessary to call orb.run() for operationdispatch to happen—if the main program had some other work to do, it could doso, and remote invocations would be dispatched in separate threads. However,in the absence of anything else to do, orb.run() is called so the thread blocksrather than exiting immediately when the end-of-file is reached. orb.run() staysblocked until the ORB is shut down.

2.5.2 Client: Using a Stringified Object Reference

1 #!/usr/bin/env python2

3 import sys4 from omniORB import CORBA5 import Example

1Notice that the object key is not globally unique across address spaces.

Page 17: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

2.5. EXAMPLE 2 — DIFFERENT ADDRESS SPACES 11

6

7 orb = CORBA.ORB_init(sys.argv, CORBA.ORB_ID)8

9 ior = sys.argv[1]10 obj = orb.string_to_object(ior)11

12 eo = obj._narrow(Example.Echo)13

14 if eo is None:15 print "Object reference is not an Example::Echo"16 sys.exit(1)17

18 message = "Hello from Python"19 result = eo.echoString(message)20

21 print "I said ’%s’. The object said ’%s’." % (message,result)

The stringified object reference is passed to the client as a command-line argu-ment2. The client uses the ORB’s string_to_object() function to convert thestring into a generic object reference (CORBA.Object ).

On line 12, the object’s _narrow() function is called to convert the CORBA.Object reference into an Example.Echo reference. If the IOR was not actually oftype Example.Echo , or something derived from it, _narrow() returns None.

In fact, since Python is a dynamically-typed language, string_to_object()is often able to return an object reference of a more derived type than CORBA.Object . See section 3.1 for details.

2.5.3 System exceptions

The keep it short, the client code shown above performs no exception handling. Arobust client (and server) should do, since there are a number of system exceptionswhich can arise.

As already mentioned, ORB_init() can raise the CORBA.INITIALIZE excep-tion if the command line arguments or configuration file are invalid. string_to_object() can raise two exceptions: if the string is not an IOR (or a valid URIwith omniORB 3), it raises CORBA.BAD_PARAM; if the string looks like an IOR, butcontains invalid data, is raises CORBA.MARSHAL.

The call to echoString() can result in any of the CORBA system exceptions,since any exceptions not caught on the server side are propagated back to theclient. Even if the implementation of echoString() does not raise any systemexceptions itself, failures in invoking the operation can cause a number of excep-tions. First, if the server process cannot be contacted, a CORBA.COMM_FAILUREexception is raised. Second, if the server process can be contacted, but the ob-ject in question does not exist there, a CORBA.OBJECT_NOT_EXISTexception israised. Various events can also cause CORBA.TRANSIENTto be raised. If that oc-

2The code does not check that there is actually an IOR on the command line!

Page 18: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

12 CHAPTER 2. THE BASICS

curs, omniORB’s default behaviour is to automatically retry the invocation, withexponential back-off.

As explained later in section 3.1, the call to _narrow() may also involve acall to the object to confirm its type. This means that _narrow() can also raiseCORBA.COMM_FAILURE, CORBA.OBJECT_NOT_EXIST, and CORBA.TRANSIENT.

Section 6.10 describes how exception handlers can be installed for all the vari-ous system exceptions, to avoid surrounding all code with try . . . except blocks.

2.5.4 Lifetime of a CORBA object

CORBA objects are either transient or persistent. The majority are transient, mean-ing that the lifetime of the CORBA object (as contacted through an object reference)is the same as the lifetime of its servant object. Persistent objects can live beyondthe destruction of their servant object, the POA they were created in, and eventheir process. Persistent objects are, of course, only contactable when their associ-ated servants are active, or can be activated by their POA with a servant manager3.A reference to a persistent object can be published, and will remain valid even ifthe server process is restarted.

A POA’s Lifespan Policy determines whether objects created within it are tran-sient or persistent. The Root POA has the TRANSIENTpolicy. (Note that since onlythe Root POA is available when using omniORBpy with omniORB 2.8, it is notpossible to create persistent objects in that environment.)

An alternative to creating persistent objects is to register object references ina naming service and bind them to fixed pathnames. Clients can bind to the objectimplementations at runtime by asking the naming service to resolve the pathnamesto the object references. CORBA defines a standard naming service, which is acomponent of the Common Object Services (COS) [OMG98], that can be used forthis purpose. The next section describes an example of how to use the COS NamingService.

2.6 Example 3 — Using the Naming Service

In this example, the object implementation uses the Naming Service [OMG98] topass on the object reference to the client. This method is far more practical thanusing stringified object references. The full listings of the server and client arebelow.

The names used by the Naming service consist of a sequence of name compo-nents. Each name component has an id and a kind field, both of which are strings.All name components except the last one are bound to naming contexts. A namingcontext is analogous to a directory in a filing system: it can contain names of ob-ject references or other naming contexts. The last name component is bound to anobject reference.

3The POA itself can be activated on demand with an adapter activator.

Page 19: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

2.6. EXAMPLE 3 — USING THE NAMING SERVICE 13

Sequences of name components can be represented as a flat string, using ‘.’ toseparate the id and kind fields, and ‘/’ to separate name components from eachother4. In our example, the Echo object reference is bound to the stringified name‘test.my_context/ExampleEcho.Object ’.

The kind field is intended to describe the name in a syntax-independent way.The naming service does not interpret, assign, or manage these values. However,both the name and the kind attribute must match for a name lookup to succeed.In this example, the kind values for test and ExampleEcho are chosen to be‘my_context ’ and ‘Object ’ respectively. This is an arbitrary choice as there is nostandardised set of kind values.

2.6.1 Obtaining the Root Context object reference

The initial contact with the Naming Service can be established via the root context.The object reference to the root context is provided by the ORB and can be ob-tained by calling resolve_initial_references() . The following code frag-ment shows how it is used:

import CosNamingorb = CORBA.ORB_init(sys.argv, CORBA.ORB_ID)obj = orb.resolve_initial_references("NameService");cxt = obj._narrow(CosNaming.NamingContext)

Remember, omniORB constructs its internal list of initial references at initial-isation time using the information provided in the configuration file omniORB.cfg , or given on the command line. If this file is not present, the internal listwill be empty and resolve_initial_references() will raise a CORBA.ORB.InvalidName exception.

Note that, like string_to_object() , resolve_initial_references()returns base CORBA.Object , so we should narrow it to the interface we want. Inthis case, we want CosNaming.NamingContext 5.

2.6.2 The Naming Service interface

It is beyond the scope of this chapter to describe in detail the Naming Service in-terface. You should consult the CORBA services specification [OMG98] (chapter3).

2.6.3 Server code

Hopefully, the server code is self-explanatory:4There are escaping rules to cope with id and kind fields which contain ‘.’ and ‘/’ characters.

See chapter 4 of this manual, and chapter 3 of the CORBA services specification, as updated for theInteroperable Naming Service [OMG00a].

5If you are on-the-ball, you will have noticed that we didn’t call _narrow() when resolving theRoot POA. The reason it is safe to miss it out is given in section 3.1.

Page 20: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

14 CHAPTER 2. THE BASICS

#!/usr/bin/env pythonimport sysfrom omniORB import CORBA, PortableServerimport CosNaming, Example, Example__POA

# Define an implementation of the Echo interfaceclass Echo_i (Example__POA.Echo):

def echoString(self, mesg):print "echoString() called with message:", mesgreturn mesg

# Initialise the ORB and find the root POAorb = CORBA.ORB_init(sys.argv, CORBA.ORB_ID)poa = orb.resolve_initial_references("RootPOA")

# Create an instance of Echo_i and an Echo object referenceei = Echo_i()eo = ei._this()

# Obtain a reference to the root naming contextobj = orb.resolve_initial_references("NameService")rootContext = obj._narrow(CosNaming.NamingContext)

if rootContext is None:print "Failed to narrow the root naming context"sys.exit(1)

# Bind a context named "test.my_context" to the root contextname = [CosNaming.NameComponent("test", "my_context")]try:

testContext = rootContext.bind_new_context(name)print "New test context bound"

except CosNaming.NamingContext.AlreadyBound, ex:print "Test context already exists"obj = rootContext.resolve(name)testContext = obj._narrow(CosNaming.NamingContext)if testContext is None:

print "test.mycontext exists but is not a NamingContext"sys.exit(1)

# Bind the Echo object to the test contextname = [CosNaming.NameComponent("ExampleEcho", "Object")]try:

testContext.bind(name, eo)print "New ExampleEcho object bound"

except CosNaming.NamingContext.AlreadyBound:testContext.rebind(name, eo)

Page 21: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

2.6. EXAMPLE 3 — USING THE NAMING SERVICE 15

print "ExampleEcho binding already existed -- rebound"

# Activate the POApoaManager = poa._get_the_POAManager()poaManager.activate()

# Block for ever (or until the ORB is shut down)orb.run()

2.6.4 Client code

Hopefully the client code is self-explanatory too:

#!/usr/bin/env pythonimport sysfrom omniORB import CORBAimport CosNaming, Example

# Initialise the ORBorb = CORBA.ORB_init(sys.argv, CORBA.ORB_ID)

# Obtain a reference to the root naming contextobj = orb.resolve_initial_references("NameService")rootContext = obj._narrow(CosNaming.NamingContext)

if rootContext is None:print "Failed to narrow the root naming context"sys.exit(1)

# Resolve the name "test.my_context/ExampleEcho.Object"name = [CosNaming.NameComponent("test", "my_context"),

CosNaming.NameComponent("ExampleEcho", "Object")]try:

obj = rootContext.resolve(name)

except CosNaming.NamingContext.NotFound, ex:print "Name not found"sys.exit(1)

# Narrow the object to an Example::Echoeo = obj._narrow(Example.Echo)

if (eo is None):print "Object reference is not an Example::Echo"sys.exit(1)

# Invoke the echoString operationmessage = "Hello from Python"result = eo.echoString(message)

Page 22: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

16 CHAPTER 2. THE BASICS

print "I said ’%s’. The object said ’%s’." % (message,result)

2.7 Global IDL definitions

As we have seen, the Python mapping maps IDL modules to Python packages withthe same name. This poses a problem for IDL declarations at global scope. Globaldeclarations are generally a bad idea since they make name clashes more likely,but they must be supported.

Since Python does not have a concept of a global scope (only a per-moduleglobal scope, which is dangerous to modify), global declarations are mapped to aspecially named Python package. By default, this package is named _GlobalIDL ,with skeletons in _GlobalIDL__POA . The package name may be changed withomniidl’s -Wbglobal option, described in section 5.2. The omniORB C++ Echoexample, with IDL:

interface Echo {string echoString(in string mesg);

};

can therefore be supported with code like

#!/usr/bin/env python

import sysfrom omniORB import CORBAimport _GlobalIDL

orb = CORBA.ORB_init(sys.argv, CORBA.ORB_ID)

ior = sys.argv[1]obj = orb.string_to_object(ior)eo = obj._narrow(_GlobalIDL.Echo)

message = "Hello from Python"result = eo.echoString(message)print "I said ’%s’. The object said ’%s’" % (message,result)

Page 23: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

Chapter 3

Python language mapping issues

omniORBpy adheres to the standard Python mapping [OMG00b], so there is noneed to describe the mapping here. This chapter outlines a number of issues whichare not addressed by the standard (or are optional), and how they are resolved inomniORBpy.

3.1 Narrowing object references

As explained in chapter 2, whenever you receive an object reference declared to bebase CORBA::Object , such as from NamingContext::resolve() or ORB::string_to_object() , you should narrow the reference to the type you require.You might think that since Python is a dynamically typed language, narrowingshould never be necessary. Unfortunately, although omniORBpy often generatesobject references with the right types, it cannot do so in all circumstances.

The rules which govern when narrowing is required are quite complex. To betotally safe, you can always narrow object references to the type you are expecting.The advantages of this approach are that it is simple and that it is guaranteed towork with all Python ORBs.

The disadvantage with calling narrow for all received object references is thatmuch of the time it is guaranteed not to be necessary. If you understand the situa-tions in which narrowing is necessary, you can avoid spurious narrowing.

3.1.1 The gory details

When object references are transmitted (or stored in stringified IORs), they containa single type identifier string, termed the repository id. Normally, the repository idrepresents the most derived interface of the object. However, it is also permitted tobe the empty string, or to refer to an interface higher up the inheritance hierarchy.To give a concrete example, suppose there are two IDL files:

// a.idlmodule M1 {

17

Page 24: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

18 CHAPTER 3. PYTHON LANGUAGE MAPPING ISSUES

interface A {void opA();

};};

// b.idl#include "a.idl"module M2 {

interface B : M1::A {void opB();

};};

A reference to an object with interface B will normally contain the repository id‘IDL:M2/B:1.0 ’1. It is also permitted to have an empty repository id, or the id‘IDL:M1/A:1.0 ’. ‘IDL:M1/A:1.0 ’ is unlikely unless the server is being deliber-ately obtuse.

Whenever omniORBpy receives an object reference from somewhere—eitheras a return value or as an operation argument—it has a particular target interfacein mind, which it compares with the repository id it has received. A target of baseCORBA::Object is just one (common) case. For example, in the following IDL:

// c.idl#include "a.idl"module M3 {

interface C {Object getObj();M1::A getA();

};};

the target interface for getObj ’s return value is CORBA::Object ; the target inter-face for getA ’s return value is M1::A .

omniORBpy uses the result of comparing the received and target repositoryids to determine the type of the object reference it creates. The object reference haseither the type of the received reference, or the target type, according to this table:

Case Objref Type1. The received id is the same as the target id received2. The received id is not the same as the target id, but

the ORB knows that the received interface is derivedfrom the target interface

received

3. The received id is unknown to the ORB target4. The received id is not the same as the target id, and

the ORB knows that the received interface is not de-rived from the target interface

target

1It is possible to change the repository id strings associated with particular interfaces using theID , version and prefix pragmas.

Page 25: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

3.2. SUPPORT FOR ANY VALUES 19

Cases 1 and 2 are the most common. Case 2 explains why it is not necessaryto narrow the result of calling resolve_initial_references("RootPOA") :the return is always of the known type PortableServer.POA , which is derivedfrom the target type of CORBA.Object .

Case 3 is also quite common. Suppose a client knows about IDL modules M1and M3 from above, but not module M2. When it calls getA() on an instance ofM3::C , the return value may validly be of type M2::B , which it does not know. Bycreating an object reference of type M1::A in this case, the client is still able to callthe object’s opA() operation. On the other hand, if getObj() returns an object oftype M2::B , the ORB will create a reference to base CORBA::Object , since that isthe target type.

Note that the ORB never rejects an object reference due to it having the wrongtype. Even if it knows that the received id is not derived from the target interface(case 4), it might be the case that the object actually has a more derived interface,which is derived from both the type it is claiming to be and the target type. That is,of course, extremely unlikely.

In cases 3 and 4, the ORB confirms the type of the object by calling _is_a() justbefore the first invocation on the object. If it turns out that the object is not of theright type after all, the CORBA.INV_OBJREFexception is raised. The alternativeto this approach would be to check the types of object references when they werereceived, rather than waiting until the first invocation. That would be inefficient,however, since it is quite possible that a received object reference will never beused. It may also cause objects to be activated earlier than expected.

In summary, whenever your code receives an object reference, you should bearin mind what omniORBpy’s idea of the target type is. You must not assume thatthe ORB will always correctly figure out a more derived type than the target. Oneconsequence of this is that you must always narrow a plain CORBA::Object to amore specific type before invoking on it2. You can assume that the object referenceyou receive is of the target type, or something derived from it, although the objectit refers to may turn out to be invalid. The fact that omniORBpy often is ablefigure out a more derived type than the target is only useful when using the Pythoninteractive command line.

3.2 Support for Any values

In statically typed languages, such as C++, Anys can only be used with built-intypes and IDL-declared types for which stubs have been generated. If, for example,a C++ program receives an Any containing a struct for which it does not have staticknowledge, it cannot easily extract the struct contents. The only solution is to usethe inconvenient DynAny interface.

Since Python is a dynamically typed language, it does not have this difficulty.When omniORBpy receives an Any containing types it does not know, it is able to

2Unless you are invoking pseudo operations like _is_a() and _non_existent() .

Page 26: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

20 CHAPTER 3. PYTHON LANGUAGE MAPPING ISSUES

create new Python types which behave exactly as if there were statically generatedstubs available. Note that this behaviour is not required by the Python mappingspecification, so other Python ORBs may not be so accommodating.

The equivalent of DynAny creation can be achieved by dynamically writingand importing new IDL, as described in section 6.12.

There is, however, a minor fly in the ointment when it comes to receivingAnys. When an Any is transmitted, it is sent as a TypeCode followed by the ac-tual value. Normally, the TypeCodes for entities with names—members of structs,for example—contain those names as strings. That permits omniORBpy to createtypes with the corresponding names. Unfortunately, the GIOP specification per-mits TypeCodes to be sent with empty strings where the names would normallybe3. In this situation, the types which omniORBpy creates cannot be given thecorrect names. The contents of all types except structs and exceptions can be ac-cessed without having to know their names, through the standard interfaces. Un-known structs and exceptions received by omniORBpy have an attribute named‘_values ’ which contains a sequence of the member values. This attribute isomniORBpy specific.

Similarly, TypeCodes for constructed types such as structs and unions normallycontain the repository ids of those types. This means that omniORBpy can usetypes statically declared in the stubs when they are available. Once again, thespecification permits the repository id strings to be empty4. This means that evenif stubs for a type received in an Any are available, it may not be able to create aPython value with the right type. For example, with a struct definition such as:

module M {struct S {

string str;long l;

};};

The transmitted TypeCode for M::S may contain only the information that it is astructure containing a string followed by a long, not that it is type M::S , or whatthe member names are.

To cope with this situation, omniORBpy has an extension to the standard in-terface which allows you to coerce an Any value to a known type. Calling anAny’s value() method with a TypeCode argument returns either a value of therequested type, or None if the requested TypeCode is not equivalent to the Any’sTypeCode. The following code is guaranteed to be safe, but is not standard:

a = # Acquire an Any from somewherev = a.value(CORBA.TypeCode(CORBA.id(M.S)))if v is not None:

3This is now deprecated, but some ORBs may still send empty strings. No version of omniORBhas ever sent empty strings.

4And once again, this practice is deprecated.

Page 27: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

3.3. INTERFACE REPOSITORY STUBS 21

print v.strelse:

print "The Any does not contain a value compatible with M::S."

3.3 Interface Repository stubs

The Interface Repository interfaces are declared in IDL module CORBAso, accord-ing to the Python mapping, the stubs for them should appear in the Python CORBAmodule, along with all the other CORBA definitions. However, since the stubs areextremely large, omniORBpy does not include them by default. To do so wouldunnecessarily increase the memory footprint and start-up time.

The Interface Repository stubs are automatically included if you define theOMNIORBPY_IMPORT_IR_STUBSenvironment variable. Alternatively, you canimport the stubs at run-time by calling the omniORB.importIRStubs() func-tion. In both cases, the stubs become available in the Python CORBAmodule.

3.4 Using omniORBpy with omniORB 2.8

omniORBpy is designed to work with omniORB 3. When it is used with omniORB2.8, many facilities are not available. This section describes the limitations.

If you require facilities which are not available with omniORB 2.8, you cancause your program to bail-out gracefully by detecting the omniORB version atstart-up. The omniORB.coreVersion() function returns a string of the formmajor.minor.micro which indicates what version of omniORB is in use. The twopossible values are currently ‘2.8.0 ’ and ‘3.0.0 ’. Versions which differ only inmicro version number are guaranteed to be compatible with each other.

3.4.1 POA functions

Under 2.8, only the root POA is available. It supports only the following functions:

• destroy()

• _get_the_name()

• _get_the_POAManager()

• activate_object()

• deactivate_object()

• servant_to_id()

• servant_to_reference()

• reference_to_servant()

• reference_to_id()

Page 28: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

22 CHAPTER 3. PYTHON LANGUAGE MAPPING ISSUES

• id_to_servant()

• id_to_reference()

The POAManager interface only supports:

• activate()

• get_state()

For both interfaces, all other operations fail, raising the CORBA.NO_IMPLEMENTexception.

3.4.2 Local / remote transparency

omniORB 3 goes to great lengths to make sure that the semantics of local objectsare identical to those for remote objects. omniORB 2.8 does not. omniORBpy alsotries very hard to keep local and remote semantics identical, but on the foundationof omniORB 2.8 it is not always possible.

In most cases, you will not notice a difference between local and remote oper-ations. The cases where local/remote transparency is broken under omniORB 2.8are:

• An object is not deactivated until all local references to it have been released.

• When invoking on an object reference to a local object of the wrong type,as described in section 3.1, CORBA.INV_OBJREFis not raised. Instead, ifthe operation name does not exist on the object, CORBA.NO_IMPLEMENTisraised; if the operation name does exist but the argument types are wrong,CORBA.BAD_PARAMis raised; if the operation exists and the argument typesare correct, the operation is executed.

• Exception handlers (described later in section 6.10) are not executed whenlocal objects raise system exceptions. Exceptions are always propagated tothe caller.

In all of these cases, omniORB 3 properly preserves local/remote transparency.

Page 29: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

Chapter 4

Interoperable Naming Service

omniORB 3 supports the Interoperable Naming Service (INS), which will be partof CORBA 2.4. The following is a summary of the new facilities described in theINS edited chapters document [OMG00a]. These facilities are not available whenusing omniORBpy with omniORB 2.8.

4.1 Object URIs

As well as accepting IOR-format strings, ORB::string_to_object() now alsosupports two new Uniform Resource Identifier (URI) [BLFIM98] formats, whichcan be used to specify objects in a convenient human-readable form. The existingIOR-format strings are now also considered URIs.

4.1.1 corbaloc

corbaloc URIs allow you to specify object references which can be contacted byIIOP, or found through ORB::resolve_initial_references() . To specifyan IIOP object reference, you use a URI of the form:

corbaloc:iiop: <host>: <port>/ <object key>

for example:

corbaloc:iiop:myhost.example.com:1234/MyObjectKey

which specifies an object with key ‘MyObjectKey’ within a process running onmyhost.example.com listening on port 1234. Object keys containing non-ASCIIcharacters can use the standard URI % escapes:

corbaloc:iiop:myhost.example.com:1234/My%efObjectKey

23

Page 30: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

24 CHAPTER 4. INTEROPERABLE NAMING SERVICE

denotes an object key with the value 239 (hex ef) in the third octet.The protocol name ‘iiop ’ can be abbreviated to the empty string, so the origi-

nal URI can be written:

corbaloc::myhost.example.com:1234/MyObjectKey

The IANA has assigned port number 28091 for use by corbaloc , so if the server islistening on that port, you can leave the port number out. The following two URIsrefer to the same object:

corbaloc::myhost.example.com:2809/MyObjectKeycorbaloc::myhost.example.com/MyObjectKey

You can specify an object which is available at more than one location by separatingthe locations with commas:

corbaloc::myhost.example.com,:localhost:1234/MyObjectKey

Note that you must restate the protocol for each address, hence the ‘: ’ before‘localhost ’. It could equally have been written ‘iiop:localhost ’.

You can also specify an IIOP version number, although omniORB only supportsIIOP 1.0 at present:

corbaloc::[email protected]/MyObjectKey

Alternatively, to use resolve_initial_references() , you use a URI of theform:

corbaloc:rir:/NameService

4.1.2 corbaname

corbaname URIs cause string_to_object() to look-up a name in a CORBANaming service. They are an extension of the corbaloc syntax:

corbaname: <corbaloc location>/ <object key>#<stringified name>

for example:

corbaname::myhost/NameService#project/example/echo.objcorbaname:rir:/NameService#project/example/echo.obj

Note that the object found with the corbaloc -style portion must be of type Cos-Naming::NamingContext , or something derived from it. If the object key (orrir name) is ‘NameService ’, it can be left out:

1Not 2089 as printed in [OMG00a]!

Page 31: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

4.2. CONFIGURING RESOLVE_INITIAL_REFERENCES 25

corbaname::myhost#project/example/echo.objcorbaname:rir:#project/example/echo.obj

The stringified name portion can also be left out, in which case the URI denotes theCosNaming::NamingContext which would have been used for a look-up:

corbaname::myhost.example.comcorbaname:rir:

The first of these examples is the easiest way of specifying the location of a namingservice.

4.2 Configuring resolve_initial_references

The INS adds two new command line arguments which provide a portable way ofconfiguring ORB::resolve_initial_references() :

4.2.1 ORBInitRef

-ORBInitRef takes an argument of the form <ObjectId>=<ObjectURI>. So, forexample, with command line arguments of:

-ORBInitRef NameService=corbaname::myhost.example.com

resolve_initial_references("NameService") will return a reference tothe object with key ‘NameService’ available on myhost.example.com, port 2809.Since IOR-format strings are considered URIs, you can also say things like:

-ORBInitRef NameService=IOR:00ff...

4.2.2 ORBDefaultInitRef

-ORBDefaultInitRef provides a prefix string which is used to resolve other-wise unknown names. When resolve_initial_references() is unable toresolve a name which has been specifically configured (with -ORBInitRef ), itconstructs a string consisting of the default prefix, a ‘/ ’ character, and the namerequested. The string is then fed to string_to_object() . So, for example, witha command line of:

-ORBDefaultInitRef corbaloc::myhost.example.com

a call to resolve_initial_references("MyService") will return the objectreference denoted by ‘corbaloc::myhost.example.com/MyService ’.

Similarly, a corbaname prefix can be used to cause look-ups in the namingservice. Note, however, that since a ‘/ ’ character is always added to the prefix, itis impossible to specify a look-up in the root context of the naming service—youhave to use a sub-context, like:

Page 32: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

26 CHAPTER 4. INTEROPERABLE NAMING SERVICE

-ORBDefaultInitRef corbaname::myhost.example.com#services

4.2.3 omniORB configuration file

As an extension to the standard facilities of the INS, omniORB supports configu-ration file entries named ORBInitRef and ORBDefaultInitRef . The syntax isidentical to the command line arguments. omniORB.cfg might contain:

ORBInitRef NameService=corbaname::myhost.example.comORBDefaultInitRef corbaname:rir:#services

4.2.4 Resolution order

With all these options for specifying object references to be returned by resolve_initial_references() , it is important to understand the order in which theoptions are tried. The resolution order, as required by the CORBA specification, is:

1. Check for special names such as ‘RootPOA’2.

2. Resolve with an -ORBInitRef argument.

3. Resolve with the -ORBDefaultInitRef prefix, if present.

4. Resolve with an ORBInitRef (or old-style NAMESERVICE) entry in the con-figuration file.

5. Resolve with the ORBDefaultInitRef entry in the configuration file, ifpresent.

6. Resolve with the deprecated ORBInitialHost boot agent.

This order mostly has the expected consequences—in particular that command linearguments override entries in the configuration file. However, you must be carefulwith the default prefixes. Suppose you have configured a ‘NameService ’ entry inthe configuration file, and you specify a default prefix on the command line with:

-ORBDefaultInitRef corbaname:rir:#services

expecting unknown services to be looked up in the configured naming service.Now, step 3 above means that resolve_initial_references("MyService")should be processed with the steps:

1. Construct the URI ‘corbaname:rir:#services/MyService ’ and give itto string_to_object() .

2In fact, a strict reading of the specification says that it should be possible to override ‘RootPOA’etc. with -ORBInitRef , but since POAs are locality constrained that is ridiculous.

Page 33: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

4.3. OMNINAMES 27

2. Resolve the first part of the corbaname URI by callingresolve_initial_references("NameService") .

3. Construct the URI ‘corbaname:rir:#services/NameService ’ and giveit to string_to_object() .

4. Resolve the first part of the corbaname URI by callingresolve_initial_references("NameService") .

5. . . . and so on for ever. . .

omniORB detects loops like this and throws either CORBA.ORB.InvalidName ifthe loop started with a call to resolve_initial_references() , or CORBA.BAD_PARAMif it started with a call to string_to_object() . To avoid the prob-lem you must either specify the NameService reference on the command line, orput the DefaultInitRef in the configuration file.

4.3 omniNames

4.3.1 NamingContextExt

omniNames now supports the CosNaming::NamingContextExt interface:

module CosNaming {interface NamingContextExt : NamingContext {

typedef string StringName;typedef string Address;typedef string URLString;

StringName to_string(in Name n) raises(InvalidName);Name to_name (in StringName sn) raises(InvalidName);

exception InvalidAddress {};

URLString to_url(in Address addr, in StringName sn)raises(InvalidAddress, InvalidName);

Object resolve_str(in StringName n)raises(NotFound, CannotProceed, InvalidName, AlreadyBound);

};};

to_string() and to_name() convert from CosNaming::Name sequencesto flattened strings and vice-versa. Note that calling these operations involves re-mote calls to the naming service, so they are not particularly efficient. The omni-ORB.URI module contains equivalent nameToString() and stringToName()functions, which do not involve remote calls.

Page 34: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

28 CHAPTER 4. INTEROPERABLE NAMING SERVICE

A CosNaming::Name is stringified by separating name components with ‘/ ’characters. The kind and id fields of each component are separated by ‘. ’ char-acters. If the kind field is empty, the representation has no trailing ‘. ’; if the idis empty, the representation starts with a ‘. ’ character; if both id and kind areempty, the representation is just a ‘. ’. The backslash ‘\ ’ is used to escape the mean-ing of ‘/ ’, ‘. ’ and ‘\ ’ itself.

to_url() takes a corbaloc style address and key string (but without thecorbaloc: part), and a stringified name, and returns a corbaname URI (incor-rectly called a URL) string, having properly escaped any invalid characters. Thespecification does not make it clear whether or not the address string should alsobe escaped by the operation; omniORB does not escape it. For this reason, it is bestto avoid calling to_url() if the address part contains escapable characters. Thelocal function omniORB.URI.addrAndNameToURI() is equivalent.

resolve_str() is equivalent to calling to_name() followed by the inheritedresolve() operation. There are no string-based equivalents of the various bindoperations.

4.3.2 Use with corbaname

To make it easy to use omniNames with corbaname URIs, it now starts with thedefault port of 2809, and an object key of ‘NameService ’ for the root namingcontext. This is only possible when it is started ‘fresh’, rather than with a log filefrom an older omniNames version.

If you have a previous omniNames log, configured to run on a different port,and with a different object key for its root context, all is not lost. If the root context’sobject key is not ‘NameService ’, omniNames creates a forwarding agent with thatkey. Effectively, this means that there are two object keys which refer to the rootcontext—‘NameService ’ and whatever the original key was.

For the port number, there are two options. The first is to run omniNames witha command line argument like:

omniNames -logdir /the/log/dir -ORBpoa_iiop_port 2809

This causes it to listen on both port 2809 and whatever port it listened on before.The disadvantage with this is that the IORs to all naming contexts now contain twoIIOP profiles, one for each port, which, amongst other things, increases the size ofthe omniNames log.

The second option is to use omniMapper, as described below.

4.4 omniMapper

omniMapper is a simple daemon which listens on port 2809 (or any other port),and redirects IIOP requests for configured object keys to associated persistent IORs.It can be used to make a naming service (even an old non-INS aware version of

Page 35: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

4.5. CREATING OBJECTS WITH SIMPLE OBJECT KEYS 29

omniNames or other ORB’s naming service) appear on port 2809 with the objectkey ‘NameService ’. The same goes for any other service you may wish to specify,such as an interface repository. omniMapper is started with a command line of:

omniMapper [-port <port>] [-config <config file>] [-v]

The -port option allows you to choose a port other than 2809 to listen on3. The-config option specifies a location for the configuration file. The default name is/etc/omniMapper.cfg , or C:\omniMapper.cfg on Windows. omniMapperdoes not normally print anything; the -v option makes it verbose so it prints con-figuration information and a record of the redirections it makes, to standard out-put.

The configuration file is very simple. Each line contains a string to be used asan object key, some white space, and an IOR (or any valid URI) that it will redirectthat object key to. Comments should be prefixed with a ‘#’ character. For example:

# Example omniMapper.cfgNameService IOR:000f...InterfaceRepository IOR:0100...

omniMapper can either be run on a single machine, in much the same way asomniNames, or it can be run on every machine, with a common configuration file.That way, each machine’s omniORB configuration file could contain the line:

ORBDefaultInitRef corbaloc::localhost

4.5 Creating objects with simple object keys

In normal use, omniORB creates object keys containing various information in-cluding POA names and various non-ASCII characters. Since object keys are sup-posed to be opaque, this is not usually a problem. The INS breaks this opacity andrequires servers to create objects with human-friendly keys.

If you wish to make your objects available with human-friendly URIs, thereare two options. The first is to use omniMapper as described above, in conjunctionwith a PERSISTENTPOA. The second is to create objects with the required keysyourself. You do this with a special POA with the name ‘omniINSPOA’, acquiredfrom resolve_initial_references() . This POA has the USER_IDand PER-SISTENT policies, and the special property that the object keys it creates containonly the object ids given to the POA, and no other data. It is a normal POA in allother respects, so you can activate/deactivate it, create children, and so on, in theusual way.

3You can also play the -ORBpoa_iiop_port trick to make it listen on more than one port.

Page 36: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

30 CHAPTER 4. INTEROPERABLE NAMING SERVICE

Page 37: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

Chapter 5

The IDL compiler

omniORBpy uses a new IDL compiler, named omniidl, which is also used by omni-ORB 3. It consists of a generic front-end parser written in C++, and a number ofback-ends written in Python. omniidl is very strict about IDL validity, so you mayfind that it reports errors in IDL which compiles fine with earlier versions of omni-ORB, and with other ORBs.

The general form of an omniidl command line is:

omniidl [options] -b <back-end> [back-end options] <file 1> <file 2> . . .

5.1 Common options

The following options are common to all back-ends:

-D name[=value] Define name for the preprocessor.-U name Undefine name for the preprocessor.-I dir Include dir in the preprocessor search path.-E Only run the preprocessor, sending its output to stdout.-Y cmd Use cmd as the preprocessor, rather than the normal C preprocessor.-N Do not run the preprocessor.-T Use a temporary file, not a pipe, for preprocessor output.-Wparg[,arg. . . ] Send arguments to the preprocessor.-b back-end Run the specified back-end. For omniORBpy, use -bpython .-Wbarg[,arg. . . ] Send arguments to the back-end.-nf Do not warn about unresolved forward declarations.-k Keep comments after declarations, to be used by some back-ends.-K Keep comments before declarations, to be used by some back-ends.-C dir Change directory to dir before writing output files.-d Dump the parsed IDL then exit, without running a back-end.-p dir Use dir as a path to find omniidl back-ends.-V Print version information then exit.

31

Page 38: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

32 CHAPTER 5. THE IDL COMPILER

-u Print usage information.-v Verbose: trace compilation stages.

Most of these options are self explanatory, but some are not so obvious.

5.1.1 Preprocessor interactions

IDL is processed by the C preprocessor before omniidl parses it. Unlike the old IDLcompiler, which used different C preprocessors on different platforms, omniidlalways uses the GNU C preprocessor (which it builds with the name omnicpp).The -D , -U , and -I options are just sent to the preprocessor. Note that the currentdirectory is not on the include search path by default—use ‘-I. ’ for that. The -Yoption can be used to specify a different preprocessor to omnicpp. Beware that linedirectives inserted by other preprocessors are likely to confuse omniidl.

5.1.1.1 Windows 9x

The output from the C preprocessor is normally fed to the omniidl parser througha pipe. On some Windows 98 machines (but not all!) the pipe does not work, andthe preprocessor output is echoed to the screen. When this happens, the omniidlparser sees an empty file, and produces useless stub files with strange long names.To avoid the problem, use the ‘-T ’ option to create a temporary file between thetwo stages.

5.1.2 Forward-declared interfaces

If you have an IDL file like:

interface I;interface J {

attribute I the_I;};

then omniidl will normally issue a warning:

test.idl:1: Warning: Forward declared interface ‘::I’ was neverfully defined

It is illegal to declare such IDL in isolation, but it is valid to define interface I in aseparate file. If you have a lot of IDL with this sort of construct, you will drownunder the warning messages. Use the -nf option to suppress them.

Page 39: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

5.2. PYTHON BACK-END OPTIONS 33

5.1.3 Comments

By default, omniidl discards comments in the input IDL. However, with the -k and-K options, it preserves the comments for use by the back-ends. The C++ back-endignores this information, but it is relatively easy to write new back-ends which domake use of comments.

The two different options relate to how comments are attached to declarationswithin the IDL. Given IDL like:

interface I {void op1();// A commentvoid op2();

};

the -k flag will attach the comment to op1() ; the -K flag will attach it to op2() .

5.2 Python back-end options

When you specify the Python back-end (with -bpython ), the following -Wb op-tions are available. Note that the -Wb options must be specified after the -bpythonoption, so omniidl knows which back-end to give the arguments to.

-Wbstdout Send the generated stubs to standard output, rather than to a file.-Wbinline Output stubs for #included files in line with the main file.-Wbglobal= g Use g as the name for the global IDL scope (default _GlobalIDL ).-Wbpackage= p Put both Python modules and stub files in package p.-Wbmodules= p Put Python modules in package p.-Wbstubs= p Put stub files in package p.

The -Wbstdout option is not really useful if you are invoking omniidl your-self. It is used by omniORB.importIDL() , described in section 6.12.

When you compile an IDL file which #includes other IDL files, omniidl nor-mally only generates code for the main file, assuming that code for the includedfiles will be generated separately. Instead, you can use the -Wbinline option togenerate code for the main IDL file and all included files in a single stub file.

Definitions declared at IDL global scope are normally placed in a Python mod-ule named ‘_GlobalIDL ’. The -Wbglobal allows you to change that.

As explained in section 2.2, when you compile an IDL file like:

// echo_example.idlmodule Example {

interface Echo {string echoString(in string mesg);

};};

Page 40: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

34 CHAPTER 5. THE IDL COMPILER

omniidl generates directories named Example and Example__POA , which pro-vide the standard Python mapping modules, and also the file example_echo_idl.py which contains the actual definitions. The latter file contains code whichinserts the definitions in the standard modules. This arrangement means that it isnot possible to move all of the generated code into a Python package by simplyplacing the files in a suitably named directory. You may wish to do this to avoidclashes with names in use elsewhere in your software.

You can place all generated code in a package using the -Wbpackage com-mand line option. For example,

omniidl -bpython -Wbpackage=generated echo_example.idl

creates a directory named ‘generated ’, containing the generated code. The stubmodule is now called ‘generated.Example ’, and the actual stub definitions arein ‘generated.example_echo_idl ’. If you wish to split the modules and thestub definitions into different Python packages, you can use the -Wbmodules and-Wbstubs options.

Note that if you use these options to change the module package, the interfaceto the generated code is not strictly-speaking CORBA compliant. You may have tochange your code if you ever use a Python ORB other than omniORBpy.

5.3 Examples

Generate the Python stubs for a file a.idl :

omniidl -bpython a.idl

As above, but put the stubs in a package called ‘stubs ’:

omniidl -bpython -Wbstubs=stubs a.idl

Generate both Python and C++ stubs for two IDL files (requires omniORB 3):

omniidl -bpython -bcxx a.idl b.idl

Just check the IDL files for validity, generating no output:

omniidl a.idl b.idl

Page 41: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

Chapter 6

The omniORBpy API

In this chapter, we introduce the omniORBpy API. The purpose of this API is toprovide access points to omniORB specific functionality that is not covered by theCORBA specification. Obviously, if you use this API in your application, that partof your code is not going to be portable to run unchanged on other vendors’ ORBs.To make it easier to identify omniORB dependent code, this API is defined in the‘omniORB’ module.

6.1 ORB initialisation options

CORBA::ORB_init() accepts the following standard command-line arguments:

-ORBid omniORB3 The identifier must be ‘omniORB3’.-ORBInitRef <ObjectId>=<ObjectURI> See section 4.2.-ORBDefaultInitRef <Default URI> See section 4.2.

and the following omniORB-specific arguments:

-ORBtraceLevel <level> See section 6.3.-ORBtraceInvocations See section 6.3.-ORBstrictIIOP See section 6.8.-ORBgiopMaxMsgSize <size in bytes> See section 6.5.-ORBobjectTableSize <number of entries> See section 6.6.-ORBserverName <string> See section 6.4.-ORBno_bootstrap_agent See section 6.7.-ORBverifyObjectExistsAndType <0 or 1> See section 6.8.-ORBinConScanPeriod <0–max integer> See section 7.3.-ORBoutConScanPeriod <0–max integer> See section 7.3.-ORBclientCallTimeOutPeriod <0–max integer> See section 7.3.-ORBserverCallTimeOutPeriod <0–max integer> See section 7.3.-ORBscanGranularity <0–max integer> See section 7.3.

35

Page 42: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

36 CHAPTER 6. THE OMNIORBPY API

-ORBlcdMode See section 6.8.-ORBpoa_iiop_port <port no.> See section 6.2.-ORBpoa_iiop_name_port <hostname[:port no.]> See section 6.2.-ORBhelp Lists all ORB command line options.

and these two obsolete omniORB-specific arguments:

-ORBInitialHost <string> See section 6.7.-ORBInitialPort <1–65535>] See section 6.7.

As defined in the CORBA specification, any command-line arguments understoodby the ORB will be removed from argv when the initialisation functions return.Therefore, an application is not required to handle any command-line argumentsit does not understand.

6.2 Hostname and port

Normally, omniORB lets the operating system pick which port number it shoulduse to listen for IIOP calls. Alternatively, you can specify a particular port us-ing -ORBpoa_iiop_port . If you specify -ORBpoa_iiop_port more than once,omniORB will listen on all the ports you specify.

By default, the ORB can work out the IP address of the host machine. This ad-dress is recorded in the object references of the local objects. However, when thehost has multiple network interfaces and multiple IP addresses, it may be desirablefor the application to control what address the ORB should use. This can be doneby defining the environment variable OMNIORB_USEHOSTNAMEto contain the pre-ferred host name or IP address in dot-numeric form. Alternatively, the same can beachieved using the -ORBpoa_iiop_name_port option. You can optionally spec-ify a port number too. Again, you can specify more than one host name by using-ORBpoa_iiop_name_port more than once.

When using omniORB 2.8, these two options are named -BOAiiop_port and-BOAiiop_name_port .

6.3 Run-time Tracing and Diagnostic Messages

omniORB can output tracing and diagnostic messages to the standard error stream.You can vary the amount of tracing using the -ORBtraceLevel <level> com-mand line argument. For instance:

$ example_echo_srv.py -ORBtraceLevel 5

You can also inspect or modify the trace level at run-time. A call to omniORB.traceLevel( level) sets the level; calling the function with no argument returnsthe current level.

Page 43: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

6.4. SERVER NAME 37

At the moment, the following trace levels are defined:

level 0 turn off all tracing and informational messageslevel 1 informational messages onlylevel 2 the above plus configuration informationlevel 5 the above plus notifications when server threads

are created or communication endpoints are shut-down

level 10–20 the above plus execution and exception traceslevel 25 the above plus hex dumps of all data sent and re-

ceived by the ORB via its network connections.

With omniORB 3, you can also use -ORBtraceInvocations to trace all opera-tion invocations.

6.4 Server Name

Applications can optionally specify a name to identify the server process. At themoment, this name is only used by the host-based access control module. See sec-tion 7.5 for details. The server name can be changed by specifying the command-line option: -ORBserverName <string>.

6.5 GIOP Message Size

omniORB sets a limit on the GIOP message size that can be sent or received. Themaximum size can be set with the command-line option -ORBgiopMaxMsgSize .The exact value is somewhat arbitrary. The reason such a limit exists is to providesome way to protect the server side from resource exhaustion. Think about thecase when the server receives a rogue GIOP(IIOP) request message that containsa sequence length field set to 231. With a reasonable message size limit, the servercan reject this rogue message straight away.

6.6 Object table size

omniORB uses a hash table to store the mapping from object keys to servant ob-jects. Normally, it dynamically re-sizes the hash table when it becomes too full ortoo empty. This is the most efficient trade-off between performance and memoryusage. However, since all POA operations which add or remove objects from thetable can (very occasionally) cause the object table to resize, the time spent in POAoperations is much less predictable than if the table size was fixed.

The -ORBobjectTableSize argument allows you to choose a fixed size forthe object table. This prevents omniORB from resizing it. Note that omniORB uses

Page 44: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

38 CHAPTER 6. THE OMNIORBPY API

an open hash table so you can have any number of objects active, no matter whatsize table you specify. If you have many more active objects than hash table entries,object look-up performance will become linear with the number of objects.

6.7 Obsolete Initial Object Reference Bootstrapping

Starting from 2.6.0, but superseded by the Interoperable Naming Service in omni-ORB 3, a mechanism is available for the ORB runtime to obtain the initial objectreferences to CORBA services. The bootstrap service is a special object with theobject key ‘INIT’ and the following interface1:

// IDLmodule CORBA {

interface InitialReferences {Object get(in ORB::ObjectId id);// returns the initial object reference of the service// identified by <id>. For example the id for the// Naming service is "NameService".

ORB::ObjectIdList list();// returns the list of service ids that this agent knows

};};

By default, all omniORB servers contain an instance of this object and are ableto respond to remote invocations. To prevent the ORB from instantiating this ob-ject, the command-line option -ORBno_bootstrap_agent should be specified.

In particular, the Naming Service omniNames is able to respond to a querythrough this interface and return the object reference of its root context. In effect,the bootstrap agent provides a level of indirection. All omniORB clients still haveto be supplied with the address of the bootstrap agent. However, the informa-tion is much easier to specify than a stringified IOR! Another advantage of thisapproach is that it is completely compatible with JavaIDL. This makes it possiblefor programs written for JavaIDL to share a Naming Service with omniORB.

The address of the bootstrap agent is given by the ORBInitialHost andORBInitialPort parameter in the omniORB configuration file (section 1.2). Theparameters can also be specified as command-line options (section 6.1). The pa-rameter ORBInitialPort is optional. If it is not specified, port number 900 willbe used.

During initialisation, the ORB reads the parameters in the omniORB config-uration file. If the parameter NAMESERVICEis specified, the stringified IOR isused as the object reference of the root naming context. If the parameter is absentand the parameter ORBInitialHost is present, the ORB contacts the bootstrap

1This interface was first defined by Sun’s NEO and is in used in Sun’s JavaIDL.

Page 45: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

6.8. GIOP LOWEST COMMON DENOMINATOR MODE 39

agent at the address specified to obtain the root naming context when the appli-cation calls resolve_initial_references() . If neither is present, resolve_initial_references() returns a nil object reference. Finally, the commandline argument -ORBInitialHost overrides any parameters in the configurationfile. The ORB always contacts the bootstrap agent at the address specified to obtainthe root naming context.

Now we are ready to describe a simple way to set up omniNames.

1. Start omniNames for the first time on a machine (e.g. wobble):

$ omniNames -start 1234

2. Add to omniORB.cfg:

ORBInitialHost wobble

ORBInitialPort 1234

3. All omniORB applications will now be able to contact omniNames.

Alternatively, the command line options can be used, for example:

$ eg3_impl -ORBInitialHost wobble -ORBInitialPort 1234 &

$ eg3_clt -ORBInitialHost wobble -ORBInitialPort 1234

6.8 GIOP Lowest Common Denominator Mode

Sometimes, to cope with bugs in another ORB, it is necessary to disable variousGIOP and IIOP features in order to achieve interoperability. If the command lineoption -ORBlcdMode is present, the ORB enters the so-called ‘lowest commondenominator mode’. It bends over backwards to cope with bugs in the ORB at theother end. This is purely a transitional measure. The long term solution is to reportthe bugs to the other vendors and ask them to fix them expediently.

In some (sloppy) IIOP implementations, the message size value in the IIOPheader can be larger than the actual body size, i.e. there is garbage at the end. Asthe spec does not say the message size must match the body size exactly, this isnot a clear violation of the spec. omniORB’s default policy is to expect incomingmessages to be formatted properly. Any messages that have garbage at the endwill be rejected.

-ORBlcdMode sets omniORB to silently skip the unread part of such invalidmessages. Alternatively, you can change just this policy with a command line ar-gument of -ORBstrictIIOP 0 . The problem with doing this is that the headermessage size may actually be garbage, caused by a bug in the sender’s code. Thereceiving thread may block forever as it tries to read more data from the connec-tion. In this case the sender won’t send any more as it thinks it has marshalled inall the data.

Page 46: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

40 CHAPTER 6. THE OMNIORBPY API

By default, omniORB uses the GIOP LOCATE_REQUEST message to verifythe existence of an object prior to the first invocation. If another vendor’s ORB isknown not to be able to handle this GIOP message, you can disable this featurewith the -ORBverifyObjectExistsAndType option, and hence achieve inter-operability.

6.9 GIOP Requesting Principal field

In versions 1.0 and 1.1 of the GIOP specification, request messages contain a ‘prin-cipal’ field which was intended to identify the client. The meaning of the principalfield was never specified, and its use is now deprecated. The field is not presentin GIOP 1.2. omniORB normally uses the string ‘nobody ’ in the principal field.However, some systems (e.g. the GNOME desktop environment) use the princi-pal field as an authentication mechanism, so omniORB allows you to configure theprincipal by setting the OMNIORB_PRINCIPALenvironment variable.

6.10 System Exception Handlers

By default, all system exceptions which are raised during an operation invocation,with the exception of CORBA.TRANSIENT, are propagated to the application code.Some applications may prefer to trap these exceptions within the proxy objects sothat the application logic does not have to deal with the error condition. For ex-ample, when a CORBA.COMM_FAILUREis received, an application may just wantto retry the invocation until it finally succeeds. This approach is useful for objectsthat are persistent and their operations are idempotent.

omniORBpy provides a set of functions to install exception handlers. Once theyare installed, proxy objects will call these handlers when the associated systemexceptions are raised by the ORB runtime. Handlers can be installed for CORBA.TRANSIENT, CORBA.COMM_FAILUREand CORBA.SystemException . This lasthandler covers all system exceptions other than the two covered by the first twohandlers. An exception handler can be installed for individual proxy objects, or itcan be installed for all proxy objects in the address space.

6.10.1 CORBA.TRANSIENT handlers

When a CORBA.TRANSIENTexception is raised by the ORB runtime, the defaultbehaviour of the proxy objects is to retry indefinitely until the operation succeeds,with an exponentially increasing delay (up to a limit) between retries.

The ORB runtime will raise CORBA.TRANSIENTunder the following condi-tions:

1. When a cached network connection is broken while an operation invocation

Page 47: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

6.11. LOCATION FORWARDING 41

is in progress. The ORB will try to open a new connection at the next invoca-tion.

2. When the proxy object has been redirected by a location forward message bythe remote object to a new location and the object at the new location cannotbe contacted. In addition to the CORBA.TRANSIENTexception, the proxyobject also resets its internal state so that the next invocation will be directedat the original location of the remote object.

3. When the remote object reports CORBA.TRANSIENT.

You can override the default behaviour by installing your own exception han-dler. The function to call has signature:

omniORB.installTransientExceptionHandler(cookie, function [, object])

The arguments are a cookie, which is any Python object, a call-back function,and optionally an object reference. If the object reference is present, the exceptionhandler is installed for just that object; otherwise the handler is installed for allobjects with no handler of their own.

The call-back function must have the signature

function(cookie, retries, exc) -> boolean

When a TRANSIENTexception occurs, the function is called, passing the cookieobject, a count of how many times the operation has been retried, and the TRAN-SIENT exception object itself. If the function returns true, the operation is retried;if it returns false, the TRANSIENT exception is raised in the application.

6.10.2 CORBA.COMM_FAILURE and CORBA.SystemException

There are two other functions for registering exception handlers: one for CORBA.COMM_FAILURE, and one for all other exceptions. For both these cases, the defaultis for there to be no handler, so exceptions are propagated to the application.

omniORB.installCommFailureExceptionHandler(cookie, function [, object])omniORB.installSystemExceptionHandler(cookie, function [, object])

In both cases, the call-back function has the same signature as for TRANSIENThandlers.

6.11 Location forwarding

Any CORBA operation invocation can return a LOCATION_FORWARDmessage tothe caller, indicating that it should retry the invocation on a new object reference.The standard allows ServantManagers to trigger LOCATION_FORWARDs by rais-ing the PortableServer::ForwardRequest exception, but it does not provide

Page 48: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

42 CHAPTER 6. THE OMNIORBPY API

a similar mechanism for normal servants. omniORBpy provides the omniORB.LOCATION_FORWARDexception for this purpose. The exception object is initialisedwith the target object reference. It can be thrown by any operation implementation.omniORB.LOCATION_FORWARDis not supported on omniORB 2.8.0.

6.12 Dynamic importing of IDL

omniORBpy is usually used with pre-generated stubs. Since Python is a dynamiclanguage, however, it is possible to compile and import new stubs at run-time.

Dynamic importing is achieved with omniORB.importIDL() and omniORB.importIDLString() . Their signatures are:

importIDL(filename [, args ]) -> tupleimportIDLString(string [, args ]) -> tuple

The first function compiles and imports the specified file; the second takesa string containing the IDL definitions. The functions work by forking omniidland importing its output; they both take an optional argument containing a listof strings which are used as arguments for omniidl. For example, the followingcommand runs omniidl with an include path set:

m = omniORB.importIDL("test.idl", ["-I/my/include/path"])

Instead of specifying omniidl arguments on each import, you can set the argu-ments to be used for all calls using the omniORB.omniidlArguments() func-tion.

Both import functions return a tuple containing the names of the Python mod-ules which have been imported. The modules themselves can be accessed throughsys.modules . For example:

// test.idlconst string s = "Hello";module M1 {

module M2 {const long l = 42;

};};module M3 {

const short s = 5;};

From Python:

>>> import sys, omniORB>>> omniORB.importIDL("test.idl")(’M1’, ’M1.M2’, ’M3’, ’_GlobalIDL’)>>> sys.modules["M1.M2"].l42>>> sys.modules["M3"].s5

Page 49: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

6.12. DYNAMIC IMPORTING OF IDL 43

>>> sys.modules["_GlobalIDL"].s’Hello’

Page 50: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

44 CHAPTER 6. THE OMNIORBPY API

Page 51: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

Chapter 7

Connection Management

This chapter describes how omniORB manages network connections.

7.1 Background

In CORBA, the ORB is the ‘middleware’ that allows a client to invoke an operationon an object without regard to its implementation or location. In order to invokean operation on an object, a client needs to ‘bind’ to the object by acquiring its ob-ject reference. Such a reference may be obtained as the result of an operation onanother object (such as a naming service) or by conversion from a stringified repre-sentation. If the object is in a different address space, the binding process involvesthe ORB building a proxy object in the client’s address space. The ORB arrangesfor invocations on the proxy object to be transparently mapped to equivalent invo-cations on the implementation object.

For the sake of interoperability, CORBA mandates that all ORBs should supportIIOP as the means to communicate remote invocations over a TCP/IP connection.IIOP is asymmetric with respect to the roles of the parties at the two ends of aconnection. At one end is the client which can only initiate remote invocations. Atthe other end is the server which can only receive remote invocations.

Notice that in CORBA, as in most distributed systems, remote bindings areestablished implicitly without application intervention. This provides the illusionthat all objects are local, a property known as ‘location transparency’. CORBAdoes not specify when such bindings should be established or how they should bemultiplexed over the underlying network connections. Instead, ORBs are free toimplement implicit binding by a variety of means.

The rest of this chapter describes how omniORB manages network connectionsand the programming interface to fine tune the management policy.

45

Page 52: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

46 CHAPTER 7. CONNECTION MANAGEMENT

7.2 The Model

omniORB is designed from the ground up to be fully multi-threaded. The objec-tive is to maximise the degree of concurrency and at the same time eliminate anyunnecessary thread overhead. Another objective is to minimise the interferenceby the activities of other threads on the progress of a remote invocation. In otherwords, thread ‘cross-talk’ should be minimised within the ORB. To achieve theseobjectives, the degree of multiplexing at every level is kept to a minimum.

On the client side of a connection, the thread that invokes on a proxy objectdrives the IIOP protocol directly and blocks on the connection to receive the reply.On the server side, a dedicated thread blocks on the connection. When it receivesa request, it performs the up-call to the object and sends the reply when the up-callreturns. There is no thread switching along the call chain.

With this design, there is at most one call in-flight at any time on a connec-tion. If there is only one connection, concurrent invocations to the same remoteaddress space would have to be serialised. To eliminate this limitation, omniORBimplements a dynamic policy—multiple connections to the same remote addressspace are created on demand and cached when there are concurrent invocations inprogress.

To be more precise, a network connection to another address space is only es-tablished when a remote invocation is about to be made. Therefore, there may beone or more object references in one address space that refer to objects in a differentaddress space but unless the application invokes on these objects, no network con-nection is made. The maximum number of connections opened to another addressspace is 5 by default. This parameter can be changed by calling the omniORB.maxTcpConnectionPerServer function before calling ORB_init() .

It is wasteful to leave a connection open when it has been left unused for aconsiderable time. Too many idle connections could block out new connections toa server when it runs out of spare communication channels. For example, mostUnix platforms have a limit on the number of file handles a process can open. 64is the usual default limit. The value can be increased to a maximum of a thousandor more by changing the ‘ulimit’ in the shell.

7.3 Idle Connection Shutdown and Remote Call Timeout

Inside the ORB, a thread is dedicated to scan for idle connections. The thread looksafter both the outgoing connections and the incoming connections.

When a connection is idle for a period of time, the connection is shutdown.Similarly, if a remote call has not completed within a defined period of time, theconnection is shutdown and the ORB will return COMM_FAILUREto the client.

How often the internal thread scans the connections is determined by the valueof the scan granularity. This value is defaulted to 5 seconds and can be changedusing the command-line option -ORBscanGranularity . Notice that this value

Page 53: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

7.4. INTEROPERABILITY CONSIDERATIONS 47

determines the precision the ORB is able to keep to the value of the idle connectionor remote call timeout.

How long the ORB will wait before it shuts down an idle connection is deter-mined by the idleConnectionPeriods. There are separate values for incoming andoutgoing connections. The default values are 180 and 120 seconds for incomingand outgoing connections respectively. These values can be changed using thecommand-line options -ORBinConScanPeriod and -ORBoutConScanPeriod .

Similarly, how long the ORB will wait for a remote call to complete is deter-mined by the parameter clientCallTimeOutPeriod for the client side and the server-CallTimeOutPeroid for the server side. By default calls will not timeout on eitherthe client or server side.

The timeout can be changed with the -ORBclientCallTimeOutPeriod and-ORBserverCallTimeOutPeriod options. The scan can be disabled completelyby setting the scan granularity to 0.

7.4 Interoperability Considerations

The IIOP specification allows both the client and the server to shutdown a con-nection unilaterally. When one end is about to shutdown a connection, it shouldsend a closeConnection message to the other end. It should also make sure that themessage will reach the other end before it proceeds to shutdown the connection.

The client should distinguish between an orderly and an abnormal connec-tion shutdown. When a client receives a closeConnection message before the con-nection is closed, the condition is an orderly shutdown. If the message is not re-ceived, the condition is an abnormal shutdown. In an abnormal shutdown, theORB should raise a COMM_FAILUREexception whereas in an orderly shutdown,the ORB should not raise an exception and should try to re-establish a new connec-tion transparently.

omniORB implements these semantics completely. However, it is known thatsome ORBs are not (yet) able to distinguish between an orderly and an abnor-mal shutdown. Usually this is manifested as the client in these ORBs seeing aCOMM_FAILUREoccasionally when connected to an omniORB server. The work-around is either to catch the exception in the application code and retry, or to turnoff the idle connection shutdown inside the omniORB server.

7.5 Connection Acceptance

omniORB provides the hook to implement a connection acceptance policy. Insidethe ORB runtime, a thread is dedicated to receive new connections. When thethread is given the handle of a new connection by the operating system, it calls thepolicy module to decide if the connection can be accepted. If the answer is yes, theORB will start serving requests coming in from that connection. Otherwise, theconnection is shutdown immediately.

Page 54: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

48 CHAPTER 7. CONNECTION MANAGEMENT

There can be a number of policy module implementations. The basic one is adummy module which just accepts every connection.

In addition, a host-based access control module is available on Unix platforms.The module uses the IP address of the client to decide if the connection can beaccepted. The module is implemented using tcp_wrappers 7.6. The access con-trol policy can be defined as rules in two access control files: hosts.allow andhosts.deny . The syntax of the rules is described in the manual page hosts_access(5) which can be found in appendix A. The syntax defines a simple ac-cess control language that is based on client (host name/address, user name), andserver (process name, host name/address) patterns. When searching for a matchon the server process name, the ORB uses the value of omniORB::serverName .ORB_init() uses the argument argv[0] to set the default value of this variable.This can be overridden by the application with the -ORBserverName <string>command line argument

The default location of the access control files is /etc . This can be overriddenby the extra options in omniORB.cfg . For instance:

# omniORB configuration file - extra options

GATEKEEPER_ALLOWFILE /project/omni/var/hosts.allow

GATEKEEPER_DENYFILE /project/omni/var/hosts.deny

As each policy module is implemented as a separate library, the choice of policymodule is determined at program linkage time. For instance, if the host-basedaccess control module is in use:

% eg1 -ORBtraceLevel 2omniORB gateKeeper is tcpwrapGK 1.0 - based on tcp_wrappers_7.6I said,"Hello!". The Object said,"Hello!"

Whereas if the dummy module is in use:

% eg1 -ORBtraceLevel 2omniORB gateKeeper is not installed. All incoming are accepted.I said,"Hello!". The Object said,"Hello!"

Page 55: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

Appendix A

hosts_access(5)

DESCRIPTION

This manual page describes a simple access control language that is based on client(host name/address, user name), and server (process name, host name/address)patterns. Examples are given at the end. The impatient reader is encouraged toskip to the EXAMPLES section for a quick introduction.

An extended version of the access control language is described in the hosts_options(5) document. The extensions are turned on at program build time bybuilding with -DPROCESS_OPTIONS.

In the following text, daemon is the process name of a network daemon pro-cess, and client is the name and/or address of a host requesting service. Networkdaemon process names are specified in the inetd configuration file.

ACCESS CONTROL FILES

The access control software consults two files. The search stops at the first match:

• Access will be granted when a (daemon,client) pair matches an entry in the/etc/hosts.allow file.

• Otherwise, access will be denied when a (daemon,client) pair matches anentry in the /etc/hosts.deny file.

• Otherwise, access will be granted.

A non-existing access control file is treated as if it were an empty file. Thus,access control can be turned off by providing no access control files.

ACCESS CONTROL RULES

Each access control file consists of zero or more lines of text. These lines are pro-cessed in order of appearance. The search terminates when a match is found.

49

Page 56: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

50 APPENDIX A. HOSTS_ACCESS(5)

• A newline character is ignored when it is preceded by a backslash character.This permits you to break up long lines so that they are easier to edit.

• Blank lines or lines that begin with a # character are ignored. This permitsyou to insert comments and whitespace so that the tables are easier to read.

• All other lines should satisfy the following format, things between [] beingoptional: daemon_list : client_list [ : shell_command ]

daemon_list is a list of one or more daemon process names (argv[0] values)or wildcards (see below).

client_list is a list of one or more host names, host addresses, patterns orwildcards (see below) that will be matched against the client host name or address.

The more complex forms daemon@host and user@host are explained in thesections on server endpoint patterns and on client username lookups, respectively.

List elements should be separated by blanks and/or commas.With the exception of NIS (YP) netgroup lookups, all access control checks are

case insensitive.

PATTERNS

The access control language implements the following patterns:

• A string that begins with a . character. A host name is matched if the lastcomponents of its name match the specified pattern. For example, the pattern.tue.nl matches the host name wzv.win.tue.nl .

• A string that ends with a . character. A host address is matched if its firstnumeric fields match the given string. For example, the pattern 131.155.matches the address of (almost) every host on the Eindhoven University net-work (131.155.x.x ).

• A string that begins with an character is treated as an NIS (formerly YP)netgroup name. A host name is matched if it is a host member of the specifiednetgroup. Netgroup matches are not supported for daemon process namesor for client user names.

• An expression of the form n.n.n.n/m.m.m.m is interpreted as a ‘net/mask’pair. A host address is matched if ‘net’ is equal to the bitwise AND of the ad-dress and the ‘mask’. For example, the net/mask pattern 131.155.72.0/255.255.254.0 matches every address in the range 131.155.72.0 to131.155.73.255 .

Page 57: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

51

WILDCARDS

The access control language supports explicit wildcards:

ALLThe universal wildcard, always matches.

LOCALMatches any host whose name does not contain a dot character.

UNKNOWNMatches any user whose name is unknown, and matches any host whosename or address are unknown. This pattern should be used with care: hostnames may be unavailable due to temporary name server problems. A net-work address will be unavailable when the software cannot figure out whattype of network it is talking to.

KNOWNMatches any user whose name is known, and matches any host whose nameand address are known. This pattern should be used with care: host namesmay be unavailable due to temporary name server problems. A networkaddress will be unavailable when the software cannot figure out what typeof network it is talking to.

PARANOIDMatches any host whose name does not match its address. When tcpd isbuilt with -DPARANOID (default mode), it drops requests from such clientseven before looking at the access control tables. Build without -DPARANOIDwhen you want more control over such requests.

OPERATORS

EXCEPTIntended use is of the form: list_1 EXCEPT list_2 ; this construct matchesanything that matches list_1 unless it matches list_2 . The EXCEPToper-ator can be used in daemon_lists and in client_lists . The EXCEPTop-erator can be nested: if the control language would permit the use of paren-theses, a EXCEPT b EXCEPT cwould parse as (a EXCEPT (b EXCEPTc)) .

SHELL COMMANDS

If the first-matched access control rule contains a shell command, that commandis subjected to %<letter> substitutions (see next section). The result is executedby a /bin/sh child process with standard input, output and error connected to

Page 58: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

52 APPENDIX A. HOSTS_ACCESS(5)

/dev/null. Specify an & at the end of the command if you do not want to waituntil it has completed.

Shell commands should not rely on the PATH setting of the inetd. Instead,they should use absolute path names, or they should begin with an explicit PATH=whatever statement.

The hosts_options(5) document describes an alternative language that uses theshell command field in a different and incompatible way.

% EXPANSIONS

The following expansions are available within shell commands:

%a (%A) The client (server) host address.

%c Client information: user@host, user@address, a host name, or just an ad-dress, depending on how much information is available.

%d The daemon process name (argv[0] value).

%h (%H) The client (server) host name or address, if the host name is unavailable.

%n (%N) The client (server) host name (or "unknown" or "paranoid").

%p The daemon process id.

%s Server information: daemon@host, daemon@address, or just a daemon name,depending on how much information is available.

%u The client user name (or "unknown").

%%Expands to a single %character.

Characters in % expansions that may confuse the shell are replaced by under-scores.

SERVER ENDPOINT PATTERNS

In order to distinguish clients by the network address that they connect to, usepatterns of the form:

process_name@host_pattern : client_list ...Patterns like these can be used when the machine has different internet ad-

dresses with different internet hostnames. Service providers can use this facilityto offer FTP, GOPHER or WWW archives with internet names that may even be-long to different organisations. See also the ‘twist’ option in the hosts_options(5)document. Some systems (Solaris, FreeBSD) can have more than one internet ad-dress on one physical interface; with other systems you may have to resort toSLIP or PPP pseudo interfaces that live in a dedicated network address space.

Page 59: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

53

The host_pattern obeys the same syntax rules as host names and addressesin client_list context. Usually, server endpoint information is available onlywith connection-oriented services.

CLIENT USERNAME LOOKUP

When the client host supports the RFC 931 protocol or one of its descendants(TAP, IDENT, RFC 1413) the wrapper programs can retrieve additional informationabout the owner of a connection. Client username information, when available, islogged together with the client host name, and can be used to match patterns like:

daemon_list : ... user_pattern@host_pattern ...The daemon wrappers can be configured at compile time to perform rule-

driven username lookups (default) or to always interrogate the client host. Inthe case of rule-driven username lookups, the above rule would cause usernamelookup only when both the daemon_list and the host_pattern match.

A user pattern has the same syntax as a daemon process pattern, so the samewildcards apply (netgroup membership is not supported). One should not getcarried away with username lookups, though.

• The client username information cannot be trusted when it is needed most,i.e. when the client system has been compromised. In general, ALL and(UN)KNOWN are the only user name patterns that make sense.

• Username lookups are possible only with TCP-based services, and only whenthe client host runs a suitable daemon; in all other cases the result is ‘un-known’.

• A well-known UNIX kernel bug may cause loss of service when usernamelookups are blocked by a firewall. The wrapper README document de-scribes a procedure to find out if your kernel has this bug.

• Username lookups may cause noticeable delays for non-UNIX users. Thedefault timeout for username lookups is 10 seconds: too short to cope withslow networks, but long enough to irritate PC users.

Selective username lookups can alleviate the last problem. For example, a rulelike:

daemon_list : @pcnetgroup ALL@ALLwould match members of the pc netgroup without doing username lookups,

but would perform username lookups with all other systems.

DETECTING ADDRESS SPOOFING ATTACKS

A flaw in the sequence number generator of many TCP/IP implementations allowsintruders to easily impersonate trusted hosts and to break in via, for example, the

Page 60: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

54 APPENDIX A. HOSTS_ACCESS(5)

remote shell service. The IDENT (RFC931 etc.) service can be used to detect suchand other host address spoofing attacks.

Before accepting a client request, the wrappers can use the IDENT service tofind out that the client did not send the request at all. When the client host pro-vides IDENT service, a negative IDENT lookup result (the client matches UN-KNOWN@host) is strong evidence of a host spoofing attack.

A positive IDENT lookup result (the client matches KNOWN@host) is less trust-worthy. It is possible for an intruder to spoof both the client connection and theIDENT lookup, although doing so is much harder than spoofing just a client con-nection. It may also be that the client’s IDENT server is lying.

Note: IDENT lookups don’t work with UDP services.

EXAMPLES

The language is flexible enough that different types of access control policy can beexpressed with a minimum of fuss. Although the language uses two access controltables, the most common policies can be implemented with one of the tables beingtrivial or even empty.

When reading the examples below it is important to realise that the allow tableis scanned before the deny table, that the search terminates when a match is found,and that access is granted when no match is found at all.

The examples use host and domain names. They can be improved by includingaddress and/or network/netmask information, to reduce the impact of temporaryname server lookup failures.

MOSTLY CLOSED

In this case, access is denied by default. Only explicitly authorised hosts are per-mitted access.

The default policy (no access) is implemented with a trivial deny file:

/etc/hosts.deny:ALL: ALL

This denies all service to all hosts, unless they are permitted access by entriesin the allow file.

The explicitly authorised hosts are listed in the allow file. For example:

/etc/hosts.allow:ALL: LOCAL @some_netgroupALL: .foobar.edu EXCEPT terminalserver.foobar.edu

The first rule permits access from hosts in the local domain (no . in the hostname) and from members of the some_netgroup netgroup. The second rule per-mits access from all hosts in the foobar.edu domain (notice the leading dot),with the exception of terminalserver.foobar.edu .

Page 61: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

55

MOSTLY OPEN

Here, access is granted by default; only explicitly specified hosts are refused ser-vice.

The default policy (access granted) makes the allow file redundant so that itcan be omitted. The explicitly non-authorised hosts are listed in the deny file. Forexample:

/etc/hosts.deny:ALL: some.host.name, .some.domainALL EXCEPT in.fingerd: other.host.name, .other.domain

The first rule denies some hosts and domains all services; the second rule stillpermits finger requests from other hosts and domains.

BOOBY TRAPS

The next example permits tftp requests from hosts in the local domain (notice theleading dot). Requests from any other hosts are denied. Instead of the requestedfile, a finger probe is sent to the offending host. The result is mailed to the supe-ruser.

/etc/hosts.allow:in.tftpd: LOCAL, .my.domain

/etc/hosts.deny:in.tftpd: ALL: (/some/where/safe\_finger -l @%h | \

/usr/ucb/mail -s %d-%h root) &

The safe_finger command comes with the tcpd wrapper and should be in-stalled in a suitable place. It limits possible damage from data sent by the remotefinger server. It gives better protection than the standard finger command.

The expansion of the %h (client host) and %d (service name) sequences is de-scribed in the section on shell commands.

Warning: do not booby-trap your finger daemon, unless you are prepared forinfinite finger loops.

On network firewall systems this trick can be carried even further. The typicalnetwork firewall only provides a limited set of services to the outer world. Allother services can be "bugged" just like the above tftp example. The result is anexcellent early-warning system.

DIAGNOSTICS

An error is reported when a syntax error is found in a host access control rule;when the length of an access control rule exceeds the capacity of an internal buffer;when an access control rule is not terminated by a newline character; when theresult of expansion would overflow an internal buffer; when a system call failsthat shouldnt́. All problems are reported via the syslog daemon.

Page 62: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

56 APPENDIX A. HOSTS_ACCESS(5)

FILES

/etc/hosts.allow , (daemon,client) pairs that are granted access./etc/hosts.deny , (daemon,client) pairs that are denied access.

SEE ALSO

tcpd(8) tcp/ip daemon wrapper program.tcpdchk(8), tcpdmatch(8), test programs.

BUGS

If a name server lookup times out, the host name will not be available to the accesscontrol software, even though the host is registered.

Domain name server lookups are case insensitive; NIS (formerly YP) netgrouplookups are case sensitive.

AUTHOR

Wietse Venema ([email protected])Department of Mathematics and Computing ScienceEindhoven University of TechnologyDen Dolech 2, P.O. Box 513,5600 MB Eindhoven, The Netherlands

Page 63: The omniORBpy version 1.3 User’s Guidedocs/external/python/omniOrb/omniORB... · 2004. 7. 4. · Chapter 1 Introduction omniORBpy is an Object Request Broker (ORB) that implements

Bibliography

[BLFIM98] T. Berners-Lee, R. Fielding, U.C. Irvine, and L. Masinter. Uniform Re-source Identifiers (URI): Generic Syntax. RFC 2396, August 1998.

[OMG98] Object Management Group. CORBAServices: Common Object ServicesSpecification, December 1998.

[OMG99] Object Management Group. The Common Object Request Broker: Ar-chitecture and Specification, 2.3.1 edition, October 1999. From http://cgi.omg.org/corba/cichpter.html .

[OMG00a] Object Management Group. Interoperable Naming Service revised chap-ters, August 2000. From http://cgi.omg.org/cgi-bin/doc?ptc/00-08-07 .

[OMG00b] Object Management Group. Python Language Mapping Specifica-tion, April 2000. From http://cgi.omg.org/cgi-bin/doc?ptc/00-04-08 .

57