Revert "Minor modernization of DynamicAny code"
[ACE_TAO.git] / TAO / tao / Strategies / SHMIOP_Profile.cpp
blob2af43d557933ae46b24439892f274bd3a24d7527
1 #include "tao/Strategies/SHMIOP_Profile.h"
3 #if defined (TAO_HAS_SHMIOP) && (TAO_HAS_SHMIOP != 0)
5 #include "tao/CDR.h"
6 #include "tao/SystemException.h"
7 #include "tao/ORB.h"
8 #include "tao/ORB_Core.h"
9 #include "tao/debug.h"
10 #include "tao/IIOP_EndpointsC.h"
12 #include "ace/OS_NS_stdio.h"
13 #include "ace/OS_NS_string.h"
14 #include "ace/os_include/os_netdb.h"
15 #include "ace/Truncate.h"
16 #include <cstring>
18 static const char prefix_[] = "shmiop";
20 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
22 const char TAO_SHMIOP_Profile::object_key_delimiter_ = '/';
24 char
25 TAO_SHMIOP_Profile::object_key_delimiter () const
27 return TAO_SHMIOP_Profile::object_key_delimiter_;
30 TAO_SHMIOP_Profile::TAO_SHMIOP_Profile (const ACE_MEM_Addr &addr,
31 const TAO::ObjectKey &object_key,
32 const TAO_GIOP_Message_Version &version,
33 TAO_ORB_Core *orb_core)
34 : TAO_Profile (TAO_TAG_SHMEM_PROFILE,
35 orb_core,
36 object_key,
37 version),
38 endpoint_ (addr,
39 orb_core->orb_params ()->use_dotted_decimal_addresses ()),
40 count_ (1)
44 TAO_SHMIOP_Profile::TAO_SHMIOP_Profile (const char* host,
45 CORBA::UShort port,
46 const TAO::ObjectKey &object_key,
47 const ACE_INET_Addr &addr,
48 const TAO_GIOP_Message_Version &version,
49 TAO_ORB_Core *orb_core)
50 : TAO_Profile (TAO_TAG_SHMEM_PROFILE,
51 orb_core,
52 object_key,
53 version),
54 endpoint_ (host, port, addr),
55 count_ (1)
59 TAO_SHMIOP_Profile::TAO_SHMIOP_Profile (TAO_ORB_Core *orb_core)
60 : TAO_Profile (TAO_TAG_SHMEM_PROFILE,
61 orb_core,
62 TAO_GIOP_Message_Version (TAO_DEF_GIOP_MAJOR, TAO_DEF_GIOP_MINOR)),
63 endpoint_ (),
64 count_ (1)
68 TAO_SHMIOP_Profile::~TAO_SHMIOP_Profile ()
70 // Clean up the list of endpoints since we own it.
71 // Skip the head, since it is not dynamically allocated.
72 TAO_Endpoint *tmp = 0;
74 for (TAO_Endpoint *next = this->endpoint ()->next ();
75 next != 0;
76 next = tmp)
78 tmp = next->next ();
79 delete next;
83 TAO_Endpoint*
84 TAO_SHMIOP_Profile::endpoint ()
86 return &this->endpoint_;
89 CORBA::ULong
90 TAO_SHMIOP_Profile::endpoint_count () const
92 return this->count_;
95 // return codes:
96 // -1 -> error
97 // 0 -> can't understand this version
98 // 1 -> success.
99 int
100 TAO_SHMIOP_Profile::decode_profile (TAO_InputCDR& cdr)
102 // Decode host and port into the <endpoint_>.
103 if (cdr.read_string (this->endpoint_.host_.out ()) == 0
104 || cdr.read_ushort (this->endpoint_.port_) == 0)
106 if (TAO_debug_level > 0)
108 TAOLIB_DEBUG ((LM_DEBUG,
109 ACE_TEXT ("TAO (%P|%t) SHMIOP_Profile::decode - ")
110 ACE_TEXT ("error while decoding host/port")));
112 return -1;
115 if (cdr.good_bit ())
117 // Invalidate the object_addr_ until first access.
118 this->endpoint_.object_addr_.set_type (-1);
120 return 1;
123 return -1;
126 void
127 TAO_SHMIOP_Profile::parse_string_i (const char *string)
129 // Pull off the "hostname:port/" part of the objref
130 // Copy the string because we are going to modify it...
131 CORBA::String_var copy (string);
133 char *start = copy.inout ();
134 char *cp = std::strchr (start, ':'); // Look for a port
136 if (cp == 0)
138 // No host/port delimiter!
139 throw ::CORBA::INV_OBJREF (
140 CORBA::SystemException::_tao_minor_code (
141 TAO::VMCID,
142 EINVAL),
143 CORBA::COMPLETED_NO);
146 char *okd = std::strchr (start, this->object_key_delimiter_);
148 if (okd == 0)
150 // No object key delimiter!
151 throw ::CORBA::INV_OBJREF (
152 CORBA::SystemException::_tao_minor_code (
153 TAO::VMCID,
154 EINVAL),
155 CORBA::COMPLETED_NO);
158 // Don't increment the pointer 'cp' directly since we still need
159 // to use it immediately after this block.
161 CORBA::ULong length = ACE_Utils::truncate_cast<CORBA::ULong> (okd - (cp + 1));
162 // Don't allocate space for the colon ':'.
164 CORBA::String_var tmp = CORBA::string_alloc (length);
166 ACE_OS::strncpy (tmp.inout (), cp + 1, length);
167 tmp[length] = '\0';
169 if (ACE_OS::strspn (tmp.in (), "1234567890") == length)
171 this->endpoint_.port_ =
172 static_cast <CORBA::UShort> (ACE_OS::atoi (tmp.in ()));
174 else
176 ACE_INET_Addr ia;
177 if (ia.string_to_addr (tmp.in ()) == -1)
179 throw ::CORBA::INV_OBJREF (
180 CORBA::SystemException::_tao_minor_code (
181 TAO::VMCID,
182 EINVAL),
183 CORBA::COMPLETED_NO);
185 else
187 this->endpoint_.port_ = ia.get_port_number ();
191 length = ACE_Utils::truncate_cast<CORBA::ULong> (cp - start);
193 tmp = CORBA::string_alloc (length);
195 ACE_OS::strncpy (tmp.inout (), start, length);
196 tmp[length] = '\0';
198 this->endpoint_.host_ = tmp._retn ();
200 ACE_INET_Addr host_addr;
202 if (ACE_OS::strcmp (this->endpoint_.host_.in (), "") == 0)
204 char tmp_host [MAXHOSTNAMELEN + 1];
206 // If no host is specified: assign the default host : the local host.
207 if (host_addr.get_host_name (tmp_host,
208 sizeof (tmp_host)) != 0)
210 const char *tmp = host_addr.get_host_addr ();
211 if (tmp == 0)
213 if (TAO_debug_level > 0)
214 TAOLIB_DEBUG ((LM_DEBUG,
215 ACE_TEXT ("\n\nTAO (%P|%t) ")
216 ACE_TEXT ("SHMIOP_Profile::parse_string ")
217 ACE_TEXT ("- %p\n\n"),
218 ACE_TEXT ("cannot determine hostname")));
220 // @@ What's the right exception to throw here?
221 throw ::CORBA::INV_OBJREF (
222 CORBA::SystemException::_tao_minor_code (
223 TAO::VMCID,
224 EINVAL),
225 CORBA::COMPLETED_NO);
227 else
228 this->endpoint_.host_ = tmp;
230 else
232 this->endpoint_.host_ = (const char *) tmp_host;
236 if (this->endpoint_.object_addr_.set (this->endpoint_.port_,
237 this->endpoint_.host_.in ()) == -1)
239 if (TAO_debug_level > 0)
241 TAOLIB_DEBUG ((LM_DEBUG,
242 ACE_TEXT ("TAO (%P|%t) SHMIOP_Profile::parse_string () -\n")
243 ACE_TEXT ("TAO (%P|%t) ACE_INET_Addr::set () failed")));
246 // @@ What's the right exception to throw here?
247 throw ::CORBA::INV_OBJREF (
248 CORBA::SystemException::_tao_minor_code (
249 TAO::VMCID,
250 EINVAL),
251 CORBA::COMPLETED_NO);
254 TAO::ObjectKey ok;
255 TAO::ObjectKey::decode_string_to_sequence (ok,
256 okd + 1); // increment past the object key separator
258 (void) this->orb_core ()->object_key_table ().bind (ok,
259 this->ref_object_key_);
262 CORBA::Boolean
263 TAO_SHMIOP_Profile::do_is_equivalent (const TAO_Profile *other_profile)
265 const TAO_SHMIOP_Profile *op =
266 dynamic_cast <const TAO_SHMIOP_Profile *> (other_profile);
268 if (op == 0)
269 return 0;
271 // Check endpoints equivalence.
272 const TAO_SHMIOP_Endpoint *other_endp = &op->endpoint_;
273 for (TAO_SHMIOP_Endpoint *endp = &this->endpoint_;
274 endp != 0;
275 endp = endp->next_)
277 if (endp->is_equivalent (other_endp))
278 other_endp = other_endp->next_;
279 else
280 return 0;
283 return 1;
286 CORBA::ULong
287 TAO_SHMIOP_Profile::hash (CORBA::ULong max)
289 // Get the hashvalue for all endpoints.
290 CORBA::ULong hashval = 0;
291 for (TAO_SHMIOP_Endpoint *endp = &this->endpoint_;
292 endp != 0;
293 endp = endp->next_)
295 hashval += endp->hash ();
298 hashval += this->version_.minor;
299 hashval += this->tag ();
301 const TAO::ObjectKey &ok =
302 this->ref_object_key_->object_key ();
304 if (ok.length () >= 4)
306 hashval += ok[1];
307 hashval += ok[3];
310 hashval += this->hash_service_i (max);
312 return hashval % max;
315 void
316 TAO_SHMIOP_Profile::add_endpoint (TAO_SHMIOP_Endpoint *endp)
318 endp->next_ = this->endpoint_.next_;
319 this->endpoint_.next_ = endp;
321 this->count_++;
324 char *
325 TAO_SHMIOP_Profile::to_string () const
327 CORBA::String_var key;
328 TAO::ObjectKey::encode_sequence_to_string (key.inout(),
329 this->ref_object_key_->object_key ());
331 size_t buflen = (8 /* corbaloc */ +
332 1 /* colon separator */ +
333 ACE_OS::strlen (::prefix_) +
334 1 /* colon separator */ +
335 1 /* major version */ +
336 1 /* decimal point */ +
337 1 /* minor version */ +
338 1 /* `@' character */ +
339 ACE_OS::strlen (this->endpoint_.host ()) +
340 1 /* colon separator */ +
341 5 /* port number */ +
342 1 /* object key separator */ +
343 ACE_OS::strlen (key.in ()));
345 char * buf = CORBA::string_alloc (static_cast <CORBA::ULong> (buflen));
347 static const char digits [] = "0123456789";
349 ACE_OS::sprintf (buf,
350 "corbaloc:%s:%c.%c@%s:%d%c%s",
351 ::prefix_,
352 digits [this->version_.major],
353 digits [this->version_.minor],
354 this->endpoint_.host (),
355 this->endpoint_.port (),
356 this->object_key_delimiter_,
357 key.in ());
358 return buf;
361 const char *
362 TAO_SHMIOP_Profile::prefix ()
364 return ::prefix_;
367 void
368 TAO_SHMIOP_Profile::create_profile_body (TAO_OutputCDR &encap) const
370 encap.write_octet (TAO_ENCAP_BYTE_ORDER);
372 // The GIOP version
373 encap.write_octet (this->version_.major);
374 encap.write_octet (this->version_.minor);
376 // STRING hostname from profile
377 encap.write_string (this->endpoint_.host ());
379 // UNSIGNED SHORT port number
380 encap.write_ushort (this->endpoint_.port ());
382 // OCTET SEQUENCE for object key
383 if (this->ref_object_key_)
384 encap << this->ref_object_key_->object_key ();
385 else
387 TAOLIB_ERROR ((LM_ERROR,
388 "(%P|%t) TAO - SHMIOP_Profile::create_profile_body "
389 "no object key marshalled\n"));
392 if (this->version_.major > 1
393 || this->version_.minor > 0)
394 this->tagged_components ().encode (encap);
398 TAO_SHMIOP_Profile::encode_endpoints ()
400 // Create a data structure and fill it with endpoint info for wire
401 // transfer.
402 // We include information for the head of the list
403 // together with other endpoints because even though its addressing
404 // info is transmitted using standard ProfileBody components, its
405 // priority is not!
406 TAO::IIOPEndpointSequence endpoints;
407 endpoints.length (this->count_);
409 TAO_SHMIOP_Endpoint *endpoint = &this->endpoint_;
410 for (CORBA::ULong i = 0;
411 i < this->count_;
412 ++i)
414 endpoints[i].host = endpoint->host ();
415 endpoints[i].port = endpoint->port ();
416 endpoints[i].priority = endpoint->priority ();
418 endpoint = endpoint->next_;
421 // Encode the data structure.
422 TAO_OutputCDR out_cdr;
423 if ((out_cdr << ACE_OutputCDR::from_boolean (TAO_ENCAP_BYTE_ORDER)) == 0
424 || (out_cdr << endpoints) == 0)
425 return -1;
426 size_t length = out_cdr.total_length ();
428 IOP::TaggedComponent tagged_component;
429 tagged_component.tag = TAO_TAG_ENDPOINTS;
430 tagged_component.component_data.length (static_cast <CORBA::ULong>(length));
431 CORBA::Octet *buf =
432 tagged_component.component_data.get_buffer ();
434 for (const ACE_Message_Block *iterator = out_cdr.begin ();
435 iterator != 0;
436 iterator = iterator->cont ())
438 size_t i_length = iterator->length ();
439 ACE_OS::memcpy (buf, iterator->rd_ptr (), i_length);
441 buf += i_length;
444 // Add component with encoded endpoint data to this profile's
445 // TaggedComponents.
446 tagged_components_.set_component (tagged_component);
448 return 0;
452 TAO_SHMIOP_Profile::decode_endpoints ()
454 IOP::TaggedComponent tagged_component;
455 tagged_component.tag = TAO_TAG_ENDPOINTS;
457 if (this->tagged_components_.get_component (tagged_component))
459 const CORBA::Octet *buf =
460 tagged_component.component_data.get_buffer ();
462 TAO_InputCDR in_cdr (reinterpret_cast <const char*> (buf),
463 tagged_component.component_data.length ());
465 // Extract the Byte Order.
466 CORBA::Boolean byte_order;
467 if ((in_cdr >> ACE_InputCDR::to_boolean (byte_order)) == 0)
468 return -1;
469 in_cdr.reset_byte_order (static_cast<int> (byte_order));
471 // Extract endpoints sequence.
472 TAO::IIOPEndpointSequence endpoints;
474 if ((in_cdr >> endpoints) == 0)
475 return -1;
477 // Get the priority of the first endpoint (head of the list.
478 // It's other data is extracted as part of the standard profile
479 // decoding.
480 this->endpoint_.priority (endpoints[0].priority);
482 // Use information extracted from the tagged component to
483 // populate the profile. Skip the first endpoint, since it is
484 // always extracted through standard profile body. Also, begin
485 // from the end of the sequence to preserve endpoint order,
486 // since <add_endpoint> method reverses the order of endpoints
487 // in the list.
488 for (CORBA::ULong i = endpoints.length () - 1;
489 i > 0;
490 --i)
492 TAO_SHMIOP_Endpoint *endpoint = 0;
493 ACE_NEW_RETURN (endpoint,
494 TAO_SHMIOP_Endpoint (endpoints[i].host,
495 endpoints[i].port,
496 endpoints[i].priority),
497 -1);
499 this->add_endpoint (endpoint);
503 return 0;
506 TAO_END_VERSIONED_NAMESPACE_DECL
508 #endif /* TAO_HAS_SHMIOP && TAO_HAS_SHMIOP != 0 */