diff options
Diffstat (limited to 'TAO/tao/Transport_Connector.cpp')
-rw-r--r-- | TAO/tao/Transport_Connector.cpp | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/TAO/tao/Transport_Connector.cpp b/TAO/tao/Transport_Connector.cpp new file mode 100644 index 00000000000..6cb3dc997bd --- /dev/null +++ b/TAO/tao/Transport_Connector.cpp @@ -0,0 +1,236 @@ +#include "Transport_Connector.h" +#include "Transport.h" +#include "ORB_Core.h" +#include "Invocation.h" +#include "MProfile.h" +#include "Profile.h" +#include "Environment.h" +#include "Thread_Lane_Resources.h" +#include "debug.h" + + +#if !defined (__ACE_INLINE__) +# include "Transport_Connector.inl" +#endif /* __ACE_INLINE__ */ + + +ACE_RCSID (tao, + Connector, + "$Id$") + +// Connector +TAO_Connector::TAO_Connector (CORBA::ULong tag) + : tag_(tag), + orb_core_ (0) +{ +} + +TAO_Connector::~TAO_Connector (void) +{ +} + +int +TAO_Connector::make_mprofile (const char *string, + TAO_MProfile &mprofile + ACE_ENV_ARG_DECL) +{ + // This method utilizes the "Template Method" design pattern to + // parse the given URL style IOR for the protocol being used + // and create an mprofile from it. + // + // The methods that must be defined by all Connector sub-classes are: + // make_profile + // check_prefix + + // Check for a valid string + if (!string || !*string) + { + ACE_THROW_RETURN (CORBA::INV_OBJREF ( + CORBA_SystemException::_tao_minor_code ( + TAO_DEFAULT_MINOR_CODE, + EINVAL), + CORBA::COMPLETED_NO), + -1); + } + + // Check for the proper prefix in the IOR. If the proper prefix isn't + // in the IOR then it is not an IOR we can use. + if (this->check_prefix (string) != 0) + { + return 1; + // Failure: not the correct IOR for this protocol. + // DO NOT throw an exception here since the Connector_Registry + // should be allowed the opportunity to continue looking for + // an appropriate connector. + } + + if (TAO_debug_level > 0) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - TAO_Connector::make_mprofile ") + ACE_TEXT ("<%s>\n"), + string)); + } + + ACE_CString ior; + + ior.set (string, ACE_OS::strlen (string), 1); + + // Find out where the protocol ends + int ior_index = ior.find ("://"); + + if (ior_index == ACE_CString::npos) + { + ACE_THROW_RETURN (CORBA::INV_OBJREF (), -1); + // No colon ':' in the IOR! + } + else + { + ior_index += 3; + // Add the length of the colon and the two forward slashes `://' + // to the IOR string index (i.e. 3) + } + + // Find the object key + const int objkey_index = + ior.find (this->object_key_delimiter (), ior_index); + + if (objkey_index == 0 || objkey_index == ACE_CString::npos) + { + ACE_THROW_RETURN (CORBA::INV_OBJREF (), -1); + // Failure: No endpoints specified or no object key specified. + } + + const char endpoint_delimiter = ','; + // The delimiter used to seperate inidividual addresses. + + // Count the number of endpoints in the IOR. This will be the number + // of entries in the MProfile. + + CORBA::ULong profile_count = 1; + // Number of endpoints in the IOR (initialized to 1). + + // Only check for endpoints after the protocol specification and + // before the object key. + for (int i = ior_index; i < objkey_index; ++i) + { + if (ior[i] == endpoint_delimiter) + profile_count++; + } + + // Tell the MProfile object how many Profiles it should hold. + // MProfile::set(size) returns the number profiles it can hold. + if (mprofile.set (profile_count) != ACE_static_cast (int, profile_count)) + { + ACE_THROW_RETURN (CORBA::INV_OBJREF ( + CORBA_SystemException::_tao_minor_code ( + TAO_MPROFILE_CREATION_ERROR, + 0), + CORBA::COMPLETED_NO), + -1); + // Error while setting the MProfile size! + } + + // The idea behind the following loop is to split the IOR into several + // strings that can be parsed by each profile. + // For example, + // `1.3@moo,shu,1.1@chicken/arf' + // will be parsed into: + // `1.3@moo/arf' + // `shu/arf' + // `1.1@chicken/arf' + + int begin = 0; + int end = ior_index - 1; + // Initialize the end of the endpoint index + + for (CORBA::ULong j = 0; j < profile_count; ++j) + { + begin = end + 1; + + if (j < profile_count - 1) + end = ior.find (endpoint_delimiter, begin); + else + end = objkey_index; // Handle last endpoint differently + + if (end < ACE_static_cast (int, ior.length ()) && end != ior.npos) + { + ACE_CString endpoint = ior.substring (begin, end - begin); + + // Add the object key to the string. + endpoint += ior.substring (objkey_index); + + // The endpoint should now be of the form: + // `N.n@endpoint/object_key' + // or + // `endpoint/object_key' + + TAO_Profile *profile = + this->make_profile (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + // Failure: Problem during profile creation + + // Initialize a Profile using the individual endpoint + // string. + // @@ Not exception safe! We need a TAO_Profile_var! + profile->parse_string (endpoint.c_str () + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Give up ownership of the profile. + if (mprofile.give_profile (profile) == -1) + { + profile->_decr_refcnt (); + + ACE_THROW_RETURN (CORBA::INV_OBJREF ( + CORBA_SystemException::_tao_minor_code ( + TAO_MPROFILE_CREATION_ERROR, + 0), + CORBA::COMPLETED_NO), + -1); + // Failure presumably only occurs when MProfile is full! + // This should never happen. + } + } + else + { + ACE_THROW_RETURN (CORBA::INV_OBJREF (), -1); + // Unable to seperate endpoints + } + } + + return 0; // Success +} + +int +TAO_Connector::connect (TAO_GIOP_Invocation *invocation, + TAO_Transport_Descriptor_Interface *desc + ACE_ENV_ARG_DECL_NOT_USED) +{ + TAO_Transport *base_transport = 0; + + // Check the Cache first for connections + // If transport found, reference count is incremented on assignment + if (this->orb_core ()->lane_resources ().transport_cache ().find_transport (desc, + base_transport) == 0) + { + if (TAO_debug_level > 2) + ACE_DEBUG ((LM_DEBUG, + ACE_LIB_TEXT ("(%P|%t) IIOP_Connector::connect - ") + ACE_LIB_TEXT ("got an existing transport with id %d\n"), + base_transport->id ())); + + TAO_Transport *&transport = invocation->transport (); + + // No need to _duplicate and release since base_transport + // is going out of scope. Transport now has control of + // base_transport. + transport = base_transport; + + // Succesful + return 0; + } + + return this->make_connect (invocation, + desc); +} |