diff options
Diffstat (limited to 'TAO/tao/PortableGroup/UIPMC_Profile.cpp')
-rw-r--r-- | TAO/tao/PortableGroup/UIPMC_Profile.cpp | 736 |
1 files changed, 736 insertions, 0 deletions
diff --git a/TAO/tao/PortableGroup/UIPMC_Profile.cpp b/TAO/tao/PortableGroup/UIPMC_Profile.cpp new file mode 100644 index 00000000000..98e590db8f4 --- /dev/null +++ b/TAO/tao/PortableGroup/UIPMC_Profile.cpp @@ -0,0 +1,736 @@ +// This may look like C, but it's really -*- C++ -*- +// $Id$ + + +#include "UIPMC_Profile.h" +#include "tao/CDR.h" +#include "tao/Environment.h" +#include "tao/ORB.h" +#include "tao/ORB_Core.h" +#include "tao/debug.h" +#include "target_specification.h" + +#include "miopC.h" +#include "PortableGroupC.h" + +ACE_RCSID(tao, UIPMC_Profile, "$Id$") + +#if !defined (__ACE_INLINE__) +# include "UIPMC_Profile.i" +#endif /* __ACE_INLINE__ */ + +static const char prefix_[] = "uipmc"; + +const char TAO_UIPMC_Profile::object_key_delimiter_ = '/'; + +char +TAO_UIPMC_Profile::object_key_delimiter (void) const +{ + return TAO_UIPMC_Profile::object_key_delimiter_; +} + + +TAO_UIPMC_Profile::TAO_UIPMC_Profile (TAO_ORB_Core *orb_core) + : TAO_Profile (TAO_TAG_UIPMC_PROFILE, + orb_core, + TAO_GIOP_Version (TAO_DEF_GIOP_MAJOR, TAO_DEF_GIOP_MINOR)), + endpoint_ (), + count_ (1), + tagged_profile_ () +{ +} + +TAO_UIPMC_Profile::TAO_UIPMC_Profile (const ACE_INET_Addr &addr, + TAO_ORB_Core *orb_core) + : TAO_Profile (TAO_TAG_UIPMC_PROFILE, + orb_core, + TAO_GIOP_Version (TAO_DEF_GIOP_MAJOR, TAO_DEF_GIOP_MINOR)), + endpoint_ (addr), + count_ (1), + tagged_profile_ () +{ +} + +TAO_UIPMC_Profile::TAO_UIPMC_Profile (const CORBA::Octet class_d_address[4], + CORBA::UShort port, + TAO_ORB_Core *orb_core) + : TAO_Profile (TAO_TAG_UIPMC_PROFILE, + orb_core, + TAO_GIOP_Version (TAO_DEF_GIOP_MAJOR, TAO_DEF_GIOP_MINOR)), + endpoint_ (class_d_address, port), + count_ (1), + tagged_profile_ () +{ +} + +/* + +TAO_UIPMC_Profile::TAO_UIPMC_Profile (const char *string, + TAO_ORB_Core *orb_core, + CORBA::Environment &ACE_TRY_ENV) + : TAO_Profile (TAO_TAG_UIPMC_PROFILE, + orb_core, + TAO_GIOP_Version (TAO_DEF_GIOP_MAJOR, TAO_DEF_GIOP_MINOR)), + endpoint_ (), + count_ (1), + tagged_profile_ () +{ + this->add_group_component (); + this->parse_string (string, ACE_TRY_ENV); + ACE_CHECK; +} + +TAO_UIPMC_Profile::TAO_UIPMC_Profile (TAO_ORB_Core *orb_core) + : TAO_Profile (TAO_TAG_UIPMC_PROFILE, + orb_core, + TAO_GIOP_Version (TAO_DEF_GIOP_MAJOR, TAO_DEF_GIOP_MINOR)), + endpoint_ (), + count_ (1), + tagged_profile_ () +{ +} +*/ + +TAO_UIPMC_Profile::~TAO_UIPMC_Profile (void) +{ +} + +// return codes: +// -1 -> error +// 0 -> can't understand this version +// 1 -> success. + +int +TAO_UIPMC_Profile::decode (TAO_InputCDR& cdr) +{ + CORBA::ULong encap_len = cdr.length (); + + // Read and verify major, minor versions, ignoring UIPMC profiles + // whose versions we don't understand. + CORBA::Octet major = 0, minor = 0; + + if (!(cdr.read_octet (major) + && major == TAO_DEF_MIOP_MAJOR + && cdr.read_octet (minor))) + { + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) UIPMC_Profile::decode - v%d.%d\n"), + major, + minor)); + return -1; + } + + this->version_.major = major; + + if (minor <= TAO_DEF_MIOP_MINOR) + this->version_.minor = minor; + + // Decode endpoint. + CORBA::Short ip_version; + if (!(cdr.read_short (ip_version) + && ip_version == MIOP::IPv4)) + { + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) UIPMC_Profile::decode - Unexpected IP version %d\n"), + ip_version)); + return -1; + } + + /* Read in the IPv4 port and address */ + if (cdr.read_ushort (this->endpoint_.port_) == 0 + || cdr.read_octet_array (this->endpoint_.class_d_address_, 4) == 0) + { + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) UIPMC_Profile::decode - ") + ACE_TEXT ("error while decoding host/port"))); + return -1; + } + + if (this->tagged_components_.decode (cdr) == 0) + return -1; + + if (cdr.length () != 0 && TAO_debug_level) + // If there is extra data in the profile we are supposed to + // ignore it, but print a warning just in case... + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("%d bytes out of %d left after UIPMC profile data\n"), + cdr.length (), + encap_len)); + + if (cdr.good_bit ()) + { + // Tell the endpoint to update its cached address. @@ Frank: Fix this smelly piece of code! + this->endpoint_.update_object_addr (); + + return 1; + } + + return -1; +} + + +void +TAO_UIPMC_Profile::parse_string (const char * /*string*/, + CORBA::Environment &ACE_TRY_ENV) +{ + ACE_THROW (CORBA::INV_OBJREF ( + CORBA_SystemException::_tao_minor_code ( + TAO_DEFAULT_MINOR_CODE, + EINVAL), + CORBA::COMPLETED_NO)); + +/* + // Remove the "N.n@" version prefix, if it exists, and verify the + // version is one that we accept. + + // Check for version + if (isdigit (string [0]) && + string[1] == '.' && + isdigit (string [2]) && + string[3] == '@') + { + // @@ This may fail for non-ascii character sets [but take that + // with a grain of salt] + this->version_.set_version ((char) (string [0] - '0'), + (char) (string [2] - '0')); + string += 4; + // Skip over the "N.n@" + } + + if (this->version_.major != TAO_DEF_GIOP_MAJOR || + this->version_.minor > TAO_DEF_GIOP_MINOR) + { + ACE_THROW_RETURN (CORBA::INV_OBJREF ( + CORBA_SystemException::_tao_minor_code ( + TAO_DEFAULT_MINOR_CODE, + EINVAL), + CORBA::COMPLETED_NO), + -1); + } + + // Pull off the "hostname:port/" part of the objref + // Copy the string because we are going to modify it... + CORBA::String_var copy (string); + + char *start = copy.inout (); + char *cp_pos = ACE_OS::strchr (start, ':'); // Look for a port + + char *okd = ACE_OS::strchr (start, this->object_key_delimiter_); + + if (okd == 0) + { + // No object key delimiter! + ACE_THROW_RETURN (CORBA::INV_OBJREF ( + CORBA_SystemException::_tao_minor_code ( + TAO_DEFAULT_MINOR_CODE, + EINVAL), + CORBA::COMPLETED_NO), + -1); + } + + // The default port number. + const char def_port [] = ":683"; + + // Length of port. + CORBA::ULong length = 0; + + // Length of host string. + CORBA::ULong length_host = 0; + + // Length of <cp> + CORBA::ULong length_cp = + ACE_OS::strlen ((const char *)okd) + sizeof (def_port); + + CORBA::String_var cp = CORBA::string_alloc (length_cp); + + if (cp_pos == 0) + { + // No host/port delimiter! Dont raise an exception. Use the + // default port No. 683 + ACE_OS::strcpy (cp, def_port); + ACE_OS::strcat (cp, okd); + + length = + ACE_OS::strlen (cp.in ()) - + ACE_OS::strlen ((const char *)okd) - + 1; + + length_host = + ACE_OS::strlen (start) + + sizeof (def_port) - + ACE_OS::strlen (cp.in ()) -1; + } + else + { + // The port is specified: + cp = (const char *)cp_pos; + + length = + ACE_OS::strlen (cp.in ()) + - ACE_OS::strlen ((const char *)okd) + 1; + + length_host = + ACE_OS::strlen ((const char *)start) + - ACE_OS::strlen (cp.in ()); + } + + CORBA::String_var tmp = CORBA::string_alloc (length); + + ACE_OS::strncpy (tmp.inout (), cp.in () + 1, length); + tmp[length] = '\0'; + + this->endpoint_.port_ = (CORBA::UShort) ACE_OS::atoi (tmp.in ()); + + tmp = CORBA::string_alloc (length_host); + + ACE_OS::strncpy (tmp.inout (), start, length_host); + tmp[length_host] = '\0'; + + this->endpoint_.host_ = tmp._retn (); + + ACE_INET_Addr host_addr; + + if (ACE_OS::strcmp (this->endpoint_.host_.in (), "") == 0) + { + char tmp_host [MAXHOSTNAMELEN + 1]; + + // If no host is specified: assign the default host : the local host. + if (host_addr.get_host_name (tmp_host, + sizeof (tmp_host)) != 0) + { + const char *tmp = host_addr.get_host_addr (); + if (tmp == 0) + { + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("\n\nTAO (%P|%t) ") + ACE_TEXT ("UIPMC_Profile::parse_string ") + ACE_TEXT ("- %p\n\n"), + ACE_TEXT ("cannot determine hostname"))); + return -1; + } + this->endpoint_.host_ = tmp; + } + else + { + this->endpoint_.host_ = (const char *) tmp_host; + } + } + + if (this->endpoint_.object_addr_.set (this->endpoint_.port_, + this->endpoint_.host_.in ()) == -1) + { + if (TAO_debug_level > 0) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("%p\n"), + ACE_TEXT ("Error Occured !") + ACE_TEXT ("TAO (%P|%t) UIPMC_Profile::parse_string - \n") + ACE_TEXT ("TAO (%P|%t) ACE_INET_Addr::set () failed"))); + } + return -1; + } + + start = ++okd; // increment past the object key separator + + TAO_ObjectKey::decode_string_to_sequence (this->object_key_, start); + + return 1; +*/ +} + +CORBA::Boolean +TAO_UIPMC_Profile::is_equivalent (const TAO_Profile *other_profile) +{ + + if (other_profile->tag () != TAO_TAG_UIPMC_PROFILE) + return 0; + + const TAO_UIPMC_Profile *op = + ACE_dynamic_cast (const TAO_UIPMC_Profile *, other_profile); + + if (!(this->version_ == op->version_ + && this->endpoint_.is_equivalent (&op->endpoint_))) + return 0; + + return 1; +} + +CORBA::ULong +TAO_UIPMC_Profile::hash (CORBA::ULong max, + CORBA::Environment &) +{ + // Get the hashvalue for all endpoints. + CORBA::ULong hashval = this->endpoint_.hash (); + + hashval += this->version_.minor; + hashval += this->tag (); + + return hashval % max; +} + +TAO_Endpoint* +TAO_UIPMC_Profile::endpoint (void) +{ + return &this->endpoint_; +} + +int +TAO_UIPMC_Profile::encode_endpoints (void) +{ + return 1; +} + +size_t +TAO_UIPMC_Profile::endpoint_count (void) +{ + return 1; +} + +char * +TAO_UIPMC_Profile::to_string (CORBA::Environment &) +{ + // @@ Frank: Update to pull out GroupID information... + + u_int buflen = (ACE_OS::strlen (::prefix_) + + 3 /* "loc" */ + + 1 /* colon separator */ + + 2 /* double-slash separator */ + + 1 /* major version */ + + 1 /* decimal point */ + + 1 /* minor version */ + + 1 /* `@' character */ + + 15 /* dotted decimal IPv4 address */ + + 1 /* colon separator */ + + 5 /* port number */); + + char * buf = CORBA::string_alloc (buflen); + + static const char digits [] = "0123456789"; + + ACE_OS::sprintf (buf, + "%sloc://%c.%c@%d.%d.%d.%d:%d%c%s", + ::prefix_, + digits [this->version_.major], + digits [this->version_.minor], + this->endpoint_.class_d_address_[0], + this->endpoint_.class_d_address_[1], + this->endpoint_.class_d_address_[2], + this->endpoint_.class_d_address_[3], + this->endpoint_.port ()); + return buf; +} + +const char * +TAO_UIPMC_Profile::prefix (void) +{ + return ::prefix_; +} + +int +TAO_UIPMC_Profile::encode (TAO_OutputCDR &stream) const +{ + // UNSIGNED LONG, protocol tag + stream.write_ulong (this->tag ()); + + // Create the encapsulation.... + TAO_OutputCDR encap (ACE_CDR::DEFAULT_BUFSIZE, + TAO_ENCAP_BYTE_ORDER, + this->orb_core ()->output_cdr_buffer_allocator (), + this->orb_core ()->output_cdr_dblock_allocator (), + this->orb_core ()->orb_params ()->cdr_memcpy_tradeoff (), + this->orb_core ()->to_iso8859 (), + this->orb_core ()->to_unicode ()); + + + // Create the profile body + this->create_profile_body (encap); + + // write the encapsulation as an octet sequence... + + stream << CORBA::ULong (encap.total_length ()); + stream.write_octet_array_mb (encap.begin ()); + + return 1; +} + + +IOP::TaggedProfile & +TAO_UIPMC_Profile::create_tagged_profile (void) +{ + // Check whether we have already created the TaggedProfile + if (this->tagged_profile_.profile_data.length () == 0) + { + // As we have not created we will now create the TaggedProfile + this->tagged_profile_.tag = TAO_TAG_UIPMC_PROFILE; + + // Create the encapsulation.... + TAO_OutputCDR encap (ACE_CDR::DEFAULT_BUFSIZE, + TAO_ENCAP_BYTE_ORDER, + this->orb_core ()->output_cdr_buffer_allocator (), + this->orb_core ()->output_cdr_dblock_allocator (), + this->orb_core ()->orb_params ()->cdr_memcpy_tradeoff (), + this->orb_core ()->to_iso8859 (), + this->orb_core ()->to_unicode ()); + + // Create the profile body + this->create_profile_body (encap); + + CORBA::ULong length = + ACE_static_cast(CORBA::ULong,encap.total_length ()); + +#if (TAO_NO_COPY_OCTET_SEQUENCES == 1) + // Place the message block in to the Sequence of Octets that we + // have + this->tagged_profile_.profile_data.replace (length, + encap.begin ()); +#else + this->tagged_profile_.profile_data.length (length); + CORBA::Octet *buffer = + this->tagged_profile_.profile_data.get_buffer (); + for (const ACE_Message_Block *i = encap.begin (); + i != encap.end (); + i = i->next ()) + { + ACE_OS::memcpy (buffer, i->rd_ptr (), i->length ()); + buffer += i->length (); + } +#endif /* TAO_NO_COPY_OCTET_SEQUENCES == 1 */ + } + + return this->tagged_profile_; +} + +void +TAO_UIPMC_Profile::create_profile_body (TAO_OutputCDR &encap) const +{ + encap.write_octet (TAO_ENCAP_BYTE_ORDER); + + // The GIOP version + // Note: Only GIOP 1.2 and above are supported currently for MIOP. + encap.write_octet (this->version_.major); + encap.write_octet (this->version_.minor); + + // IP Version. + encap.write_short (MIOP::IPv4); + + // The IPv4 port number. + encap.write_ushort (this->endpoint_.port ()); + + // The IPv4 multicast address (MSB first). + encap.write_octet_array (this->endpoint_.class_d_address_, 4); + + // UIPMC is only supported by versions of GIOP that have tagged components, + // so unconditionally encode the components. + this->tagged_components ().encode (encap); +} + +/* +int +TAO_UIPMC_Profile::decode_endpoints (void) +{ + IOP::TaggedComponent tagged_component; + tagged_component.tag = TAO_TAG_ENDPOINTS; + + if (this->tagged_components_.get_component (tagged_component)) + { + const CORBA::Octet *buf = + tagged_component.component_data.get_buffer (); + + TAO_InputCDR in_cdr (ACE_reinterpret_cast (const char*, buf), + tagged_component.component_data.length ()); + + // Extract the Byte Order. + CORBA::Boolean byte_order; + if ((in_cdr >> ACE_InputCDR::to_boolean (byte_order)) == 0) + return -1; + in_cdr.reset_byte_order (ACE_static_cast(int, byte_order)); + + // Extract endpoints sequence. + TAO_UIPMCEndpointSequence endpoints; + + if ((in_cdr >> endpoints) == 0) + return -1; + + // Get the priority of the first endpoint (head of the list. + // It's other data is extracted as part of the standard profile + // decoding. + this->endpoint_.priority (endpoints[0].priority); + + // Use information extracted from the tagged component to + // populate the profile. Skip the first endpoint, since it is + // always extracted through standard profile body. Also, begin + // from the end of the sequence to preserve endpoint order, + // since <add_endpoint> method reverses the order of endpoints + // in the list. + for (CORBA::ULong i = endpoints.length () - 1; + i > 0; + --i) + { + TAO_UIPMC_Endpoint *endpoint = 0; + ACE_NEW_RETURN (endpoint, + TAO_UIPMC_Endpoint (endpoints[i].host, + endpoints[i].port, + endpoints[i].priority), + -1); + + this->add_endpoint (endpoint); + } + } + + return 0; +} +*/ + +int +TAO_UIPMC_Profile::add_group_component (const char *domain_id, + PortableGroup::ObjectGroupId group_id, + PortableGroup::ObjectGroupRefVersion ref_version) +{ + PortableGroup::TagGroupTaggedComponent group; + + // Encode the data structure. + group.version.major = TAO_DEF_MIOP_MAJOR; + group.version.minor = TAO_DEF_MIOP_MINOR; + + group.group_domain_id = CORBA::string_dup (domain_id); + group.object_group_id = group_id; + group.object_group_ref_version = ref_version; + + TAO_OutputCDR out_cdr; + if ((out_cdr << group) == 0) + return -1; + CORBA::ULong length = out_cdr.total_length (); + + IOP::TaggedComponent tagged_component; + tagged_component.tag = TAO_TAG_GROUP; + tagged_component.component_data.length (length); + CORBA::Octet *buf = + tagged_component.component_data.get_buffer (); + + for (const ACE_Message_Block *iterator = out_cdr.begin (); + iterator != 0; + iterator = iterator->cont ()) + { + CORBA::ULong i_length = iterator->length (); + ACE_OS::memcpy (buf, iterator->rd_ptr (), i_length); + + buf += i_length; + } + + // Add component with encoded endpoint data to this profile's + // TaggedComponents. + this->tagged_components_.set_component (tagged_component); + return 0; +} + +void +TAO_UIPMC_Profile::request_target_specifier (TAO_Target_Specification &target_spec) +{ + // Point the target specifier to our Tagged Profile + target_spec.target_specifier (this->create_tagged_profile ()); +} + +int +TAO_UIPMC_Profile::supports_multicast (void) const +{ + // Yes! We support multicast! + return 1; +} + +int +TAO_UIPMC_Profile::extract_group_component (IOP::TaggedProfile &profile, + PortableGroup::TagGroupTaggedComponent &group) +{ + // Create the decoding stream from the encapsulation in the buffer, +#if (TAO_NO_COPY_OCTET_SEQUENCES == 1) + TAO_InputCDR cdr (profile.profile_data.mb ()); +#else + TAO_InputCDR cdr (ACE_reinterpret_cast(char*,profile.profile_data.get_buffer ()), + profile.profile_data.length ()); +#endif /* TAO_NO_COPY_OCTET_SEQUENCES == 1 */ + + CORBA::ULong encap_len = cdr.length (); + + // Extract the Byte Order. + CORBA::Boolean byte_order; + if ((cdr >> ACE_InputCDR::to_boolean (byte_order)) == 0) + return -1; + cdr.reset_byte_order (ACE_static_cast(int, byte_order)); + + // Read and verify major, minor versions, ignoring UIPMC profiles + // whose versions we don't understand. + CORBA::Octet major, minor; + + // Read the version. We just read it here. We don't*do any* + // processing. + if (!(cdr.read_octet (major) + && cdr.read_octet (minor))) + { + if (TAO_debug_level > 0) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) UIPMC_Profile::decode - v%d.%d\n"), + major, + minor)); + } + return -1; + } + + // Decode endpoint. + CORBA::Short ip_version; + if (!(cdr.read_short (ip_version) + && ip_version == MIOP::IPv4)) + { + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) UIPMC_Profile::decode - Unexpected IP version %d\n"), + ip_version)); + return -1; + } + + CORBA::Octet class_d_address_[4]; + CORBA::UShort port_; + + /* Read in the IPv4 port and address */ + if (cdr.read_ushort (port_) == 0 + || cdr.read_octet_array (class_d_address_, 4) == 0) + { + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) UIPMC_Profile::decode - ") + ACE_TEXT ("error while decoding host/port"))); + return -1; + } + + TAO_Tagged_Components tagged_components; + if (tagged_components.decode (cdr) == 0) + return -1; + + IOP::TaggedComponent tagged_component; + tagged_component.tag = TAO_TAG_GROUP; + + // Try to find it. + if (tagged_components.get_component (tagged_component) == 0) + return -1; + + // Found it. + const CORBA::Octet *buf = + tagged_component.component_data.get_buffer (); + + TAO_InputCDR in_cdr (ACE_reinterpret_cast (const char*, buf), + tagged_component.component_data.length ()); + + // Extract the Byte Order. + if ((in_cdr >> ACE_InputCDR::to_boolean (byte_order)) == 0) + return -1; + in_cdr.reset_byte_order (ACE_static_cast(int, byte_order)); + + if ((in_cdr >> group) == 0) + return -1; + + return 0; +} |