1 #include "tao/Strategies/DIOP_Profile.h"
3 #if defined (TAO_HAS_DIOP) && (TAO_HAS_DIOP != 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 the_prefix
[] = "diop";
20 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
22 const char TAO_DIOP_Profile::object_key_delimiter_
= '/';
25 TAO_DIOP_Profile::object_key_delimiter () const
27 return TAO_DIOP_Profile::object_key_delimiter_
;
31 TAO_DIOP_Profile::TAO_DIOP_Profile (const ACE_INET_Addr
&addr
,
32 const TAO::ObjectKey
&object_key
,
33 const TAO_GIOP_Message_Version
&version
,
34 TAO_ORB_Core
*orb_core
)
35 : TAO_Profile (TAO_TAG_DIOP_PROFILE
,
40 orb_core
->orb_params ()->use_dotted_decimal_addresses ()),
45 TAO_DIOP_Profile::TAO_DIOP_Profile (const char* host
,
47 const TAO::ObjectKey
&object_key
,
48 const ACE_INET_Addr
&addr
,
49 const TAO_GIOP_Message_Version
&version
,
50 TAO_ORB_Core
*orb_core
)
51 : TAO_Profile (TAO_TAG_DIOP_PROFILE
,
55 endpoint_ (host
, port
, addr
),
60 TAO_DIOP_Profile::TAO_DIOP_Profile (TAO_ORB_Core
*orb_core
)
61 : TAO_Profile (TAO_TAG_DIOP_PROFILE
,
63 TAO_GIOP_Message_Version (TAO_DEF_GIOP_MAJOR
, TAO_DEF_GIOP_MINOR
)),
69 TAO_DIOP_Profile::~TAO_DIOP_Profile ()
71 // Clean up the list of endpoints since we own it.
72 // Skip the head, since it is not dynamically allocated.
73 TAO_Endpoint
*tmp
= 0;
75 for (TAO_Endpoint
*next
= this->endpoint ()->next ();
86 // 0 -> can't understand this version
90 TAO_DIOP_Profile::decode_profile (TAO_InputCDR
& cdr
)
92 // @@ NOTE: This code is repeated thrice. Need to factor out in a
94 // Decode host and port into the <endpoint_>.
95 if (cdr
.read_string (this->endpoint_
.host_
.out ()) == 0
96 || cdr
.read_ushort (this->endpoint_
.port_
) == 0)
98 if (TAO_debug_level
> 0)
99 TAOLIB_DEBUG ((LM_DEBUG
,
100 ACE_TEXT ("TAO (%P|%t) - DIOP_Profile::decode_profile, ")
101 ACE_TEXT ("error while decoding host/port\n")));
107 // Invalidate the object_addr_ until first access.
108 this->endpoint_
.object_addr_
.set_type (-1);
117 TAO_DIOP_Profile::parse_string_i (const char *ior
)
119 // Pull off the "hostname:port/" part of the objref
120 // Copy the string because we are going to modify it...
121 const char *okd
= std::strchr (ior
, this->object_key_delimiter_
);
123 if (okd
== 0 || okd
== ior
)
125 // No object key delimiter or no hostname specified.
126 throw ::CORBA::INV_OBJREF (
127 CORBA::SystemException::_tao_minor_code (
130 CORBA::COMPLETED_NO
);
133 // Length of host string.
134 CORBA::ULong length_host
= 0;
136 const char *cp_pos
= std::strchr (ior
, ':'); // Look for a port
137 #if defined (ACE_HAS_IPV6)
138 // IPv6 numeric address in host string?
139 bool ipv6_in_host
= false;
141 // Check if this is a (possibly) IPv6 supporting profile containing a
142 // decimal IPv6 address representation.
143 if ((this->version ().major
> TAO_MIN_IPV6_IIOP_MAJOR
||
144 this->version ().minor
>= TAO_MIN_IPV6_IIOP_MINOR
) &&
147 // In this case we have to find the end of the numeric address and
148 // start looking for the port separator from there.
149 const char *cp_pos_a
= std::strchr (ior
, ']');
152 // No valid IPv6 address specified.
153 if (TAO_debug_level
> 0)
155 TAOLIB_DEBUG ((LM_ERROR
,
156 ACE_TEXT ("\nTAO (%P|%t) - DIOP_Profile::parse_string_i, ")
157 ACE_TEXT ("invalid IPv6 decimal address specified.\n")));
160 throw ::CORBA::INV_OBJREF (
161 CORBA::SystemException::_tao_minor_code (
164 CORBA::COMPLETED_NO
);
168 if (cp_pos_a
[1] == ':') // Look for a port
169 cp_pos
= cp_pos_a
+ 1;
172 ipv6_in_host
= true; // host string contains full IPv6 numeric address
175 #endif /* ACE_HAS_IPV6 */
179 if (TAO_debug_level
> 0)
181 TAOLIB_ERROR ((LM_ERROR
,
182 ACE_TEXT ("\nTAO (%P|%t) DIOP_Profile: ")
183 ACE_TEXT ("Host address may be omited only when no port has been specified.\n")));
185 // No hostname specified! It is required by the spec.
186 throw ::CORBA::INV_OBJREF (
187 CORBA::SystemException::_tao_minor_code (
190 CORBA::COMPLETED_NO
);
192 else if (cp_pos
!= 0)
194 // A port number or port name was specified.
195 CORBA::ULong length_port
= ACE_Utils::truncate_cast
<CORBA::ULong
> (okd
- cp_pos
- 1);
197 CORBA::String_var tmp
= CORBA::string_alloc (length_port
);
199 ACE_OS::strncpy (tmp
.inout (), cp_pos
+ 1, length_port
);
200 tmp
[length_port
] = '\0';
202 if (ACE_OS::strspn (tmp
.in (), "1234567890") == length_port
)
204 this->endpoint_
.port_
=
205 static_cast<CORBA::UShort
> (ACE_OS::atoi (tmp
.in ()));
210 if (ia
.string_to_addr (tmp
.in ()) == -1)
212 throw ::CORBA::INV_OBJREF (
213 CORBA::SystemException::_tao_minor_code (
216 CORBA::COMPLETED_NO
);
220 this->endpoint_
.port_
= ia
.get_port_number ();
224 length_host
= ACE_Utils::truncate_cast
<CORBA::ULong
> (cp_pos
- ior
);
227 length_host
= ACE_Utils::truncate_cast
<CORBA::ULong
> (okd
- ior
);
229 #if defined (ACE_HAS_IPV6)
231 length_host
-= 2; // don't store '[' and ']'
232 #endif /* ACE_HAS_IPV6 */
234 CORBA::String_var tmp
= CORBA::string_alloc (length_host
);
236 #if defined (ACE_HAS_IPV6)
238 ACE_OS::strncpy (tmp
.inout (), ior
+ 1, length_host
);
240 #endif /* ACE_HAS_IPV6 */
241 // Skip the trailing '/'
242 ACE_OS::strncpy (tmp
.inout (), ior
, length_host
);
243 tmp
[length_host
] = '\0';
245 this->endpoint_
.host_
= tmp
._retn ();
246 #if defined (ACE_HAS_IPV6)
247 this->endpoint_
.is_ipv6_decimal_
= ipv6_in_host
;
248 #endif /* ACE_HAS_IPV6 */
250 if (ACE_OS::strcmp (this->endpoint_
.host_
.in (), "") == 0)
252 ACE_INET_Addr host_addr
;
254 char tmp_host
[MAXHOSTNAMELEN
+ 1];
256 // If no host is specified: assign the default host, i.e. the
258 if (host_addr
.get_host_name (tmp_host
,
259 sizeof (tmp_host
)) != 0)
261 // Can't get the IP address since the INET_Addr wasn't
262 // initialized. Just throw an exception.
264 if (TAO_debug_level
> 0)
265 TAOLIB_DEBUG ((LM_DEBUG
,
266 ACE_TEXT ("TAO (%P|%t) - ")
267 ACE_TEXT ("DIOP_Profile::parse_string_i, ")
269 ACE_TEXT ("cannot determine hostname")));
271 // @@ What's the right exception to throw here?
272 throw ::CORBA::INV_OBJREF (
273 CORBA::SystemException::_tao_minor_code (
276 CORBA::COMPLETED_NO
);
279 this->endpoint_
.host_
= CORBA::string_dup (tmp_host
);
283 TAO::ObjectKey::decode_string_to_sequence (ok
,
286 (void) this->orb_core ()->object_key_table ().bind (ok
,
287 this->ref_object_key_
);
291 TAO_DIOP_Profile::do_is_equivalent (const TAO_Profile
*other_profile
)
293 const TAO_DIOP_Profile
*op
=
294 dynamic_cast<const TAO_DIOP_Profile
*> (other_profile
);
296 // Make sure we have a TAO_DIOP_Profile.
300 // Check endpoints equivalence.
301 const TAO_DIOP_Endpoint
*other_endp
= &op
->endpoint_
;
302 for (TAO_DIOP_Endpoint
*endp
= &this->endpoint_
;
306 if (endp
->is_equivalent (other_endp
))
307 other_endp
= other_endp
->next_
;
316 TAO_DIOP_Profile::hash (CORBA::ULong max
)
318 // Get the hashvalue for all endpoints.
319 CORBA::ULong hashval
= 0;
320 for (TAO_DIOP_Endpoint
*endp
= &this->endpoint_
;
324 hashval
+= endp
->hash ();
327 hashval
+= this->version_
.minor
;
328 hashval
+= this->tag ();
330 const TAO::ObjectKey
&ok
=
331 this->ref_object_key_
->object_key ();
333 if (ok
.length () >= 4)
339 hashval
+= this->hash_service_i (max
);
341 return hashval
% max
;
345 TAO_DIOP_Profile::endpoint ()
347 return &this->endpoint_
;
351 TAO_DIOP_Profile::endpoint_count () const
357 TAO_DIOP_Profile::add_endpoint (TAO_DIOP_Endpoint
*endp
)
359 endp
->next_
= this->endpoint_
.next_
;
360 this->endpoint_
.next_
= endp
;
366 TAO_DIOP_Profile::to_string () const
368 // corbaloc:diop:1.2@host:port,diop:1.2@host:port,.../key
370 CORBA::String_var key
;
371 TAO::ObjectKey::encode_sequence_to_string (key
.inout (),
372 this->ref_object_key_
->object_key ());
376 1 /* colon separator */ +
377 1 /* object key separator */ +
378 ACE_OS::strlen (key
.in ()));
380 ACE_OS::strlen (::the_prefix
) /* "diop" */ +
381 1 /* colon separator */);
383 const TAO_DIOP_Endpoint
*endp
= 0;
384 for (endp
= &this->endpoint_
; endp
!= 0; endp
= endp
->next_
)
388 1 /* major version */ +
389 1 /* decimal point */ +
390 1 /* minor version */ +
391 1 /* `@' character */ +
392 ACE_OS::strlen (endp
->host ()) +
393 1 /* colon separator */ +
394 5 /* port number */ +
396 #if defined (ACE_HAS_IPV6)
397 if (endp
->is_ipv6_decimal_
)
398 buflen
+= 2; // room for '[' and ']'
399 #endif /* ACE_HAS_IPV6 */
402 static const char digits
[] = "0123456789";
404 char * buf
= CORBA::string_alloc (static_cast<CORBA::ULong
> (buflen
));
406 ACE_OS::strcpy (buf
, "corbaloc:");
408 for (endp
= &this->endpoint_
; endp
!= 0; endp
= endp
->next_
)
410 if (&this->endpoint_
!= endp
)
411 ACE_OS::strcat (buf
, ",");
413 #if defined (ACE_HAS_IPV6)
414 if (endp
->is_ipv6_decimal_
)
416 // Don't publish scopeid if included.
417 ACE_CString
tmp (endp
->host ());
418 ACE_CString::size_type pos
= tmp
.find ('%');
419 if (pos
!= ACE_CString::npos
)
421 tmp
= tmp
.substr (0, pos
+ 1);
424 ACE_OS::sprintf (buf
+ ACE_OS::strlen (buf
),
427 digits
[this->version_
.major
],
428 digits
[this->version_
.minor
],
434 ACE_OS::sprintf (buf
+ ACE_OS::strlen (buf
),
437 digits
[this->version_
.major
],
438 digits
[this->version_
.minor
],
442 ACE_OS::sprintf (buf
+ ACE_OS::strlen (buf
),
444 this->object_key_delimiter_
,
451 TAO_DIOP_Profile::prefix ()
457 TAO_DIOP_Profile::create_profile_body (TAO_OutputCDR
&encap
) const
459 encap
.write_octet (TAO_ENCAP_BYTE_ORDER
);
462 encap
.write_octet (this->version_
.major
);
463 encap
.write_octet (this->version_
.minor
);
465 // STRING hostname from profile
466 #if defined (ACE_HAS_IPV6)
467 // For IPv6 decimal addresses make sure the possibly included scopeid
468 // is not published as this has only local meaning.
471 if (this->endpoint_
.is_ipv6_decimal_
&&
472 (pos
= std::strchr (host
= this->endpoint_
.host (), '%')) != 0)
475 size_t len
= pos
- host
;
476 tmp
.set (this->endpoint_
.host (), len
, 1);
477 encap
.write_string (tmp
.c_str ());
480 #endif /* ACE_HAS_IPV6 */
481 encap
.write_string (this->endpoint_
.host ());
483 // UNSIGNED SHORT port number
484 encap
.write_ushort (this->endpoint_
.port ());
486 // OCTET SEQUENCE for object key
487 if (this->ref_object_key_
)
488 encap
<< this->ref_object_key_
->object_key ();
491 TAOLIB_ERROR ((LM_ERROR
,
492 "TAO (%P|%t) - DIOP_Profile::create_profile_body, "
493 "no object key marshalled\n"));
496 if (this->version_
.major
> 1
497 || this->version_
.minor
> 0)
498 this->tagged_components ().encode (encap
);
502 TAO_DIOP_Profile::encode_endpoints ()
504 // Create a data structure and fill it with endpoint info for wire
506 // We include information for the head of the list
507 // together with other endpoints because even though its addressing
508 // info is transmitted using standard ProfileBody components, its
511 TAO::IIOPEndpointSequence endpoints
;
512 endpoints
.length (this->count_
);
514 const TAO_DIOP_Endpoint
*endpoint
= &this->endpoint_
;
515 for (CORBA::ULong i
= 0;
519 #if defined (ACE_HAS_IPV6)
520 if (endpoint
->is_ipv6_decimal_
)
522 // Don't publish scopeid if included.
523 ACE_CString
tmp (endpoint
->host ());
524 ACE_CString::size_type pos
= tmp
.find ('%');
525 if (pos
!= ACE_CString::npos
)
527 tmp
= tmp
.substr (0, pos
+ 1);
529 endpoints
[i
].host
= tmp
.c_str ();
532 endpoints
[i
].host
= tmp
.c_str ();
535 #endif /* ACE_HAS_IPV6 */
536 endpoints
[i
].host
= endpoint
->host ();
537 endpoints
[i
].port
= endpoint
->port ();
538 endpoints
[i
].priority
= endpoint
->priority ();
540 endpoint
= endpoint
->next_
;
543 // Encode the data structure.
544 TAO_OutputCDR out_cdr
;
545 if ((out_cdr
<< ACE_OutputCDR::from_boolean (TAO_ENCAP_BYTE_ORDER
)) == 0
546 || (out_cdr
<< endpoints
) == 0)
549 this->set_tagged_components (out_cdr
);
555 TAO_DIOP_Profile::decode_endpoints ()
557 IOP::TaggedComponent tagged_component
;
558 tagged_component
.tag
= TAO_TAG_ENDPOINTS
;
560 if (this->tagged_components_
.get_component (tagged_component
))
562 const CORBA::Octet
*buf
=
563 tagged_component
.component_data
.get_buffer ();
565 TAO_InputCDR
in_cdr (reinterpret_cast<const char*> (buf
),
566 tagged_component
.component_data
.length ());
568 // Extract the Byte Order.
569 CORBA::Boolean byte_order
;
570 if ((in_cdr
>> ACE_InputCDR::to_boolean (byte_order
)) == 0)
572 in_cdr
.reset_byte_order (static_cast<int> (byte_order
));
574 // Extract endpoints sequence.
575 TAO::IIOPEndpointSequence endpoints
;
577 if (! (in_cdr
>> endpoints
))
580 // Get the priority of the first endpoint (head of the list.
581 // It's other data is extracted as part of the standard profile
583 this->endpoint_
.priority (endpoints
[0].priority
);
585 // Use information extracted from the tagged component to
586 // populate the profile. Skip the first endpoint, since it is
587 // always extracted through standard profile body. Also, begin
588 // from the end of the sequence to preserve endpoint order,
589 // since <add_endpoint> method reverses the order of endpoints
591 for (CORBA::ULong i
= endpoints
.length () - 1;
595 TAO_DIOP_Endpoint
*endpoint
= 0;
596 ACE_NEW_RETURN (endpoint
,
597 TAO_DIOP_Endpoint (endpoints
[i
].host
,
599 endpoints
[i
].priority
),
602 this->add_endpoint (endpoint
);
609 TAO_END_VERSIONED_NAMESPACE_DECL
611 #endif /* TAO_HAS_DIOP && TAO_HAS_DIOP != 0 */