diff options
author | fhunleth <fhunleth@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2001-07-03 23:53:23 +0000 |
---|---|---|
committer | fhunleth <fhunleth@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2001-07-03 23:53:23 +0000 |
commit | 90b1277ac1378475a80fdc189fc590204250defc (patch) | |
tree | 0e2aaed80c78b3013593d0465f5963e2100d404f /TAO/tao/Strategies | |
parent | c36a729e5ea2409d1ef6344c45699cc1d95a7ab9 (diff) | |
download | ATCD-90b1277ac1378475a80fdc189fc590204250defc.tar.gz |
ChangeLogTag:Tue Jul 3 18:25:41 2001 Frank Hunleth <fhunleth@cs.wustl.edu>
Diffstat (limited to 'TAO/tao/Strategies')
23 files changed, 4191 insertions, 2 deletions
diff --git a/TAO/tao/Strategies/DIOP_Acceptor.cpp b/TAO/tao/Strategies/DIOP_Acceptor.cpp new file mode 100644 index 00000000000..0cb8f29f33d --- /dev/null +++ b/TAO/tao/Strategies/DIOP_Acceptor.cpp @@ -0,0 +1,760 @@ +// This may look like C, but it's really -*- C++ -*- +// $Id$ + +#include "DIOP_Acceptor.h" + +#if defined (TAO_HAS_DIOP) && (TAO_HAS_DIOP != 0) + +#include "DIOP_Profile.h" +#include "tao/MProfile.h" +#include "tao/ORB_Core.h" +#include "tao/debug.h" +#include "tao/Protocols_Hooks.h" + +#include "ace/Auto_Ptr.h" + +#if !defined(__ACE_INLINE__) +#include "DIOP_Acceptor.i" +#endif /* __ACE_INLINE__ */ + +ACE_RCSID(tao, DIOP_Acceptor, "$Id$") + + +TAO_DIOP_Acceptor::TAO_DIOP_Acceptor (CORBA::Boolean flag) + : TAO_Acceptor (TAO_TAG_UDP_PROFILE), + addrs_ (0), + hosts_ (0), + endpoint_count_ (0), + version_ (TAO_DEF_GIOP_MAJOR, TAO_DEF_GIOP_MINOR), + orb_core_ (0), + lite_flag_ (flag), + connection_handler_ (0) +{ +} + +TAO_DIOP_Acceptor::~TAO_DIOP_Acceptor (void) +{ + // Make sure we are closed before we start destroying the + // strategies. + this->close (); + + delete [] this->addrs_; + + for (size_t i = 0; i < this->endpoint_count_; ++i) + CORBA::string_free (this->hosts_[i]); + + delete [] this->hosts_; +} + +// TODO = +// 2) For V1.[1,2] there are tagged components + +int +TAO_DIOP_Acceptor::create_mprofile (const TAO_ObjectKey & object_key, + TAO_MProfile &mprofile, + CORBA::Boolean share_profile) +{ + // Sanity check. + if (this->endpoint_count_ == 0) + return -1; + + // Check if multiple endpoints should be put in one profile or + // if they should be spread across multiple profiles. + if (share_profile == 1) + return this->create_shared_profile (object_key, + mprofile); + else + return this->create_new_profiles (object_key, + mprofile); +} + +int +TAO_DIOP_Acceptor::create_new_profiles (const TAO_ObjectKey &object_key, + TAO_MProfile &mprofile) +{ + // Adding this->endpoint_count_ to the TAO_MProfile. + int count = mprofile.profile_count (); + if ((mprofile.size () - count) < this->endpoint_count_ + && mprofile.grow (count + this->endpoint_count_) == -1) + return -1; + + // Create a profile for each acceptor endpoint. + for (size_t i = 0; i < this->endpoint_count_; ++i) + { + TAO_DIOP_Profile *pfile = 0; + ACE_NEW_RETURN (pfile, + TAO_DIOP_Profile (this->hosts_[i], + this->addrs_[i].get_port_number (), + object_key, + this->addrs_[i], + this->version_, + this->orb_core_), + -1); + + if (mprofile.give_profile (pfile) == -1) + { + pfile->_decr_refcnt (); + pfile = 0; + return -1; + } + + if (this->orb_core_->orb_params ()->std_profile_components () == 0) + continue; + + pfile->tagged_components ().set_orb_type (TAO_ORB_TYPE); + + CONV_FRAME::CodeSetComponentInfo code_set_info; + code_set_info.ForCharData.native_code_set = + TAO_DEFAULT_CHAR_CODESET_ID; + code_set_info.ForWcharData.native_code_set = + TAO_DEFAULT_WCHAR_CODESET_ID; + pfile->tagged_components ().set_code_sets (code_set_info); + } + + return 0; +} + +int +TAO_DIOP_Acceptor::create_shared_profile (const TAO_ObjectKey &object_key, + TAO_MProfile &mprofile) +{ + size_t index = 0; + TAO_Profile *pfile = 0; + TAO_DIOP_Profile *iiop_profile = 0; + + // First see if <mprofile> already contains a DIOP profile. + for (TAO_PHandle i = 0; i != mprofile.profile_count (); ++i) + { + pfile = mprofile.get_profile (i); + if (pfile->tag () == TAO_TAG_UDP_PROFILE) + { + iiop_profile = ACE_dynamic_cast (TAO_DIOP_Profile *, + pfile); + break; + } + } + + // If <mprofile> doesn't contain a DIOP_Profile, we need to create + // one. + if (iiop_profile == 0) + { + ACE_NEW_RETURN (iiop_profile, + TAO_DIOP_Profile (this->hosts_[0], + this->addrs_[0].get_port_number (), + object_key, + this->addrs_[0], + this->version_, + this->orb_core_), + -1); + iiop_profile->endpoint ()->priority (this->priority ()); + + if (mprofile.give_profile (iiop_profile) == -1) + { + iiop_profile->_decr_refcnt (); + iiop_profile = 0; + return -1; + } + + if (this->orb_core_->orb_params ()->std_profile_components () != 0) + { + iiop_profile->tagged_components ().set_orb_type (TAO_ORB_TYPE); + + CONV_FRAME::CodeSetComponentInfo code_set_info; + code_set_info.ForCharData.native_code_set = + TAO_DEFAULT_CHAR_CODESET_ID; + code_set_info.ForWcharData.native_code_set = + TAO_DEFAULT_WCHAR_CODESET_ID; + iiop_profile->tagged_components ().set_code_sets (code_set_info); + } + + index = 1; + } + + // Add any remaining acceptor endpoints to the DIOP_Profile. + for (; + index < this->endpoint_count_; + ++index) + { + TAO_DIOP_Endpoint *endpoint = 0; + ACE_NEW_RETURN (endpoint, + TAO_DIOP_Endpoint (this->hosts_[index], + this->addrs_[index].get_port_number (), + this->addrs_[index]), + -1); + endpoint->priority (this->priority_); + iiop_profile->add_endpoint (endpoint); + } + + return 0; +} + +int +TAO_DIOP_Acceptor::is_collocated (const TAO_Endpoint *endpoint) +{ + const TAO_DIOP_Endpoint *endp = + ACE_dynamic_cast (const TAO_DIOP_Endpoint *, endpoint); + + // Make sure the dynamically cast pointer is valid. + if (endp == 0) + return 0; + + for (size_t i = 0; i < this->endpoint_count_; ++i) + { + // compare the port and sin_addr (numeric host address) + if (endp->object_addr () == this->addrs_[i]) + return 1; // Collocated + } + + return 0; // Not collocated +} + +int +TAO_DIOP_Acceptor::close (void) +{ + if (this->connection_handler_) + { + // Remove the connection handler from the reactor in the case + // of a valid handle, or close it yourself, if the handle is invalid. + // Either way it will cause the connection handler to be destructed. + if (this->connection_handler_->get_handle () != ACE_INVALID_HANDLE) + { + this->orb_core_->reactor ()->remove_handler (this->connection_handler_, + ACE_Event_Handler::READ_MASK); + } + else + { + this->connection_handler_->handle_close (); + } + this->connection_handler_ = 0; + } + return 0; +} + +int +TAO_DIOP_Acceptor::open (TAO_ORB_Core *orb_core, + int major, + int minor, + const char *address, + const char *options) +{ + this->orb_core_ = orb_core; + + if (this->init_tcp_properties () != 0) + return -1; + + if (this->hosts_ != 0) + { + // The hostname cache has already been set! + // This is bad mojo, i.e. an internal TAO error. + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("TAO (%P|%t) ") + ACE_TEXT ("DIOP_Acceptor::open - "), + ACE_TEXT ("hostname already set\n\n")), + -1); + } + + if (address == 0) + return -1; + + if (major >=0 && minor >= 0) + this->version_.set_version (ACE_static_cast (CORBA::Octet, + major), + ACE_static_cast (CORBA::Octet, + minor)); + // Parse options + if (this->parse_options (options) == -1) + return -1; + + ACE_INET_Addr addr; + + const char *port_separator_loc = ACE_OS::strchr (address, ':'); + const char *specified_hostname = 0; + char tmp_host[MAXHOSTNAMELEN + 1]; + + if (port_separator_loc == address) + { + // The address is a port number or port name. No hostname was + // specified. The hostname for each network interface and the + // fully qualified domain name must be obtained. + + // Check for multiple network interfaces. + if (this->probe_interfaces (orb_core) == -1) + return -1; + + // First convert the port into a usable form. + if (addr.set (address + sizeof (':')) != 0) + return -1; + + // Now reset the port and set the host. + if (addr.set (addr.get_port_number (), + ACE_static_cast (ACE_UINT32, INADDR_ANY), + 1) != 0) + return -1; + else + return this->open_i (addr); + } + else if (port_separator_loc == 0) + { + // The address is a hostname. No port was specified, so assume + // port zero (port will be chosen for us). + if (addr.set ((unsigned short) 0, address) != 0) + return -1; + + specified_hostname = address; + } + else + { + // Host and port were specified. + if (addr.set (address) != 0) + return -1; + + // Extract out just the host part of the address. + size_t len = port_separator_loc - address; + ACE_OS::memcpy (tmp_host, address, len); + tmp_host[len] = '\0'; + + specified_hostname = tmp_host; + } + + this->endpoint_count_ = 1; // Only one hostname to store + + ACE_NEW_RETURN (this->addrs_, + ACE_INET_Addr[this->endpoint_count_], + -1); + + ACE_NEW_RETURN (this->hosts_, + char *[this->endpoint_count_], + -1); + + if (this->hostname (orb_core, + addr, + this->hosts_[0], + specified_hostname) != 0) + return -1; + + // Copy the addr. The port is (re)set in + // TAO_DIOP_Acceptor::open_i(). + if (this->addrs_[0].set (addr) != 0) + return -1; + + return this->open_i (addr); +} + +int +TAO_DIOP_Acceptor::open_default (TAO_ORB_Core *orb_core, + int major, + int minor, + const char *options) +{ + this->orb_core_ = orb_core; + + if (this->init_tcp_properties () != 0) + return -1; + + if (this->hosts_ != 0) + { + // The hostname cache has already been set! + // This is bad mojo, i.e. an internal TAO error. + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("TAO (%P|%t) ") + ACE_TEXT ("DIOP_Acceptor::open_default - "), + ACE_TEXT ("hostname already set\n\n")), + -1); + } + + if (major >=0 && minor >= 0) + this->version_.set_version (ACE_static_cast (CORBA::Octet, + major), + ACE_static_cast (CORBA::Octet, + minor)); + + // Parse options + if (this->parse_options (options) == -1) + return -1; + + // Check for multiple network interfaces. + if (this->probe_interfaces (orb_core) == -1) + return -1; + + // Now that each network interface's hostname has been cached, open + // an endpoint on each network interface using the INADDR_ANY + // address. + ACE_INET_Addr addr; + + // @@ Michael: The following needs to be verified. + if (addr.set (ACE_DEFAULT_SERVER_PORT, // old: ACE_static_cast(u_short, 0), + ACE_static_cast(ACE_UINT32, INADDR_ANY), + 1) != 0) + return -1; + + return this->open_i (addr); +} + +int +TAO_DIOP_Acceptor::open_i (const ACE_INET_Addr& addr) +{ + // @@ Michael: UDP changes --------------- + + ACE_NEW_RETURN (this->connection_handler_, + TAO_DIOP_Connection_Handler (this->orb_core_, + this->lite_flag_, + 0 /* TAO_DIOP_Properties */), + -1); + + this->connection_handler_->local_addr (addr); + this->connection_handler_->open_server (); + + // Register only with a valid handle + if (this->connection_handler_->get_handle () != ACE_INVALID_HANDLE) + { + this->orb_core_->reactor ()->register_handler (this->connection_handler_, + ACE_Event_Handler::READ_MASK); + } + // ------------------------------------ + + + // Set the port for each addr. If there is more than one network + // interface then the endpoint created on each interface will be on + // the same port. This is how a wildcard socket bind() is supposed + // to work. + u_short port = addr.get_port_number (); + for (size_t j = 0; j < this->endpoint_count_; ++j) + this->addrs_[j].set_port_number (port, 1); + + if (TAO_debug_level > 5) + { + for (size_t i = 0; i < this->endpoint_count_; ++i) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("\nTAO (%P|%t) DIOP_Acceptor::open_i - ") + ACE_TEXT ("listening on: <%s:%u>\n"), + this->hosts_[i], + this->addrs_[i].get_port_number ())); + } + } + + return 0; +} + +int +TAO_DIOP_Acceptor::hostname (TAO_ORB_Core *orb_core, + ACE_INET_Addr &addr, + char *&host, + const char *specified_hostname) +{ + if (orb_core->orb_params ()->use_dotted_decimal_addresses ()) + { + // If dotted decimal addresses are enabled, + // just return ours. + return this->dotted_decimal_address (addr, host); + } + else + if (specified_hostname != 0) + { + // If the user specified a hostname, pass it back + // blindly as it overrides our choice of hostname. + host = CORBA::string_dup (specified_hostname); + } + else + { + char tmp_host[MAXHOSTNAMELEN + 1]; + + // Get the hostname associated with our address + if (addr.get_host_name (tmp_host, sizeof (tmp_host)) != 0) + { + // On failure, just return the decimal address. + return this->dotted_decimal_address (addr, host); + } + else + { + host = CORBA::string_dup (tmp_host); + } + } + + return 0; +} + +int +TAO_DIOP_Acceptor::dotted_decimal_address (ACE_INET_Addr &addr, + char *&host) +{ + const char *tmp = addr.get_host_addr (); + if (tmp == 0) + { + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("\n\nTAO (%P|%t) ") + ACE_TEXT ("DIOP_Acceptor::dotted_decimal_address ") + ACE_TEXT ("- %p\n\n"), + ACE_TEXT ("cannot determine hostname"))); + return -1; + } + + host = CORBA::string_dup (tmp); + return 0; +} + +int +TAO_DIOP_Acceptor::probe_interfaces (TAO_ORB_Core *orb_core) +{ + // Extract the hostname for each network interface, and then cache + // it. The hostnames will then be used when creating a + // TAO_DIOP_Profile for each endpoint setup on the probed + // network interfaces. + ACE_INET_Addr *if_addrs = 0; + size_t if_cnt = 0; + + if (ACE::get_ip_interfaces (if_cnt, + if_addrs) != 0 + && errno != ENOTSUP) + { + // In the case where errno == ENOTSUP, if_cnt and if_addrs will + // not be modified, and will each remain equal to zero. This + // causes the default interface to be used. + return -1; + } + + if (if_cnt == 0 || if_addrs == 0) + { + if (TAO_debug_level > 0) + { + ACE_DEBUG ((LM_WARNING, + ACE_TEXT ("TAO (%P|%t) Unable to probe network ") + ACE_TEXT ("interfaces. Using default."))); + } + + if_cnt = 1; // Force the network interface count to be one. + delete [] if_addrs; + ACE_NEW_RETURN (if_addrs, + ACE_INET_Addr[if_cnt], + -1); + } + + // Scan for the loopback interface since it shouldn't be included in + // the list of cached hostnames unless it is the only interface. + size_t lo_cnt = 0; // Loopback interface count + for (size_t j = 0; j < if_cnt; ++j) + if (if_addrs[j].get_ip_address () == INADDR_LOOPBACK) + lo_cnt++; + + // The instantiation for this template is in + // tao/DIOP_Connector.cpp. + ACE_Auto_Basic_Array_Ptr<ACE_INET_Addr> safe_if_addrs (if_addrs); + + // If the loopback interface is the only interface then include it + // in the list of interfaces to query for a hostname, otherwise + // exclude it from the list. + if (if_cnt == lo_cnt) + this->endpoint_count_ = if_cnt; + else + this->endpoint_count_ = if_cnt - lo_cnt; + + ACE_NEW_RETURN (this->addrs_, + ACE_INET_Addr[this->endpoint_count_], + -1); + + ACE_NEW_RETURN (this->hosts_, + char *[this->endpoint_count_], + -1); + + // The number of hosts/interfaces we want to cache may not be the + // same as the number of detected interfaces so keep a separate + // count. + size_t host_cnt = 0; + + for (size_t i = 0; i < if_cnt; ++i) + { + // Ignore any loopback interface if there are other + // non-loopback interfaces. + if (if_cnt != lo_cnt && + if_addrs[i].get_ip_address() == INADDR_LOOPBACK) + continue; + + if (this->hostname (orb_core, + if_addrs[i], + this->hosts_[host_cnt]) != 0) + return -1; + + // Copy the addr. The port is (re)set in + // TAO_DIOP_Acceptor::open_i(). + if (this->addrs_[host_cnt].set (if_addrs[i]) != 0) + return -1; + + host_cnt++; + } + + return 0; +} + +CORBA::ULong +TAO_DIOP_Acceptor::endpoint_count (void) +{ + return this->endpoint_count_; +} + +int +TAO_DIOP_Acceptor::object_key (IOP::TaggedProfile &profile, + TAO_ObjectKey &object_key) +{ + // 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::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) DIOP_Profile::decode - v%d.%d\n"), + major, + minor)); + } + return -1; + } + + CORBA::String_var host; + CORBA::UShort port = 0; + + // Get host and port. No processing here too.. + if (cdr.read_string (host.out ()) == 0 + || cdr.read_ushort (port) == 0) + { + if (TAO_debug_level > 0) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) TAO_Tagged_Profile::decode - ") + ACE_TEXT ("error while decoding host/port"))); + } + return -1; + } + + // ... and object key. + if ((cdr >> object_key) == 0) + return -1; + + // We are NOT bothered about the rest. + + return 1; +} + + +int +TAO_DIOP_Acceptor::parse_options (const char *str) +{ + if (str == 0) + return 0; // No options to parse. Not a problem. + + // Use an option format similar to the one used for CGI scripts in + // HTTP URLs. + // e.g.: option1=foo&option2=bar + + ACE_CString options (str); + + size_t len = options.length (); + + const char option_delimiter = '&'; + + // Count the number of options. + + CORBA::ULong option_count = 1; + // Number of endpoints in the string (initialized to 1). + + // Only check for endpoints after the protocol specification and + // before the object key. + for (size_t i = 0; i < len; ++i) + if (options[i] == option_delimiter) + option_count++; + + // The idea behind the following loop is to split the options into + // (option, name) pairs. + // For example, + // `option1=foo&option2=bar' + // will be parsed into: + // `option1=foo' + // `option2=bar' + + int begin = 0; + int end = -1; + + for (CORBA::ULong j = 0; j < option_count; ++j) + { + begin += end + 1; + + if (j < option_count - 1) + end = options.find (option_delimiter, begin); + else + end = len - begin; // Handle last endpoint differently + + if (end == begin) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("TAO (%P|%t) Zero length DIOP option.\n")), + -1); + else if (end != ACE_CString::npos) + { + ACE_CString opt = options.substring (begin, end); + + int slot = opt.find ("="); + + if (slot == ACE_static_cast (int, len - 1) + || slot == ACE_CString::npos) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("TAO (%P|%t) DIOP option <%s> is ") + ACE_TEXT ("missing a value.\n"), + opt.c_str ()), + -1); + + ACE_CString name = opt.substring (0, slot); + ACE_CString value = opt.substring (slot + 1); + + if (name.length () == 0) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("TAO (%P|%t) Zero length DIOP ") + ACE_TEXT ("option name.\n")), + -1); + + if (name == "priority") + { + CORBA::Short corba_priority = + ACE_static_cast (CORBA::Short, + ACE_OS::atoi (value.c_str ())); + + if (corba_priority >= 0 + /* && corba_priority < 32768 */) + // priority_ and corba_priority will always be less + // than 32768 since CORBA::Short is a signed 16 bit + // integer. + this->priority_ = corba_priority; + else + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("TAO (%P|%t) Invalid DIOP endpoint ") + ACE_TEXT ("priority: <%s>\n"), + value.c_str ()), + -1); + } + else + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("TAO (%P|%t) Invalid DIOP option: <%s>\n"), + name.c_str ()), + -1); + } + } + return 0; +} + +int +TAO_DIOP_Acceptor::init_tcp_properties (void) +{ + // @@ Michael: We use UDP, so we do not set TCP settings. + return 0; +} + +#endif /* TAO_HAS_DIOP && TAO_HAS_DIOP != 0 */ diff --git a/TAO/tao/Strategies/DIOP_Acceptor.h b/TAO/tao/Strategies/DIOP_Acceptor.h new file mode 100644 index 00000000000..326c6d0e1d0 --- /dev/null +++ b/TAO/tao/Strategies/DIOP_Acceptor.h @@ -0,0 +1,186 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file DIOP_Acceptor.h + * + * $Id$ + * + * DIOP specific acceptor processing + * + * @author Michael Kircher + */ +//============================================================================= + + +#ifndef TAO_DIOP_ACCEPTOR_H +#define TAO_DIOP_ACCEPTOR_H +#include "ace/pre.h" + +#include "tao/corbafwd.h" + +#if defined (TAO_HAS_DIOP) && (TAO_HAS_DIOP != 0) + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "tao/Pluggable.h" +#include "DIOP_Connection_Handler.h" +#include "tao/Acceptor_Impl.h" + +#include "tao/GIOP_Message_Version.h" + +// TAO DIOP_Acceptor concrete call defination + +/** + * @class TAO_DIOP_Acceptor + * + * @brief TAO_DIOP_Acceptor + * + * The DIOP-specific bridge class for the concrete acceptor. + */ +class TAO_Strategies_Export TAO_DIOP_Acceptor : public TAO_Acceptor +{ +public: + /// Constructor. + TAO_DIOP_Acceptor (CORBA::Boolean flag = 0); + + /// Destructor. + ~TAO_DIOP_Acceptor (void); + + /// @@ Helper method for the implementation repository, should go + /// away + const ACE_INET_Addr& address (void) const; + + /// Returns the array of endpoints in this acceptor + const ACE_INET_Addr *endpoints (void); + + /** + * The TAO_Acceptor methods, check the documentation in + * Pluggable.h for details. + */ + virtual int open (TAO_ORB_Core *orb_core, + int version_major, + int version_minor, + const char *address, + const char *options = 0); + virtual int open_default (TAO_ORB_Core *orb_core, + int version_major, + int version_minor, + const char *options = 0); + virtual int close (void); + virtual int create_mprofile (const TAO_ObjectKey &object_key, + TAO_MProfile &mprofile, + CORBA::Boolean share_profile); + + virtual int is_collocated (const TAO_Endpoint *endpoint); + virtual CORBA::ULong endpoint_count (void); + + virtual int object_key (IOP::TaggedProfile &profile, + TAO_ObjectKey &key); + + /** + * Set the host name for the given addr. + * A hostname may be forced by using specified_hostname. This + * is useful if the given address corresponds to more than one + * hostname and the desired one cannot be determined in any + * other way. + */ + int hostname (TAO_ORB_Core *orb_core, + ACE_INET_Addr &addr, + char *&host, + const char *specified_hostname = 0); + + /** + * Set the host name for the given address using the dotted decimal + * format. + */ + int dotted_decimal_address (ACE_INET_Addr &addr, + char *&host); + +protected: + + /** + * Implement the common part of the open*() methods. This method is + * virtual to allow a derived class implementation to be invoked + * instead. + */ + virtual int open_i (const ACE_INET_Addr &addr); + + /** + * Probe the system for available network interfaces, and initialize + * the <addrs_> array with an ACE_INET_Addr for each network + * interface. The port for each initialized ACE_INET_Addr will be + * set in the open_i() method. This method only gets invoked when + * no explicit hostname is provided in the specified endpoint. + */ + int probe_interfaces (TAO_ORB_Core *orb_core); + + /// Parse protocol specific options. + virtual int parse_options (const char *options); + + /// Obtain tcp properties that must be used by this acceptor, i.e., + /// initialize <tcp_properties_>. + int init_tcp_properties (void); + + /// Helper method to add a new profile to the mprofile for + /// each endpoint. + int create_new_profiles (const TAO_ObjectKey &object_key, + TAO_MProfile &mprofile); + + /// Helper method to create a profile that contains all of + /// our endpoints. + int create_shared_profile (const TAO_ObjectKey &object_key, + TAO_MProfile &mprofile); + +protected: + + /// Array of ACE_INET_Addr instances, each one corresponding to a + /// given network interface. + ACE_INET_Addr *addrs_; + + /** + * Cache the information about the endpoints serviced by this + * acceptor. + * There may in fact be multiple hostnames for this endpoint. For + * example, if the IP address is INADDR_ANY (0.0.0.0) then there + * will be possibly a different hostname for each interface. + */ + char **hosts_; + + /// The number of host names cached in the hosts_ array (equivalent + /// to the number of endpoints opened by this Acceptor). + size_t endpoint_count_; + + /** + * The GIOP version for this endpoint + * @@ Theoretically they shouldn't be here!! We need to look at a + * way to move this out + */ + TAO_GIOP_Message_Version version_; + + /// ORB Core. + TAO_ORB_Core *orb_core_; + + /// TCP configuration properties to be used for all + /// connections opened by this acceptor. + TAO_DIOP_Properties tcp_properties_; + + /// Should we use GIOP lite?? + CORBA::Boolean lite_flag_; + +private: + // @@ Frank: From DIOP_Acceptor.h + TAO_DIOP_Connection_Handler *connection_handler_; + +}; + +#if defined(__ACE_INLINE__) +#include "DIOP_Acceptor.i" +#endif /* __ACE_INLINE__ */ + +#endif /* TAO_HAS_DIOP && TAO_HAS_DIOP != 0 */ + +#include "ace/post.h" +#endif /* TAO_DIOP_ACCEPTOR_H */ diff --git a/TAO/tao/Strategies/DIOP_Acceptor.i b/TAO/tao/Strategies/DIOP_Acceptor.i new file mode 100644 index 00000000000..9aaf71a3d41 --- /dev/null +++ b/TAO/tao/Strategies/DIOP_Acceptor.i @@ -0,0 +1,23 @@ +// -*- C++ -*- +// $Id$ + +ACE_INLINE const ACE_INET_Addr& +TAO_DIOP_Acceptor::address (void) const +{ + ACE_ASSERT (this->addrs_ != 0); + + // @@ This is busted. + // The Implementation Repository will have to start supporting + // IORs with multiple profiles. For now, we just return the + // first addr. + // -Ossama + return this->addrs_[0]; +} + +ACE_INLINE const ACE_INET_Addr * +TAO_DIOP_Acceptor::endpoints (void) +{ + ACE_ASSERT (this->addrs_ != 0); + + return this->addrs_; +} diff --git a/TAO/tao/Strategies/DIOP_Connection_Handler.cpp b/TAO/tao/Strategies/DIOP_Connection_Handler.cpp new file mode 100644 index 00000000000..9b95deeea56 --- /dev/null +++ b/TAO/tao/Strategies/DIOP_Connection_Handler.cpp @@ -0,0 +1,402 @@ +// $Id$ + + +#include "DIOP_Connection_Handler.h" + +#if defined (TAO_HAS_DIOP) && (TAO_HAS_DIOP != 0) + +#include "tao/Timeprobe.h" +#include "tao/debug.h" +#include "tao/ORB_Core.h" +#include "tao/ORB.h" +#include "tao/CDR.h" +#include "tao/Messaging_Policy_i.h" +#include "tao/Server_Strategy_Factory.h" +#include "tao/Transport_Cache_Manager.h" +#include "tao/Base_Transport_Property.h" + +#include "DIOP_Transport.h" +#include "DIOP_Endpoint.h" + +#if !defined (__ACE_INLINE__) +# include "DIOP_Connection_Handler.i" +#endif /* ! __ACE_INLINE__ */ + +ACE_RCSID(tao, DIOP_Connect, "$Id$") + + + +TAO_DIOP_Connection_Handler::TAO_DIOP_Connection_Handler (ACE_Thread_Manager *t) + : TAO_DIOP_SVC_HANDLER (t, 0 , 0), + TAO_Connection_Handler (0), + pending_upcalls_ (1), + tcp_properties_ (0) +{ + // This constructor should *never* get called, it is just here to + // make the compiler happy: the default implementation of the + // Creation_Strategy requires a constructor with that signature, we + // don't use that implementation, but some (most?) compilers + // instantiate it anyway. + ACE_ASSERT (this->orb_core () != 0); +} + + +TAO_DIOP_Connection_Handler::TAO_DIOP_Connection_Handler (TAO_ORB_Core *orb_core, + CORBA::Boolean /* flag*/, + void *arg) + : TAO_DIOP_SVC_HANDLER (orb_core->thr_mgr (), 0, 0), + TAO_Connection_Handler (orb_core), + pending_upcalls_ (1), + tcp_properties_ (ACE_static_cast + (TAO_DIOP_Properties *, arg)) +{ + TAO_DIOP_Transport* specific_transport = 0; + ACE_NEW(specific_transport, + TAO_DIOP_Transport(this, orb_core, 0)); + + // store this pointer (indirectly increment ref count) + this->transport(specific_transport); + TAO_Transport::release (specific_transport); +} + + +TAO_DIOP_Connection_Handler::~TAO_DIOP_Connection_Handler (void) +{ + this->udp_socket_.close (); +} + +// DIOP Additions - Begin +ACE_HANDLE +TAO_DIOP_Connection_Handler::get_handle (void) const +{ + return this->udp_socket_.get_handle (); +} + + +const ACE_INET_Addr & +TAO_DIOP_Connection_Handler::addr (void) +{ + return this->addr_; +} + + +void +TAO_DIOP_Connection_Handler::addr (const ACE_INET_Addr &addr) +{ + this->addr_ = addr; +} + + +const ACE_INET_Addr & +TAO_DIOP_Connection_Handler::local_addr (void) +{ + return local_addr_; +} + + +void +TAO_DIOP_Connection_Handler::local_addr (const ACE_INET_Addr &addr) +{ + local_addr_ = addr; +} + + +const ACE_SOCK_Dgram & +TAO_DIOP_Connection_Handler::dgram (void) +{ + return this->udp_socket_; +} +// DIOP Additions - End + + +int +TAO_DIOP_Connection_Handler::open (void*) +{ + this->udp_socket_.open (this->local_addr_); + + ACE_DEBUG ((LM_DEBUG, + "Opened connector on %s:%d\n", + this->local_addr_.get_host_name (), + this->local_addr_.get_port_number ())); + + // Set the id in the transport now that we're active. + this->transport ()->id ((int) this->get_handle ()); + + return 0; +} + +int +TAO_DIOP_Connection_Handler::open_server (void) +{ + this->udp_socket_.open (this->local_addr_); + ACE_DEBUG ((LM_DEBUG, + "Opened acceptor on %s:%d\n", + this->local_addr_.get_host_name (), + this->local_addr_.get_port_number ())); + + this->transport ()->id ((int) this->get_handle ()); + + return 0; +} + +int +TAO_DIOP_Connection_Handler::activate (long flags, + int n_threads, + int force_active, + long priority, + int grp_id, + ACE_Task_Base *task, + ACE_hthread_t thread_handles[], + void *stack[], + size_t stack_size[], + ACE_thread_t thread_names[]) +{ + if (TAO_debug_level) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) DIOP_Connection_Handler::activate %d ") + ACE_TEXT ("threads, flags = %d\n"), + n_threads, + flags, + THR_BOUND)); + // @@ Michael: I believe we do not need active service handlers right now. + // @@ Frank: Not disabled yet... + + // Set the id in the transport now that we're active. + this->transport ()->id ((int) this->get_handle ()); + + return TAO_DIOP_SVC_HANDLER::activate (flags, + n_threads, + force_active, + priority, + grp_id, + task, + thread_handles, + stack, + stack_size, + thread_names); +} + +int +TAO_DIOP_Connection_Handler::svc (void) +{ + // @@ Michael: I believe we do not need active service handlers right now. + // @@ Frank: Not yet... + + // This method is called when an instance is "activated", i.e., + // turned into an active object. Presumably, activation spawns a + // thread with this method as the "worker function". + + // Clear the non-blocking mode here + ACE_Flag_Manip::clr_flags (this->get_handle (), + ACE_NONBLOCK); + + // Call the implementation here + return this->svc_i (); +} + + +int +TAO_DIOP_Connection_Handler::handle_close (ACE_HANDLE handle, + ACE_Reactor_Mask rm) +{ + // @@ Alex: we need to figure out if the transport decides to close + // us or something else. If it is something else (for example + // the cached connector trying to make room for other + // connections) then we should let the transport know, so it can + // in turn take appropiate action (such as sending exceptions to + // all waiting reply handlers). + if (TAO_debug_level) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) ") + ACE_TEXT ("DIOP_Connection_Handler::handle_close ") + ACE_TEXT ("(%d, %d)\n"), + handle, + rm)); + + --this->pending_upcalls_; + if (this->pending_upcalls_ <= 0) + { + // @@ Why are we doing checks for is_registered flags here if the + // handlers are not registered with the reactor? - Bala + if (this->transport ()->wait_strategy ()->is_registered ()) + { + // @@ Frank: Added reactor check. not sure if this is right? + if (this->reactor ()) + { + // Make sure there are no timers. + this->reactor ()->cancel_timer (this); + } + + // Set the flag to indicate that it is no longer registered with + // the reactor, so that it isn't included in the set that is + // passed to the reactor on ORB destruction. + this->transport ()->wait_strategy()->is_registered (0); + } + + // Close the handle.. + if (this->get_handle () != ACE_INVALID_HANDLE) + { + // Purge the entry too + this->transport ()->mark_invalid (); + + // Signal the transport that we will no longer have + // a reference to it. This will eventually call + // TAO_Transport::release (). + this->transport (0); + } + + // Follow usual Reactor-style lifecycle semantics and commit + // suicide. + this->destroy (); + } + + return 0; +} + +ACE_HANDLE +TAO_DIOP_Connection_Handler::fetch_handle (void) +{ + return this->get_handle (); +} + + +int +TAO_DIOP_Connection_Handler::add_transport_to_cache (void) +{ + ACE_INET_Addr addr; + + // Get the peername. + if (this->peer ().get_remote_addr (addr) == -1) + return -1; + + // Construct an DIOP_Endpoint object + TAO_DIOP_Endpoint endpoint (addr, + 0); + + // Construct a property object + TAO_Base_Transport_Property prop (&endpoint); + + // Add the handler to Cache + return this->orb_core ()->transport_cache ()->cache_transport (&prop, + this->transport ()); +} + +// @@ Frank: Hopefully this isn't needed +/* +int +TAO_DIOP_Connection_Handler::process_listen_point_list ( + DIOP::ListenPointList &listen_list) +{ + // Get the size of the list + CORBA::ULong len = listen_list.length (); + + for (CORBA::ULong i = 0; i < len; ++ i) + { + DIOP::ListenPoint listen_point = listen_list[i]; + ACE_INET_Addr addr (listen_point.port, + listen_point.host.in ()); + + + // Construct an DIOP_Endpoint object + TAO_DIOP_Endpoint endpoint (addr, + 0); + + // Construct a property object + TAO_Base_Transport_Property prop (&endpoint); + + // Mark the connection as bidirectional + prop.set_bidir_flag (1); + + // The property for this handler has changed. Recache the + // handler with this property + int retval = this->transport ()->recache_transport (&prop); + if (retval == -1) + return retval; + + // Make the handler idle and ready for use + this->transport ()->make_idle (); + } + + return 0; +} +*/ + +int +TAO_DIOP_Connection_Handler::handle_input (ACE_HANDLE h) +{ + return this->handle_input_i (h); +} + + +int +TAO_DIOP_Connection_Handler::handle_input_i (ACE_HANDLE, + ACE_Time_Value *max_wait_time) +{ + this->pending_upcalls_++; + + // Call the transport read the message + int result = this->transport ()->read_process_message (max_wait_time); + + // Now the message has been read + if (result == -1 && TAO_debug_level > 0) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - %p\n"), + ACE_TEXT ("DIOP_Connection_Handler::handle_input_i \n"))); + + } + + // The upcall is done. Bump down the reference count + if (--this->pending_upcalls_ <= 0) + result = -1; + + // @@ Michael: + // We always return 0, as we do not have any + // send errors. + return 0; +} + +// @@ Frank: From DIOP_Connect.cpp +int +TAO_DIOP_Connection_Handler::handle_cleanup (void) +{ + // Deregister this handler with the ACE_Reactor. + if (this->reactor ()) + { + ACE_Reactor_Mask mask = + ACE_Event_Handler::ALL_EVENTS_MASK | ACE_Event_Handler::DONT_CALL; + + // Make sure there are no timers. + this->reactor ()->cancel_timer (this); + + // Remove self from reactor. + this->reactor ()->remove_handler (this, mask); + } + + return 0; +} + + + + +// **************************************************************** + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) + +// Instantiated in IIOP_Connection_Handler.cpp +//template class ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>; + +template class ACE_Concurrency_Strategy<TAO_DIOP_Connection_Handler>; +template class ACE_Creation_Strategy<TAO_DIOP_Connection_Handler>; + +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) + +// Instantiated in IIOP_Connection_Handler.cpp +//#pragma instantiate ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> + +#pragma instantiate ACE_Concurrency_Strategy<TAO_DIOP_Connection_Handler> +#pragma instantiate ACE_Creation_Strategy<TAO_DIOP_Connection_Handler> + +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ + +#endif /* TAO_HAS_DIOP && TAO_HAS_DIOP != 0 */ diff --git a/TAO/tao/Strategies/DIOP_Connection_Handler.h b/TAO/tao/Strategies/DIOP_Connection_Handler.h new file mode 100644 index 00000000000..b0291796f43 --- /dev/null +++ b/TAO/tao/Strategies/DIOP_Connection_Handler.h @@ -0,0 +1,194 @@ +// This may look like C, but it's really -*- C++ -*- +// =================================================================== +/** + * @file DIOP_Connection_Handler.h + * + * $Id$ + * + * @author Michael Kircher + */ +// =================================================================== + +#ifndef TAO_DIOP_CONNECTION_HANDLER_H +#define TAO_DIOP_CONNECTION_HANDLER_H +#include "ace/pre.h" + +#include "tao/corbafwd.h" + +#if defined (TAO_HAS_DIOP) && (TAO_HAS_DIOP != 0) + +#include "ace/Reactor.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +#pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/Acceptor.h" + +#include "tao/corbafwd.h" +#include "tao/Wait_Strategy.h" +#include "tao/Connection_Handler.h" +#include "DIOP_Transport.h" +//#include "tao/DIOPC.h" +#include "ace/SOCK_Dgram.h" +#include "strategies_export.h" + +// Forward Decls +class TAO_Pluggable_Messaging; + +// **************************************************************** + +/** + * @class TAO_DIOP_Properties + * + * @brief TCP protocol properties specification for a set of + * connections. + * + */ + +class TAO_Strategies_Export TAO_DIOP_Properties +{ + +public: + int send_buffer_size; + int recv_buffer_size; + int no_delay; +}; + + + +// **************************************************************** + +/** + * @class TAO_DIOP_Connection_Handler + * + * @brief Handles requests on a single connection. + * + * The Connection handler which is common for the Acceptor and + * the Connector + */ + + +class TAO_Strategies_Export TAO_DIOP_Connection_Handler : public TAO_DIOP_SVC_HANDLER, + public TAO_Connection_Handler +{ + +public: + + TAO_DIOP_Connection_Handler (ACE_Thread_Manager* t = 0); + + /// Constructor. <arg> parameter is used by the Acceptor to pass the + /// protocol configuration properties for this connection. + TAO_DIOP_Connection_Handler (TAO_ORB_Core *orb_core, + CORBA::Boolean flag, + void *arg); + + + /// Destructor. + ~TAO_DIOP_Connection_Handler (void); + + /// Called by the <Strategy_Acceptor> when the handler is completely + /// connected. Argument is unused. + virtual int open (void *); + + // @@ Frank: Similar to open, but called on server + virtual int open_server (void); + + /// = Active object activation method. + virtual int activate (long flags = THR_NEW_LWP, + int n_threads = 1, + int force_active = 0, + long priority = ACE_DEFAULT_THREAD_PRIORITY, + int grp_id = -1, + ACE_Task_Base *task = 0, + ACE_hthread_t thread_handles[] = 0, + void *stack[] = 0, + size_t stack_size[] = 0, + ACE_thread_t thread_names[] = 0); + + /// Only used when the handler is turned into an active object by + /// calling <activate>. This serves as the event loop in such cases. + virtual int svc (void); + + /// Perform appropriate closing. + virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE, + ACE_Reactor_Mask = ACE_Event_Handler::NULL_MASK); + + /// Return the underlying handle + virtual ACE_HANDLE fetch_handle (void); + + /// Add ourselves to Cache. + int add_transport_to_cache (void); + + // @@ Frank: Not needed + /* + /// Process the <listen_list> + int process_listen_point_list (DIOP::ListenPointList &listen_list); + */ + + // DIOP Additions - Begin + ACE_HANDLE get_handle (void) const; + + const ACE_INET_Addr &addr (void); + + void addr (const ACE_INET_Addr &addr); + + const ACE_INET_Addr &local_addr (void); + + void local_addr (const ACE_INET_Addr &addr); + + const ACE_INET_Addr &server_addr (void); + + void server_addr (const ACE_INET_Addr &addr); + + const ACE_SOCK_Dgram &dgram (void); + // DIOP Additions - End + +protected: + + /// = Event Handler overloads + + /// Reads a message from the <peer()>, dispatching and servicing it + /// appropriately. + /// handle_input() just delegates on handle_input_i() which timeouts + /// after <max_wait_time>, this is used in thread-per-connection to + /// ensure that server threads eventually exit. + + virtual int handle_input (ACE_HANDLE = ACE_INVALID_HANDLE); + virtual int handle_input_i (ACE_HANDLE = ACE_INVALID_HANDLE, + ACE_Time_Value *max_wait_time = 0); + + virtual int handle_cleanup (); + + // DIOP Additions - Begin + ACE_SOCK_Dgram udp_socket_; + + // This is always the remote address + ACE_INET_Addr addr_; + + // This is always the local address for the connector + ACE_INET_Addr local_addr_; + + // DIOP Additions - End + +private: + + /// Count nested upcalls on this + /// svc_handler i.e., the connection can close during nested upcalls, + /// you should not delete the svc_handler until the stack unwinds + /// from the nested upcalls. + u_long pending_upcalls_; + + /// TCP configuration for this connection. + TAO_DIOP_Properties *tcp_properties_; +}; + + +#if defined (__ACE_INLINE__) +#include "DIOP_Connection_Handler.i" +#endif /* __ACE_INLINE__ */ + +#endif /* TAO_HAS_DIOP && TAO_HAS_DIOP != 0 */ + +#include "ace/post.h" +#endif /* TAO_DIOP_CONNECTION_HANDLER_H */ diff --git a/TAO/tao/Strategies/DIOP_Connection_Handler.i b/TAO/tao/Strategies/DIOP_Connection_Handler.i new file mode 100644 index 00000000000..7f2b3228624 --- /dev/null +++ b/TAO/tao/Strategies/DIOP_Connection_Handler.i @@ -0,0 +1,3 @@ +// -*- C++ -*- +// $Id$ + diff --git a/TAO/tao/Strategies/DIOP_Connector.cpp b/TAO/tao/Strategies/DIOP_Connector.cpp new file mode 100644 index 00000000000..ef5e3a96665 --- /dev/null +++ b/TAO/tao/Strategies/DIOP_Connector.cpp @@ -0,0 +1,276 @@ +// This may look like C, but it's really -*- C++ -*- +// $Id$ + +#include "DIOP_Connector.h" + +#if defined (TAO_HAS_DIOP) && (TAO_HAS_DIOP != 0) + +#include "ace/Connector.h" + +#include "tao/debug.h" +#include "tao/ORB_Core.h" +#include "tao/Environment.h" +#include "tao/Base_Transport_Property.h" +#include "tao/Protocols_Hooks.h" + +#include "DIOP_Profile.h" + + +ACE_RCSID (DIOP, + DIOP_Connector, + "$Id$") + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) + + +template class ACE_Svc_Tuple<TAO_DIOP_Connection_Handler>; +template class ACE_Map_Manager<int, ACE_Svc_Tuple<TAO_DIOP_Connection_Handler> *, TAO_SYNCH_RW_MUTEX>; +template class ACE_Map_Iterator_Base<int, ACE_Svc_Tuple<TAO_DIOP_Connection_Handler> *, TAO_SYNCH_RW_MUTEX>; +template class ACE_Map_Entry<int,ACE_Svc_Tuple<TAO_DIOP_Connection_Handler>*>; + +template class ACE_Map_Entry<ACE_INET_Addr, TAO_DIOP_Connection_Handler *>; + +template class ACE_Map_Iterator<int,ACE_Svc_Tuple<TAO_DIOP_Connection_Handler>*,TAO_SYNCH_RW_MUTEX>; +template class ACE_Map_Reverse_Iterator<int,ACE_Svc_Tuple<TAO_DIOP_Connection_Handler>*,TAO_SYNCH_RW_MUTEX>; +template class ACE_Hash_Map_Iterator_Base_Ex < ACE_INET_Addr, TAO_DIOP_Connection_Handler *, ACE_Hash < ACE_INET_Addr >, ACE_Equal_To < ACE_INET_Addr >, ACE_Null_Mutex >; +template class ACE_Hash_Map_Iterator_Ex<ACE_INET_Addr, TAO_DIOP_Connection_Handler *, ACE_Hash<ACE_INET_Addr>, ACE_Equal_To<ACE_INET_Addr>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Reverse_Iterator_Ex<ACE_INET_Addr, TAO_DIOP_Connection_Handler *, ACE_Hash<ACE_INET_Addr>, ACE_Equal_To<ACE_INET_Addr>, ACE_Null_Mutex>; + +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) + +#pragma instantiate ACE_Svc_Tuple<TAO_DIOP_Connection_Handler> +#pragma instantiate ACE_Map_Manager<int, ACE_Svc_Tuple<TAO_DIOP_Connection_Handler> *, TAO_SYNCH_RW_MUTEX> +#pragma instantiate ACE_Map_Iterator_Base<int, ACE_Svc_Tuple<TAO_DIOP_Connection_Handler> *, TAO_SYNCH_RW_MUTEX> +#pragma instantiate ACE_Map_Entry<int,ACE_Svc_Tuple<TAO_DIOP_Connection_Handler>*> + +#pragma instantiate ACE_Map_Entry<ACE_INET_Addr, TAO_DIOP_Connection_Handler *>; + +#pragma instantiate ACE_Map_Iterator<int,ACE_Svc_Tuple<TAO_DIOP_Connection_Handler>*,TAO_SYNCH_RW_MUTEX> +#pragma instantiate ACE_Map_Reverse_Iterator<int,ACE_Svc_Tuple<TAO_DIOP_Connection_Handler>*,TAO_SYNCH_RW_MUTEX> + +#pragma instantiate ACE_Hash_Map_Iterator_Base_Ex < ACE_INET_Addr,TAO_DIOP_Connection_Handler *, ACE_Hash < ACE_INET_Addr >, ACE_Equal_To < ACE_INET_Addr >, ACE_Null_Mutex > +#pragma instantiate ACE_Hash_Map_Iterator_Ex<ACE_INET_Addr, TAO_DIOP_Connection_Handler *, ACE_Hash<ACE_INET_Addr>, ACE_Equal_To<ACE_INET_Addr>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Reverse_Iterator_Ex<ACE_INET_Addr, TAO_DIOP_Connection_Handler *, ACE_Hash<ACE_INET_Addr>, ACE_Equal_To<ACE_INET_Addr>, ACE_Null_Mutex> + +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ + +TAO_DIOP_Connector::TAO_DIOP_Connector (CORBA::Boolean flag) + : TAO_Connector (TAO_TAG_UDP_PROFILE), + lite_flag_ (flag) +{ +} + +TAO_DIOP_Connector::~TAO_DIOP_Connector (void) +{ +} + +int +TAO_DIOP_Connector::open (TAO_ORB_Core *orb_core) +{ + this->orb_core (orb_core); + + // @@ Michael: We do not use traditional connection management. + + return 0; +} + +int +TAO_DIOP_Connector::close (void) +{ + // @@ Michael: UDP Addition ------------------------------------ + + // The list of service handlers cleans itself?? + SvcHandlerIterator iter (svc_handler_table_); + + while (!iter.done ()) + { + // Delete the connection handler + delete (*iter).int_id_; + iter++; + } + // ----------------------------------------------------------------- + + // @@ Michael: We do not use traditional connection management. + return 0; +} + +int +TAO_DIOP_Connector::connect (TAO_Transport_Descriptor_Interface *desc, + TAO_Transport *&transport, + ACE_Time_Value * /*max_wait_time*/, + CORBA::Environment &) +{ + TAO_Endpoint *endpoint = desc->endpoint (); + + if (endpoint->tag () != TAO_TAG_UDP_PROFILE) + return -1; + + TAO_DIOP_Endpoint *diop_endpoint = + ACE_dynamic_cast (TAO_DIOP_Endpoint *, + endpoint ); + if (diop_endpoint == 0) + return -1; + + const ACE_INET_Addr &remote_address = + diop_endpoint->object_addr (); + + // Verify that the remote ACE_INET_Addr was initialized properly. + // Failure can occur if hostname lookup failed when initializing the + // remote ACE_INET_Addr. + if (remote_address.get_type () != AF_INET) + { + if (TAO_debug_level > 0) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) DIOP connection failed.\n") + ACE_TEXT ("TAO (%P|%t) This is most likely ") + ACE_TEXT ("due to a hostname lookup ") + ACE_TEXT ("failure.\n"))); + } + + return -1; + } + + TAO_DIOP_Connection_Handler *svc_handler = 0; + + // @@ Michael -- UDP Additions ---------------------------- + + if (svc_handler_table_.find (remote_address, svc_handler) == -1) + { + TAO_DIOP_Connection_Handler *svc_handler_i = 0; + ACE_NEW_RETURN (svc_handler_i, + TAO_DIOP_Connection_Handler (this->orb_core (), + this->lite_flag_, + 0 /* TAO_DIOP_Properties */), + -1); + + svc_handler_i->local_addr (ACE_sap_any_cast (ACE_INET_Addr &)); + svc_handler_i->addr (remote_address); + + svc_handler_i->open (0); + + svc_handler_table_.bind (remote_address, + svc_handler_i); + svc_handler = svc_handler_i; + + if (TAO_debug_level > 2) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) DIOP_Connector::connect - ") + ACE_TEXT ("new connection on HANDLE %d\n"), + svc_handler->get_handle ())); + } + + // --------------------------------------------------------- + + // @@ Michael: We do not use traditional connection management. + + transport = TAO_Transport::_duplicate (svc_handler->transport ()); + + return 0; +} + +int +TAO_DIOP_Connector::preconnect (const char *) +{ + // @@ Michael: We do not support preconnects. + return 0; +} + +TAO_Profile * +TAO_DIOP_Connector::create_profile (TAO_InputCDR& cdr) +{ + TAO_Profile *pfile; + ACE_NEW_RETURN (pfile, + TAO_DIOP_Profile (this->orb_core ()), + 0); + + int r = pfile->decode (cdr); + if (r == -1) + { + pfile->_decr_refcnt (); + pfile = 0; + } + + return pfile; +} + +TAO_Profile * +TAO_DIOP_Connector::make_profile (CORBA::Environment &ACE_TRY_ENV) +{ + // The endpoint should be of the form: + // N.n@host:port/object_key + // or: + // host:port/object_key + + TAO_Profile *profile = 0; + ACE_NEW_THROW_EX (profile, + TAO_DIOP_Profile (this->orb_core ()), + CORBA::NO_MEMORY ( + CORBA::SystemException::_tao_minor_code ( + TAO_DEFAULT_MINOR_CODE, + ENOMEM), + CORBA::COMPLETED_NO)); + ACE_CHECK_RETURN (0); + + return profile; +} + +int +TAO_DIOP_Connector::check_prefix (const char *endpoint) +{ + // Check for a valid string + if (!endpoint || !*endpoint) + return -1; // Failure + + const char *protocol[] = { "diop", "dioploc" }; + + size_t slot = ACE_OS::strchr (endpoint, ':') - endpoint; + + size_t len0 = ACE_OS::strlen (protocol[0]); + size_t len1 = ACE_OS::strlen (protocol[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 (slot == len0 + && ACE_OS::strncasecmp (endpoint, protocol[0], len0) == 0) + return 0; + else if (slot == len1 + && ACE_OS::strncasecmp (endpoint, protocol[1], len1) == 0) + return 0; + + return -1; + // Failure: not an DIOP IOR + // DO NOT throw an exception here. +} + +char +TAO_DIOP_Connector::object_key_delimiter (void) const +{ + return TAO_DIOP_Profile::object_key_delimiter_; +} + +int +TAO_DIOP_Connector::init_tcp_properties (void) +{ + // @@ Michael: We have not TCP, so we have no TCP properties. + return 0; +} + + +// **************************************************************** + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) + +template class ACE_Hash <ACE_INET_Addr>; +template class ACE_Equal_To <ACE_INET_Addr>; +template class ACE_Hash_Map_Manager_Ex<ACE_INET_Addr, TAO_DIOP_Connection_Handler *, ACE_Hash <ACE_INET_Addr>, ACE_Equal_To <ACE_INET_Addr>, ACE_Null_Mutex>; +template class ACE_Hash_Map_Entry<ACE_INET_Addr, TAO_DIOP_Connection_Handler *>; +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) + +#pragma instantiate ACE_Hash <ACE_INET_Addr>; +#pragma instantiate ACE_Equal_To <ACE_INET_Addr> +#pragma instantiate ACE_Hash_Map_Manager_Ex<ACE_INET_Addr, TAO_DIOP_Connection_Handler *, ACE_Hash <ACE_INET_Addr>, ACE_Equal_To <ACE_INET_Addr>, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Entry<ACE_INET_Addr, TAO_DIOP_Connection_Handler *>; +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ + +#endif /* TAO_HAS_DIOP && TAO_HAS_DIOP != 0 */ diff --git a/TAO/tao/Strategies/DIOP_Connector.h b/TAO/tao/Strategies/DIOP_Connector.h new file mode 100644 index 00000000000..71b97ae529d --- /dev/null +++ b/TAO/tao/Strategies/DIOP_Connector.h @@ -0,0 +1,103 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file DIOP_Connector.h + * + * $Id$ + * + * DIOP specific connector processing + * + * @author Michael Kircher + */ +//============================================================================= + +#ifndef TAO_DIOP_CONNECTOR_H +#define TAO_DIOP_CONNECTOR_H +#include "ace/pre.h" + +#include "tao/corbafwd.h" + +#if defined (TAO_HAS_DIOP) && (TAO_HAS_DIOP != 0) + +#include "tao/Pluggable.h" +#include "DIOP_Connection_Handler.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +// **************************************************************** + +/** + * @class TAO_DIOP_Connector + * + * @brief DIOP-specific Connector bridge for pluggable protocols. + * + * Concrete instance of the TAO_Connector class. Responsible + * for establishing a connection with a server and is called from the + * Connector_Registory. + */ +class TAO_Strategies_Export TAO_DIOP_Connector : public TAO_Connector +{ +public: + // = Initialization and termination methods. + /// Constructor. + TAO_DIOP_Connector (CORBA::Boolean flag = 0); + + /// Destructor. + ~TAO_DIOP_Connector (void); + + // = The TAO_Connector methods, please check the documentation on + // Pluggable.h + int open (TAO_ORB_Core *orb_core); + int close (void); + int connect (TAO_Transport_Descriptor_Interface *desc, + TAO_Transport *&transport, + ACE_Time_Value *max_wait_time, + CORBA::Environment &ACE_TRY_ENV); + int preconnect (const char *preconnections); + TAO_Profile *create_profile (TAO_InputCDR& cdr); + + virtual int check_prefix (const char *endpoint); + + virtual char object_key_delimiter (void) const; + +protected: + + /// = More TAO_Connector methods, please check the documentation on + /// Pluggable.h + virtual TAO_Profile * make_profile (CORBA::Environment &ACE_TRY_ENV); + + /// Obtain tcp properties that must be used by this connector, i.e., + /// initialize <tcp_properties_>. + int init_tcp_properties (void); + +protected: + + /// TCP configuration properties to be used for all + /// connections established by this connector. + TAO_DIOP_Properties tcp_properties_; + + /// Do we need to use a GIOP_Lite for sending messages? + CORBA::Boolean lite_flag_; + +private: + // @@ Michael: UDP Addition + ACE_Hash_Map_Manager_Ex < ACE_INET_Addr, + TAO_DIOP_Connection_Handler *, + ACE_Hash < ACE_INET_Addr >, + ACE_Equal_To < ACE_INET_Addr >, + ACE_Null_Mutex > svc_handler_table_; + + typedef ACE_Hash_Map_Iterator_Ex < ACE_INET_Addr, + TAO_DIOP_Connection_Handler *, + ACE_Hash < ACE_INET_Addr >, + ACE_Equal_To < ACE_INET_Addr >, + ACE_Null_Mutex > SvcHandlerIterator; +}; + +#endif /* TAO_HAS_DIOP && TAO_HAS_DIOP != 0 */ + +#include "ace/post.h" +#endif /* TAO_DIOP_CONNECTOR_H */ diff --git a/TAO/tao/Strategies/DIOP_Endpoint.cpp b/TAO/tao/Strategies/DIOP_Endpoint.cpp new file mode 100644 index 00000000000..9f059a1ebc3 --- /dev/null +++ b/TAO/tao/Strategies/DIOP_Endpoint.cpp @@ -0,0 +1,192 @@ +// This may look like C, but it's really -*- C++ -*- +// $Id$ + + +#include "DIOP_Endpoint.h" + +#if defined (TAO_HAS_DIOP) && (TAO_HAS_DIOP != 0) + +#include "DIOP_Connection_Handler.h" +#include "tao/debug.h" + +ACE_RCSID(tao, DIOP_Endpoint, "$Id$") + + +#if !defined (__ACE_INLINE__) +# include "DIOP_Endpoint.i" +#endif /* __ACE_INLINE__ */ + +TAO_DIOP_Endpoint::TAO_DIOP_Endpoint (const ACE_INET_Addr &addr, + int use_dotted_decimal_addresses) + : TAO_Endpoint (TAO_TAG_UDP_PROFILE), + host_ (), + port_ (0), + object_addr_ (addr), + /* hint_ (0), */ + next_ (0) +{ + this->set (addr, use_dotted_decimal_addresses); +} + +TAO_DIOP_Endpoint::TAO_DIOP_Endpoint (const char *host, + CORBA::UShort port, + const ACE_INET_Addr &addr) + : TAO_Endpoint (TAO_TAG_UDP_PROFILE), + host_ (), + port_ (port), + object_addr_ (addr), + /* hint_ (0), */ + next_ (0) +{ + if (host != 0) + this->host_ = host; +} + +TAO_DIOP_Endpoint::TAO_DIOP_Endpoint (void) + : TAO_Endpoint (TAO_TAG_UDP_PROFILE), + host_ (), + port_ (0), + object_addr_ (), + /* hint_ (0), */ + next_ (0) +{ +} + +TAO_DIOP_Endpoint::TAO_DIOP_Endpoint (const char *host, + CORBA::UShort port, + CORBA::Short priority) + : TAO_Endpoint (TAO_TAG_UDP_PROFILE), + host_ (), + port_ (port), + object_addr_ (), + /* hint_ (0),*/ + next_ (0) +{ + if (host != 0) + this->host_ = host; + + this->object_addr_.set_type (-1); + this->priority (priority); +} + +TAO_DIOP_Endpoint::~TAO_DIOP_Endpoint (void) +{ + +} + +int +TAO_DIOP_Endpoint::set (const ACE_INET_Addr &addr, + int use_dotted_decimal_addresses) +{ + char tmp_host[MAXHOSTNAMELEN + 1]; + + if (use_dotted_decimal_addresses + || addr.get_host_name (tmp_host, sizeof (tmp_host)) != 0) + { + const char *tmp = addr.get_host_addr (); + if (tmp == 0) + { + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("\n\nTAO (%P|%t) ") + ACE_TEXT ("DIOP_Endpoint::set ") + ACE_TEXT ("- %p\n\n"), + ACE_TEXT ("cannot determine hostname"))); + return -1; + } + else + this->host_ = tmp; + } + else + this->host_ = CORBA::string_dup (tmp_host); + + this->port_ = addr.get_port_number(); + + return 0; +} + +int +TAO_DIOP_Endpoint::addr_to_string (char *buffer, size_t length) +{ + size_t actual_len = + ACE_OS::strlen (this->host_.in ()) // chars in host name + + sizeof (':') // delimiter + + ACE_OS::strlen ("65536") // max port + + sizeof ('\0'); + + if (length < actual_len) + return -1; + + ACE_OS::sprintf (buffer, "%s:%d", + this->host_.in (), this->port_); + + return 0; +} + +const char * +TAO_DIOP_Endpoint::host (const char *h) +{ + this->host_ = h; + + return this->host_.in (); +} + +void +TAO_DIOP_Endpoint::reset_hint (void) +{ + // Commented out for the time being.... + /* if (this->hint_) + this->hint_->cleanup_hint ((void **) &this->hint_); */ +} + +TAO_Endpoint * +TAO_DIOP_Endpoint::next (void) +{ + return this->next_; +} + +TAO_Endpoint * +TAO_DIOP_Endpoint::duplicate (void) +{ + // @@ Bala, we probably need to make sure that the duplicate has the + // same priority as the original. Although it does not matter in + // the context this method is currently used, if somebody ends up + // using this method for some other purpose later, this will be a + // seed for bugs. + + TAO_DIOP_Endpoint *endpoint = 0; + + ACE_NEW_RETURN (endpoint, + TAO_DIOP_Endpoint (this->host_.in (), + this->port_, + this->object_addr_), + 0); + + return endpoint; +} + +CORBA::Boolean +TAO_DIOP_Endpoint::is_equivalent (const TAO_Endpoint *other_endpoint) +{ + TAO_Endpoint *endpt = ACE_const_cast (TAO_Endpoint *, + other_endpoint); + + TAO_DIOP_Endpoint *endpoint = ACE_dynamic_cast (TAO_DIOP_Endpoint *, + endpt); + if (endpoint == 0) + return 0; + + return + this->port_ == endpoint->port_ + && ACE_OS::strcmp (this->host_.in (), endpoint->host_.in ()) == 0; +} + +CORBA::ULong +TAO_DIOP_Endpoint::hash (void) +{ + return + ACE::hash_pjw (this->host_.in ()) + + this->port_; +} + +#endif /* TAO_HAS_DIOP && TAO_HAS_DIOP != 0 */ diff --git a/TAO/tao/Strategies/DIOP_Endpoint.h b/TAO/tao/Strategies/DIOP_Endpoint.h new file mode 100644 index 00000000000..ea1a83eced3 --- /dev/null +++ b/TAO/tao/Strategies/DIOP_Endpoint.h @@ -0,0 +1,144 @@ +// This may look like C, but it's really -*- C++ -*- + + +//============================================================================= +/** + * @file DIOP_Endpoint.h + * + * $Id$ + * + * DIOP implementation of PP Framework Endpoint interface. + * + * @author Michael Kircher + */ +//============================================================================= + + +#ifndef TAO_DIOP_ENDPOINT_H +#define TAO_DIOP_ENDPOINT_H +#include "ace/pre.h" + +#include "tao/corbafwd.h" + +#if defined (TAO_HAS_DIOP) && (TAO_HAS_DIOP != 0) + +#include "tao/Endpoint.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "tao/ORB.h" +#include "ace/INET_Addr.h" +#include "strategies_export.h" + + +class TAO_DIOP_Connection_Handler; + +/** + * @class TAO_DIOP_Endpoint + * + * @brief TAO_DIOP_Endpoint + * + * DIOP-specific implementation of PP Framework Endpoint interface. + */ +class TAO_Strategies_Export TAO_DIOP_Endpoint : public TAO_Endpoint +{ +public: + + friend class TAO_DIOP_Profile; + friend class TAO_SSLIOP_Profile; + + // = Initialization and termination methods. + + /// Default constructor. + TAO_DIOP_Endpoint (void); + + /// Constructor. This is the most efficient constructor since it + /// does not require any address resolution processing. + TAO_DIOP_Endpoint (const char *host, + CORBA::UShort port, + const ACE_INET_Addr &addr); + + /// Constructor. + TAO_DIOP_Endpoint (const ACE_INET_Addr &addr, + int use_dotted_decimal_addresses); + + /// Constructor. This constructor is used when decoding endpoints. + TAO_DIOP_Endpoint (const char *host, + CORBA::UShort port, + CORBA::Short priority); + + /// Destructor. + ~TAO_DIOP_Endpoint (void); + + // = Implementation of abstract TAO_Endpoint methods. See + // Endpoint.h for their documentation. + + virtual TAO_Endpoint *next (void); + virtual int addr_to_string (char *buffer, size_t length); + virtual void reset_hint (void); + + /// Makes a copy of <this> + virtual TAO_Endpoint *duplicate (void); + + /// Return true if this endpoint is equivalent to <other_endpoint>. Two + /// endpoints are equivalent iff their port and host are the same. + CORBA::Boolean is_equivalent (const TAO_Endpoint *other_endpoint); + + /// Return a hash value for this object. + CORBA::ULong hash (void); + + // Allocates memory and returns a copy of <this> + + // = DIOP_Endpoint-specific methods. + + /// Return a reference to the <object_addr>. + const ACE_INET_Addr &object_addr (void) const; + + /// Return a pointer to the host string. This object maintains + /// ownership of this string. + const char *host (void) const; + + /// Copy the string <h> into <host_> and return the resulting pointer. + /// This object maintains ownership of this string. + const char *host (const char *h); + + /// Return the port number. + CORBA::UShort port (void) const; + + /// Set the port number. + CORBA::UShort port (CORBA::UShort p); + + //TAO_DIOP_Connection_Handler *&hint (void); + // Access to our <hint_>. + +private: + + /// Helper method for setting INET_Addr. + int set (const ACE_INET_Addr &addr, + int use_dotted_decimal_addresses); + + /// String representing the host name. + CORBA::String_var host_; + + /// TCP port number. + CORBA::UShort port_; + + /// Cached instance of <ACE_INET_Addr> for use in making + /// invocations, etc. + ACE_INET_Addr object_addr_; + + /// DIOP Endpoints can be stringed into a list. Return the next + /// endpoint in the list, if any. + TAO_DIOP_Endpoint *next_; +}; + +#if defined (__ACE_INLINE__) +# include "DIOP_Endpoint.i" +#endif /* __ACE_INLINE__ */ + +#endif /* TAO_HAS_DIOP && TAO_HAS_DIOP != 0 */ + +#include "ace/post.h" +#endif /* TAO_DIOP_PROFILE_H */ diff --git a/TAO/tao/Strategies/DIOP_Endpoint.i b/TAO/tao/Strategies/DIOP_Endpoint.i new file mode 100644 index 00000000000..ad9b9d97a30 --- /dev/null +++ b/TAO/tao/Strategies/DIOP_Endpoint.i @@ -0,0 +1,52 @@ +// -*- C++ -*- +// $Id$ + +ACE_INLINE const ACE_INET_Addr & +TAO_DIOP_Endpoint::object_addr (void) const +{ + // The object_addr_ is initialized here, rather than at IOR decode + // time for several reasons: + // 1. A request on the object may never be invoked. + // 2. The DNS setup may have changed dynamically. + // ...etc.. + + // We need to modify the object_addr_ in this method. Do so using a + // non-const copy of the <this> pointer. + TAO_DIOP_Endpoint *endpoint = + ACE_const_cast (TAO_DIOP_Endpoint *, + this); + + if (this->object_addr_.get_type () != AF_INET + && endpoint->object_addr_.set (this->port_, + this->host_.in ()) == -1) + { + // If this call fails, it most likely due a hostname lookup + // failure caused by a DNS misconfiguration. If a request is + // made to the object at the given host and port, then a + // CORBA::TRANSIENT() exception should be thrown. + + // Invalidate the ACE_INET_Addr. This is used as a flag to + // denote that ACE_INET_Addr initialization failed. + endpoint->object_addr_.set_type (-1); + } + + return this->object_addr_; +} + +ACE_INLINE const char * +TAO_DIOP_Endpoint::host (void) const +{ + return this->host_.in (); +} + +ACE_INLINE CORBA::UShort +TAO_DIOP_Endpoint::port (void) const +{ + return this->port_; +} + +ACE_INLINE CORBA::UShort +TAO_DIOP_Endpoint::port (CORBA::UShort p) +{ + return this->port_ = p; +} diff --git a/TAO/tao/Strategies/DIOP_Factory.cpp b/TAO/tao/Strategies/DIOP_Factory.cpp new file mode 100644 index 00000000000..3d0d8cc1f7b --- /dev/null +++ b/TAO/tao/Strategies/DIOP_Factory.cpp @@ -0,0 +1,90 @@ +// $Id$ + +#include "DIOP_Factory.h" + +#if defined (TAO_HAS_DIOP) && (TAO_HAS_DIOP != 0) + +#include "DIOP_Acceptor.h" +#include "DIOP_Connector.h" + +ACE_RCSID(TAO_Strategies, DIOP_Factory, "$Id$") + +static const char prefix_[] = "diop"; + +TAO_DIOP_Protocol_Factory::TAO_DIOP_Protocol_Factory (void) + : TAO_Protocol_Factory (TAO_TAG_UDP_PROFILE), + major_ (TAO_DEF_GIOP_MAJOR), + minor_ (TAO_DEF_GIOP_MINOR) +{ +} + +TAO_DIOP_Protocol_Factory::~TAO_DIOP_Protocol_Factory (void) +{ +} + +int +TAO_DIOP_Protocol_Factory::match_prefix (const ACE_CString &prefix) +{ + // Check for the proper prefix for this protocol. + return (ACE_OS::strcasecmp (prefix.c_str (), ::prefix_) == 0); +} + +const char * +TAO_DIOP_Protocol_Factory::prefix (void) const +{ + return ::prefix_; +} + +char +TAO_DIOP_Protocol_Factory::options_delimiter (void) const +{ + return '/'; +} + +TAO_Acceptor * +TAO_DIOP_Protocol_Factory::make_acceptor (void) +{ + TAO_Acceptor *acceptor = 0; + + ACE_NEW_RETURN (acceptor, + TAO_DIOP_Acceptor, + 0); + + return acceptor; +} + +int +TAO_DIOP_Protocol_Factory::init (int /* argc */, + char* /* argv */ []) +{ + return 0; +} + +TAO_Connector * +TAO_DIOP_Protocol_Factory::make_connector (void) +{ + TAO_Connector *connector = 0; + + ACE_NEW_RETURN (connector, + TAO_DIOP_Connector, + 0); + return connector; +} + +int +TAO_DIOP_Protocol_Factory::requires_explicit_endpoint (void) const +{ + return 0; +} + +ACE_STATIC_SVC_DEFINE (TAO_DIOP_Protocol_Factory, + ACE_TEXT ("DIOP_Factory"), + ACE_SVC_OBJ_T, + &ACE_SVC_NAME (TAO_DIOP_Protocol_Factory), + ACE_Service_Type::DELETE_THIS | + ACE_Service_Type::DELETE_OBJ, + 0) + +ACE_FACTORY_DEFINE (TAO_Strategies, TAO_DIOP_Protocol_Factory) + +#endif /* TAO_HAS_DIOP && TAO_HAS_DIOP != 0 */ diff --git a/TAO/tao/Strategies/DIOP_Factory.h b/TAO/tao/Strategies/DIOP_Factory.h new file mode 100644 index 00000000000..a469c29be6e --- /dev/null +++ b/TAO/tao/Strategies/DIOP_Factory.h @@ -0,0 +1,72 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file DIOP_Factory.h + * + * $Id$ + * + * @author Michael Kircher + */ +//============================================================================= + + +#ifndef TAO_DIOP_FACTORY_H +#define TAO_DIOP_FACTORY_H +#include "ace/pre.h" + +#include "tao/corbafwd.h" + +#if defined (TAO_HAS_DIOP) && (TAO_HAS_DIOP != 0) + +#include "tao/Protocol_Factory.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/Service_Config.h" +#include "strategies_export.h" + +class TAO_Acceptor; +class TAO_Connector; + +class TAO_Strategies_Export TAO_DIOP_Protocol_Factory : public TAO_Protocol_Factory +{ +public: + TAO_DIOP_Protocol_Factory (void); + virtual ~TAO_DIOP_Protocol_Factory (void); + + // = Service Configurator hooks. + /// Dynamic linking hook + virtual int init (int argc, char* argv[]); + + /// Verify prefix is a match + virtual int match_prefix (const ACE_CString &prefix); + + /// Returns the prefix used by the protocol. + virtual const char *prefix (void) const; + + /// Return the character used to mark where an endpoint ends and + /// where its options begin. + virtual char options_delimiter (void) const; + + // = Check Protocol_Factory.h for a description of these methods. + virtual TAO_Acceptor *make_acceptor (void); + virtual TAO_Connector *make_connector (void); + virtual int requires_explicit_endpoint (void) const; + +private: + /// Changing the version number can be used to provide backwards + /// compatibility with old clients. + int major_; + int minor_; +}; + +ACE_STATIC_SVC_DECLARE (TAO_DIOP_Protocol_Factory) +ACE_FACTORY_DECLARE (TAO_Strategies, TAO_DIOP_Protocol_Factory) + +#endif /* TAO_HAS_DIOP && TAO_HAS_DIOP != 0 */ + +#include "ace/post.h" +#endif /* TAO_DIOP_FACTORY_H */ diff --git a/TAO/tao/Strategies/DIOP_Profile.cpp b/TAO/tao/Strategies/DIOP_Profile.cpp new file mode 100644 index 00000000000..f13a7205458 --- /dev/null +++ b/TAO/tao/Strategies/DIOP_Profile.cpp @@ -0,0 +1,677 @@ +// This may look like C, but it's really -*- C++ -*- +// $Id$ + + +#include "DIOP_Profile.h" + +#if defined (TAO_HAS_DIOP) && (TAO_HAS_DIOP != 0) + +#include "tao/CDR.h" +#include "tao/Environment.h" +#include "tao/ORB.h" +#include "tao/ORB_Core.h" +#include "tao/debug.h" +#include "tao/iiop_endpoints.h" + +ACE_RCSID (DIOP, + DIOP_Profile, + "$Id$") + +#if !defined (__ACE_INLINE__) +# include "DIOP_Profile.i" +#endif /* __ACE_INLINE__ */ + +static const char prefix_[] = "diop"; + +const char TAO_DIOP_Profile::object_key_delimiter_ = '/'; + +char +TAO_DIOP_Profile::object_key_delimiter (void) const +{ + return TAO_DIOP_Profile::object_key_delimiter_; +} + + +TAO_DIOP_Profile::TAO_DIOP_Profile (const ACE_INET_Addr &addr, + const TAO_ObjectKey &object_key, + const TAO_GIOP_Message_Version &version, + TAO_ORB_Core *orb_core) + : TAO_Profile (TAO_TAG_UDP_PROFILE, orb_core, version), + endpoint_ (addr, + orb_core->orb_params ()->use_dotted_decimal_addresses ()), + count_ (1), + object_key_ (object_key), + tagged_profile_ () +{ +} + +TAO_DIOP_Profile::TAO_DIOP_Profile (const char* host, + CORBA::UShort port, + const TAO_ObjectKey &object_key, + const ACE_INET_Addr &addr, + const TAO_GIOP_Message_Version &version, + TAO_ORB_Core *orb_core) + : TAO_Profile (TAO_TAG_UDP_PROFILE, orb_core, version), + endpoint_ (host, port, addr), + count_ (1), + object_key_ (object_key), + tagged_profile_ () +{ +} + +TAO_DIOP_Profile::TAO_DIOP_Profile (TAO_ORB_Core *orb_core) + : TAO_Profile (TAO_TAG_UDP_PROFILE, + orb_core, + TAO_GIOP_Message_Version (TAO_DEF_GIOP_MAJOR, TAO_DEF_GIOP_MINOR)), + endpoint_ (), + count_ (1), + object_key_ (), + tagged_profile_ () +{ +} + +TAO_DIOP_Profile::~TAO_DIOP_Profile (void) +{ + // Clean up the list of endpoints since we own it. + // Skip the head, since it is not dynamically allocated. + TAO_Endpoint *tmp = 0; + + for (TAO_Endpoint *next = this->endpoint ()->next (); + next != 0; + next = tmp) + { + tmp = next->next (); + delete next; + } +} + +// return codes: +// -1 -> error +// 0 -> can't understand this version +// 1 -> success. + +int +TAO_DIOP_Profile::decode (TAO_InputCDR& cdr) +{ + CORBA::ULong encap_len = cdr.length (); + + // Read and verify major, minor versions, ignoring DIOP profiles + // whose versions we don't understand. + CORBA::Octet major = 0, minor = 0; + + if (!(cdr.read_octet (major) + && major == TAO_DEF_GIOP_MAJOR + && cdr.read_octet (minor))) + { + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) DIOP_Profile::decode - v%d.%d\n"), + major, + minor)); + return -1; + } + + this->version_.major = major; + + if (minor <= TAO_DEF_GIOP_MINOR) + this->version_.minor = minor; + + // Decode host and port into the <endpoint_>. + if (cdr.read_string (this->endpoint_.host_.out ()) == 0 + || cdr.read_ushort (this->endpoint_.port_) == 0) + { + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) DIOP_Profile::decode - ") + ACE_TEXT ("error while decoding host/port"))); + return -1; + } + + // ... and object key. + + if ((cdr >> this->object_key_) == 0) + return -1; + + // Tagged Components *only* exist after version 1.0! + // For GIOP 1.2, DIOP and GIOP have same version numbers! + if (this->version_.major > 1 + || this->version_.minor > 0) + 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 DIOP profile data\n"), + cdr.length (), + encap_len)); + + if (this->decode_endpoints () == -1) + return -1; + + if (cdr.good_bit ()) + { + // Invalidate the object_addr_ until first access. + this->endpoint_.object_addr_.set_type (-1); + + return 1; + } + + return -1; +} + +void +TAO_DIOP_Profile::parse_string (const char *string, + CORBA::Environment &ACE_TRY_ENV) +{ + if (!string || !*string) + { + 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 (CORBA::INV_OBJREF ( + CORBA_SystemException::_tao_minor_code ( + TAO_DEFAULT_MINOR_CODE, + EINVAL), + CORBA::COMPLETED_NO)); + } + + // 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 (CORBA::INV_OBJREF ( + CORBA_SystemException::_tao_minor_code ( + TAO_DEFAULT_MINOR_CODE, + EINVAL), + CORBA::COMPLETED_NO)); + } + + // 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 ("DIOP_Profile::parse_string ") + ACE_TEXT ("- %p\n\n"), + ACE_TEXT ("cannot determine hostname"))); + + // @@ What's the right exception to throw here? + ACE_THROW (CORBA::INV_OBJREF ( + CORBA_SystemException::_tao_minor_code ( + TAO_DEFAULT_MINOR_CODE, + EINVAL), + CORBA::COMPLETED_NO)); + } + 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) DIOP_Profile::parse_string - \n") + ACE_TEXT ("TAO (%P|%t) ACE_INET_Addr::set () failed"))); + } + + // @@ What's the right exception to throw here? + ACE_THROW (CORBA::INV_OBJREF ( + CORBA_SystemException::_tao_minor_code ( + TAO_DEFAULT_MINOR_CODE, + EINVAL), + CORBA::COMPLETED_NO)); + } + + start = ++okd; // increment past the object key separator + + TAO_ObjectKey::decode_string_to_sequence (this->object_key_, start); +} + +CORBA::Boolean +TAO_DIOP_Profile::is_equivalent (const TAO_Profile *other_profile) +{ + + if (other_profile->tag () != TAO_TAG_UDP_PROFILE) + return 0; + + const TAO_DIOP_Profile *op = + ACE_dynamic_cast (const TAO_DIOP_Profile *, other_profile); + + + if (!(this->object_key_ == op->object_key_ + && this->version_ == op->version_ + && this->count_ == op->count_)) + return 0; + + // Check endpoints equivalence. + const TAO_DIOP_Endpoint *other_endp = &op->endpoint_; + for (TAO_DIOP_Endpoint *endp = &this->endpoint_; + endp != 0; + endp = endp->next_) + { + if (endp->is_equivalent (other_endp)) + other_endp = other_endp->next_; + else + return 0; + } + + return 1; +} + +CORBA::ULong +TAO_DIOP_Profile::hash (CORBA::ULong max, + CORBA::Environment &) +{ + // Get the hashvalue for all endpoints. + CORBA::ULong hashval = 0; + for (TAO_DIOP_Endpoint *endp = &this->endpoint_; + endp != 0; + endp = endp->next_) + { + hashval += endp->hash (); + } + + hashval += this->version_.minor; + hashval += this->tag (); + + if (this->object_key_.length () >= 4) + { + hashval += this->object_key_ [1]; + hashval += this->object_key_ [3]; + } + + return hashval % max; +} + +TAO_Endpoint* +TAO_DIOP_Profile::endpoint (void) +{ + return &this->endpoint_; +} + +size_t +TAO_DIOP_Profile::endpoint_count (void) +{ + return this->count_; +} + +void +TAO_DIOP_Profile::add_endpoint (TAO_DIOP_Endpoint *endp) +{ + endp->next_ = this->endpoint_.next_; + this->endpoint_.next_ = endp; + + this->count_++; +} + +char * +TAO_DIOP_Profile::to_string (CORBA::Environment &) +{ + CORBA::String_var key; + TAO_ObjectKey::encode_sequence_to_string (key.inout(), + this->object_key_); + + 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 */ + + ACE_OS::strlen (this->endpoint_.host ()) + + 1 /* colon separator */ + + 5 /* port number */ + + 1 /* object key separator */ + + ACE_OS::strlen (key.in ())); + + char * buf = CORBA::string_alloc (buflen); + + static const char digits [] = "0123456789"; + + ACE_OS::sprintf (buf, + "%sloc://%c.%c@%s:%d%c%s", + ::prefix_, + digits [this->version_.major], + digits [this->version_.minor], + this->endpoint_.host (), + this->endpoint_.port (), + this->object_key_delimiter_, + key.in ()); + return buf; +} + +const char * +TAO_DIOP_Profile::prefix (void) +{ + return ::prefix_; +} + +int +TAO_DIOP_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 ()->output_cdr_msgblock_allocator (), + this->orb_core ()->orb_params ()->cdr_memcpy_tradeoff (), + TAO_DEF_GIOP_MAJOR, + TAO_DEF_GIOP_MINOR, + 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_DIOP_Profile::create_tagged_profile (void) +{ + // Check whether we have already created the TaggedProfile + if (this->tagged_profile_.profile_data.get_buffer () == 0) + { + // As we have not created we will now create the TaggedProfile + this->tagged_profile_.tag = TAO_TAG_UDP_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 ()->output_cdr_msgblock_allocator (), + this->orb_core ()->orb_params ()->cdr_memcpy_tradeoff (), + TAO_DEF_GIOP_MAJOR, + TAO_DEF_GIOP_MINOR, + 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_DIOP_Profile::create_profile_body (TAO_OutputCDR &encap) const +{ + encap.write_octet (TAO_ENCAP_BYTE_ORDER); + + // The GIOP version + encap.write_octet (this->version_.major); + encap.write_octet (this->version_.minor); + + // STRING hostname from profile + encap.write_string (this->endpoint_.host ()); + + // UNSIGNED SHORT port number + encap.write_ushort (this->endpoint_.port ()); + + // OCTET SEQUENCE for object key + encap << this->object_key_; + + if (this->version_.major > 1 + || this->version_.minor > 0) + this->tagged_components ().encode (encap); +} + +int +TAO_DIOP_Profile::encode_endpoints (void) +{ + // Create a data structure and fill it with endpoint info for wire + // transfer. + // We include information for the head of the list + // together with other endpoints because even though its addressing + // info is transmitted using standard ProfileBody components, its + // priority is not! + + TAO_IIOPEndpointSequence endpoints; + endpoints.length (this->count_); + + const TAO_DIOP_Endpoint *endpoint = &this->endpoint_; + for (size_t i = 0; + i < this->count_; + ++i) + { + endpoints[i].host = endpoint->host (); + endpoints[i].port = endpoint->port (); + endpoints[i].priority = endpoint->priority (); + + endpoint = endpoint->next_; + } + + // Encode the data structure. + TAO_OutputCDR out_cdr; + if ((out_cdr << ACE_OutputCDR::from_boolean (TAO_ENCAP_BYTE_ORDER) + == 0) + || (out_cdr << endpoints) == 0) + return -1; + CORBA::ULong length = out_cdr.total_length (); + + IOP::TaggedComponent tagged_component; + tagged_component.tag = TAO_TAG_ENDPOINTS; + 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. + tagged_components_.set_component (tagged_component); + + return 0; +} + +int +TAO_DIOP_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_IIOPEndpointSequence 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_DIOP_Endpoint *endpoint = 0; + ACE_NEW_RETURN (endpoint, + TAO_DIOP_Endpoint (endpoints[i].host, + endpoints[i].port, + endpoints[i].priority), + -1); + + this->add_endpoint (endpoint); + } + } + + return 0; +} + +#endif /* TAO_HAS_DIOP && TAO_HAS_DIOP != 0 */ diff --git a/TAO/tao/Strategies/DIOP_Profile.h b/TAO/tao/Strategies/DIOP_Profile.h new file mode 100644 index 00000000000..4dc557db187 --- /dev/null +++ b/TAO/tao/Strategies/DIOP_Profile.h @@ -0,0 +1,206 @@ +// This may look like C, but it's really -*- C++ -*- + + +//============================================================================= +/** + * @file DIOP_Profile.h + * + * $Id$ + * + * DIOP profile specific processing + * + * + * @author Michael Kircher + */ +//============================================================================= + + +#ifndef TAO_DIOP_PROFILE_H +#define TAO_DIOP_PROFILE_H +#include "ace/pre.h" + +#include "tao/corbafwd.h" + +#if defined (TAO_HAS_DIOP) && (TAO_HAS_DIOP != 0) + +#include "tao/Profile.h" +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "tao/Object_KeyC.h" +#include "DIOP_Endpoint.h" + +#include "ace/Synch.h" + + +// TAO DIOP_Profile concrete Profile definitions +/** + * @class TAO_DIOP_Profile + * + * @brief This class defines the protocol specific attributes required + * for locating ORBs over a TCP/IP network. + * + * This class defines the DIOP profile as specified in the CORBA + * specification. + */ +class TAO_Strategies_Export TAO_DIOP_Profile : public TAO_Profile +{ +public: + /// The object key delimiter that DIOP uses or expects. + static const char object_key_delimiter_; + virtual char object_key_delimiter (void) const; + + /// Return the char string prefix. + static const char *prefix (void); + + /// Profile constructor, same as above except the object_key has + /// already been marshaled. + TAO_DIOP_Profile (const ACE_INET_Addr &addr, + const TAO_ObjectKey &object_key, + const TAO_GIOP_Message_Version &version, + TAO_ORB_Core *orb_core); + + /// Profile constructor, this is the most efficient since it + /// doesn't require any address resolution processing. + TAO_DIOP_Profile (const char *host, + CORBA::UShort port, + const TAO_ObjectKey &object_key, + const ACE_INET_Addr &addr, + const TAO_GIOP_Message_Version &version, + TAO_ORB_Core *orb_core); + + + /// Profile constructor, default. + TAO_DIOP_Profile (TAO_ORB_Core *orb_core); + + /// Destructor is to be called only through <_decr_refcnt>. + ~TAO_DIOP_Profile (void); + + /// Initialize this object using the given input string. + /// Url-style string contain only one endpoint. + virtual void parse_string (const char *string, + CORBA::Environment &ACE_TRY_ENV); + + /** + * Return a string representation for this profile. + * client must deallocate memory. + * This is used to create url-style reference. Only one + * endpoint is included into the string. + */ + virtual char * to_string (CORBA::Environment &ACE_TRY_ENV); + + /// Initialize this object using the given CDR octet string. + virtual int decode (TAO_InputCDR& cdr); + + /// Encode this profile in a stream, i.e. marshal it. + virtual int encode (TAO_OutputCDR &stream) const; + + /** + * Encodes this profile's endpoints into a tagged component. + * This is done only if RTCORBA is enabled, since currently this is + * the only case when we have more than one endpoint per profile. + * Returns 0 on success and -1 on failure. + * + * Endpoints are transmitted using TAO-proprietory tagged component. + * Component tag is TAO_TAG_ENDPOINTS and component data is an + * encapsulation of a sequence of structs, each representing a + * single endpoint. Data format is specified in iiop_endpoins.pidl. + * + * Multiple TAG_ALTERNATE_DIOP_ADDRESS components can be used + * instead of a single proprietory component to transmit multiple + * endpoints. This is somewhat slower and less convenient. Also, + * TAG_ALTERNATE_DIOP_ADDRESS does not provide for transmission of + * endpoint priorities. + * + */ + virtual int encode_endpoints (void); + + /// @@ deprecated. return a reference to the Object Key. + virtual const TAO_ObjectKey &object_key (void) const; + + /// Return a pointer to the Object Key. The caller owns the memory + /// allocated for the returned key. + virtual TAO_ObjectKey *_key (void) const; + + /// Return pointer to the head of this profile's endpoints list. + virtual TAO_Endpoint *endpoint (void); + + /// Return how many endpoints this profile contains. + virtual size_t endpoint_count (void); + + /** + * Add <endp> to this profile's list of endpoints (it is inserted + * next to the head of the list). This profiles takes ownership of + * <endp>. + */ + void add_endpoint (TAO_DIOP_Endpoint *endp); + + /** + * Return true if this profile is equivalent to other_profile. Two + * profiles are equivalent iff their tag, object_key, version and + * all endpoints are the same. + */ + virtual CORBA::Boolean is_equivalent (const TAO_Profile *other_profile); + + /// Return a hash value for this object. + virtual CORBA::ULong hash (CORBA::ULong max, + CORBA::Environment &ACE_TRY_ENV); + + /// Please refer to Profile.h for the documentation of this + /// function. + virtual IOP::TaggedProfile &create_tagged_profile (void); + +private: + + /// Creates an encapsulation of the ProfileBody struct in the <cdr> + void create_profile_body (TAO_OutputCDR &cdr) const; + + /** + * Helper for <decode>. Decodes endpoints from a tagged component. + * Decode only if RTCORBA is enabled. Furthermore, we may not find + * TAO_TAG_ENDPOINTS component, e.g., if we are talking to nonRT + * version of TAO or some other ORB. This is not an error, and we + * must proceed. Return 0 on success and -1 on failure. + */ + int decode_endpoints (void); + +protected: + + /** + * Head of this profile's list of endpoints. This endpoint is not + * dynamically allocated because a profile always contains at least + * one endpoint. + * + * Currently, a profile contains more than one endpoint, i.e., + * list contains more than just the head, only when RTCORBA is enabled. + * However, in the near future, this will be used in nonRT + * mode as well, e.g., to support TAG_ALTERNATE_DIOP_ADDRESS + * feature. + * Addressing info of the default endpoint, i.e., head of the list, + * is transmitted using standard DIOP ProfileBody components. See + * <encode_endpoints> method documentation above for how the rest of + * the endpoint list is transmitted. + */ + TAO_DIOP_Endpoint endpoint_; + + /// Number of endpoints in the list headed by <endpoint_>. + size_t count_; + +private: + + /// object_key associated with this profile. + TAO_ObjectKey object_key_; + + /// Our tagged profile + IOP::TaggedProfile tagged_profile_; +}; + +#if defined (__ACE_INLINE__) +# include "DIOP_Profile.i" +#endif /* __ACE_INLINE__ */ + +#endif /* TAO_HAS_DIOP && TAO_HAS_DIOP != 0 */ + +#include "ace/post.h" +#endif /* TAO_DIOP_PROFILE_H */ diff --git a/TAO/tao/Strategies/DIOP_Profile.i b/TAO/tao/Strategies/DIOP_Profile.i new file mode 100644 index 00000000000..2c18a75ae92 --- /dev/null +++ b/TAO/tao/Strategies/DIOP_Profile.i @@ -0,0 +1,24 @@ +// -*- C++ -*- +// $Id$ + +ACE_INLINE const TAO_ObjectKey & +TAO_DIOP_Profile::object_key (void) const +{ + return this->object_key_; +} + +ACE_INLINE TAO_ObjectKey * +TAO_DIOP_Profile::_key (void) const +{ + TAO_ObjectKey *key = 0; + + ACE_NEW_RETURN (key, + TAO_ObjectKey (this->object_key_), + 0); + + return key; +} + + + + diff --git a/TAO/tao/Strategies/DIOP_Transport.cpp b/TAO/tao/Strategies/DIOP_Transport.cpp new file mode 100644 index 00000000000..28bfc2c927a --- /dev/null +++ b/TAO/tao/Strategies/DIOP_Transport.cpp @@ -0,0 +1,546 @@ +// This may look like C, but it's really -*- C++ -*- +// $Id$ + +#include "DIOP_Transport.h" + +#if defined (TAO_HAS_DIOP) && (TAO_HAS_DIOP != 0) + +#include "DIOP_Connection_Handler.h" +#include "DIOP_Acceptor.h" +#include "DIOP_Profile.h" +#include "tao/Acceptor_Registry.h" +#include "tao/operation_details.h" +#include "tao/Timeprobe.h" +#include "tao/CDR.h" +#include "tao/Transport_Mux_Strategy.h" +#include "tao/Wait_Strategy.h" +#include "tao/Sync_Strategies.h" +#include "tao/Stub.h" +#include "tao/ORB_Core.h" +#include "tao/debug.h" +#include "tao/GIOP_Message_Base.h" +#include "tao/GIOP_Message_Lite.h" + +#if !defined (__ACE_INLINE__) +# include "DIOP_Transport.i" +#endif /* ! __ACE_INLINE__ */ + +ACE_RCSID (tao, DIOP_Transport, "$Id$") + +TAO_DIOP_Transport::TAO_DIOP_Transport (TAO_DIOP_Connection_Handler *handler, + TAO_ORB_Core *orb_core, + CORBA::Boolean flag) + : TAO_Transport (TAO_TAG_UDP_PROFILE, + orb_core) + , connection_handler_ (handler) + , messaging_object_ (0) +{ + // @@ Michael: Set the input CDR size to ACE_MAX_DGRAM_SIZE so that + // we read the whole UDP packet on a single read. + if (flag) + { + // Use the lite version of the protocol + ACE_NEW (this->messaging_object_, + TAO_GIOP_Message_Lite (orb_core, + ACE_MAX_DGRAM_SIZE)); + } + else + { + // Use the normal GIOP object + ACE_NEW (this->messaging_object_, + TAO_GIOP_Message_Base (orb_core, + ACE_MAX_DGRAM_SIZE)); + } +} + +TAO_DIOP_Transport::~TAO_DIOP_Transport (void) +{ + delete this->messaging_object_; +} + +ACE_Event_Handler * +TAO_DIOP_Transport::event_handler_i (void) +{ + return this->connection_handler_; +} + +TAO_Pluggable_Messaging * +TAO_DIOP_Transport::messaging_object (void) +{ + return this->messaging_object_; +} + +ssize_t +TAO_DIOP_Transport::send_i (iovec *iov, int iovcnt, + size_t &bytes_transferred, + const ACE_Time_Value *) +{ + const ACE_INET_Addr &addr = this->connection_handler_->addr (); + ssize_t retval = this->connection_handler_->dgram ().send (iov, + iovcnt, + addr); + if (retval > 0) + bytes_transferred = retval; + + // @@ Michael: + // Always return a positive number of bytes sent, as we do + // not handle sending errors in DIOP. + return 1; +} + +ssize_t +TAO_DIOP_Transport::recv_i (char *buf, + size_t len, + const ACE_Time_Value * /* max_wait_time */) +{ + ACE_INET_Addr from_addr; + + ssize_t n = this->connection_handler_->dgram ().recv (buf, + len, + from_addr); + + if (TAO_debug_level > 0) + { + ACE_DEBUG ((LM_DEBUG, + "TAO_DIOP_Transport::recv_i: received %d bytes from %s:%d %d\n", + n, + from_addr.get_host_name (), + from_addr.get_port_number (), + errno)); + } + + // Remember the from addr to eventually use it as remote + // addr for the reply. + this->connection_handler_->addr (from_addr); + + return n; +} + + +int +TAO_DIOP_Transport::read_process_message (ACE_Time_Value *max_wait_time, + int block) +{ + // Read the message of the socket + int result = this->messaging_object_->read_message (this, + block, + max_wait_time); + + if (result == -1) + { + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - %p\n"), + ACE_TEXT ("DIOP_Transport::read_process_message, failure in read_message ()"))); + + this->tms_->connection_closed (); + return -1; + } + if (result < 2) + return result; + + // Now we know that we have been able to read the complete message + // here.. We loop here to see whether we have read more than one + // message in our read. + // Set the result state + result = 1; + + // See we use the reactor semantics again + while (result > 0) + { + result = this->process_message (); + } + + return result; +} + + +int +TAO_DIOP_Transport::register_handler_i (void) +{ + // @@ Michael: + // + // We do never register register the handler with the reactor + // as we never need to be informed about any incoming data, + // assuming we only use one-ways. + // If we would register and ICMP Messages would arrive, e.g + // due to a not reachable server, we would get informed - as this + // disturbs the general DIOP assumptions of not being + // interested in any network failures, we ignore ICMP messages. + return 0; + /* + // @@ It seems like this method should go away, the right reactor is + // picked at object creation time. + ACE_Reactor *r = this->orb_core_->reactor (); + + if (r == this->connection_handler_->reactor ()) + return 0; + + // Set the flag in the Connection Handler + this->connection_handler_->is_registered (1); + + + // Register the handler with the reactor + return r->register_handler (this->connection_handler_, + ACE_Event_Handler::READ_MASK); + */ +} + + +int +TAO_DIOP_Transport::send_request (TAO_Stub *stub, + TAO_ORB_Core *orb_core, + TAO_OutputCDR &stream, + int two_way, + ACE_Time_Value *max_wait_time) +{ + if (this->ws_->sending_request (orb_core, + two_way) == -1) + return -1; + + if (this->send_message (stream, + stub, + two_way, + max_wait_time) == -1) + + return -1; + + return this->idle_after_send (); +} + +int +TAO_DIOP_Transport::send_message (TAO_OutputCDR &stream, + TAO_Stub *stub, + int twoway, + ACE_Time_Value *max_wait_time) +{ + // Format the message in the stream first + if (this->messaging_object_->format_message (stream) != 0) + return -1; + + // Strictly speaking, should not need to loop here because the + // socket never gets set to a nonblocking mode ... some Linux + // versions seem to need it though. Leaving it costs little. + + // This guarantees to send all data (bytes) or return an error. + ssize_t n = this->send_message_i (stub, + twoway, + stream.begin (), + max_wait_time); + + if (n == -1) + { + if (TAO_debug_level) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO: (%P|%t|%N|%l) closing transport %d after fault %p\n"), + this->id (), + ACE_TEXT ("send_message ()\n"))); + + return -1; + } + + return 1; +} + + + +int +TAO_DIOP_Transport::messaging_init (CORBA::Octet major, + CORBA::Octet minor) +{ + this->messaging_object_->init (major, + minor); + return 1; +} + +// @@ Frank: Hopefully DIOP doesn't need this +/* +int +TAO_DIOP_Transport::tear_listen_point_list (TAO_InputCDR &cdr) +{ + 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)); + + DIOP::ListenPointList listen_list; + if ((cdr >> listen_list) == 0) + return -1; + + // As we have received a bidirectional information, set the flag to + // 1 + this->bidirectional_flag (1); + return this->connection_handler_->process_listen_point_list (listen_list); +} +*/ + +int +TAO_DIOP_Transport::process_message (void) +{ + // Check whether we have messages for processing + int retval = + this->messaging_object_->more_messages (); + + if (retval <= 0) + return retval; + + // Get the <message_type> that we have received + TAO_Pluggable_Message_Type t = + this->messaging_object_->message_type (); + + + int result = 0; + if (t == TAO_PLUGGABLE_MESSAGE_CLOSECONNECTION) + { + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - %p\n"), + ACE_TEXT ("Close Connection Message recd \n"))); + + this->tms_->connection_closed (); + } + else if (t == TAO_PLUGGABLE_MESSAGE_REQUEST) + { + if (this->messaging_object_->process_request_message (this, + this->orb_core ()) == -1) + return -1; + } + else if (t == TAO_PLUGGABLE_MESSAGE_REPLY) + { + TAO_Pluggable_Reply_Params params (this->orb_core ()); + if (this->messaging_object_->process_reply_message (params) == -1) + { + + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - %p\n"), + ACE_TEXT ("DIOP_Transport::process_message, process_reply_message ()"))); + + this->messaging_object_->reset (); + this->tms_->connection_closed (); + return -1; + } + + + result = + this->tms_->dispatch_reply (params); + + // @@ Somehow it seems dangerous to reset the state *after* + // dispatching the request, what if another threads receives + // another reply in the same connection? + // My guess is that it works as follows: + // - For the exclusive case there can be no such thread. + // - The the muxed case each thread has its own message_state. + // I'm pretty sure this comment is right. Could somebody else + // please look at it and confirm my guess? + + // @@ The above comment was found in the older versions of the + // code. The code was also written in such a way that, when + // the client thread on a call from handle_input () from the + // reactor a call would be made on the handle_client_input + // (). The implementation of handle_client_input () looked so + // flaky. It used to create a message state upon entry in to + // the function using the TMS and destroy that on exit. All + // this was fine _theoretically_ for multiple threads. But + // the flakiness was originating in the implementation of + // get_message_state () where we were creating message state + // only once and dishing it out for every thread till one of + // them destroy's it. So, it looked broken. That has been + // changed. Why?. To my knowledge, the reactor does not call + // handle_input () on two threads at the same time. So, IMHO + // that defeats the purpose of creating a message state for + // every thread. This is just my guess. If we run in to + // problems this place needs to be revisited. If someone else + // is going to take a look please contact bala@cs.wustl.edu + // for details on this-- Bala + + + + if (result == -1) + { + // Something really critical happened, we will forget about + // every reply on this connection. + if (TAO_debug_level > 0) + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("TAO (%P|%t) : DIOP_Transport::") + ACE_TEXT ("process_message - ") + ACE_TEXT ("dispatch reply failed\n"))); + + this->messaging_object_->reset (); + this->tms_->connection_closed (); + return -1; + } + + if (result == 0) + { + this->messaging_object_->reset (); + + // The reply dispatcher was no longer registered. + // This can happened when the request/reply + // times out. + // To throw away all registered reply handlers is + // not the right thing, as there might be just one + // old reply coming in and several valid new ones + // pending. If we would invoke <connection_closed> + // we would throw away also the valid ones. + //return 0; + } + + + // This is a NOOP for the Exclusive request case, but it actually + // destroys the stream in the muxed case. + //this->tms_->destroy_message_state (message_state); + } + else if (t == TAO_PLUGGABLE_MESSAGE_MESSAGERROR) + { + return -1; + } + + return 1; +} + +// @@ Frank: Hopefully DIOP doesn't need this +/* +void +TAO_DIOP_Transport::set_bidir_context_info (TAO_Operation_Details &opdetails) +{ + + // Get a handle on to the acceptor registry + TAO_Acceptor_Registry * ar = + this->orb_core ()->acceptor_registry (); + + + // Get the first acceptor in the registry + TAO_AcceptorSetIterator acceptor = ar->begin (); + + DIOP::ListenPointList listen_point_list; + + for (; + acceptor != ar->end (); + acceptor++) + { + // Check whether it is a DIOP acceptor + if ((*acceptor)->tag () == TAO_TAG_UDP_PROFILE) + { + this->get_listen_point (listen_point_list, + *acceptor); + } + } + + // We have the ListenPointList at this point. Create a output CDR + // stream at this point + TAO_OutputCDR cdr; + + // Marshall the information into the stream + if ((cdr << ACE_OutputCDR::from_boolean (TAO_ENCAP_BYTE_ORDER)== 0) + || (cdr << listen_point_list) == 0) + return; + + // Add this info in to the svc_list + opdetails.service_context ().set_context (IOP::BI_DIR_DIOP, + cdr); + + return; +} + + +int +TAO_DIOP_Transport::get_listen_point ( + DIOP::ListenPointList &listen_point_list, + TAO_Acceptor *acceptor) +{ + TAO_DIOP_Acceptor *iiop_acceptor = + ACE_dynamic_cast (TAO_DIOP_Acceptor *, + acceptor ); + + // Get the array of endpoints serviced by <iiop_acceptor> + const ACE_INET_Addr *endpoint_addr = + iiop_acceptor->endpoints (); + + // Get the count + size_t count = + iiop_acceptor->endpoint_count (); + + // Get the local address of the connection + ACE_INET_Addr local_addr; + + if (this->connection_handler_->peer ().get_local_addr (local_addr) + == -1) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("(%P|%t) Could not resolve local host") + ACE_TEXT (" address in set_bidir_context_info () \n")), + -1); + } + + + // Note: Looks like there is no point in sending the list of + // endpoints on interfaces on which this connection has not + // been established. If this is wrong, please correct me. + char *local_interface = 0; + + // Get the hostname for the local address + if (iiop_acceptor->hostname (this->orb_core_, + local_addr, + local_interface) == -1) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("(%P|%t) Could not resolve local host") + ACE_TEXT (" name \n")), + -1); + } + + ACE_INET_Addr *tmp_addr = ACE_const_cast (ACE_INET_Addr *, + endpoint_addr); + + for (size_t index = 0; + index <= count; + index++) + { + // Get the listen point on that acceptor if it has the same + // interface on which this connection is established + char *acceptor_interface = 0; + + if (iiop_acceptor->hostname (this->orb_core_, + tmp_addr[index], + acceptor_interface) == -1) + continue; + + // @@ This is very bad for performance, but it is a one time + // affair + if (ACE_OS::strcmp (local_interface, + acceptor_interface) == 0) + { + // We have the connection and the acceptor endpoint on the + // same interface + DIOP::ListenPoint point; + point.host = CORBA::string_dup (local_interface); + point.port = endpoint_addr[index].get_port_number (); + + // Get the count of the number of elements + CORBA::ULong len = listen_point_list.length (); + + // Increase the length by 1 + listen_point_list.length (len + 1); + + // Add the new length to the list + listen_point_list[len] = point; + } + + // @@ This is bad.... + CORBA::string_free (acceptor_interface); + } + + CORBA::string_free (local_interface); + return 1; +} +*/ + +void +TAO_DIOP_Transport::transition_handler_state_i (void) +{ + this->connection_handler_ = 0; +} + +#endif /* TAO_HAS_DIOP && TAO_HAS_DIOP != 0 */ diff --git a/TAO/tao/Strategies/DIOP_Transport.h b/TAO/tao/Strategies/DIOP_Transport.h new file mode 100644 index 00000000000..e8732f433cf --- /dev/null +++ b/TAO/tao/Strategies/DIOP_Transport.h @@ -0,0 +1,148 @@ +// This may look like C, but it's really -*- C++ -*- +// -*- C++ -*- +// =================================================================== +/** + * @file DIOP_Transport.h + * + * $Id$ + * + * @author Michael Kircher + */ +// =================================================================== + +#ifndef TAO_DIOP_TRANSPORT_H +#define TAO_DIOP_TRANSPORT_H +#include "ace/pre.h" + +#include "tao/corbafwd.h" + +#if defined (TAO_HAS_DIOP) && (TAO_HAS_DIOP != 0) + +#include "tao/Transport.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/SOCK_Stream.h" +#include "ace/Synch.h" +#include "ace/Svc_Handler.h" +#include "strategies_export.h" + +// Forward decls. +class TAO_DIOP_Connection_Handler; +class TAO_ORB_Core; +class TAO_Operation_Details; +class TAO_Pluggable_Messaging; +class TAO_Acceptor; + +// Service Handler for this transport +typedef ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> + TAO_DIOP_SVC_HANDLER; + +/** + * @class TAO_DIOP_Transport + * + * @brief Specialization of the base TAO_Transport class to handle the + * DIOP protocol. + * + * + * + */ + +class TAO_Strategies_Export TAO_DIOP_Transport : public TAO_Transport +{ +public: + + /// Constructor. + TAO_DIOP_Transport (TAO_DIOP_Connection_Handler *handler, + TAO_ORB_Core *orb_core, + CORBA::Boolean flag); + + /// Default destructor. + ~TAO_DIOP_Transport (void); + +protected: + /** @name Overridden Template Methods + * + * These are implementations of template methods declared by TAO_Transport. + */ + //@{ + + virtual ACE_Event_Handler *event_handler_i (void); + + virtual TAO_Pluggable_Messaging *messaging_object (void); + + /// Write the complete Message_Block chain to the connection. + virtual ssize_t send_i (iovec *iov, int iovcnt, + size_t &bytes_transferred, + const ACE_Time_Value *max_wait_time); + + /// Read len bytes from into buf. + virtual ssize_t recv_i (char *buf, + size_t len, + const ACE_Time_Value *s = 0); + + /// Read and process the message from the connection. The processing + /// of the message is done by delegating the work to the underlying + /// messaging object + virtual int read_process_message (ACE_Time_Value *max_time_value = 0, + int block =0); + + virtual int register_handler_i (void); + + /// Method to do whatever it needs to do when the connection + /// handler is being closed and destroyed. + virtual void transition_handler_state_i (void); + +public: + /// @@TODO: These methods IMHO should have more meaningful + /// names. The names seem to indicate nothing. + virtual int send_request (TAO_Stub *stub, + TAO_ORB_Core *orb_core, + TAO_OutputCDR &stream, + int twoway, + ACE_Time_Value *max_wait_time); + + virtual int send_message (TAO_OutputCDR &stream, + TAO_Stub *stub = 0, + int twoway = 1, + ACE_Time_Value *max_time_wait = 0); + + /// Initialising the messaging object + virtual int messaging_init (CORBA::Octet major, + CORBA::Octet minor); + +private: + /// Process the message that we have read + int process_message (void); + + // @@ Frank : Not needed + /* + /// Set the Bidirectional context info in the service context list + void set_bidir_context_info (TAO_Operation_Details &opdetails); + + /// Add the listen points in <acceptor> to the <listen_point_list> + /// if this connection is in the same interface as that of the + /// endpoints in the <acceptor> + int get_listen_point (DIOP::ListenPointList &listen_point_list, + TAO_Acceptor *acceptor); + */ +private: + + /// The connection service handler used for accessing lower layer + /// communication protocols. + TAO_DIOP_Connection_Handler *connection_handler_; + + /// Our messaging object. + TAO_Pluggable_Messaging *messaging_object_; +}; + +#if defined (__ACE_INLINE__) +#include "DIOP_Transport.i" +#endif /* __ACE_INLINE__ */ + +#endif /* TAO_HAS_DIOP && TAO_HAS_DIOP != 0 */ + +#include "ace/post.h" +#endif /* TAO_DIOP_TRANSPORT_H */ diff --git a/TAO/tao/Strategies/DIOP_Transport.i b/TAO/tao/Strategies/DIOP_Transport.i new file mode 100644 index 00000000000..81bf354f364 --- /dev/null +++ b/TAO/tao/Strategies/DIOP_Transport.i @@ -0,0 +1,2 @@ +// -*- C++ -*- +//$Id$ diff --git a/TAO/tao/Strategies/Makefile b/TAO/tao/Strategies/Makefile index 717381335ad..d88f0419edf 100644 --- a/TAO/tao/Strategies/Makefile +++ b/TAO/tao/Strategies/Makefile @@ -23,6 +23,13 @@ include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU include $(TAO_ROOT)/rules.tao.GNU CPP_SRCS += \ + DIOP_Factory \ + DIOP_Profile \ + DIOP_Transport \ + DIOP_Connector \ + DIOP_Acceptor \ + DIOP_Connection_Handler \ + DIOP_Endpoint \ UIOP_Factory \ UIOP_Lite_Factory \ UIOP_Profile \ diff --git a/TAO/tao/Strategies/Makefile.bor b/TAO/tao/Strategies/Makefile.bor index ba548e586e8..f297b77b06f 100644 --- a/TAO/tao/Strategies/Makefile.bor +++ b/TAO/tao/Strategies/Makefile.bor @@ -22,6 +22,13 @@ OBJFILES = \ $(OBJDIR)\SHMIOP_Acceptor.obj \ $(OBJDIR)\SHMIOP_Connection_Handler.obj \ $(OBJDIR)\SHMIOP_Endpoint.obj \ + $(OBJDIR)\DIOP_Factory.obj \ + $(OBJDIR)\DIOP_Profile.obj \ + $(OBJDIR)\DIOP_Transport.obj \ + $(OBJDIR)\DIOP_Connector.obj \ + $(OBJDIR)\DIOP_Acceptor.obj \ + $(OBJDIR)\DIOP_Connection_Handler.obj \ + $(OBJDIR)\DIOP_Endpoint.obj \ $(OBJDIR)\TAO_Strategies_Internal.obj \ $(OBJDIR)\uiop_endpoints.obj \ $(OBJDIR)\advanced_resource.obj \ diff --git a/TAO/tao/Strategies/TAO_Strategies_Internal.cpp b/TAO/tao/Strategies/TAO_Strategies_Internal.cpp index f5fd25d8ad5..4aaea70973b 100644 --- a/TAO/tao/Strategies/TAO_Strategies_Internal.cpp +++ b/TAO/tao/Strategies/TAO_Strategies_Internal.cpp @@ -8,6 +8,7 @@ #include "advanced_resource.h" #include "UIOP_Factory.h" #include "SHMIOP_Factory.h" +#include "DIOP_Factory.h" #include "tao/Object_Loader.h" @@ -59,7 +60,11 @@ TAO_Strategies_Internal::open_services (int &argc, #if TAO_HAS_SHMIOP == 1 ACE_Service_Config::static_svcs ()-> insert (&ace_svc_desc_TAO_SHMIOP_Protocol_Factory); -#endif /* TAO_HAS_UIOP == 1 */ +#endif /* TAO_HAS_SHMIOP == 1 */ +#if TAO_HAS_DIOP == 1 + ACE_Service_Config::static_svcs ()-> + insert (&ace_svc_desc_TAO_DIOP_Protocol_Factory); +#endif /* TAO_HAS_DIOP == 1 */ int result = 0; if (skip_service_config_open == 0) diff --git a/TAO/tao/Strategies/advanced_resource.cpp b/TAO/tao/Strategies/advanced_resource.cpp index c590e862fec..029c6c1932b 100644 --- a/TAO/tao/Strategies/advanced_resource.cpp +++ b/TAO/tao/Strategies/advanced_resource.cpp @@ -8,6 +8,7 @@ #include "UIOP_Factory.h" #include "SHMIOP_Factory.h" +#include "DIOP_Factory.h" #include "Reactor_Per_Priority.h" #include "LFU_Connection_Purging_Strategy.h" @@ -43,7 +44,13 @@ TAO_Resource_Factory_Changer::TAO_Resource_Factory_Changer (void) #if TAO_HAS_SHMIOP == 1 ACE_Service_Config::static_svcs ()-> insert (&ace_svc_desc_TAO_SHMIOP_Protocol_Factory); -#endif /* TAO_HAS_UIOP == 1 */ +#endif /* TAO_HAS_SHMIOP == 1 */ + +#if TAO_HAS_DIOP == 1 + ACE_Service_Config::static_svcs ()-> + insert (&ace_svc_desc_TAO_DIOP_Protocol_Factory); +#endif /* TAO_HAS_DIOP == 1 */ + } TAO_Advanced_Resource_Factory::TAO_Advanced_Resource_Factory (void) @@ -368,6 +375,69 @@ TAO_Advanced_Resource_Factory::init_protocol_factories (void) } #endif /* TAO_HAS_SHMIOP && TAO_HAS_SHMIOP != 0 */ +#if defined (TAO_HAS_DIOP) && (TAO_HAS_DIOP != 0) + protocol_factory = + ACE_Dynamic_Service<TAO_Protocol_Factory>::instance ("DIOP_Factory"); + + if (protocol_factory == 0) + { + if (TAO_debug_level > 0) + ACE_ERROR ((LM_WARNING, + "(%P|%t) WARNING - No %s found in Service Repository." + " Using default instance.\n", + "DIOP Protocol Factory")); + + ACE_NEW_RETURN (protocol_factory, + TAO_DIOP_Protocol_Factory, + -1); + + ACE_AUTO_PTR_RESET (safe_protocol_factory, + protocol_factory, + TAO_Protocol_Factory); + + transfer_ownership = 1; + } + else + { + transfer_ownership = 0; + } + + ACE_NEW_RETURN (item, TAO_Protocol_Item ("DIOP_Factory"), -1); + // If the TAO_Protocol_Item retains ownership of the + // TAO_Protocol_Factory then we used an auto_ptr<> above, so + // release the TAO_Protocol_Factory from it. Otherwise, we + // obtained the TAO_Protocol_Factory from the Service + // Configurator so an auto_ptr<> wasn't used since the Service + // Configurator retains ownership, hence there was no need to + // use an auto_ptr<> in this method. + item->factory ((transfer_ownership ? + safe_protocol_factory.release () : + protocol_factory), + transfer_ownership); + + if (this->protocol_factories_.insert (item) == -1) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("TAO (%P|%t) Unable to add ") + ACE_TEXT ("<%s> to protocol factory set.\n"), + item->protocol_name ().c_str ())); + + delete item; + + if (transfer_ownership == 0) + delete protocol_factory; + + return -1; + } + + if (TAO_debug_level > 0) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) Loaded default ") + ACE_TEXT ("protocol <DIOP_Factory>\n"))); + } +#endif /* TAO_HAS_DIOP && TAO_HAS_DIOP != 0 */ + return 0; } |