diff options
author | Ossama Othman <ossama-othman@users.noreply.github.com> | 1999-12-16 21:17:33 +0000 |
---|---|---|
committer | Ossama Othman <ossama-othman@users.noreply.github.com> | 1999-12-16 21:17:33 +0000 |
commit | 92de2ddbe32df88b432f5e3e1de74ca143452db9 (patch) | |
tree | 04888cafa9b68036dbbc3a46330ac80a6754d9bb /TAO/docs | |
parent | 6ec166be7ea093ae760cf21a4702c2c5be6a5f03 (diff) | |
download | ATCD-92de2ddbe32df88b432f5e3e1de74ca143452db9.tar.gz |
ChangeLogTag:Thu Dec 16 14:53:23 1999 Ossama Othman <othman@cs.wustl.edu>
Diffstat (limited to 'TAO/docs')
-rw-r--r-- | TAO/docs/index.html | 2 | ||||
-rw-r--r-- | TAO/docs/pluggable.html | 551 | ||||
-rw-r--r-- | TAO/docs/pluggable_protocols/cross_ref_motif.png | bin | 0 -> 147 bytes | |||
-rw-r--r-- | TAO/docs/pluggable_protocols/img1.png | bin | 0 -> 27555 bytes | |||
-rw-r--r-- | TAO/docs/pluggable_protocols/img2.png | bin | 0 -> 15874 bytes | |||
-rw-r--r-- | TAO/docs/pluggable_protocols/img3.png | bin | 0 -> 18831 bytes | |||
-rw-r--r-- | TAO/docs/pluggable_protocols/img4.png | bin | 0 -> 18899 bytes | |||
-rw-r--r-- | TAO/docs/pluggable_protocols/img5.png | bin | 0 -> 23693 bytes | |||
-rw-r--r-- | TAO/docs/pluggable_protocols/index.html | 3013 | ||||
-rw-r--r-- | TAO/docs/pluggable_protocols/pluggable_protocols.css | 31 |
10 files changed, 3045 insertions, 552 deletions
diff --git a/TAO/docs/index.html b/TAO/docs/index.html index 070783aadf8..7aa2b77be70 100644 --- a/TAO/docs/index.html +++ b/TAO/docs/index.html @@ -33,7 +33,7 @@ HREF="http://www.omg.org/library/c2indx.html">CORBA</a> Documentation</h3> <dt><a HREF="minimumTAO.html">Minimum TAO</a> </dt><P> <dt><p><a href="../../docs/exceptions.html">Exception Handling</a></p> <dt><a HREF="Tags.html">Tags and Magic Numbers</a> </dt><P> - <dt><a HREF="pluggable.html">Writing Pluggable Protocols</a> </dt><P> + <dt><a HREF="pluggable_protocols/index.html">Writing Pluggable Protocols</a> </dt><P> </dl> </td></font> </tr> diff --git a/TAO/docs/pluggable.html b/TAO/docs/pluggable.html deleted file mode 100644 index d7dc1eb1c86..00000000000 --- a/TAO/docs/pluggable.html +++ /dev/null @@ -1,551 +0,0 @@ -<!-- $Id$ --> -<!-- HTML document created using Webford 2.01 --> -<!-- on Wednesday 8 December 1999 at 12:23 PM --> - -<HTML> -<HEAD> -<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=ISO-8859-1"> -<META NAME="Generator" CONTENT="Webford 2.01"> - -<body text="#000000" link="#0000ff" vlink="#cc0000" bgcolor="#ffffff"> - -<TITLE>Notes on Pluggable Protocols for the TAO ORB</TITLE> -<HR> -<H3>Notes on Pluggable Protocols for the TAO ORB</h3><P> - -By Bruce Task <<A -HREF="mailto:btrask@contactsystems.com">btrask@contactsystems.com</A>> - -<P>This paper is some notes on the steps I took to add a different transport layer to -the TAO ORB. I was given some initial guidelines on adding an additional protocol -and these proved very helpful. Beyond that there was not much more documentation -and so I hope the information in this paper will serve to further assist anybody whose -is adding a pluggable protocol to the TAO ORB. - -<P>I found that in order to successfully add the new protocol capabilities, one had to -have a very good understanding of some of the patterns upon which the ACE framework -is built. These are the REACTOR, ACCEPTOR, CONNECTOR, FACTORY, STRATEGY, -and SERVICE CONFIGURATOR PATTERN. The papers that I found helpful on these -were: -<BR> -<BLOCKQUOTE>Reactor - Reactor1-93.pdf<BR> - Reactor2-93.pdf<BR> - Reactor-rules.ps<BR> - Reactor-siemens.ps<BR> - Svc-conf.ps<BR> - Acc-Con.ps</BLOCKQUOTE> -<BR> -<P>These are all readily available from the TAO and ACE website. -<BR> -<P>My starting point for understanding how to add a pluggable protocol to the TAO ORB came -from mailing list entry from Carlos O'Ryan (coryan@cs.wustl.edu). One can find it in -the archives of the comp.soft-sys.ace. It is dated 1999/06/02 RE: [ace-users] TAO: ATM pluggable -protocol. I will repeat the section of that email that was particularly useful to me. (In the email, -he is responding to someone who had inquired about adding the ATM protocol). -<BR> - - <BLOCKQUOTE>Basically, you need to look at the following files: -<BR> - IIOP_Profile.{h,i,cpp} - IIOP_Connector.{h,i,cpp} - IIOP_Acceptor.{h,i,cpp} - IIOP_Factory.{h,i,cpp} - IIOP_Transport.{h,i,cpp} - Connect.{h,i,cpp} [probably will be renamed IIOP_Connect VSN] -<BR> -<P> The profile class handles the addressing format for your transport. It would -basically be a wrapper around the ACE_ATM_Addr() class. -The Connector and Acceptor classes are simply wrappers around -ACE_Acceptor<ACE_ATM_ACCEPTOR> and -ACE_Connector<ACE_ATM_ACCEPTOR>, again no big deal (I think). -The factory is even simpler. - -<P>Things get really interesting in the Transport and Connect classes. Transport -just implements external polymorphism over the Client_Connector_Handler and -the Service_Connnector_Handler objects defined in the Connect.{h,i,cpp}, those are -simply ACE_Svc_Handler<ACE_ATM_Stream>, but they don't do much work, they -just delegate on the Transport classes. This somewhat strange design is easy to -understand once you realize that all the ACE_Svc_Handler<> classes are not type -compatible (except in their most basic ACE_Event_Handler form). So they must -be wrapped using the TAO_Transport class. - -</BLOCKQUOTE> - -<BR> -<P>Review also the index.html file entitled "Release Information for the ACE ORB (TAO)" -in the tao\docs\releasenotes\ directory, section "Pluggable Protocols" -<BR><P> -Just for completeness sake, I'll include some other mailing list entries which were helpful -in getting me started. The following is from Ossama Othman (othman@cs.wustl.edu). - -<BLOCKQUOTE>The stock TAO distribution has support for two transport protocols, -TCP/IP and local namespace sockets (aka Unix Domain sockets). However, -TAO's pluggable protocols framework allows users to add support for -additional transport protocols. All you'd really have to do is -implement a SCRAMNet pluggable transport protocol with the interface -TAO's pluggable protocol framework provides and you'd be able to use -SCRAMNet with TAO just as easily as the IIOP (GIOP over TCP/IP) and -UIOP (GIOP over Unix domains sockets) protocols. -<BR> -The idea is to implement GIOP messaging over a SCRAMNet transport. If -you model your implementation on TAO's IIOP and UIOP implementations -then it should be fairly straightforward to add SCRAMNet support to -TAO. The hard part is adding SCRAMNet support to ACE. -<BR> -. . . -<BR> -It's actually not that bad. The easiest way to add a pluggable protocol -to TAO, IMO, is to base your pluggable protocol on existing ones. As -long as you have the same interface for your protocol as the existing -ones then it is fairly easy to add support for your protocol to TAO. -However, in order to do that you have to add ACE_SCRAMNet_{Acceptor, -Connector, Stream, Addr} implementations, for example, to ACE since -TAO's existing pluggable protocols use those ACE classes/interfaces. -<BR> - -As long as you use -the same interface for your protocol as the interface for ace/ACE_SOCK* -and tao/IIOP* then you shouldn't have much of a problem.</BLOCKQUOTE> -<BR> -<P>Here are some links that describe the pluggable protocols framework but -not how to implement one. -<BR> -http://www.cs.wustl.edu/~schmidt/ACE_wrappers/TAO/docs/releasenotes/index.html#pp -http://www.cs.wustl.edu/~schmidt/PfHSN.ps.gz - -<BR> -<P>Note also that the TAO files pluggable.* are important to review and understand as they contain -the abstract classes that form the common inteface for TAO's pluggable protocol framework. -<BR> -<P>Getting a full understanding on how IIOP was implemented (GIOP over TCP/IP) and also seeing -how provisions were made to add UIOP, was very helpful to adding my own protocol. -In understanding IIOP, I needed to review the section of the OMG CORBA spec on GIOP, -IIOP and Object references and see how this would apply to my protocol. -<BR> -<P>In my case, I added a transport layer that uses SCRAMNet (from Systran Corp) replicated shared memory hardware. This is actual physical memory cards located on two different machines. When a change is made to one memory then that change appears very quickly (very low latency here) in -the other memory. I decided that I would implement GIOP over SCRAMNet as this seemed -to be the simplest. With SCRAMNet, one could implement this transport layer into the TAO ORB -in a few different ways, GIOP over SCRAMNet, Environment-specific inter-ORB protocol (ESIOP) -or using collocation (since it is shared replicated memory). I have not done the latter two, only -GIOP over SCRAMNet just to get a proof of concept working. -<BR><P> -For a graphical representation of the extensions for the new SCRAMNet classes I have may a skeletal -Rose diagram showing (at this point) the inheritance relationships of the new and existing classes. -See (TBD) ftp site for this Rose diagram. -<BR><P> -The new classes created were. -<BR> -<BLOCKQUOTE>TAO_SCRAMNet_Profile (Derived from TAO_Profile in pluggable.h)<BR> -TAO_SCRAMNet_Acceptor (Derived from TAO_Acceptor in pluggable.h) <BR> -TAO_SCRAMNet_Connector (Derived from TAO_Connector in pluggable.h)<BR> -TAO_SCRAMNet_Transport (Derived from TAO_Transport in pluggable.h) - <BLOCKQUOTE>TAO_SCRAMNet_Server_Transport<BR> - TAO_SCRAMNet_Client_Trasnport</BLOCKQUOTE><BR> -TAO_SCRAMNet_Protocol_Factory (Derived from TAO_Protocol Factory in protocol_factory.h)<BR> -TAO_SCRAMNet_Handler_Base (as in IIOP_Connect.h) - <BLOCKQUOTE>TAO_SCRAMNet_Client_Connection_Handler<BR> - TAO_SCRAMNet_Server_Connection_Handler</BLOCKQUOTE></BLOCKQUOTE><BR> - - -<BLOCKQUOTE>ACE_SCRAMNet_Addr<BR> -ACE_SCRAMNet_Acceptor<BR> -ACE_SCRAMNet_Connector<BR> -ACE_SCRAMNet_Stream</BLOCKQUOTE><BR> -<BR> -<P>I closely followed the way that IIOP and UIOP were defined and implemented in the definition and -implementation of the SCRAMNet classes. Following the existing protocol implementation was -the largest source of help for me. Being able to step through the operation of the ORB for -the IIOP protocol and then transposing that over to my protocol made the process relatively painless -and quite the learning experience. -<BR><P> -I am using TAO under Phar Lap's Embedded Tool Suite Real-Time Operating System which is an RTOS which supports a subset of the Win32 API and Winsock 1.1. Because of the new SCRAMNet transport hardware I needed to change the ORBs core reactor to a WFMO_Reactor. Any instance -of the TAO ORB can only have one reactor type or it won't work. In my case I am using -an ORB in one thread that uses the WFMO_Reactor and the SCRAMNet transport, and an ORB -in another thread that uses a Select Reactor and the IIOP protocol. -I won't go into much of the SCRAMNet specific stuff as I assume most people are interested in -adding a pluggable protocol in general. -<BR><P> - -Some specifics:<BR> For completeness, I show the whole function in some instances even though I only needed to add or change a few lines. -<BR> -1. One of the first additions I made was to GIOP.h -<BR> -// namespace TAO_IOP -<BR> -// Assigned Protocol/Profile tag values. ORB protcols may be uniquely<BR> -// identified by tags such as these. This allows each ORB's own<BR> -// objref profiles to be interchanged using IORs.<BR> -//<BR> -// Email to tag-request@omg.org to allocate tags.<BR> -typedef CORBA::ULong TAO_IOP_Profile_ID; -<BR> -enum -{ - <BLOCKQUOTE>TAO_IOP_TAG_INVALID = -1,<BR> - TAO_IOP_TAG_INTERNET_IOP = 0, // IIOP<BR> - TAO_IOP_TAG_MULTIPLE_COMPONENTS = 1, // DCE-CIOP<BR> - TAO_IOP_TAG_UNIX_IOP = TAO_TAG_UIOP_PROFILE, // Read corbafwd.h<BR> - TAO_IOP_TAG_SCRAMNET_IOP = 3, // SCRAMNET<BR> - - // = This is a subset of the list of other profile tags.<BR> - TAO_IOP_TAG_ONC_IOP = 0x4f4e4300 // ONC IOP</BLOCKQUOTE> -};<BR><P> - -I arbitrarily set the TAO_IOP_TAG_SCRAMNET = 3. Note that this value was NOT allocated to me by OMG. I used it just to get things working with the new protocol. -Adding the new tag was needed (as it says) so that the server and client could interchange IORs (which contain protocol specific information). -<BR><P> - -2. I added the following line to orbconf.h: -<BR> -// SCRAMNet support (GIOP over the SCRAMNet replicated memory transport)<BR> -#define TAO_HAS_SCRAMNET -<BR> -as I use #ifdefs in other places in the code. -<BR><P> -3. Specifically, in the file TAO_Internal.cpp: -<BR><P> -int -TAO_Internal::open_services (int &argc, -<BLOCKQUOTE><BLOCKQUOTE> char **argv,<BR> - int ignore_default_svc_conf_file,<BR> - int skip_service_config_open)</BLOCKQUOTE></BLOCKQUOTE><BR> -{<BR> -<BLOCKQUOTE>ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX, guard, *ACE_Static_Object_Lock::instance (), -1));<BR> -#if defined (TAO_PLATFORM_SVC_CONF_FILE_NOTSUP)<BR> - ignore_default_svc_conf_file = 1;<BR> -#endif /* TAO_PLATFORM_SVC_CONF_FILE_NOTSUP */</BLOCKQUOTE><BR> - - <BLOCKQUOTE>if (TAO_Internal::service_open_count_++ == 0)<BR> - {<BR> - <BLOCKQUOTE>ACE_Service_Config::static_svcs ()->insert (&ace_svc_desc_TAO_Default_Resource_Factory);<BR> - ACE_Service_Config::static_svcs ()->insert (&ace_svc_desc_TAO_Default_Client_Strategy_Factory);<BR> - ACE_Service_Config::static_svcs ()->insert (&ace_svc_desc_TAO_Default_Server_Strategy_Factory);<BR> - ACE_Service_Config::static_svcs ()->insert (&ace_svc_desc_TAO_IIOP_Protocol_Factory);<BR> -#if defined (TAO_HAS_UIOP)<BR> - ACE_Service_Config::static_svcs ()->insert (&ace_svc_desc_TAO_UIOP_Protocol_Factory);<BR> -#endif /* TAO_HAS_UIOP */<BR> -// HAS SCRAMNET - BRT <BR> -<FONT COLOR=Blue>#if defined (TAO_HAS_SCRAMNET)<BR> - ACE_Service_Config::static_svcs ()->insert (&ace_svc_desc_TAO_SCRAMNet_Protocol_Factory);<BR> -#endif /* TAO_HAS_SCRAMNET */<BR></FONT> - // add descriptor to list of static objects.<BR> - - int result = 0;<BR> - - if (skip_service_config_open == 0)<BR> - result = ACE_Service_Config::open (argc, argv, - <BLOCKQUOTE> ACE_DEFAULT_LOGGER_KEY,<BR> - 0, // Don't ignore static services.<BR> - ignore_default_svc_conf_file);</BLOCKQUOTE><BR> - - // @@ What the heck do these things do and do we need to avoid<BR> - // calling them if we're not invoking the svc.conf file?<BR> - if (TAO_Internal::resource_factory_args_ != 0)<BR> - ACE_Service_Config::process_directive (TAO_Internal::resource_factory_args_);<BR> - if (TAO_Internal::client_strategy_args_ != 0)<BR> - ACE_Service_Config::process_directive (TAO_Internal::client_strategy_args_);<BR> - if (TAO_Internal::server_strategy_args_ != 0)<BR> - ACE_Service_Config::process_directive (TAO_Internal::server_strategy_args_);<BR> - - return result;</BLOCKQUOTE><BR> - }<BR> - else<BR> - return 0;</BLOCKQUOTE><BR> -}<BR> -<BR><P> -I added the SCRAMNet lines to insert the SCRAMNet protocol factory into the service -configurator. -<BR><P> -4. Also, in default resource.cpp: -<BR> -int<BR> -TAO_Default_Resource_Factory::init_protocol_factories (void)<BR> -{<BR> - <BLOCKQUOTE>TAO_ProtocolFactorySetItor end = protocol_factories_.end ();<BR> - TAO_ProtocolFactorySetItor factory = protocol_factories_.begin (); -<BR> - if (factory == end)<BR> - {<BR> - <BLOCKQUOTE>TAO_Protocol_Factory *protocol_factory = 0;<BR> - TAO_Protocol_Item *item = 0;<BR> - - protocol_factory = - ACE_Dynamic_Service<TAO_Protocol_Factory>::instance ("IIOP_Factory");<BR> -</BLOCKQUOTE> - <BLOCKQUOTE> if (protocol_factory == 0)<BR> - {<BR> - if (TAO_orbdebug)<BR> - ACE_ERROR ((LM_WARNING,<BR> - "TAO (%P|%t) No %s found in Service Repository. "<BR> - "Using default instance IIOP Protocol Factory.\n"));<BR> - - ACE_NEW_RETURN (protocol_factory,<BR> - TAO_IIOP_Protocol_Factory,<BR> - -1);<BR> - }<BR></BLOCKQUOTE> - - <BLOCKQUOTE> ACE_NEW_RETURN (item, TAO_Protocol_Item ("IIOP_Factory"), -1);<BR> - item->factory (protocol_factory);<BR> - - if (this->protocol_factories_.insert (item) == -1)<BR> - {<BR> - delete item;<BR> - delete protocol_factory;<BR> - - ACE_ERROR_RETURN ((LM_ERROR,<BR> - "TAO (%P|%t) Unable to add "<BR> - "<%s> to protocol factory set.\n",<BR> - item->protocol_name ().c_str ()),<BR> - -1);<BR></BLOCKQUOTE> - }<BR> - - if (TAO_debug_level > 0)<BR> - {<BLOCKQUOTE> - ACE_DEBUG ((LM_DEBUG,<BR> - "TAO (%P|%t) Loaded default protocol <IIOP_Factory>\n"));<BR></BLOCKQUOTE> - }<BR> - -#if defined (TAO_HAS_UIOP)<BR> - protocol_factory =<BR> - ACE_Dynamic_Service<TAO_Protocol_Factory>::instance ("UIOP_Factory");<BR> - - if (protocol_factory == 0)<BR> - { - <BLOCKQUOTE> if (TAO_orbdebug)<BR> - ACE_ERROR ((LM_WARNING,<BR> - "(%P|%t) WARNING - No %s found in Service Repository."<BR> - " Using default instance.\n",<BR> - "UIOP Protocol Factory"));<BR> - - ACE_NEW_RETURN (protocol_factory,<BR> - TAO_UIOP_Protocol_Factory,<BR> - -1);<BR></BLOCKQUOTE> - }<BR> - - ACE_NEW_RETURN (item, TAO_Protocol_Item ("UIOP_Factory"), -1);<BR> - item->factory (protocol_factory);<BR> - - if (this->protocol_factories_.insert (item) == -1)<BR> - { - <BLOCKQUOTE>delete item;<BR> - delete protocol_factory;<BR> - - ACE_ERROR_RETURN ((LM_ERROR,<BR> - "TAO (%P|%t) Unable to add "<BR> - "<%s> to protocol factory set.\n",<BR> - item->protocol_name ().c_str ()),<BR> - -1);</BLOCKQUOTE> - }<BR> - - if (TAO_debug_level > 0)<BR> - {<BLOCKQUOTE> - ACE_DEBUG ((LM_DEBUG,<BR> - "TAO (%P|%t) Loaded default protocol <UIOP_Factory>\n"));</BLOCKQUOTE> - }<BR> -#endif /* TAO_HAS_UIOP */<BR> -<FONT COLOR=Blue>#if defined (TAO_HAS_SCRAMNET)<BR> - protocol_factory =<BR> - ACE_Dynamic_Service<TAO_Protocol_Factory>::instance ("SCRAMNet_Factory");<BR> - - if (protocol_factory == 0)<BR> - { - <BLOCKQUOTE> if (TAO_orbdebug)<BR> - ACE_ERROR ((LM_WARNING,<BR> - "(%P|%t) WARNING - No %s found in Service Repository."<BR> - " Using default instance.\n",<BR> - "SCRAMNet Protocol Factory"));<BR> - - ACE_NEW_RETURN (protocol_factory,<BR> - TAO_SCRAMNet_Protocol_Factory,<BR> - -1);</BLOCKQUOTE> - }<BR> - - ACE_NEW_RETURN (item, TAO_Protocol_Item ("SCRAMNet_Factory"), -1);<BR> - item->factory (protocol_factory);<BR> - - if (this->protocol_factories_.insert (item) == -1)<BR> - { -<BLOCKQUOTE> delete item;<BR> - delete protocol_factory;<BR> - - ACE_ERROR_RETURN ((LM_ERROR,<BR> - "TAO (%P|%t) Unable to add "<BR> - "<%s> to protocol factory set.\n",<BR> - item->protocol_name ().c_str ()),<BR> - -1);</BLOCKQUOTE> - }<BR> - - if (TAO_debug_level > 0)<BR> - { -<BLOCKQUOTE> ACE_DEBUG ((LM_DEBUG,<BR> - "TAO (%P|%t) Loaded protocol <SCRAMNet_Factory>\n"));</BLOCKQUOTE> - }<BR> -#endif /* TAO_HAS_SCRAMNET */<BR> -</FONT> - - return 0;<BR> - }<BR> - - for (; factory != end; factory++)<BR> - { - <BLOCKQUOTE>const ACE_CString &name = (*factory)->protocol_name ();<BR> - (*factory)->factory (<BR> - ACE_Dynamic_Service<TAO_Protocol_Factory>::instance (name.c_str ()));<BR> - if ((*factory)->factory () == 0)<BR> - {<BLOCKQUOTE> - ACE_ERROR_RETURN ((LM_ERROR,<BR> - "TAO (%P|%t) Unable to load protocol <%s>, %p\n",<BR> - name.c_str (), ""),<BR> - -1);</BLOCKQUOTE> - }<BR> - - if (TAO_debug_level > 0)<BR> - { - <BLOCKQUOTE>ACE_DEBUG ((LM_DEBUG,<BR> - "TAO (%P|%t) Loaded protocol <%s>\n",<BR> - name.c_str ()));</BLOCKQUOTE> - }</BLOCKQUOTE> - }<BR> - return 0;</BLOCKQUOTE><BR> -<BR> -<BR><P> -I added the SCRAMNet lines so that the protocol is initialized correctly. Note here, -that following how IIOP and UIOP were implemented helped out. -<BR><P> - -Because I am using a WFMO Reactor and an ISR that signals particular Win32 Events, -I needed to change the registration of the service handlers. For example in Acceptor.cpp: -<BR><P> -// Initialize the appropriate strategies for creation, passive<BR> -// connection acceptance, and concurrency, and then register <this><BR> -// with the Reactor and listen for connection requests at the<BR> -// designated <local_addr>.<BR> -<BR><P> -template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int<BR> -ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::open<BR> - (const ACE_PEER_ACCEPTOR_ADDR &local_addr,<BR> - ACE_Reactor *reactor,<BR> - ACE_Creation_Strategy<SVC_HANDLER> *cre_s,<BR> - ACE_Accept_Strategy<SVC_HANDLER, ACE_PEER_ACCEPTOR_2> *acc_s,<BR> - ACE_Concurrency_Strategy<SVC_HANDLER> *con_s,<BR> - ACE_Scheduling_Strategy<SVC_HANDLER> *sch_s,<BR> - const ASYS_TCHAR *service_name,<BR> - const ASYS_TCHAR *service_description,<BR> - int use_select)<BR> -{<BR> -<BLOCKQUOTE>ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::open");<BR> - - if (this->service_name_ == 0 && service_name != 0) - <BLOCKQUOTE>ACE_ALLOCATOR_RETURN (this->service_name_,<BR> - ACE_OS::strdup (service_name),<BR> - -1);</BLOCKQUOTE> - if (this->service_description_ == 0 && service_description != 0)<BR> - ACE_ALLOCATOR_RETURN (this->service_description_,<BR> - ACE_OS::strdup (service_description),<BR> - -1);<BR> - this->reactor (reactor);<BR> - - // Must supply a valid Reactor to Acceptor::open()...<BR> - if (reactor == 0)<BR> - { - <BLOCKQUOTE> errno = EINVAL;<BR> - return -1;</BLOCKQUOTE> - }<BR> - - // Initialize the creation strategy.<BR> - - if (cre_s == 0)<BR> - { - <BLOCKQUOTE> ACE_NEW_RETURN (cre_s,<BR> - CREATION_STRATEGY,<BR> - -1);<BR> - this->delete_creation_strategy_ = 1;</BLOCKQUOTE> - }<BR> - this->creation_strategy_ = cre_s;<BR> - - // Initialize the accept strategy.<BR> - - if (acc_s == 0)<BR> - { - <BLOCKQUOTE>ACE_NEW_RETURN (acc_s,<BR> - ACCEPT_STRATEGY (this->reactor ()),<BR> - -1);<BR> - this->delete_accept_strategy_ = 1;</BLOCKQUOTE> - }<BR> - this->accept_strategy_ = acc_s;<BR> - - if (this->accept_strategy_->open (local_addr, 1) == -1)<BR> - return -1;<BR> - - // Initialize the concurrency strategy.<BR> - - if (con_s == 0)<BR> - { - <BLOCKQUOTE>ACE_NEW_RETURN (con_s,<BR> - CONCURRENCY_STRATEGY,<BR> - -1);<BR> - this->delete_concurrency_strategy_ = 1;</BLOCKQUOTE> - }<BR> - this->concurrency_strategy_ = con_s;<BR> - - // Initialize the scheduling strategy.<BR> - - if (sch_s == 0)<BR> - { - <BLOCKQUOTE>ACE_NEW_RETURN (sch_s,<BR> - SCHEDULING_STRATEGY,<BR> - -1);<BR> - this->delete_scheduling_strategy_ = 1;</BLOCKQUOTE> - }<BR> - this->scheduling_strategy_ = sch_s;<BR> - - this->use_select_ = use_select;<BR> - -<FONT COLOR=Blue>//BRT<BR> -#ifdef ACE_HAS_SCRAMNET<BR> - return this->reactor ()->register_handler(this, accept_event2);<BR> -#else<BR> - return this->reactor ()->register_handler(this,<BR> - ACE_Event_Handler::ACCEPT_MASK);<BR> -#endif</BLOCKQUOTE><BR></FONT> -}<BR> -<BR><P> -I needed to associate the acceptor with a Win32 event. - -<BR><P> - -5. In OS.h include the following lines: -<BR><P> -// Handle ACE_SCRAMNet*<BR> -# define ACE_SCRAMNET_ACCEPTOR ACE_SCRAMNet_Acceptor, ACE_SCRAMNet_Addr<BR> -# define ACE_SCRAMNET_CONNECTOR ACE_SCRAMNet_Connector, ACE_SCRAMNet_Addr<BR> -# define ACE_SCRAMNET_STREAM ACE_SCRAMNet_Stream, ACE_SCRAMNet_Addr<BR> -<BR><P> - -RE: IORs<BR> -I found that I needed to have a full understanding of what the exact contents of -a TAO-created IOR were as I needed to be able to understand how to decode the -location information that was now written in the IOR with the SCRAMNet -specific information. Decoding of the preconnect and endpoint info is important. -The endpoint info both in the command line arguments and in the IOR are different -for the each protocol and so your implemention of the new classes has to parse this -information correctly. -<BR><P> -In order to create the ORB with the Win32 Reactor at the core as well as the -SCRAMNet protocol factory loaded and initialize I needed to use the -svc.conf file with the the following options - -ORBReactorType wfmo --ORBProtocolFactory SCRAMNet_Factory -<BR><P> - -Beyond the above, I just traced through the operation of the IIOP -protocol in action to see exactly where I needed to just graft on the -new ACE_SCRAMNet classes, the TAO_SCRAMNet classes and their -associated implementations for send and recv so that the SCRAMNet -hardware was used as the transport and not the ethernet hardware. -Questions, comments, changes are welcome. I can be reached at <A -HREF="mailto:btrask@contactsystems.com">btrask@contactsystems.com</A> - -</BODY> -</HTML> diff --git a/TAO/docs/pluggable_protocols/cross_ref_motif.png b/TAO/docs/pluggable_protocols/cross_ref_motif.png Binary files differnew file mode 100644 index 00000000000..7dd2dddf5ac --- /dev/null +++ b/TAO/docs/pluggable_protocols/cross_ref_motif.png diff --git a/TAO/docs/pluggable_protocols/img1.png b/TAO/docs/pluggable_protocols/img1.png Binary files differnew file mode 100644 index 00000000000..5899eb18c0b --- /dev/null +++ b/TAO/docs/pluggable_protocols/img1.png diff --git a/TAO/docs/pluggable_protocols/img2.png b/TAO/docs/pluggable_protocols/img2.png Binary files differnew file mode 100644 index 00000000000..1ddb28513a5 --- /dev/null +++ b/TAO/docs/pluggable_protocols/img2.png diff --git a/TAO/docs/pluggable_protocols/img3.png b/TAO/docs/pluggable_protocols/img3.png Binary files differnew file mode 100644 index 00000000000..c80c7edf6a8 --- /dev/null +++ b/TAO/docs/pluggable_protocols/img3.png diff --git a/TAO/docs/pluggable_protocols/img4.png b/TAO/docs/pluggable_protocols/img4.png Binary files differnew file mode 100644 index 00000000000..8eab370af23 --- /dev/null +++ b/TAO/docs/pluggable_protocols/img4.png diff --git a/TAO/docs/pluggable_protocols/img5.png b/TAO/docs/pluggable_protocols/img5.png Binary files differnew file mode 100644 index 00000000000..eda658abd7d --- /dev/null +++ b/TAO/docs/pluggable_protocols/img5.png diff --git a/TAO/docs/pluggable_protocols/index.html b/TAO/docs/pluggable_protocols/index.html new file mode 100644 index 00000000000..15df3182a6a --- /dev/null +++ b/TAO/docs/pluggable_protocols/index.html @@ -0,0 +1,3013 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> + +<!-- $Id$ --> + +<HTML> +<HEAD> +<TITLE>Implementing Pluggable Protocols for TAO</TITLE> + +<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> +<META HTTP-EQUIV="Content-Style-Type" CONTENT="text/css"> + +<LINK REL="STYLESHEET" HREF="pluggable_protocols.css"> + +</HEAD> + +<BODY TEXT = "#000000" LINK="#000fff" VLINK="#ff0f0f" BGCOLOR="#ffffff"> + +<P> + +<P> + +<H1 ALIGN="CENTER">Implementing Pluggable Protocols for TAO</H1> +<P ALIGN="CENTER"><STRONG>Fred Kuhns, Douglas C. Schmidt, Carlos O'Ryan, Ossama Othman</STRONG></P> + +<P ALIGN="CENTER"> +Center for Distributed Object Computing<BR> +Washington University at St.Louis +</P> + +<P> +<BR><HR> +<!-- Table of Contents --> +<UL> +<LI><A HREF="#SECTION100">Overview of Implementation of Pluggable Protocols for TAO</A> +<UL> +<LI><A HREF="#SECTION110">The Hard Way</A> +<LI><A HREF="#SECTION120">The Path of Least Resistance</A> +<UL> +<LI><A HREF="#SECTION121">Basic Requirements</A> +<LI><A HREF="#SECTION122">Basics of Implementing a Pluggable Protocol for TAO</A> +</UL> +</UL> +<LI><A HREF="#SECTION200">Pluggable Protocol Framework Components</A> +<UL> +<LI><A HREF="#SECTION210">The <TT> Acceptor</TT></A> +<UL> +<LI><A HREF="#SECTION211">Context</A> +<LI><A HREF="#SECTION212">Problem</A> +<LI><A HREF="#SECTION213">Solution</A> +<LI><A HREF="#SECTION214">Applying the solution to TAO</A> +<LI><A HREF="#SECTION215"><TT> Acceptor</TT> Implementation</A> +</UL> +<LI><A HREF="#SECTION220">The <TT> Connector</TT></A> +<UL> +<LI><A HREF="#SECTION221">Context</A> +<LI><A HREF="#SECTION222">Problem</A> +<LI><A HREF="#SECTION223">Solution</A> +<LI><A HREF="#SECTION224">Applying the solution in TAO</A> +<LI><A HREF="#SECTION225"><TT> Connector</TT> Implementation</A> +</UL> +<LI><A HREF="#SECTION230">The <TT> Profile</TT> Object</A> +<LI><A HREF="#SECTION240">The <TT> Protocol_Factory</TT> Object</A> +<LI><A HREF="#SECTION250">The <TT> Transport</TT> Object</A> +<UL> +<LI><A HREF="#SECTION251">Context</A> +<LI><A HREF="#SECTION252">Problem</A> +<LI><A HREF="#SECTION253">Solution</A> +<LI><A HREF="#SECTION254">Applying the solution in TAO</A> +<LI><A HREF="#SECTION255"><TT> Transport</TT> Implementation</A> +</UL> +</UL> +<LI><A HREF="#SECTION300">Notes From a "Real World" Pluggable Protocol Implementation</A> +<LI><A HREF="#SECTION400">Using a Pluggable Protocol</A> +<LI><A HREF="#SECTION500">Bibliography</A> +</UL> +<!-- End of Table of Contents --> +<BR><HR> + + +<P> + +<H1><A NAME="SECTION100"> +Overview of Implementation of Pluggable Protocols for TAO</A> +</H1> + +<P> +There are several basic implementation details that should be followed when +implementing pluggable protocols for TAO. This section describes them. + +<P> + +<H2><A NAME="SECTION110"> +The Hard Way</A> +</H2> + +<P> +It is possible to implement a pluggable protocol for TAO without using any ACE +components, or using existing pluggable protocols as a reference, but that is +certainly more difficult than taking advantage of the code reuse offered by +using existing ACE and TAO models and implementations. + +<P> + +<H2><A NAME="SECTION120"> +The Path of Least Resistance</A> +</H2> + +<P> +TAO takes advantage of the many useful encapsulations provided by ACE. These +include ACE's <TT>IPC_SAP</TT> classes, <TT>Event Handlers</TT> and the operation +dispatching features provided by the <TT>Reactor</TT>. However, in order to +use these encapsulations some requirements must be satisfied. + +<P> + +<H3><A NAME="SECTION121"> +Basic Requirements</A> +</H3> + +<P> +To be able to successfully use the ACE components listed above, the underlying +protocol used in the pluggable protocol for TAO should support the following +features and characteristics: + +<P> + +<UL> +<LI>Access to a session/connection via some type of handle (e.g. a UNIX file descriptor +or a Win32 <TT>HANDLE</TT>).</LI> +<LI>The ability to multiplex I/O using the <TT>select</TT> system call, or on Win32 +platforms, the <TT>WaitForMultipleObjects</TT> call on the handles that refer +to the open sessions/connections. This ability is required in order to use the +<TT>ACE_Select_Reactor</TT> or the <TT>ACE_WFMO_Reactor</TT> concrete <TT>Reactor</TT> +implementations. + +<P> +Some underlying transports do not provide any such ability. However, it may +sometimes be possible to separate data delivery from notification. For example, +TAO's shared memory transport transports data through shared memory, but since +it is not possible to use <TT>select</TT> on shared memory another mechanism +must be used for notification. One way to do this is to use a local IPC connection +strictly for notification purposes. Whenever, data is sent through shared memory, +a byte of data could be written to the local IPC connection. That local IPC +connection would be used to notify the receiving process that data is available +for reading in shared memory. Since local IPC can be multiplexed using the <TT>select</TT> +system call, the <TT>ACE_Select_Reactor</TT> can be used to handle operation +dispatching for the shared memory pluggable protocol. + +<P> + </LI> +<LI>A pluggable protocol should sit on top of lower-level implementation. The underlying +protocol implementation should not rely on any resources/features that are at +a similar or higher layer of abstraction than the pluggable protocol. For example, +if the underlying protocol needs to use Win32 resources/features such as <TT>HANDLE</TT>s +to hidden windows or the use of a window message pump then the underlying pluggable +protocol may be difficult or pointless to implement as a pluggable protocol.</LI> +</UL> + +<P> + +<H3><A NAME="SECTION122"> +Basics of Implementing a Pluggable Protocol for TAO</A> +</H3> + +<P> +One of the easiest ways to implement a pluggable protocol for TAO is to do the +following: + +<P> + +<OL> +<LI>Implement ACE <TT>IPC_SAP</TT> wrappers around the underlying protocol implementation. +For example, ACE wraps the <I>socket</I> API to create an <TT>ACE_INET_Addr</TT>, +<TT>ACE_SOCK_Acceptor</TT>, <TT>ACE_SOCK_Connector</TT> and <TT>ACE_SOCK_Stream</TT>. +<TT>IPC_SAP</TT> wrappers for other implementations, such as OSI transport +protocol layer 4, aka <I>TP4</I>, should be implemented similarly. A TP4 implementation +could have an <TT>ACE_TP4_Addr</TT>, <TT>ACE_TP4_Acceptor</TT>, <TT>ACE_TP4_Connector</TT> +and an <TT>ACE_TP4_Stream</TT>. Any new implementation should retain the interface +provided by the base <TT>IPC_SAP</TT> classes in ACE.</LI> +<LI>Once the above ACE <TT>IPC_SAP</TT> components have been implemented, creating +the necessary TAO pluggable protocol components should be fairly easy. In fact, +much of the code can be ``cut and pasted'' from existing TAO pluggable protocol +implementations. For example, TAO's UIOP pluggable protocol was, for the most +part, based entirely on the IIOP pluggable protocol code found in TAO's ``tao/IIOP_*'' +source files. The only things that had to be changed for UIOP were the protocol +prefix, address format and URL style IOR format. Each of these pluggable protocol +characteristics is documented later in this documentation.</LI> +</OL> +The next section goes into detail about TAO's pluggable protocol framework components +and their public interfaces. + +<P> +<HR> +<P> +<H1><A NAME="SECTION200"> +Pluggable Protocol Framework Components</A> +</H1> + +<P> +In order for a pluggable protocol to usable by TAO without making any modifications +to TAO itself, it must be implemented to provide the functionality dictated +by TAO's pluggable protocols framework interface. This functionality is implemented +within several components, namely the <TT>Acceptor</TT>, <TT>Connector</TT>, +<TT>Connection Handler</TT>, <TT>Protocol Factory</TT>, <TT>Profile</TT> and +<TT>Transport</TT>. This section describes each of them. + +<P> + +<H2><A NAME="SECTION210"> +The <TT>Acceptor</TT></A> +</H2> + +<P> + +<A NAME="design:accept"></A> +<P> + +<H3><A NAME="SECTION211"> +Context</A> +</H3> + +<P> +A server can accept connections at one or more endpoints, potentially using +the same protocol for all endpoints. The set of protocols that an ORB uses to +play the client role need not match the set of protocols used for the server +role. Moreover, the ORB can even be a ``pure client'', <I>i.e.</I>, a client +that only makes requests, in which case it can use several protocols to make +requests, but receive no requests from other clients. + +<P> + +<H3><A NAME="SECTION212"> +Problem</A> +</H3> + +<P> +The server must generate an IOR that includes all possible inter-ORB and transport-protocol-specific +profiles for which the object can be accessed. As with the client, it should +be possible to add new protocols without changing the ORB. + +<P> + +<H3><A NAME="SECTION213"> +Solution</A> +</H3> + +<P> +We use the Acceptor pattern [<A + HREF="pluggable_protocols.html#Schmidt:97c">1</A>] to accept the connections. As +with the Connector pattern, an Acceptor decouples the connection establishment +from the processing performed on that connection. However, in the Acceptor pattern, +the connection is accepted <I>passively</I>, rather than being initiated <I>actively</I>. + +<P> + +<H3><A NAME="SECTION214"> +Applying the solution to TAO</A> +</H3> + +<P> +Figure <A HREF="pluggable_protocols.html#server">1</A> illustrates how TAO's pluggable protocols framework leverages +the design presented in Section <A HREF="#design:transparent"><IMG ALIGN="BOTTOM" BORDER="1" ALT="[*]" + SRC="cross_ref_motif.png"></A>. The concrete ACE +<TT>Service Handler</TT> created by the ACE <TT>Acceptor</TT> is responsible +for implementing the External Polymorphism pattern and encapsulating itself +behind the <TT>Transport</TT> interface defined in our pluggable protocols framework. + +<P> + +<P></P> +<DIV ALIGN="CENTER"><A NAME="server"></A><A NAME="683"></A> +<TABLE> +<CAPTION ALIGN="BOTTOM"><STRONG>Figure 1:</STRONG> +Server Pluggable Protocol Class Diagram</CAPTION> +<TR><TD><P> + +<P> + +<DIV ALIGN="CENTER"> +<!-- MATH + $\resizebox* {5in}{!}{\includegraphics{graphics/server.eps}}$ + --> +<IMG + WIDTH="561" HEIGHT="634" ALIGN="BOTTOM" BORDER="0" + SRC="img1.png" + ALT="Server"> </DIV> +<P> +<DIV ALIGN="CENTER"></DIV></TD></TR> +</TABLE> +</DIV><P></P> + +<P> +As discussed in Section <A HREF="#design:adapt"><IMG ALIGN="BOTTOM" BORDER="1" ALT="[*]" + SRC="cross_ref_motif.png"></A>, we use the Adapter pattern to leverage +the ACE implementation of the Acceptors. This pattern also permits a seamless +integration with the lower levels of the ORB. In the Acceptor pattern, the <TT>Acceptor</TT> +object is a factory that creates <TT>Service Handler</TT>s. <TT>Service +Handler</TT>s are responsible for performing I/O with their connected peers. In +TAO's pluggable protocol framework, the <TT>Transport</TT> objects are <TT>Service +Handlers</TT> implemented as abstract classes. This design shields the ORB from +variations in the <TT>Acceptor</TT>s, <TT>Connector</TT>s, and <TT>Service +Handler</TT>s for each particular protocol. + +<P> +When a connection is established, the concrete <TT>Acceptor</TT> creates the +appropriate <TT>Connection Handler</TT> and IOP objects. The <TT>Connection +Handler</TT> also creates a <TT>Transport</TT> object that functions as a bridge. +As with the <TT>Connector</TT>, the <TT>Acceptor</TT> also acts as a bridge +object, hiding the transport- and strategy-specific details of the acceptor. + +<P> + +<H3><A NAME="SECTION215"> +<TT>Acceptor</TT> Implementation</A> +</H3> + +<P> +TAO's <TT>Acceptor</TT> interface, shown below, is declared in the file <TT><tao/Pluggable.h></TT>. +All <TT>Acceptor</TT> implementations must inherit from the <TT>TAO_Acceptor</TT> +abstract base class. + +<P> + +<DL COMPACT> +<DT> +<DD>class TAO_Export TAO_Acceptor<BR> +{<BR> + // = TITLE<BR> + // Abstract Acceptor class used for pluggable protocols.<BR> + //<BR> + // = DESCRIPTION<BR> + // Base class for the Acceptor bridge calls.<BR> +public:<BR> + TAO_Acceptor (CORBA::ULong tag);<BR> + + +<BR> + + virtual ~TAO_Acceptor (void); + +<BR> + + // Destructor + +<BR> + + + +<BR> + + CORBA::ULong tag (void) const; + +<BR> + + // The tag, each concrete class will have a specific tag value. + +<BR> + + + +<BR> + + CORBA::Short priority (void) const; + +<BR> + + // The priority for this endpoint. + +<BR> + + + +<BR> + + virtual int open (TAO_ORB_Core *orb_core, + +<BR> + + int version_major, + +<BR> + + int version_minor, + +<BR> + + const char *address, + +<BR> + + const char *options = 0) = 0; + +<BR> + + // Method to initialize acceptor for address. + +<BR> + + + +<BR> + + virtual int open_default (TAO_ORB_Core *orb_core, + +<BR> + + const char *options = 0) = 0; + +<BR> + + // Open an acceptor on the default endpoint for this protocol + +<BR> + + + +<BR> + + virtual int close (void) = 0; + +<BR> + + // Closes the acceptor + +<BR> + + + +<BR> + + virtual int create_mprofile (const TAO_ObjectKey &object_key, + +<BR> + + TAO_MProfile &mprofile) = 0; + +<BR> + + // Create the corresponding profile for this endpoint. + +<BR> + + + +<BR> + + virtual int is_collocated (const TAO_Profile* profile) = 0; + +<BR> + + // Return 1 if the <profile> has the same endpoint as the acceptor. + +<BR> + + + +<BR> + + virtual CORBA::ULong endpoint_count (void) = 0; + +<BR> + + // Returns the number of endpoints this acceptor is listening on. This + +<BR> + + // is used for determining how many profiles will be generated + +<BR> + + // for this acceptor. + +<BR> + + + +<BR> +protected: + +<BR> + + CORBA::Short priority_; + +<BR> + + // The priority for this endpoint + +<BR> + + + +<BR> +private: + +<BR> + + CORBA::ULong tag_; + +<BR> + + // IOP protocol tag. + +<BR> + + + +<BR> + +}; + +<P> + + </DD> +</DL>A description of each of the methods that must be implemented follows: + +<P> + +<DL> +<DT><STRONG>The Constructor.</STRONG></DT> +<DD>Other than initializing members of a pluggable protocol <TT>Acceptor</TT> +implementation, nothing else is really done in the constructor. For example, +the <TT>TAO_IIOP_Acceptor</TT> constructor implementation is: +<P> + +<DL COMPACT> +<DT> +<DD>TAO_IIOP_Acceptor::TAO_IIOP_Acceptor (void)<BR> +<DD> : TAO_Acceptor (TAO_TAG_IIOP_PROFILE), + +<BR> + + version_ (TAO_DEF_GIOP_MAJOR, TAO_DEF_GIOP_MINOR), + +<BR> + + orb_core_ (0), + +<BR> + + base_acceptor_ (), + +<BR> + + creation_strategy_ (0), + +<BR> + + concurrency_strategy_ (0), + +<BR> + + accept_strategy_ (0) + +<BR> + +{ + +<BR> + +}</DD> +</DL> +<P> +Note that initializing the <TT>TAO_Acceptor</TT> base class with <I>tag</I> +value is required. Tags are assigned by the OMG.In this case, <TT>TAO_TAG_IIOP_PROFILE</TT> +is defined to be the OMG assigned tag for the CORBA IIOP protocol. Until a tag +that uniquely identifies the protocol is assigned, a tag value that isn't used +by any other protocol can be used. + +<P> + +<DL> +<DT><STRONG><TT>open</TT>.</STRONG></DT> +<DD>The <TT>open</TT> method initializes the acceptor, i.e. sets +the protocol version to use (if supported), parses any protocol-specific options +(if any) and creates the endpoint passed to it. +<P> +The address specified by using the <TT>-ORBEndpoint</TT> ORB option is passed +directly to this method. If more than one address is specified within a given +<TT>-ORBEndpoint</TT> option then each address is passed one by one to this +method by the pluggable protocols framework. For example, the following <TT>-ORBEndpoint</TT> +command line option: + +<P> + +<DL COMPACT> +<DT> +<DD>-ORBEndpoint iiop://1.1@foo.xyz.com,1.0@bar.abc.com</DD> +</DL>will cause the following <TT>open</TT> method invocations to occur: + +<P> + +<DL COMPACT> +<DT> +<DD>open (orb_core, 1, 1, ``foo.xyz.com'', 0) + +<P> +open (orb_core, 1, 0, ``bar.abc.com'', 0)</DD> +</DL>Extracting individual addresses from an <TT>-ORBEndpoint</TT> option is handled +by TAO's pluggable protocols framework. It is up to the pluggable protocol to +handle the address passed to this method. + +<P> + </DD> +<DT><STRONG><TT>open_default</TT>.</STRONG></DT> +<DD>Each pluggable protocol should have the ability to +open a default endpoint. For example, it should be possible to make the pluggable +protocol open an endpoint without specifying an address, in which case an address +is chosen by the pluggable protocol. This method is invoked when <TT>-ORBEndpoint</TT> +options such as the following are used: + +<P> + +<DL COMPACT> +<DT> +<DD>-ORBEndpoint iiop://</DD> +</DL>In this case, an IIOP endpoint will be created on the local host. The port will +be chosen by the IIOP pluggable protocol. <TT>open_default</TT> will invoked +in the following manner: + +<P> + +<DL COMPACT> +<DT> +<DD>open_default (orbcore, 0)</DD> +</DL></DD> +<DT><STRONG><TT>close</TT>.</STRONG></DT> +<DD>The <TT>close</TT> method is self-explanatory. It simply shuts +down any open endpoints, and recovers resources as necessary. This method is +automatically invoked by the pluggable protocols framework when the ORB associated +with that endpoint is shut down.</DD> +<DT><STRONG><TT>create_mprofile</TT>.</STRONG></DT> +<DD>The <TT>create_mprofile</TT> method creates a protocol-specific +<TT>Profile</TT> object and gives ownership of that profile to the <TT>TAO_MProfile</TT> +object, basically a container that holds multiple profiles, passed to it. The +code for this method is typically ``boilerplate,'' i.e. it can be based almost +entirely on TAO's existing pluggable protocol implementations of <TT>create_profile</TT>. +Here is how it is implemented in TAO's IIOP acceptor: + +<P> + +<DL COMPACT> +<DT> +<DD>int<BR> +TAO_IIOP_Acceptor::create_mprofile (const TAO_ObjectKey &object_key, <BR> +TAO_MProfile &mprofile) +<BR> +{ +<BR> + // @@ we only make one for now +<BR> + int count = mprofile.profile_count (); +<BR> + if ((mprofile.size () - count) < 1 +<BR> + && mprofile.grow (count + 1) == -1) +<BR> + return -1; +<BR> + +<BR> + TAO_IIOP_Profile *pfile = 0; +<BR> + ACE_NEW_RETURN (pfile, +<BR> + TAO_IIOP_Profile (this->host_.c_str (), +<BR> + this->address_.get_port_number (), +<BR> + object_key, +<BR> + this->address_, +<BR> + this->version_, +<BR> + this->orb_core_), +<BR> + -1); +<BR> + +<BR> + if (mprofile.give_profile (pfile) == -1) +<BR> + { +<BR> + pfile->_decr_refcnt (); +<BR> + pfile = 0; +<BR> + return -1; +<BR> + } +<BR> + +<BR> + if (this->orb_core_->orb_params ()->std_profile_components () == 0) +<BR> + return 0; +<BR> + +<BR> + pfile->tagged_components ().set_orb_type (TAO_ORB_TYPE); +<BR> + +<BR> + CONV_FRAME::CodeSetComponentInfo code_set_info; +<BR> + code_set_info.ForCharData.native_code_set = +<BR> + TAO_DEFAULT_CHAR_CODESET_ID; +<BR> + code_set_info.ForWcharData.native_code_set = +<BR> + TAO_DEFAULT_WCHAR_CODESET_ID; +<BR> + pfile->tagged_components ().set_code_sets (code_set_info); +<BR> + +<BR> + pfile->tagged_components ().set_tao_priority (this->priority ()); +<BR> + +<BR> + return 0; + +<P> + +}</DD> +</DL>Most of the code that is common to all pluggable protocols will be factored +out of this method in the near future. + +<P> + </DD> +<DT><STRONG><TT>is_collocated</TT>.</STRONG></DT> +<DD>The <TT>is_collocated</TT> method checks if the <TT>Profile</TT> +has the same endpoint as the <TT>Acceptor</TT>. Assuming ACE is used as the +underlying layer between the operating system calls and a pluggable protocol, +this code is also ``boilerplate.'' TAO's IIOP implementation does the following: + +<P> + +<DL COMPACT> +<DT> +<DD>int +<BR> +TAO_IIOP_Acceptor::is_collocated (const TAO_Profile *pfile) +<BR> +{ +<BR> + const TAO_IIOP_Profile *profile = +<BR> + ACE_dynamic_cast(const TAO_IIOP_Profile *, +<BR> + pfile); +<BR> + +<BR> + // compare the port and sin_addr (numeric host address) +<BR> + return profile->object_addr () == this->address_; +<BR> +}</DD> +</DL></DD> +<DT><STRONG><TT>endpoint_count</TT>.</STRONG></DT> +<DD><TT>endpoint_count</TT> returns the number of endpoints +the <TT>Acceptor</TT> is listening on. This is used for determining how many +<TT>Profiles</TT> will be generated for this <TT>Acceptor</TT>. Currently, all +of TAO's pluggable protocols simply return <TT>1</TT>.</DD> +</DL> + +<P> + +<H2><A NAME="SECTION220"> +The <TT>Connector</TT></A> +</H2> + +<P> + +<A NAME="design:connect"></A> +<P> + +<H3><A NAME="SECTION221"> +Context</A> +</H3> + +<P> +When a client references an object, the ORB must obtain the corresponding profile +list, which is derived from the IOR and a profile ordering policy, and transparently +establish a connection to the server. + +<P> + +<H3><A NAME="SECTION222"> +Problem</A> +</H3> + +<P> +There can be one or more combinations of inter-ORB and transport protocols available +in an ORB. For a given profile, the ORB must verify the presence of the associated +IOP and transport protocol, if available. It must then locate the applicable +<TT>Connector</TT> and delegate it to establish the connection. + +<P> + +<H3><A NAME="SECTION223"> +Solution</A> +</H3> + +<P> +We use the Connector pattern [<A + HREF="pluggable_protocols.html#Schmidt:97c">1</A>] to actively establish a connection +to a remote object. This pattern decouples the connection establishment from +the processing performed after the connection is successful. As before, the +<TT>Connector Registry</TT> shown in Figure <A HREF="pluggable_protocols.html#e2e">2</A> is used + +<P></P> +<DIV ALIGN="CENTER"><A NAME="e2e"></A><A NAME="184"></A> +<TABLE> +<CAPTION ALIGN="BOTTOM"><STRONG>Figure 2:</STRONG> +Connection Establishment Using Multiple Pluggable Protocols</CAPTION> +<TR><TD><P> + +<P> + +<P> + +<DIV ALIGN="CENTER"> +<!-- MATH + $\resizebox* {9cm}{!}{\includegraphics{graphics/pp_e2e.eps}}$ + --> +<IMG + WIDTH="405" HEIGHT="460" ALIGN="BOTTOM" BORDER="0" + SRC="img2.png" + ALT="pp_e2e"> </DIV> +<P> +<DIV ALIGN="CENTER"></DIV></TD></TR> +</TABLE> +</DIV><P></P> +to locate the right <TT>Connector</TT> for the current profile. The actual +profile selected for use will depend on the set of Policies active at the time +of connection establishment. However, once a profile is selected, the connector +registry matches the profile type, represented by a well known tag, with an +instance of a concrete <TT>Connector</TT>. + +<P> + +<H3><A NAME="SECTION224"> +Applying the solution in TAO</A> +</H3> + +<P> +As described in Section <A HREF="#design:adapt"><IMG ALIGN="BOTTOM" BORDER="1" ALT="[*]" + SRC="cross_ref_motif.png"></A>, <TT>Connector</TT>s are adapters +for the ACE implementation of the Connector pattern. Thus, they are typically +lightweight objects that simply delegate to a corresponding ACE component. + +<P> +Figure <A HREF="pluggable_protocols.html#client">3</A> shows the base classes and their relations for IIOP. + +<P></P> +<DIV ALIGN="CENTER"><A NAME="client"></A><A NAME="688"></A> +<TABLE> +<CAPTION ALIGN="BOTTOM"><STRONG>Figure 3:</STRONG> +Client Pluggable Protocol Class Diagram</CAPTION> +<TR><TD><P> + +<P> + +<DIV ALIGN="CENTER"> +<!-- MATH + $\resizebox* {5in}{!}{\includegraphics{graphics/client.eps}}$ + --> +<IMG + WIDTH="563" HEIGHT="416" ALIGN="BOTTOM" BORDER="0" + SRC="img3.png" + ALT="Client"> </DIV> +<P> +<DIV ALIGN="CENTER"></DIV></TD></TR> +</TABLE> +</DIV><P></P> +This figure shows an explicit co-variance between the <TT>Profile</TT> and +the <TT>Connector</TT>s for each protocol. In general, a <TT>Connector</TT> +must downcast the <TT>Profile</TT> to its specific type. This downcast is safe +because profile creation is limited to the <TT>Connector</TT> and <TT>Acceptor</TT> +registries. In both cases, the profile is created with a matching tag. The tag +is used by the Connector Registry to choose the <TT>Connector</TT> that can +handle each profile. + +<P> +As shown in the same figure, the Connector Registry manipulates only the base +classes. Therefore, new protocols can be added without requiring any modification +to the existing pluggable protocols framework. When a connection is successfully +established, the <TT>Profile</TT> is passed a pointer to the particular IOP +object and to the <TT>Transport</TT> objects that were created. + +<P> + +<H3><A NAME="SECTION225"> +<TT>Connector</TT> Implementation</A> +</H3> + +<P> +TAO's <TT>Connector</TT> interface, shown below, is declared in the file <TT><tao/Pluggable.h></TT>. +All <TT>Connector</TT> implementations must inherit from the <TT>TAO_Connector</TT> +abstract base class. + +<P> + +<DL COMPACT> +<DT> +<DD>class TAO_Export TAO_Connector +<BR> +{ +<BR> + // = TITLE +<BR> + // Generic Connector interface definitions. +<BR> + // +<BR> + // = DESCRIPTION +<BR> + // Base class for connector bridge object. +<BR> +public: +<BR> + +<BR> + TAO_Connector (CORBA::ULong tag); +<BR> + // default constructor. +<BR> + +<BR> + virtual ~TAO_Connector (void); +<BR> + // the destructor. +<BR> + +<BR> + CORBA::ULong tag (void) const; +<BR> + // The tag identifying the specific ORB transport layer protocol. +<BR> + // For example TAO_TAG_IIOP_PROFILE = 0. The tag is used in the +<BR> + // IOR to identify the type of profile included. IOR -> {{tag0, +<BR> + // profile0} {tag1, profole1} ...} GIOP.h defines typedef +<BR> + // CORBA::ULong TAO_IOP_Profile_ID; +<BR> + +<BR> + int make_mprofile (const char *ior, +<BR> + TAO_MProfile &mprofile, +<BR> + CORBA::Environment &ACE_TRY_ENV); +<BR> + // Parse a string containing a URL style IOR and return an +<BR> + // MProfile. +<BR> + +<BR> + virtual int open (TAO_ORB_Core *orb_core) = 0; +<BR> + // Initialize object and register with reactor. +<BR> + +<BR> + virtual int close (void) = 0; +<BR> + // Shutdown Connector bridge and concreate Connector. +<BR> + +<BR> + virtual int connect (TAO_Profile *profile, +<BR> + TAO_Transport *&, +<BR> + ACE_Time_Value *max_wait_time) = 0; +<BR> + // To support pluggable we need to abstract away the connect() +<BR> + // method so it can be called from the GIOP code independant of the +<BR> + // actual transport protocol in use. +<BR> + +<BR> + virtual int preconnect (const char *preconnections) = 0; +<BR> + // Initial set of connections to be established. +<BR> + +<BR> + virtual TAO_Profile *create_profile (TAO_InputCDR& cdr) = 0; +<BR> + // Create a profile for this protocol and initialize it based on the +<BR> + // encapsulation in <cdr> +<BR> + +<BR> + virtual int check_prefix (const char *endpoint) = 0; +<BR> + // Check that the prefix of the provided endpoint is valid for use +<BR> + // with a given pluggable protocol. +<BR> + +<BR> + virtual char object_key_delimiter (void) const = 0; +<BR> + // Return the object key delimiter to use or expect. +<BR> + +<BR> +#if defined (TAO_USES_ROBUST_CONNECTION_MGMT) +<BR> + virtual int purge_connections (void) = 0; +<BR> + // Purge "old" connections. +<BR> +#endif /* TAO_USES_ROBUST_CONNECTION_MGMT */ +<BR> + +<BR> +protected: +<BR> + virtual void make_profile (const char *endpoint, +<BR> + TAO_Profile *&, +<BR> + CORBA::Environment &ACE_TRY_ENV) = 0; +<BR> + // Create a profile with a given endpoint. +<BR> + +<BR> +private: +<BR> + CORBA::ULong tag_; +<BR> + // IOP protocol tag. +<BR> +};</DD> +</DL>A description of each of the methods that must be implemented follows: + +<P> + +<DL> +<DT><STRONG>The Constructor.</STRONG></DT> +<DD>As with the <TT>Acceptor</TT> constructor, the <TT>TAO_Connector</TT> +base class should be initialized with the tag associated with the pluggable +protocol in question. Here is TAO's IIOP pluggable protocol <TT>Connector</TT> +constructor: +<P> + +<DL COMPACT> +<DT> +<DD>TAO_IIOP_Connector::TAO_IIOP_Connector (void) +<BR> + : TAO_Connector (TAO_TAG_IIOP_PROFILE), +<BR> + orb_core_ (0), +<BR> + base_connector_ () +<BR> +{ +<BR> +}</DD> +</DL></DD> +<DT><STRONG><TT>open</TT>.</STRONG></DT> +<DD>The <TT>open</TT> method simply opens the underlying connector. +This is typically an <TT>ACE_Strategy_Connector</TT> template instance. For +example, TAO's IIOP pluggable protocol uses an + +<P> + +<DL COMPACT> +<DT> +<DD>ACE_Strategy_Connector<TAO_IIOP_Client_Connection_Handler, +<BR> + ACE_SOCK_CONNECTOR></DD> +</DL>as its underlying connection strategy. No connection establishment occurs here. +Note that, if ACE is used to implement a <TT>Connector</TT>, this method should +also register the <TT>Connection Handler</TT> with an <TT>ACE_Reactor</TT>. + +<P> + </DD> +<DT><STRONG><TT>close</TT>.</STRONG></DT> +<DD><TT>close</TT> simply closes the underlying <TT>Connector</TT> +bridge and the concrete <TT>Connector</TT>.</DD> +<DT><STRONG><TT>connect</TT>.</STRONG></DT> +<DD>The <TT>connect</TT> method actively establishes a connection +to the endpoint encoded within the IOR in use. It should first verify that the +tag contained within <TT>Profile</TT> passed to it matches the tag associated +with the pluggable protocol. If the tags do not match then an attempt use a +<TT>Profile</TT> for another pluggable protocol was made. + +<P> +The <TT>Transport</TT> object must also be set in this method. This is generally +done by using the <TT>transport</TT> method found within the <TT>Connection +Handler</TT> being used. + +<P> + </DD> +<DT><STRONG><TT>preconnect</TT>.</STRONG></DT> +<DD>The <TT>preconnect</TT> method is invoked when the <TT>-ORBPreconnect</TT> +ORB option is used. It causes a blocking connection to be made to the specified +address. Multiple connections can be made to the same endpoint. For example, +the following <TT>-ORBPreconnect</TT> option will cause two IIOP blocking connections +to be made to the specified host and port: + +<P> + +<DL COMPACT> +<DT> +<DD>-ORBPreconnect iiop://foo.bar.com:1234,foo.bar.com:1234</DD> +</DL>Much of the preconnect parsing code in TAO's current <TT>preconnect</TT> implementations +will be factored out into a common method. Pluggable protocols will still be +responsible for parsing addresses, just like the <TT>open</TT> method in <TT>Acceptor</TT>s +(not <TT>Connector</TT>s). + +<P> + </DD> +<DT><STRONG><TT>check_prefix</TT>.</STRONG></DT> +<DD><TT>check_prefix</TT> checks that the protocol prefix +in a URL style IOR or preconnect endpoint is valid for use with a given pluggable +protocol. For example, the <TT>check_prefix</TT> implementation in TAO's IIOP +pluggable protocol looks like the following: + +<P> + +<DL COMPACT> +<DT> +<DD>int +<BR> +TAO_IIOP_Connector::check_prefix (const char *endpoint) +<BR> +{ +<BR> + // Check for a valid string +<BR> + if (!endpoint || !*endpoint) +<BR> + return -1; // Failure +<BR> + +<BR> + const char *protocol[] = { "iiop", "iioploc" }; +<BR> + +<BR> + size_t slot = ACE_OS::strchr (endpoint, ':') - endpoint; +<BR> + +<BR> + size_t len0 = ACE_OS::strlen (protocol[0]); +<BR> + size_t len1 = ACE_OS::strlen (protocol[1]); +<BR> + +<BR> + // Check for the proper prefix in the IOR. If the proper prefix +<BR> + // isn't in the IOR then it is not an IOR we can use. +<BR> + if (slot == len0 +<BR> + && ACE_OS::strncasecmp (endpoint, protocol[0], len0) == 0) +<BR> + return 0; +<BR> + else if (slot == len1 +<BR> + && ACE_OS::strncasecmp (endpoint, protocol[1], len1) == 0) +<BR> + return 0; +<BR> + +<BR> + return -1; +<BR> + // Failure: not an IIOP IOR +<BR> + // DO NOT throw an exception here. +<BR> +}</DD> +</DL>It checks that the protocol prefix in a URL style IOR (e.g. <TT>iioploc://foo.bar.com:1234/...</TT>) +or preconnect endpoint matches the one(s) supported by the IIOP pluggable protocol, +in this case ``<TT>iiop</TT>'' and ``<TT>iioploc</TT>.'' If no match occurs +then return an error condition (<TT>-1</TT>). Note that the protocol prefix +``<TT>iiop</TT>'' is only there for backward compatibility. It may be removed +in future TAO releases. + +<P> +This method is important for TAO's implementation of the CORBA Interoperable +Naming Service. + +<P> + </DD> +<DT><STRONG><TT>object_key_delimiter</TT>.</STRONG></DT> +<DD>The object key delimiter within a URL style +IOR is the character that separates the address from the object key. For example, +in the following IIOP URL style IOR: + +<P> + +<DL COMPACT> +<DT> +<DD>iioploc://1.1@foo.bar.com:1234/some_object_key</DD> +</DL>the object key delimiter is `<TT>/</TT>.' However, this character is not suitable +for all pluggable protocols, such as TAO's UIOP pluggable protocol, because +addresses within a URL style IOR may contain that very same character. A typical +TAO UIOP URL style IOR may look something like: + +<P> + +<DL COMPACT> +<DT> +<DD>uioploc:///tmp/foobar|some_other_object_key</DD> +</DL>In this case, the object key delimiter is a vertical bar `<TT>|</TT>' because +using the same object key delimiter that IIOP uses `<TT>/</TT>' would cause +the point where the UIOP rendezvous point ``<TT>/tmp/foobar</TT>'' ends and +where the object key ``<TT>some_other_object_key</TT>'' begins to be ambiguous. +For instance, if an IIOP object key delimiter was used in a UIOP URL style IOR +as follows: + +<P> + +<DL COMPACT> +<DT> +<DD>uioploc:///tmp/foobar/some_other_object_key</DD> +</DL>it then becomes impossible to tell if the rendezous point is ``<TT>/tmp</TT>'' +or ``<TT>/tmp/foobar</TT>,'' and similarly for the object key, hence the need +for an object key delimiter other than `<TT>/</TT>.' + +<P> +In general, this method simply returns a static variable in the associated <TT>Profile</TT> +that contains the object key delimiter appropriate for the given pluggable protocol. + +<P> + </DD> +<DT><STRONG><TT>create_profile</TT>.</STRONG></DT> +<DD>This method creates and initializes a profile using +the provided CDR stream. Most of this code is also ``boilerblate.'' As such, +it may be factored out in future TAO releases.</DD> +<DT><STRONG><TT>make_profile</TT>.</STRONG></DT> +<DD><TT>make_profile</TT> is another method that can essentially +be ``cut and pasted'' from existing TAO pluggable protocols. It is simply +a <TT>Profile</TT> factory. The <TT>Profile</TT> it creates is initialized with +an object reference of the form: + +<P> + +<DL COMPACT> +<DT> +<DD>N.n@address/object_key</DD> +</DL>or + +<P> + +<DL COMPACT> +<DT> +<DD>address/object_key</DD> +</DL>where ``<TT>N.n</TT>'' are the major and minor protocol versions, respectively, +and the `<TT>/</TT>' is the protocol-specific object key delimiter. + +<P></DD> +</DL> + +<P> + +<H2><A NAME="SECTION230"> +The <TT>Profile</TT> Object</A> +</H2> + +<P> +TAO <TT>Profile</TT> objects encapsulate all of the methods and members necessary +to create and parse a protocol-specific IOR, in addition to representing object +address and location information. TAO <TT>Profile</TT>s are based on CORBA IOR +definitions. + +<P> +All protocol-specific <TT>Profile</TT> implementations should inherit from the +<TT>TAO_Profile</TT> abstract base class. The <TT>TAO_Profile</TT> interface +is declared in the file <TT><tao/Profile.h></TT>. Its interface follows. Only +the methods that must be implemented are shown: + +<P> + +<DL COMPACT> +<DT> +<DD>class TAO_Export TAO_Profile +<BR> +{ +<BR> + // = TITLE +<BR> + // Defines the Profile interface +<BR> + // +<BR> + // = DESCRIPTION +<BR> + // An abstract base class for representing object address or location +<BR> + // information. This is based on the CORBA IOR definitions. +<BR> + // +<BR> +public: +<BR> + +<BR> + virtual int parse_string (const char *string, +<BR> + CORBA::Environment &ACE_TRY_ENV) = 0; +<BR> + // Initialize this object using the given input string. +<BR> + // Supports URL style of object references +<BR> + +<BR> + virtual char* to_string (CORBA::Environment &ACE_TRY_ENV) = 0; +<BR> + // Return a string representation for this profile. client must +<BR> + // deallocate memory. +<BR> + +<BR> + virtual int decode (TAO_InputCDR& cdr) = 0; +<BR> + // Initialize this object using the given CDR octet string. +<BR> + +<BR> + virtual int encode (TAO_OutputCDR &stream) const = 0; +<BR> + // Encode this profile in a stream, i.e. marshal it. +<BR> + +<BR> + virtual TAO_ObjectKey *_key (void) const = 0; +<BR> + // Obtain the object key, return 0 if the profile cannot be parsed. +<BR> + // The memory is owned by the caller! +<BR> + +<BR> + virtual CORBA::Boolean is_equivalent (const TAO_Profile* other_profile) = 0; +<BR> + // Return true if this profile is equivalent to other_profile. Two +<BR> + // profiles are equivalent iff their key, port, host, object_key and +<BR> + // version are the same. +<BR> + +<BR> + virtual CORBA::ULong hash (CORBA::ULong max, +<BR> + CORBA::Environment &ACE_TRY_ENV) = 0; +<BR> + // Return a hash value for this object. +<BR> + +<BR> + virtual int addr_to_string (char *buffer, size_t length) = 0; +<BR> + // Return a string representation for the address. Returns +<BR> + // -1 if buffer is too small. The purpose of this method is to +<BR> + // provide a general interface to the underlying address object's +<BR> + // addr_to_string method. This allowsthe protocol implementor to +<BR> + // select the appropriate string format. +<BR> + +<BR> + virtual void reset_hint (void) = 0; +<BR> + // This method is used with a connection has been reset requiring +<BR> + // the hint to be cleaned up and reset to NULL. +<BR> +};</DD> +</DL>TAO's existing pluggable protocols have a static member containing the object +key delimiter specific to the given pluggable protocol, in addition to a static +protocol prefix accessor method that simply returns a pointer to a static string +containing the protocol prefix specific to the pluggable protocol. Note that +both of these members will always remain constant so there is no problem in +making them static. + +<P> +Theses static member are: + +<P> + +<DL> +<DT><STRONG><TT>object_key_delimiter</TT>.</STRONG></DT> +<DD>This <I>variable</I> contains the object key +delimiter specific to the given pluggable protocol. A typical definition looks +like: +<P> + +<DL COMPACT> +<DT> +<DD>const char TAO_IIOP_Profile::object_key_delimiter = '/';</DD> +</DL></DD> +<DT><STRONG><TT>prefix</TT>.</STRONG></DT> +<DD>This <I>method</I> simply returns a pointer to a static string +that contains the protocol prefix specific to the pluggable protocol in use. +The static string for the IIOP pluggable protocol is: + +<P> + +<DL COMPACT> +<DT> +<DD>static const char prefix_[] = "iiop";</DD> +</DL>The IIOP <TT>prefix</TT> method is: + +<P> + +<DL COMPACT> +<DT> +<DD>const char * +<BR> +TAO_IIOP_Profile::prefix (void) +<BR> +{ +<BR> + return ::prefix_; +<BR> +}</DD> +</DL></DD> +</DL> +Note that it not strictly necessary to implement equivalent versions of these +static members. TAO's implementation just happens to use them. However, pluggable +protocol implementations that are based on TAO's pluggable protocols may need +them. + +<P> +Common to all concrete <TT>Profile</TT> implementations are a set of methods +that must be implemented. A description of each of these methods: + +<P> + +<DL> +<DT><STRONG>The Constructors.</STRONG></DT> +<DD>TAO's existing pluggable protocols each implement several +constructors in their concrete <TT>Profile</TT> classes. While pluggable protocols +are not strictly required to implement analogs to all of the constructors in +existing TAO pluggable protocols, it is generally a good idea to do so. All +of the constructors should initialize the <TT>TAO_Profile</TT> abstract base +class with the tag associated with the pluggable protocol. The object key should +also be set during <TT>Profile</TT> construction.</DD> +<DT><STRONG><TT>parse_string</TT>.</STRONG></DT> +<DD><TT>parse_string</TT> initialize a <TT>Profile</TT> +object using the provided string. The string passed to this method has the format: +<P> + +<DL COMPACT> +<DT> +<DD>N.n@address/object_key</DD> +</DL>or + +<P> + +<DL COMPACT> +<DT> +<DD>address/object_key</DD> +</DL>where the <TT>address</TT> and the object key delimiter `<TT>/</TT>' are pluggable +protocol specific. The <TT>parse_string</TT> method must be able to extract +the protocol version (even if it isn't used), the address and the object key +from the provided string. It is generally a good idea to use the <TT>parse_string</TT> +methods in TAO's existing pluggable protocols as a reference when implementing +this method. + +<P> + </DD> +<DT><STRONG><TT>to_string</TT>.</STRONG></DT> +<DD>This method returns the URL style representation of the +object reference encapsulated by the <TT>Profile</TT> object. Most of this code +is also ``boilerplate.'' However, the address part of the URL style IOR, returned +by this method should be specific to the pluggable protocol. For example, the +address in the following IIOP URL style IOR: + +<P> + +<DL COMPACT> +<DT> +<DD>iioploc://1.1@foo.bar.com:1234/yet_another_object_key</DD> +</DL>is ``<TT>foo.bar.com:1234</TT>.'' Much of the in TAO's existing pluggable +protocols may also be factored out because that code is common to all pluggable +protocols. + +<P> + </DD> +<DT><STRONG><TT>decode</TT>.</STRONG></DT> +<DD>The input CDR stream reference passed to this method is used +to initialize the <TT>Profile</TT> object, by extracting (<I>decoding</I> all +object reference information found within the CDR stream. Care must be taken +to extract the information in the correct order. Use existing TAO pluggable +protocol <TT>decode</TT> implementations as a reference. + +<P> +The <TT>decode</TT> method performs the inverse operation of the <TT>encode</TT> +method. + +<P> + </DD> +<DT><STRONG><TT>encode</TT>.</STRONG></DT> +<DD>This method inserts (<I>encodes</I> all of the information +encapsulated by the <TT>Profile</TT> object in to the provided output CDR stream. +Care must be taken to insert the information in the correct order. Use existing +TAO pluggable protocol <TT>encode</TT> implementations as a reference. + +<P> +The <TT>encode</TT> method performs the inverse operation of the <TT>decode</TT> +method. + +<P> + </DD> +<DT><STRONG><TT>_key</TT>.</STRONG></DT> +<DD>The <TT>_key</TT> method constructs a <TT>TAO_ObjectKey</TT> +object that is a <I>copy</I> of the object key found within the <TT>Profile</TT> +object, and returns a pointer to the newly create <TT>TAO_ObjectKey</TT> object. +Note that the <I>caller</I> owns the memory allocated by this method. TAO's +IIOP <TT>_key</TT> implementation is: + +<P> + +<DL COMPACT> +<DT> +<DD>ACE_INLINE TAO_ObjectKey * +<BR> +TAO_IIOP_Profile::_key (void) const +<BR> +{ +<BR> + TAO_ObjectKey *key = 0; +<BR> + +<BR> + ACE_NEW_RETURN (key, +<BR> + TAO_ObjectKey (this->object_key_), +<BR> + 0); +<BR> + +<BR> + return key; +<BR> +}</DD> +</DL></DD> +<DT><STRONG><TT>is_equivalent</TT>.</STRONG></DT> +<DD>The <TT>is_equivalent</TT> method implements the +CORBA specified method of the same name. It should return true if this profile +is equivalent to the profile to which it is being compared. Two profiles are +equivalent <I>if and only if</I> their tag, version, address and object key +are the same.</DD> +<DT><STRONG><TT>hash</TT>.</STRONG></DT> +<DD>The <TT>hash</TT> method implements the CORBA specified method +of the same name. It is expected to return 32 bit <TT>unsigned integer</TT> +(<TT>CORBA::ULong</TT>) that uniquely identifies the CORBA object referenced +by the <TT>Profile</TT> object. This method accepts an argument that specifies +the largest value the hash can be. + +<P> +Any algorithm deemed suitable to provide the required functionality may be used. +The <TT>ACE</TT> class in the ACE library provides implementations of several +hash algorithms. + +<P> + </DD> +<DT><STRONG><TT>addr_to_string</TT>.</STRONG></DT> +<DD><TT>addr_to_string</TT> returns a string representation +of the address. It should return <TT>-1</TT> if the supplied buffer is too small. +The stringified address should have the same form that the address in the URL +style IOR has. This method should be reentrant.</DD> +<DT><STRONG><TT>reset_hint</TT>.</STRONG></DT> +<DD>The <TT>reset_hint</TT> method resets the pointer to +a successfully used <TT>Connection Handler</TT>. If no pointer to such a <TT>Connection +Handler</TT>, i.e. a <I>hint</I> is provided by the pluggable protocol then this +method may be implemented as a ``no-op.'' A pluggable protcol that does not +provide a cached <TT>Connection Handler</TT> will not be able to take advantage +of improved <TT>Connector</TT> table look up times.</DD> +</DL> + +<P> + +<H2><A NAME="SECTION240"> +The <TT>Protocol_Factory</TT> Object</A> +</H2> + +<P> +TAO's uses the ACE's Service Configurator implementation [<A + HREF="pluggable_protocols.html#Schmidt:94k">2</A>] +to dynamically load pluggable protocol factories. A <TT>Protocol_Factory</TT> +is responsible for creating the <TT>Acceptor</TT> and <TT>Connector</TT> for +the given pluggable protocol. TAO iterates through the list of loaded <TT>Protocol +Factories</TT> and invokes a factory operation that creates the desired object: +an <TT>Acceptor</TT> on the server-side, and a <TT>Connector</TT> on the client-side. + +<P> +All <TT>Protocol_Factory</TT> implementations should be derived from the <TT>TAO_Protocol_Factory</TT> +abstract base class defined in <TT><tao/Protocol_Factory.h></TT>. The <TT>TAO_Protocol_Factory</TT> +interface is shown below: + +<P> + +<DL COMPACT> +<DT> +<DD>class TAO_Export TAO_Protocol_Factory : public ACE_Service_Object +<BR> +{ +<BR> +public: +<BR> + TAO_Protocol_Factory (void); +<BR> + virtual ~TAO_Protocol_Factory (void); +<BR> + +<BR> + virtual int init (int argc, char *argv[]); +<BR> + // Initialization hook. +<BR> + +<BR> + virtual int match_prefix (const ACE_CString &prefix); +<BR> + // Verify prefix is a match +<BR> + +<BR> + virtual const char *prefix (void) const; +<BR> + // Returns the prefix used by the protocol. +<BR> + +<BR> + virtual char options_delimiter (void) const; +<BR> + // Return the character used to mark where an endpoint ends and +<BR> + // where its options begin. +<BR> + +<BR> + // Factory methods +<BR> + virtual TAO_Acceptor *make_acceptor (void); +<BR> + // Create an acceptor +<BR> + +<BR> + virtual TAO_Connector *make_connector (void); +<BR> + // Create a connector +<BR> + +<BR> + virtual int requires_explicit_endpoint (void) const = 0; +<BR> + // Some protocols should not create a default endpoint unless the +<BR> + // user specifies a -ORBEndpoint option. For example, local IPC +<BR> + // (aka UNIX domain sockets) is unable to remove the rendesvouz +<BR> + // point if the server crashes. For those protocols is better to +<BR> + // create the endpoint only if the user requests one. +<BR> +};</DD> +</DL>Each of the important methods to be implemented are described below: + +<P> + +<DL> +<DT><STRONG><TT>init</TT>.</STRONG></DT> +<DD>The <TT>init</TT> method is invoked immediately after the pluggable +protocol factory is loaded. The <TT>Service Configurator</TT> passes <TT>Protocol +Factory</TT> options specified in a <TT>Service Configurator</TT> configuration +file (e.g. <TT>svc.conf</TT>) to this method. The passing convention is essentially +the same as command line <TT>argc</TT>/<TT>argv</TT> argument passing convention. +The only difference lies in the fact that the option parsing should begin at +<TT>argv[0]</TT> instead of <TT>argv[1]</TT>. This differs from the +standard command line passing convention because <TT>argv[0]</TT> is the +name of the program currently being run. In any case, the <TT>init</TT> method +allows protocol-specific options to be implemented. Once passed to this method, +the pluggable protocol can use them to, for example, enable or disable certain +features or flags within the <TT>Protocol Factory</TT>. Other pluggable protocol +components can then use these flags or features as necessary. +<P> +A typical <TT>Service Configurator</TT> file line that loads a pluggable protocol +dynamically, and passes arguments to the <TT>init</TT> method would look like: + +<P> + +<DL COMPACT> +<DT> +<DD>dynamic IIOP_Factory Service_Object * TAO:_make_TAO_IIOP_Protocol_Factory() "-Foo Bar"</DD> +</DL>In the above example, the arguments ``<TT>-Foo</TT>'' and ``<TT>Bar</TT>'' +would be passed as <TT>argv[0]</TT> and <TT>argv[1]</TT>, respectively, +to the <TT>Protocol_Factory init</TT> method. + +<P> + </DD> +<DT><STRONG><TT>match_prefix</TT>.</STRONG></DT> +<DD>This method verifies that protocol prefix contained +in the string passed to matches the one used by the pluggable protocol. A typical +implementation, such as the one used by the IIOP pluggable protocol, looks like: + +<P> + +<DL COMPACT> +<DT> +<DD>static const char prefix_[] = "iiop"; +<BR> + +<BR> +int +<BR> +TAO_IIOP_Protocol_Factory::match_prefix (const ACE_CString &prefix) +<BR> +{ +<BR> + // Check for the proper prefix for this protocol. +<BR> + return (ACE_OS::strcasecmp (prefix.c_str (), ::prefix_) == 0); +<BR> +}</DD> +</DL></DD> +<DT><STRONG><TT>prefix</TT>.</STRONG></DT> +<DD>The <TT>prefix</TT> method simply returns a pointer to the +static string containing the protocol prefix used by the pluggable protocol.</DD> +<DT><STRONG><TT>options_delimiter</TT>.</STRONG></DT> +<DD>The <TT>options_delimiter</TT> method is similar +to the <TT>object_key_delimiter</TT> method found in the <TT>Connector</TT>. +However, it used to delimit where an endpoint ends and where its options begin. +For example, the following <TT>-ORBEndpoint</TT> option specifies a endpoint-specific +priority: + +<P> + +<DL COMPACT> +<DT> +<DD>-ORBEndpoint iiop://1.1@foo.bar.com/priority=25</DD> +</DL>To get around ambiguities in endpoints that can have a `<TT>/</TT>' character +in them, the <TT>options_delimiter</TT> method can be used to determine what +character to be used. For example, TAO's UIOP pluggable protocol implementation +defines the following: + +<P> + +<DL COMPACT> +<DT> +<DD>char +<BR> +TAO_UIOP_Protocol_Factory::options_delimiter (void) const +<BR> +{ +<BR> + return '|'; +<BR> +}</DD> +</DL>An endpoint option for the UIOP pluggable protocol can look like the following: + +<P> + +<DL COMPACT> +<DT> +<DD>-ORBEndpoint uiop://1.1@/tmp/foo|priority=25</DD> +</DL>Notice that the `<TT>|</TT>' character is used to mark where the rendezvous +point ends and where the endpoint-specific options begin. + +<P> + +<TT>options_delimiter</TT> is a server-side related method. It is of no use +to the client-side. + +<P> + </DD> +<DT><STRONG><TT>make_acceptor</TT>.</STRONG></DT> +<DD>The <TT>make_acceptor</TT> method is a factory method +that returns a pointer to a dynamically allocated <TT>Acceptor</TT> specific +to the pluggable protocol to which the <TT>Protocol_Factory</TT> object belongs. +TAO's UIOP pluggable protocol implementation defines this method as follows: + +<P> + +<DL COMPACT> +<DT> +<DD>TAO_Acceptor * +<BR> +TAO_UIOP_Protocol_Factory::make_acceptor (void) +<BR> +{ +<BR> + TAO_Acceptor *acceptor = 0; +<BR> + +<BR> + ACE_NEW_RETURN (acceptor, +<BR> + TAO_UIOP_Acceptor, +<BR> + 0); +<BR> + +<BR> + return acceptor; +<BR> +}</DD> +</DL></DD> +<DT><STRONG><TT>make_connector</TT>.</STRONG></DT> +<DD>The <TT>make_connector</TT> method is a factory +method that returns a pointer to a dynamically allocated <TT>Connector</TT> +specific to the pluggable protocol to which the <TT>Protocol_Factory</TT> object +belongs. TAO's UIOP pluggable protocol implementation defines this method as +follows: + +<P> + +<DL COMPACT> +<DT> +<DD>TAO_Connector * +<BR> +TAO_UIOP_Protocol_Factory::make_connector (void) +<BR> +{ +<BR> + TAO_Connector *connector = 0; +<BR> + +<BR> + ACE_NEW_RETURN (connector, +<BR> + TAO_UIOP_Connector, +<BR> + 0); +<BR> + +<BR> + return connector; +<BR> +}</DD> +</DL></DD> +<DT><STRONG><TT>requires_explicit_endpoint</TT>.</STRONG></DT> +<DD>Some protocols should not create a default +endpoint unless the user specifies a -ORBEndpoint option. For example, local +IPC (aka UNIX domain sockets) is unable to remove the rendesvouz point if the +server crashes. For those protocols, it is better to create the endpoint only +if the user requests one. This method is queried by TAO before creating a default +acceptor during ORB initialization. If it returns <TT>1</TT> then no default +endpoint should be created.</DD> +</DL> +<TT>Service Object</TT>s, such as the <TT>Protocol_Factory</TT>, must be declared +in a certain way. ACE's Service Configurator implementation provides two macros +to ensure that the required additional declarations are made to make an object +have to the correct interface. The two macros are <TT>ACE_STATIC_SVC_DECLARE</TT> +and <TT>ACE_FACTORY_DECLARE</TT>. Typical usage of these declaration macros +is demonstrated by TAO's UIOP pluggable protocol implementation: + +<P> + +<DL COMPACT> +<DT> +<DD>ACE_STATIC_SVC_DECLARE (TAO_UIOP_Protocol_Factory) +<BR> +ACE_FACTORY_DECLARE (TAO, TAO_UIOP_Protocol_Factory)</DD> +</DL>also required. These are provided by ``<TT>DEFINE</TT>'' counterparts of the +above two declaration macros. An example of how to use them follows: + +<P> + +<DL COMPACT> +<DT> +<DD>ACE_STATIC_SVC_DEFINE (TAO_UIOP_Protocol_Factory, +<BR> + ASYS_TEXT ("UIOP_Factory"), +<BR> + ACE_SVC_OBJ_T, +<BR> + &ACE_SVC_NAME (TAO_UIOP_Protocol_Factory), +<BR> + ACE_Service_Type::DELETE_THIS | +<BR> + ACE_Service_Type::DELETE_OBJ, +<BR> + 0) +<BR> + +<BR> +ACE_FACTORY_DEFINE (TAO, TAO_UIOP_Protocol_Factory)</DD> +</DL>Notice that the macro arguments above have corresponding <TT>Service Configurator</TT> +configuration file entries: + +<P> + +<DL COMPACT> +<DT> +<DD>dynamic UIOP_Factory Service_Object * TAO:_make_TAO_UIOP_Protocol_Factory() "" +<BR> +static Resource_Factory "-ORBProtocolFactory UIOP_Factory"</DD> +</DL> +<P> + +<H2><A NAME="SECTION250"> +The <TT>Transport</TT> Object</A> +</H2> + +<P> + +<H3><A NAME="SECTION251"> +Context</A> +</H3> + +<P> +It is desirable to provide for alternative mappings between different ORB messaging +protocols and ORB transport adaptors. For example, a single ORB messaging protocol +such as GIOP can be mapped to any reliable, connection-oriented transport protocol, +such as TCP or TP4. Alternatively, a single transport protocol can be the basis +for alternative instantiations of ORB messaging protocols, <I>e.g.</I>, different +versions of GIOP differing in the number and types of messages, as well as in +the format of those messages. + +<P> +An ORB messaging protocol imposes requirements on any underlying network transport +protocols. For instance, the transport requirements assumed by GIOP, see Section <A HREF="#IOP"><IMG ALIGN="BOTTOM" BORDER="1" ALT="[*]" + SRC="cross_ref_motif.png"></A>, +require the underlying network transport protocol to support a reliable, connection-oriented +byte-stream. These requirements are fulfilled by TCP thus leading to the direct +mapping of GIOP onto this transport protocol. However, alternative network transport +protocols such as ATM with AAL5 encapsulation may be more appropriate in some +environments. In this case, the messaging implementation will have to provide +the missing semantics, such as reliability, in order to use GIOP. + +<P> + +<H3><A NAME="SECTION252"> +Problem</A> +</H3> + +<P> +The ORB Messaging protocol implementations must be independent of the adaptation +layer needed for transports that do not satisfy all their requirements. Otherwise, +the same messaging protocol may be re-implemented needlessly for each transport, +which is time-consuming, error-prone, and time/space inefficient. Likewise, +for those transports that can support multiple ORB Messaging protocols, it must +be possible to isolate them from the details of the ORB messaging implementation. +Care must be taken, however, because not all ORB Messaging protocols can be +used with all transport protocols, <I>i.e.</I>, some mechanism is needed to +ensure only semantically compatible protocols are configured [<A + HREF="pluggable_protocols.html#Johnson:95a">3</A>]. + +<P></P> +<DIV ALIGN="CENTER"><A NAME="iop_client"></A><A NAME="700"></A> +<TABLE> +<CAPTION ALIGN="BOTTOM"><STRONG>Figure 4:</STRONG> +Client Inter-ORB and Transport Class Diagram</CAPTION> +<TR><TD><P> + +<P> + +<DIV ALIGN="CENTER"> +<!-- MATH + $\resizebox* {5in}{!}{\includegraphics{graphics/pp_iopc.eps}}$ + --> +<IMG + WIDTH="568" HEIGHT="537" ALIGN="BOTTOM" BORDER="0" + SRC="img4.png" + ALT="pp_iopc"> </DIV> +<P> +<DIV ALIGN="CENTER"></DIV></TD></TR> +</TABLE> +</DIV><P></P> + +<P> + +<H3><A NAME="SECTION253"> +Solution</A> +</H3> + +<P> +Use the Layers architecture pattern [<A + HREF="pluggable_protocols.html#Buschmann:95b">4</A>], which decomposes +the system into groups of components, each one at a different level of abstraction.<A NAME="tex2html5" + HREF="#foot549"><SUP>1</SUP></A> For the client, the ORB uses a particular ORB messaging protocol to send a +request. This ORB messaging protocol delegates part of the work to the transport +adapter component that completes the message and sends it to the server. If +the low-level transport in use, <I>e.g.</I>, ATM, UDP, TCP/IP, etc., does not +satisfy the requirements of the ORB messaging protocol, the ORB transport adapter +component can implement them. + +<P> +In the server, the transport adapter component receives data from the underlying +communication infrastructure, such as sockets or shared memory, and it passes +the message up to the ORB messaging layer. As with the client, this layer can +be very lightweight if the requirements imposed by the ORB messaging layer are +satisfied by the underlying network transport protocol. Otherwise, it must implement +those missing requirements by building them into the concrete transport adapter +component. + +<P></P> +<DIV ALIGN="CENTER"><A NAME="iop_server"></A><A NAME="702"></A> +<TABLE> +<CAPTION ALIGN="BOTTOM"><STRONG>Figure 5:</STRONG> +Server Inter-ORB and Transport Class Diagram</CAPTION> +<TR><TD><P> + +<P> + +<DIV ALIGN="CENTER"> +<!-- MATH + $\resizebox* {5in}{!}{\includegraphics{graphics/pp_iops.eps}}$ + --> +<IMG + WIDTH="563" HEIGHT="750" ALIGN="BOTTOM" BORDER="0" + SRC="img5.png" + ALT="pp_iops"> </DIV> +<P> +<DIV ALIGN="CENTER"></DIV></TD></TR> +</TABLE> +</DIV><P></P> + +<P> + +<H3><A NAME="SECTION254"> +Applying the solution in TAO</A> +</H3> + +<P> +As shown in Figure <A HREF="pluggable_protocols.html#iop_client">4</A>, TAO implements the messaging protocol +and the transport protocol in separate components. The client ORB uses the current +profile to find the right transport and ORB messaging implementations. The creation +and initialization of these classes is controlled by the <TT>Connector</TT> +(described in Section <A HREF="pluggable_protocols.html#design:connect">2.2</A>), with each <TT>Connector</TT> instance +handling a particular ORB messaging/transport tuple. + +<P> +Figure <A HREF="pluggable_protocols.html#iop_server">5</A> illustrates how the server's implementation uses the +same transport classes, but with a different relationship. In particular, the +transport class calls back the messaging class when data is received from the +IPC mechanism. As with the client, a factory, in this case the <TT>Acceptor</TT>, +creates and initializes these objects. + +<P> + +<H3><A NAME="SECTION255"> +<TT>Transport</TT> Implementation</A> +</H3> + +<P> +All TAO pluggable protocol <TT>Transport</TT> classes must inherit from the +<TT>TAO_Transport</TT> abstract base class defined in <TT><tao/Pluggable.h></TT>. +The <TT>TAO_Transport</TT> interface is shown below. Again, only the methods +that should be implemented for a given pluggable protocol are shown: + +<P> + +<DL COMPACT> +<DT> +<DD>class TAO_Export TAO_Transport +<BR> +{ +<BR> + // = TITLE +<BR> + // Generic definitions for the Transport class. +<BR> + // +<BR> + // = DESCRIPTION +<BR> + // The transport object is created in the Service handler +<BR> + // constructor and deleted in the service handler's destructor!! +<BR> + +<BR> +public: +<BR> + TAO_Transport (CORBA::ULong tag, +<BR> + TAO_ORB_Core *orb_core); +<BR> + // default creator, requres the tag value be supplied. +<BR> + +<BR> + virtual ~TAO_Transport (void); +<BR> + // destructor +<BR> + +<BR> + virtual void close_connection (void) = 0; +<BR> + // Call the corresponding connection handler's <close> +<BR> + // method. +<BR> + +<BR> + virtual int idle (void) = 0; +<BR> + // Idles the corresponding connection handler. +<BR> + +<BR> + virtual ACE_HANDLE handle (void) = 0; +<BR> + // This method provides a way to gain access to the underlying file +<BR> + // handle used by the reactor. +<BR> + +<BR> + virtual ACE_Event_Handler *event_handler (void) = 0; +<BR> + // This method provides a way to gain access to the underlying event +<BR> + // handler used by the reactor. +<BR> + +<BR> + virtual ssize_t send (TAO_Stub *stub, +<BR> + const ACE_Message_Block *mblk, +<BR> + const ACE_Time_Value *s = 0) = 0; +<BR> + virtual ssize_t send (const ACE_Message_Block *mblk, +<BR> + const ACE_Time_Value *s = 0) = 0; +<BR> + // Write the complete Message_Block chain to the connection. +<BR> + // @@ The ACE_Time_Value *s is just a place holder for now. It is +<BR> + // not clear this this is the best place to specify this. The actual +<BR> + // timeout values will be kept in the Policies. +<BR> + +<BR> + virtual ssize_t send (const u_char *buf, +<BR> + size_t len, +<BR> + const ACE_Time_Value *s = 0) = 0; +<BR> + // Write the contents of the buffer of length len to the connection. +<BR> + +<BR> + virtual ssize_t recv (char *buf, +<BR> + size_t len, +<BR> + const ACE_Time_Value *s = 0) = 0; +<BR> + // Read len bytes from into buf. +<BR> + // @@ The ACE_Time_Value *s is just a place holder for now. It is +<BR> + // not clear this this is the best place to specify this. The actual +<BR> + // timeout values will be kept in the Policies. +<BR> + +<BR> + virtual void start_request (TAO_ORB_Core *orb_core, +<BR> + const TAO_Profile *profile, +<BR> + TAO_OutputCDR &output, +<BR> + CORBA::Environment &ACE_TRY_ENV = +<BR> + TAO_default_environment ()) +<BR> + ACE_THROW_SPEC ((CORBA::SystemException)); +<BR> + // Fill into <output> the right headers to make a request. +<BR> + +<BR> + virtual void start_locate (TAO_ORB_Core *orb_core, +<BR> + const TAO_Profile *profile, +<BR> + CORBA::ULong request_id, +<BR> + TAO_OutputCDR &output, +<BR> + CORBA::Environment &ACE_TRY_ENV = +<BR> + TAO_default_environment ()) +<BR> + ACE_THROW_SPEC ((CORBA::SystemException)); +<BR> + // Fill into <output> the right headers to make a locate request. +<BR> + +<BR> + virtual int send_request (TAO_Stub *stub, +<BR> + TAO_ORB_Core *orb_core, +<BR> + TAO_OutputCDR &stream, +<BR> + int twoway, +<BR> + ACE_Time_Value *max_time_wait) = 0; +<BR> + // Depending on the concurrency strategy used by the transport it +<BR> + // may be required to setup state to receive a reply before the +<BR> + // request is sent. +<BR> + // Using this method, instead of send(), allows the transport (and +<BR> + // wait strategy) to take appropiate action. +<BR> + +<BR> + virtual int handle_client_input (int block = 0, +<BR> + ACE_Time_Value *max_wait_time = 0); +<BR> + // Read and handle the reply. Returns 0 when there is Short Read on +<BR> + // the connection. Returns 1 when the full reply is read and +<BR> + // handled. Returns -1 on errors. +<BR> + // If <block> is 1, then reply is read in a blocking manner. +<BR> + +<BR> + virtual int register_handler (void); +<BR> + // Register the handler with the reactor. Will be called by the Wait +<BR> + // Strategy if Reactor is used for that strategy. Default +<BR> + // implementation out here returns -1 setting <errno> to ENOTSUP. +<BR> + +<BR> +};</DD> +</DL>Each method is described below: + +<P> + +<DL> +<DT><STRONG>The Constructor.</STRONG></DT> +<DD>As with all of the TAO pluggable protocol framework components +described so far, the constructor for the concrete <TT>Transport</TT> object +should also initialize the <TT>TAO_Transport</TT> base class with the tag corresponding +to the pluggable protocol.</DD> +<DT><STRONG><TT>close_connection</TT>.</STRONG></DT> +<DD>The underlying <TT>Connection Handler</TT>'s <TT>close</TT> +method is invoked my this method.</DD> +<DT><STRONG><TT>idle</TT>.</STRONG></DT> +<DD>This method idles the underlying <TT>Connection Handler</TT>.</DD> +<DT><STRONG><TT>handle</TT>.</STRONG></DT> +<DD>This method returns the underlying file handle used by the +<TT>Reactor</TT>.</DD> +<DT><STRONG><TT>event_handler</TT>.</STRONG></DT> +<DD>This method returns the underlying <TT>Event Handler</TT> +used by the <TT>Reactor</TT>.</DD> +<DT><STRONG><TT>send</TT>.</STRONG></DT> +<DD>The <TT>send</TT> writes data to the connection established +in the underlying transport, such as a TCP connection in the IIOP pluggable +protocol. Three versions of this method must be implemented. Two of them write +data contained within an <TT>ACE_Message_Block</TT> and the remaining simply +sends the data within a buffer of a given length. +<P> +When implementing this method, it is important to be aware of the correct underlying +<TT>send</TT> or <TT>write</TT> operation to use. Some of TAO's existing pluggable +protocols use the <TT>send</TT> calls provided by the operating system because +no further processing of the data being sent is necessary. However, other protocols +may process perform additional operations on the data being sent, in which case +the <TT>send</TT> operation provided by the underlying protocol implementation +should be used instead of the raw operating system <TT>send</TT> call. + +<P> + </DD> +<DT><STRONG><TT>recv</TT>.</STRONG></DT> +<DD>The <TT>recv</TT> operation reads a given number of bytes into +a supplied buffer. Unlike the <TT>send</TT> method, there is only one version +of the <TT>recv</TT> operation. The same caveat of ensuring that the appropriate +<TT>recv</TT> or <TT>read</TT> operation is used also applies to this method.</DD> +<DT><STRONG><TT>start_request</TT>.</STRONG></DT> +<DD>This method creates the appropriate header to make +a request and write it into the provided output CDR stream. This method is closely +tied to TAO's GIOP implementation. <TT>start_request</TT> implementations should +essentially be the same in all pluggable protocol implementations. The only +thing that should differ is the type of <TT>Profile</TT> being used. Note that +this method is only useful for clients.</DD> +<DT><STRONG><TT>start_locate</TT>.</STRONG></DT> +<DD>This method creates the appropriate header to make +a <I>locate</I> request and write it into the provided output CDR stream. This +method is closely tied to TAO's GIOP implementation. <TT>start_locate</TT> +implementations should essentially be the same in all pluggable protocol implementations. +The only thing that should differ is the type of <TT>Profile</TT> being used. +Note that this method is only useful for clients. Note that this method is only +useful for clients.</DD> +<DT><STRONG><TT>send_request</TT>.</STRONG></DT> +<DD>Depending on the concurrency strategy used by the transport +it may be required to setup state to receive a reply before the request is sent. +Using this method, instead of <TT>send</TT>, allows the transport (and wait +strategy) to take appropiate action. This method is closely tied to TAO's GIOP +implementation. <TT>send_request</TT> implementations should essentially be +the same in all pluggable protocol implementations. The only thing that should +differ is the type of <TT>Profile</TT> being used. Note that this method is +only useful for clients.</DD> +<DT><STRONG><TT>handle_client_input</TT>.</STRONG></DT> +<DD><TT>handle_client_input</TT> reads and handles +the reply from the server. It returns zero when there is <TT>Short Read</TT> +on the connection, returns <TT>1</TT> when the full reply is read and handled, +and returns <TT>-1</TT> on errors. Note that this method is only useful for +clients.</DD> +<DT><STRONG><TT>register_handler</TT>.</STRONG></DT> +<DD>This method registers the <TT>Connection Handler</TT> +with the <TT>Reactor</TT>. It will be called by the <TT>Wait Strategy</TT> if +the <TT>Reactor</TT> is used for that strategy. This code should essentially +be ``boilerplate'' code. It shouldn't differ much between pluggable protocol +implementations if the same ACE event handling and dispatching components are +used. Note that this method may be deprecated in the future.</DD> +</DL> +There other methods in the <TT>TAO_Transport</TT> that can be overridden. However, +the default implementations should be more than satisfactory for most pluggable +protocols. + +<P> +TAO's existing pluggable protocols implement client-side and server-side specific +<TT>Transport</TT>s. For the most part, they can be used as references for other +pluggable protocols. + +<P> +<HR> +<P> + +<H1><A NAME="SECTION300"> +Notes From a "Real World" Pluggable Protocol Implementation</A> +</H1> + +By Bruce Task <<A +HREF="mailto:btrask@contactsystems.com">btrask@contactsystems.com</A>> + +<P>This paper is some notes on the steps I took to add a different transport layer to +the TAO ORB. I was given some initial guidelines on adding an additional protocol +and these proved very helpful. Beyond that there was not much more documentation +and so I hope the information in this paper will serve to further assist anybody whose +is adding a pluggable protocol to the TAO ORB. + +<P>I found that in order to successfully add the new protocol capabilities, one had to +have a very good understanding of some of the patterns upon which the ACE framework +is built. These are the REACTOR, ACCEPTOR, CONNECTOR, FACTORY, STRATEGY, +and SERVICE CONFIGURATOR PATTERN. The papers that I found helpful on these +were: +<BR> +<BLOCKQUOTE>Reactor + Reactor1-93.pdf<BR> + Reactor2-93.pdf<BR> + Reactor-rules.ps<BR> + Reactor-siemens.ps<BR> + Svc-conf.ps<BR> + Acc-Con.ps</BLOCKQUOTE> +<BR> +<P>These are all readily available from the TAO and ACE website. +<BR> +<P>My starting point for understanding how to add a pluggable protocol to the TAO ORB came +from mailing list entry from Carlos O'Ryan (coryan@cs.wustl.edu). One can find it in +the archives of the comp.soft-sys.ace. It is dated 1999/06/02 RE: [ace-users] TAO: ATM pluggable +protocol. I will repeat the section of that email that was particularly useful to me. (In the email, +he is responding to someone who had inquired about adding the ATM protocol). +<BR> + + <BLOCKQUOTE>Basically, you need to look at the following files: +<BR> + IIOP_Profile.{h,i,cpp} + IIOP_Connector.{h,i,cpp} + IIOP_Acceptor.{h,i,cpp} + IIOP_Factory.{h,i,cpp} + IIOP_Transport.{h,i,cpp} + Connect.{h,i,cpp} [probably will be renamed IIOP_Connect VSN] +<BR> +<P> The profile class handles the addressing format for your transport. It would +basically be a wrapper around the ACE_ATM_Addr() class. +The Connector and Acceptor classes are simply wrappers around +ACE_Acceptor<ACE_ATM_ACCEPTOR> and +ACE_Connector<ACE_ATM_ACCEPTOR>, again no big deal (I think). +The factory is even simpler. + +<P>Things get really interesting in the Transport and Connect classes. Transport +just implements external polymorphism over the Client_Connector_Handler and +the Service_Connnector_Handler objects defined in the Connect.{h,i,cpp}, those are +simply ACE_Svc_Handler<ACE_ATM_Stream>, but they don't do much work, they +just delegate on the Transport classes. This somewhat strange design is easy to +understand once you realize that all the ACE_Svc_Handler<> classes are not type +compatible (except in their most basic ACE_Event_Handler form). So they must +be wrapped using the TAO_Transport class. + +</BLOCKQUOTE> + +<BR> +<P>Review also the index.html file entitled "Release Information for the ACE ORB (TAO)" +in the tao\docs\releasenotes\ directory, section "Pluggable Protocols" +<BR><P> +Just for completeness sake, I'll include some other mailing list entries which were helpful +in getting me started. The following is from Ossama Othman (othman@cs.wustl.edu). + +<BLOCKQUOTE>The stock TAO distribution has support for two transport protocols, +TCP/IP and local namespace sockets (aka Unix Domain sockets). However, +TAO's pluggable protocols framework allows users to add support for +additional transport protocols. All you'd really have to do is +implement a SCRAMNet pluggable transport protocol with the interface +TAO's pluggable protocol framework provides and you'd be able to use +SCRAMNet with TAO just as easily as the IIOP (GIOP over TCP/IP) and +UIOP (GIOP over Unix domains sockets) protocols. +<BR> +The idea is to implement GIOP messaging over a SCRAMNet transport. If +you model your implementation on TAO's IIOP and UIOP implementations +then it should be fairly straightforward to add SCRAMNet support to +TAO. The hard part is adding SCRAMNet support to ACE. +<BR> +. . . +<BR> +It's actually not that bad. The easiest way to add a pluggable protocol +to TAO, IMO, is to base your pluggable protocol on existing ones. As +long as you have the same interface for your protocol as the existing +ones then it is fairly easy to add support for your protocol to TAO. +However, in order to do that you have to add ACE_SCRAMNet_{Acceptor, +Connector, Stream, Addr} implementations, for example, to ACE since +TAO's existing pluggable protocols use those ACE classes/interfaces. +<BR> + +As long as you use +the same interface for your protocol as the interface for ace/ACE_SOCK* +and tao/IIOP* then you shouldn't have much of a problem.</BLOCKQUOTE> +<BR> +<P>Here are some links that describe the pluggable protocols framework but +not how to implement one: +<BLOCKQUOTE> +<A HREF="http://www.cs.wustl.edu/~schmidt/ACE_wrappers/TAO/docs/releasenotes/index.html#pp">http://www.cs.wustl.edu/~schmidt/ACE_wrappers/TAO/docs/releasenotes/index.html#pp</A><BR> + +<A HREF="http://www.cs.wustl.edu/~schmidt/PfHSN.ps.gz">http://www.cs.wustl.edu/~schmidt/PfHSN.ps.gz</A> +</BLOCKQUOTE> + +<BR> +<P>Note also that the TAO files pluggable.* are important to review and understand as they contain +the abstract classes that form the common inteface for TAO's pluggable protocol framework. +<BR> +<P>Getting a full understanding on how IIOP was implemented (GIOP over TCP/IP) and also seeing +how provisions were made to add UIOP, was very helpful to adding my own protocol. +In understanding IIOP, I needed to review the section of the OMG CORBA spec on GIOP, +IIOP and Object references and see how this would apply to my protocol. +<BR> +<P>In my case, I added a transport layer that uses SCRAMNet (from Systran Corp) replicated shared memory hardware. This is actual physical memory cards located on two different machines. When a change is made to one memory then that change appears very quickly (very low latency here) in +the other memory. I decided that I would implement GIOP over SCRAMNet as this seemed +to be the simplest. With SCRAMNet, one could implement this transport layer into the TAO ORB +in a few different ways, GIOP over SCRAMNet, Environment-specific inter-ORB protocol (ESIOP) +or using collocation (since it is shared replicated memory). I have not done the latter two, only +GIOP over SCRAMNet just to get a proof of concept working. +<BR><P> +For a graphical representation of the extensions for the new SCRAMNet classes I have may a skeletal +Rose diagram showing (at this point) the inheritance relationships of the new and existing classes. +See (TBD) ftp site for this Rose diagram. +<BR><P> +The new classes created were. +<BR> +<BLOCKQUOTE>TAO_SCRAMNet_Profile (Derived from TAO_Profile in pluggable.h)<BR> +TAO_SCRAMNet_Acceptor (Derived from TAO_Acceptor in pluggable.h) <BR> +TAO_SCRAMNet_Connector (Derived from TAO_Connector in pluggable.h)<BR> +TAO_SCRAMNet_Transport (Derived from TAO_Transport in pluggable.h) + <BLOCKQUOTE>TAO_SCRAMNet_Server_Transport<BR> + TAO_SCRAMNet_Client_Trasnport</BLOCKQUOTE><BR> +TAO_SCRAMNet_Protocol_Factory (Derived from TAO_Protocol Factory in protocol_factory.h)<BR> +TAO_SCRAMNet_Handler_Base (as in IIOP_Connect.h) + <BLOCKQUOTE>TAO_SCRAMNet_Client_Connection_Handler<BR> + TAO_SCRAMNet_Server_Connection_Handler</BLOCKQUOTE></BLOCKQUOTE><BR> + + +<BLOCKQUOTE>ACE_SCRAMNet_Addr<BR> +ACE_SCRAMNet_Acceptor<BR> +ACE_SCRAMNet_Connector<BR> +ACE_SCRAMNet_Stream</BLOCKQUOTE><BR> +<BR> +<P>I closely followed the way that IIOP and UIOP were defined and implemented in the definition and +implementation of the SCRAMNet classes. Following the existing protocol implementation was +the largest source of help for me. Being able to step through the operation of the ORB for +the IIOP protocol and then transposing that over to my protocol made the process relatively painless +and quite the learning experience. +<BR><P> +I am using TAO under Phar Lap's Embedded Tool Suite Real-Time Operating System which is an RTOS which supports a subset of the Win32 API and Winsock 1.1. Because of the new SCRAMNet transport hardware I needed to change the ORBs core reactor to a WFMO_Reactor. Any instance +of the TAO ORB can only have one reactor type or it won't work. In my case I am using +an ORB in one thread that uses the WFMO_Reactor and the SCRAMNet transport, and an ORB +in another thread that uses a Select Reactor and the IIOP protocol. +I won't go into much of the SCRAMNet specific stuff as I assume most people are interested in +adding a pluggable protocol in general. +<BR><P> + +Some specifics:<BR> For completeness, I show the whole function in some instances even though I only needed to add or change a few lines. +<BR> +1. One of the first additions I made was to GIOP.h +<BR> +// namespace TAO_IOP +<BR> +// Assigned Protocol/Profile tag values. ORB protcols may be uniquely<BR> +// identified by tags such as these. This allows each ORB's own<BR> +// objref profiles to be interchanged using IORs.<BR> +//<BR> +// Email to tag-request@omg.org to allocate tags.<BR> +typedef CORBA::ULong TAO_IOP_Profile_ID; +<BR> +enum +{ + <BLOCKQUOTE>TAO_IOP_TAG_INVALID = -1,<BR> + TAO_IOP_TAG_INTERNET_IOP = 0, // IIOP<BR> + TAO_IOP_TAG_MULTIPLE_COMPONENTS = 1, // DCE-CIOP<BR> + TAO_IOP_TAG_UNIX_IOP = TAO_TAG_UIOP_PROFILE, // Read corbafwd.h<BR> + TAO_IOP_TAG_SCRAMNET_IOP = 3, // SCRAMNET<BR> + + // = This is a subset of the list of other profile tags.<BR> + TAO_IOP_TAG_ONC_IOP = 0x4f4e4300 // ONC IOP</BLOCKQUOTE> +};<BR><P> + +I arbitrarily set the TAO_IOP_TAG_SCRAMNET = 3. Note that this value was NOT allocated to me by OMG. I used it just to get things working with the new protocol. +Adding the new tag was needed (as it says) so that the server and client could interchange IORs (which contain protocol specific information). +<BR><P> + +2. I added the following line to orbconf.h: +<BR> +// SCRAMNet support (GIOP over the SCRAMNet replicated memory transport)<BR> +#define TAO_HAS_SCRAMNET +<BR> +as I use #ifdefs in other places in the code. +<BR><P> +3. Specifically, in the file TAO_Internal.cpp: +<BR><P> +int +TAO_Internal::open_services (int &argc, +<BLOCKQUOTE><BLOCKQUOTE> char **argv,<BR> + int ignore_default_svc_conf_file,<BR> + int skip_service_config_open)</BLOCKQUOTE></BLOCKQUOTE><BR> +{<BR> +<BLOCKQUOTE>ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_RECURSIVE_MUTEX, guard, *ACE_Static_Object_Lock::instance (), -1));<BR> +#if defined (TAO_PLATFORM_SVC_CONF_FILE_NOTSUP)<BR> + ignore_default_svc_conf_file = 1;<BR> +#endif /* TAO_PLATFORM_SVC_CONF_FILE_NOTSUP */</BLOCKQUOTE><BR> + + <BLOCKQUOTE>if (TAO_Internal::service_open_count_++ == 0)<BR> + {<BR> + <BLOCKQUOTE>ACE_Service_Config::static_svcs ()->insert (&ace_svc_desc_TAO_Default_Resource_Factory);<BR> + ACE_Service_Config::static_svcs ()->insert (&ace_svc_desc_TAO_Default_Client_Strategy_Factory);<BR> + ACE_Service_Config::static_svcs ()->insert (&ace_svc_desc_TAO_Default_Server_Strategy_Factory);<BR> + ACE_Service_Config::static_svcs ()->insert (&ace_svc_desc_TAO_IIOP_Protocol_Factory);<BR> +#if defined (TAO_HAS_UIOP)<BR> + ACE_Service_Config::static_svcs ()->insert (&ace_svc_desc_TAO_UIOP_Protocol_Factory);<BR> +#endif /* TAO_HAS_UIOP */<BR> +// HAS SCRAMNET - BRT <BR> +<FONT COLOR=Blue>#if defined (TAO_HAS_SCRAMNET)<BR> + ACE_Service_Config::static_svcs ()->insert (&ace_svc_desc_TAO_SCRAMNet_Protocol_Factory);<BR> +#endif /* TAO_HAS_SCRAMNET */<BR></FONT> + // add descriptor to list of static objects.<BR> + + int result = 0;<BR> + + if (skip_service_config_open == 0)<BR> + result = ACE_Service_Config::open (argc, argv, + <BLOCKQUOTE> ACE_DEFAULT_LOGGER_KEY,<BR> + 0, // Don't ignore static services.<BR> + ignore_default_svc_conf_file);</BLOCKQUOTE><BR> + + // @@ What the heck do these things do and do we need to avoid<BR> + // calling them if we're not invoking the svc.conf file?<BR> + if (TAO_Internal::resource_factory_args_ != 0)<BR> + ACE_Service_Config::process_directive (TAO_Internal::resource_factory_args_);<BR> + if (TAO_Internal::client_strategy_args_ != 0)<BR> + ACE_Service_Config::process_directive (TAO_Internal::client_strategy_args_);<BR> + if (TAO_Internal::server_strategy_args_ != 0)<BR> + ACE_Service_Config::process_directive (TAO_Internal::server_strategy_args_);<BR> + + return result;</BLOCKQUOTE><BR> + }<BR> + else<BR> + return 0;</BLOCKQUOTE><BR> +}<BR> +<BR><P> +I added the SCRAMNet lines to insert the SCRAMNet protocol factory into the service +configurator. +<BR><P> +4. Also, in default resource.cpp: +<BR> +int<BR> +TAO_Default_Resource_Factory::init_protocol_factories (void)<BR> +{<BR> + <BLOCKQUOTE>TAO_ProtocolFactorySetItor end = protocol_factories_.end ();<BR> + TAO_ProtocolFactorySetItor factory = protocol_factories_.begin (); +<BR> + if (factory == end)<BR> + {<BR> + <BLOCKQUOTE>TAO_Protocol_Factory *protocol_factory = 0;<BR> + TAO_Protocol_Item *item = 0;<BR> + + protocol_factory = + ACE_Dynamic_Service<TAO_Protocol_Factory>::instance ("IIOP_Factory");<BR> +</BLOCKQUOTE> + <BLOCKQUOTE> if (protocol_factory == 0)<BR> + {<BR> + if (TAO_orbdebug)<BR> + ACE_ERROR ((LM_WARNING,<BR> + "TAO (%P|%t) No %s found in Service Repository. "<BR> + "Using default instance IIOP Protocol Factory.\n"));<BR> + + ACE_NEW_RETURN (protocol_factory,<BR> + TAO_IIOP_Protocol_Factory,<BR> + -1);<BR> + }<BR></BLOCKQUOTE> + + <BLOCKQUOTE> ACE_NEW_RETURN (item, TAO_Protocol_Item ("IIOP_Factory"), -1);<BR> + item->factory (protocol_factory);<BR> + + if (this->protocol_factories_.insert (item) == -1)<BR> + {<BR> + delete item;<BR> + delete protocol_factory;<BR> + + ACE_ERROR_RETURN ((LM_ERROR,<BR> + "TAO (%P|%t) Unable to add "<BR> + "<%s> to protocol factory set.\n",<BR> + item->protocol_name ().c_str ()),<BR> + -1);<BR></BLOCKQUOTE> + }<BR> + + if (TAO_debug_level > 0)<BR> + {<BLOCKQUOTE> + ACE_DEBUG ((LM_DEBUG,<BR> + "TAO (%P|%t) Loaded default protocol <IIOP_Factory>\n"));<BR></BLOCKQUOTE> + }<BR> + +#if defined (TAO_HAS_UIOP)<BR> + protocol_factory =<BR> + ACE_Dynamic_Service<TAO_Protocol_Factory>::instance ("UIOP_Factory");<BR> + + if (protocol_factory == 0)<BR> + { + <BLOCKQUOTE> if (TAO_orbdebug)<BR> + ACE_ERROR ((LM_WARNING,<BR> + "(%P|%t) WARNING - No %s found in Service Repository."<BR> + " Using default instance.\n",<BR> + "UIOP Protocol Factory"));<BR> + + ACE_NEW_RETURN (protocol_factory,<BR> + TAO_UIOP_Protocol_Factory,<BR> + -1);<BR></BLOCKQUOTE> + }<BR> + + ACE_NEW_RETURN (item, TAO_Protocol_Item ("UIOP_Factory"), -1);<BR> + item->factory (protocol_factory);<BR> + + if (this->protocol_factories_.insert (item) == -1)<BR> + { + <BLOCKQUOTE>delete item;<BR> + delete protocol_factory;<BR> + + ACE_ERROR_RETURN ((LM_ERROR,<BR> + "TAO (%P|%t) Unable to add "<BR> + "<%s> to protocol factory set.\n",<BR> + item->protocol_name ().c_str ()),<BR> + -1);</BLOCKQUOTE> + }<BR> + + if (TAO_debug_level > 0)<BR> + {<BLOCKQUOTE> + ACE_DEBUG ((LM_DEBUG,<BR> + "TAO (%P|%t) Loaded default protocol <UIOP_Factory>\n"));</BLOCKQUOTE> + }<BR> +#endif /* TAO_HAS_UIOP */<BR> +<FONT COLOR=Blue>#if defined (TAO_HAS_SCRAMNET)<BR> + protocol_factory =<BR> + ACE_Dynamic_Service<TAO_Protocol_Factory>::instance ("SCRAMNet_Factory");<BR> + + if (protocol_factory == 0)<BR> + { + <BLOCKQUOTE> if (TAO_orbdebug)<BR> + ACE_ERROR ((LM_WARNING,<BR> + "(%P|%t) WARNING - No %s found in Service Repository."<BR> + " Using default instance.\n",<BR> + "SCRAMNet Protocol Factory"));<BR> + + ACE_NEW_RETURN (protocol_factory,<BR> + TAO_SCRAMNet_Protocol_Factory,<BR> + -1);</BLOCKQUOTE> + }<BR> + + ACE_NEW_RETURN (item, TAO_Protocol_Item ("SCRAMNet_Factory"), -1);<BR> + item->factory (protocol_factory);<BR> + + if (this->protocol_factories_.insert (item) == -1)<BR> + { +<BLOCKQUOTE> delete item;<BR> + delete protocol_factory;<BR> + + ACE_ERROR_RETURN ((LM_ERROR,<BR> + "TAO (%P|%t) Unable to add "<BR> + "<%s> to protocol factory set.\n",<BR> + item->protocol_name ().c_str ()),<BR> + -1);</BLOCKQUOTE> + }<BR> + + if (TAO_debug_level > 0)<BR> + { +<BLOCKQUOTE> ACE_DEBUG ((LM_DEBUG,<BR> + "TAO (%P|%t) Loaded protocol <SCRAMNet_Factory>\n"));</BLOCKQUOTE> + }<BR> +#endif /* TAO_HAS_SCRAMNET */<BR> +</FONT> + + return 0;<BR> + }<BR> + + for (; factory != end; factory++)<BR> + { + <BLOCKQUOTE>const ACE_CString &name = (*factory)->protocol_name ();<BR> + (*factory)->factory (<BR> + ACE_Dynamic_Service<TAO_Protocol_Factory>::instance (name.c_str ()));<BR> + if ((*factory)->factory () == 0)<BR> + {<BLOCKQUOTE> + ACE_ERROR_RETURN ((LM_ERROR,<BR> + "TAO (%P|%t) Unable to load protocol <%s>, %p\n",<BR> + name.c_str (), ""),<BR> + -1);</BLOCKQUOTE> + }<BR> + + if (TAO_debug_level > 0)<BR> + { + <BLOCKQUOTE>ACE_DEBUG ((LM_DEBUG,<BR> + "TAO (%P|%t) Loaded protocol <%s>\n",<BR> + name.c_str ()));</BLOCKQUOTE> + }</BLOCKQUOTE> + }<BR> + return 0;</BLOCKQUOTE><BR> +<BR> +<BR><P> +I added the SCRAMNet lines so that the protocol is initialized correctly. Note here, +that following how IIOP and UIOP were implemented helped out. +<BR><P> + +Because I am using a WFMO Reactor and an ISR that signals particular Win32 Events, +I needed to change the registration of the service handlers. For example in Acceptor.cpp: +<BR><P> +// Initialize the appropriate strategies for creation, passive<BR> +// connection acceptance, and concurrency, and then register <this><BR> +// with the Reactor and listen for connection requests at the<BR> +// designated <local_addr>.<BR> +<BR><P> +template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1> int<BR> +ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::open<BR> + (const ACE_PEER_ACCEPTOR_ADDR &local_addr,<BR> + ACE_Reactor *reactor,<BR> + ACE_Creation_Strategy<SVC_HANDLER> *cre_s,<BR> + ACE_Accept_Strategy<SVC_HANDLER, ACE_PEER_ACCEPTOR_2> *acc_s,<BR> + ACE_Concurrency_Strategy<SVC_HANDLER> *con_s,<BR> + ACE_Scheduling_Strategy<SVC_HANDLER> *sch_s,<BR> + const ASYS_TCHAR *service_name,<BR> + const ASYS_TCHAR *service_description,<BR> + int use_select)<BR> +{<BR> +<BLOCKQUOTE>ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::open");<BR> + + if (this->service_name_ == 0 && service_name != 0) + <BLOCKQUOTE>ACE_ALLOCATOR_RETURN (this->service_name_,<BR> + ACE_OS::strdup (service_name),<BR> + -1);</BLOCKQUOTE> + if (this->service_description_ == 0 && service_description != 0)<BR> + ACE_ALLOCATOR_RETURN (this->service_description_,<BR> + ACE_OS::strdup (service_description),<BR> + -1);<BR> + this->reactor (reactor);<BR> + + // Must supply a valid Reactor to Acceptor::open()...<BR> + if (reactor == 0)<BR> + { + <BLOCKQUOTE> errno = EINVAL;<BR> + return -1;</BLOCKQUOTE> + }<BR> + + // Initialize the creation strategy.<BR> + + if (cre_s == 0)<BR> + { + <BLOCKQUOTE> ACE_NEW_RETURN (cre_s,<BR> + CREATION_STRATEGY,<BR> + -1);<BR> + this->delete_creation_strategy_ = 1;</BLOCKQUOTE> + }<BR> + this->creation_strategy_ = cre_s;<BR> + + // Initialize the accept strategy.<BR> + + if (acc_s == 0)<BR> + { + <BLOCKQUOTE>ACE_NEW_RETURN (acc_s,<BR> + ACCEPT_STRATEGY (this->reactor ()),<BR> + -1);<BR> + this->delete_accept_strategy_ = 1;</BLOCKQUOTE> + }<BR> + this->accept_strategy_ = acc_s;<BR> + + if (this->accept_strategy_->open (local_addr, 1) == -1)<BR> + return -1;<BR> + + // Initialize the concurrency strategy.<BR> + + if (con_s == 0)<BR> + { + <BLOCKQUOTE>ACE_NEW_RETURN (con_s,<BR> + CONCURRENCY_STRATEGY,<BR> + -1);<BR> + this->delete_concurrency_strategy_ = 1;</BLOCKQUOTE> + }<BR> + this->concurrency_strategy_ = con_s;<BR> + + // Initialize the scheduling strategy.<BR> + + if (sch_s == 0)<BR> + { + <BLOCKQUOTE>ACE_NEW_RETURN (sch_s,<BR> + SCHEDULING_STRATEGY,<BR> + -1);<BR> + this->delete_scheduling_strategy_ = 1;</BLOCKQUOTE> + }<BR> + this->scheduling_strategy_ = sch_s;<BR> + + this->use_select_ = use_select;<BR> + +<FONT COLOR=Blue>//BRT<BR> +#ifdef ACE_HAS_SCRAMNET<BR> + return this->reactor ()->register_handler(this, accept_event2);<BR> +#else<BR> + return this->reactor ()->register_handler(this,<BR> + ACE_Event_Handler::ACCEPT_MASK);<BR> +#endif</BLOCKQUOTE><BR></FONT> +}<BR> +<BR><P> +I needed to associate the acceptor with a Win32 event. + +<BR><P> + +5. In OS.h include the following lines: +<BR><P> +// Handle ACE_SCRAMNet*<BR> +# define ACE_SCRAMNET_ACCEPTOR ACE_SCRAMNet_Acceptor, ACE_SCRAMNet_Addr<BR> +# define ACE_SCRAMNET_CONNECTOR ACE_SCRAMNet_Connector, ACE_SCRAMNet_Addr<BR> +# define ACE_SCRAMNET_STREAM ACE_SCRAMNet_Stream, ACE_SCRAMNet_Addr<BR> +<BR><P> + +RE: IORs<BR> +I found that I needed to have a full understanding of what the exact contents of +a TAO-created IOR were as I needed to be able to understand how to decode the +location information that was now written in the IOR with the SCRAMNet +specific information. Decoding of the preconnect and endpoint info is important. +The endpoint info both in the command line arguments and in the IOR are different +for the each protocol and so your implemention of the new classes has to parse this +information correctly. +<BR><P> +In order to create the ORB with the Win32 Reactor at the core as well as the +SCRAMNet protocol factory loaded and initialize I needed to use the +svc.conf file with the the following options + -ORBReactorType wfmo +-ORBProtocolFactory SCRAMNet_Factory +<BR><P> + +Beyond the above, I just traced through the operation of the IIOP +protocol in action to see exactly where I needed to just graft on the +new ACE_SCRAMNet classes, the TAO_SCRAMNet classes and their +associated implementations for send and recv so that the SCRAMNet +hardware was used as the transport and not the ethernet hardware. +Questions, comments, changes are welcome. I can be reached at <A +HREF="mailto:btrask@contactsystems.com">btrask@contactsystems.com</A> + +<P> +<HR> +<P> + +<H1><A NAME="SECTION400"> +Using a Pluggable Protocol</A> +</H1> + +<P> +Once a TAO pluggable protocol is implemented, the ORB is told to load it by +adding entries to a <TT>Service Configurator</TT> configuration file (e.g. <TT>svc.conf</TT> +for that protocol. A typical <TT>svc.conf</TT> file could contain entries such +as the following: + +<P> + +<DL COMPACT> +<DT> +<DD><dynamic FOOIOP_Factory Service_Object * TAO_FOO:_make_TAO_FOOIOP_Protocol_Factory() "" +<BR> +static Resource_Factory "-ORBProtocolFactory FOOIOP_Factory" +<P> +</DD> +</DL>These entries would cause a pluggable protocol called ``FOOIOP'' to be loaded +into the ORB. By default the IIOP and UIOP (if supported) pluggable protocols +are loaded into TAO if no such entries are provided. Explicitly specifying which +protocols to load in this way prevents any pluggable protocols from being loaded +by default. Multiple pluggable protocols can be loaded simply by adding more +<TT>Service Configurator</TT> configuration file entries. For example, the following +entries would cause the TAO's IIOP and the fictional FOOIOP pluggable protocols +to be loaded: + +<P> + +<DL COMPACT> +<DT> +<DD>dynamic FOOIOP_Factory Service_Object * TAO_FOO:_make_TAO_FOOIOP_Protocol_Factory() "" +<BR> +static Resource_Factory "-ORBProtocolFactory FOOIOP_Factory" +<BR> +dynamic IIOP_Factory Service_Object * TAO:_make_TAO_IIOP_Protocol_Factory() "" +<BR> +static Resource_Factory "-ORBProtocolFactory IIOP_Factory" +<P> +</DD> +</DL>In this case, TAO's UIOP pluggable protocol would <I>not</I> be loaded. + +<P> +Note that the FOOIOP protocol resides in a library other than the TAO library, +called ``<TT>libTAO_FOO.so</TT>'' on UNIX platforms, and ``<TT>TAO_FOO.dll</TT>'' +on Win32 platforms. This ability to dynamically load pluggable protocols in +libraries that are completely separate libraries from the TAO library truly +makes TAO's pluggable protocol framework ``pluggable.'' + +<P> +Creating an endpoint specific to a given pluggable protocol is simply a matter +of using TAO's <TT>-ORBEndpoint</TT> ORB option. This is detailed in the documentation +for the <TT>open</TT> and <TT>open_default</TT> methods in the <TT>Acceptor</TT> +section of this document. Once an endpoint is created, the client uses the IOR +that points to the object on that endpoint to make requests on that object. + +<P> +<HR> +<P> + +<H2><A NAME="SECTION500"> +Bibliography</A> +</H2><DL COMPACT><DD><P></P><DT><A NAME="Schmidt:97c">1</A> +<DD> +D. C. Schmidt, ``Acceptor and Connector: Design Patterns for Initializing + Communication Services,'' in <EM> Pattern Languages of Program Design</EM> + (R. Martin, F. Buschmann, and D. Riehle, eds.), Reading, MA: Addison-Wesley, + 1997. + +<P></P><DT><A NAME="Schmidt:94k">2</A> +<DD> +D. C. Schmidt and T. Suda, ``An Object-Oriented Framework for Dynamically + Configuring Extensible Distributed Communication Systems,'' <EM> IEE/BCS + Distributed Systems Engineering Journal (Special Issue on Configurable + Distributed Systems)</EM>, vol. 2, pp. 280-293, December 1994. + +<P></P><DT><A NAME="Johnson:95a">3</A> +<DD> +H. Hueni, R. Johnson, and R. Engel, ``A Framework for Network Protocol + Software,'' in <EM> Proceedings of OOPSLA '95</EM>, (Austin, Texas), ACM, + October 1995. + +<P></P><DT><A NAME="Buschmann:95b">4</A> +<DD> +F. Buschmann, R. Meunier, H. Rohnert, P. Sommerlad, and M. Stal, <EM> Pattern-Oriented Software Architecture - A System of Patterns</EM>. +<BR>Wiley and Sons, 1996. +</DL> + +<P> + +<HR><H4>Footnotes</H4> +<DL> +<DT><A NAME="foot549">... abstraction.</A><A NAME="foot549" + HREF="pluggable_protocols.html#tex2html5"><SUP>1</SUP></A> +<DD>Protocol stacks based on the Internet or ISO OSI reference models are common +examples of the Layers architecture. + + +</DL><HR> + <ADDRESS><a href="mailto:othman@cs.wustl.edu">Ossama Othman</a></ADDRESS> +<!-- Created: Tue Dec 14 16:53:58 CST 1999 --> +<!-- hhmts start --> +Last modified: Thu Dec 16 14:30:33 CST 1999 +<!-- hhmts end --> +</BODY> +</HTML> diff --git a/TAO/docs/pluggable_protocols/pluggable_protocols.css b/TAO/docs/pluggable_protocols/pluggable_protocols.css new file mode 100644 index 00000000000..1993b851311 --- /dev/null +++ b/TAO/docs/pluggable_protocols/pluggable_protocols.css @@ -0,0 +1,31 @@ + +/* Century Schoolbook font is very similar to Computer Modern Math: cmmi */ +.MATH { font-family: "Century Schoolbook", serif; } +.MATH I { font-family: "Century Schoolbook", serif; font-shape: italic } +.BOLDMATH { font-family: "Century Schoolbook", serif; font-weight: bold } + +/* implement both fixed-size and relative sizes */ +SMALL.XTINY { font-size : xx-small } +SMALL.TINY { font-size : x-small } +SMALL.SCRIPTSIZE { font-size : smaller } +SMALL.FOOTNOTESIZE { font-size : small } +SMALL.SMALL { } +BIG.LARGE { } +BIG.XLARGE { font-size : large } +BIG.XXLARGE { font-size : x-large } +BIG.HUGE { font-size : larger } +BIG.XHUGE { font-size : xx-large } + +/* heading styles */ +H1 { } +H2 { } +H3 { } +H4 { } +H5 { } + +/* mathematics styles */ +DIV.displaymath { } /* math displays */ +TD.eqno { } /* equation-number cells */ + + +/* document-specific styles come next */ |