1 #include "tao/Strategies/SHMIOP_Profile.h"
3 #if defined (TAO_HAS_SHMIOP) && (TAO_HAS_SHMIOP != 0)
6 #include "tao/SystemException.h"
8 #include "tao/ORB_Core.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"
18 static const char prefix_
[] = "shmiop";
20 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
22 const char TAO_SHMIOP_Profile::object_key_delimiter_
= '/';
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
,
39 orb_core
->orb_params ()->use_dotted_decimal_addresses ()),
44 TAO_SHMIOP_Profile::TAO_SHMIOP_Profile (const char* host
,
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
,
54 endpoint_ (host
, port
, addr
),
59 TAO_SHMIOP_Profile::TAO_SHMIOP_Profile (TAO_ORB_Core
*orb_core
)
60 : TAO_Profile (TAO_TAG_SHMEM_PROFILE
,
62 TAO_GIOP_Message_Version (TAO_DEF_GIOP_MAJOR
, TAO_DEF_GIOP_MINOR
)),
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 ();
84 TAO_SHMIOP_Profile::endpoint ()
86 return &this->endpoint_
;
90 TAO_SHMIOP_Profile::endpoint_count () const
97 // 0 -> can't understand this version
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")));
117 // Invalidate the object_addr_ until first access.
118 this->endpoint_
.object_addr_
.set_type (-1);
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
138 // No host/port delimiter!
139 throw ::CORBA::INV_OBJREF (
140 CORBA::SystemException::_tao_minor_code (
143 CORBA::COMPLETED_NO
);
146 char *okd
= std::strchr (start
, this->object_key_delimiter_
);
150 // No object key delimiter!
151 throw ::CORBA::INV_OBJREF (
152 CORBA::SystemException::_tao_minor_code (
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
);
169 if (ACE_OS::strspn (tmp
.in (), "1234567890") == length
)
171 this->endpoint_
.port_
=
172 static_cast <CORBA::UShort
> (ACE_OS::atoi (tmp
.in ()));
177 if (ia
.string_to_addr (tmp
.in ()) == -1)
179 throw ::CORBA::INV_OBJREF (
180 CORBA::SystemException::_tao_minor_code (
183 CORBA::COMPLETED_NO
);
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
);
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 ();
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 (
225 CORBA::COMPLETED_NO
);
228 this->endpoint_
.host_
= tmp
;
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 (
251 CORBA::COMPLETED_NO
);
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_
);
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
);
271 // Check endpoints equivalence.
272 const TAO_SHMIOP_Endpoint
*other_endp
= &op
->endpoint_
;
273 for (TAO_SHMIOP_Endpoint
*endp
= &this->endpoint_
;
277 if (endp
->is_equivalent (other_endp
))
278 other_endp
= other_endp
->next_
;
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_
;
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)
310 hashval
+= this->hash_service_i (max
);
312 return hashval
% max
;
316 TAO_SHMIOP_Profile::add_endpoint (TAO_SHMIOP_Endpoint
*endp
)
318 endp
->next_
= this->endpoint_
.next_
;
319 this->endpoint_
.next_
= endp
;
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",
352 digits
[this->version_
.major
],
353 digits
[this->version_
.minor
],
354 this->endpoint_
.host (),
355 this->endpoint_
.port (),
356 this->object_key_delimiter_
,
362 TAO_SHMIOP_Profile::prefix ()
368 TAO_SHMIOP_Profile::create_profile_body (TAO_OutputCDR
&encap
) const
370 encap
.write_octet (TAO_ENCAP_BYTE_ORDER
);
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 ();
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
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
406 TAO::IIOPEndpointSequence endpoints
;
407 endpoints
.length (this->count_
);
409 TAO_SHMIOP_Endpoint
*endpoint
= &this->endpoint_
;
410 for (CORBA::ULong i
= 0;
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)
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
));
432 tagged_component
.component_data
.get_buffer ();
434 for (const ACE_Message_Block
*iterator
= out_cdr
.begin ();
436 iterator
= iterator
->cont ())
438 size_t i_length
= iterator
->length ();
439 ACE_OS::memcpy (buf
, iterator
->rd_ptr (), i_length
);
444 // Add component with encoded endpoint data to this profile's
446 tagged_components_
.set_component (tagged_component
);
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)
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)
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
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
488 for (CORBA::ULong i
= endpoints
.length () - 1;
492 TAO_SHMIOP_Endpoint
*endpoint
= 0;
493 ACE_NEW_RETURN (endpoint
,
494 TAO_SHMIOP_Endpoint (endpoints
[i
].host
,
496 endpoints
[i
].priority
),
499 this->add_endpoint (endpoint
);
506 TAO_END_VERSIONED_NAMESPACE_DECL
508 #endif /* TAO_HAS_SHMIOP && TAO_HAS_SHMIOP != 0 */