1 #include "tao/Strategies/SCIOP_Profile.h"
6 #include "tao/SystemException.h"
8 #include "tao/ORB_Core.h"
10 #include "tao/StringSeqC.h"
11 #include "tao/Strategies/sciop_endpointsC.h"
12 #include "ace/os_include/os_netdb.h"
14 static const char prefix_
[] = "sciop";
16 const char TAO_SCIOP_Profile::object_key_delimiter_
= '/';
18 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
21 TAO_SCIOP_Profile::object_key_delimiter () const
23 return TAO_SCIOP_Profile::object_key_delimiter_
;
26 TAO_SCIOP_Profile::TAO_SCIOP_Profile (const ACE_INET_Addr
&addr
,
27 const TAO::ObjectKey
&object_key
,
28 const TAO_GIOP_Message_Version
&version
,
29 TAO_ORB_Core
*orb_core
)
30 : TAO_Profile (TAO_TAG_SCIOP_PROFILE
,
35 orb_core
->orb_params ()->use_dotted_decimal_addresses ()),
40 TAO_SCIOP_Profile::TAO_SCIOP_Profile (const char* host
,
42 const TAO::ObjectKey
&object_key
,
43 const ACE_INET_Addr
&addr
,
44 const TAO_GIOP_Message_Version
&version
,
45 TAO_ORB_Core
*orb_core
)
46 : TAO_Profile (TAO_TAG_SCIOP_PROFILE
,
50 endpoint_ (host
, port
, addr
),
55 TAO_SCIOP_Profile::TAO_SCIOP_Profile (TAO_ORB_Core
*orb_core
)
56 : TAO_Profile (TAO_TAG_SCIOP_PROFILE
,
58 TAO_GIOP_Message_Version (TAO_DEF_SCIOP_MAJOR
, TAO_DEF_SCIOP_MINOR
)),
64 TAO_SCIOP_Profile::~TAO_SCIOP_Profile ()
66 // Clean up the list of endpoints since we own it.
67 // Skip the head, since it is not dynamically allocated.
68 TAO_Endpoint
*tmp
= 0;
70 for (TAO_Endpoint
*next
= this->endpoint ()->next ();
80 TAO_SCIOP_Profile::decode_profile (TAO_InputCDR
& cdr
)
82 // Decode multiple endpoints, starting with the primary (endpoint_)
83 CORBA::StringSeq endpointSeq
;
86 this->endpoint_
.host_
= endpointSeq
[0];
88 if (cdr
.read_ushort (this->endpoint_
.port_
) == 0)
90 if (TAO_debug_level
> 0)
91 TAOLIB_DEBUG ((LM_DEBUG
,
92 ACE_TEXT ("TAO (%P|%t) SCIOP_Profile::decode - ")
93 ACE_TEXT ("error while decoding host/port")));
97 // Add multiple endpoints > 1
99 for (int i
=endpointSeq
.length() - 1; i
> 0 ; i
--)
101 TAO_SCIOP_Endpoint
*endpoint
= 0;
102 ACE_NEW_RETURN (endpoint
,
103 TAO_SCIOP_Endpoint (endpointSeq
[i
],
104 this->endpoint_
.port_
,
105 this->endpoint_
.priority()),
109 endpoint
->preferred_interfaces (this->orb_core ());
111 this->add_endpoint (endpoint
);
114 // SCIOR has a max_streams variable
115 // We are ignoring it for now since ACE SCTP code fixes at 1 anyway.
117 CORBA::UShort max_streams
;
118 if ((cdr
.read_ushort(max_streams
)) == 0) {
124 // Invalidate the object_addr_ until first access.
125 this->endpoint_
.object_addr_
.set_type (-1);
134 TAO_SCIOP_Profile::parse_string_i (const char *ior
)
136 // Pull off the "hostname:port/" part of the objref
137 // Copy the string because we are going to modify it...
139 const char *okd
= std::strchr (ior
, this->object_key_delimiter_
);
141 if (okd
== 0 || okd
== ior
)
143 // No object key delimiter or no hostname specified.
144 throw ::CORBA::INV_OBJREF (
145 CORBA::SystemException::_tao_minor_code (
148 CORBA::COMPLETED_NO
);
151 // Length of host string.
152 CORBA::ULong length_host
= 0;
154 const char *cp_pos
= std::strchr (ior
, ':'); // Look for a port
158 // No hostname specified! It is required by the spec.
159 throw ::CORBA::INV_OBJREF (
160 CORBA::SystemException::_tao_minor_code (
163 CORBA::COMPLETED_NO
);
165 else if (cp_pos
!= 0)
167 // A port number or port name was specified.
168 CORBA::ULong length_port
= okd
- cp_pos
- 1;
170 CORBA::String_var tmp
= CORBA::string_alloc (length_port
);
172 ACE_OS::strncpy (tmp
.inout (), cp_pos
+ 1, length_port
);
173 tmp
[length_port
] = '\0';
175 this->endpoint_
.port_
=
176 static_cast<CORBA::UShort
> (ACE_OS::atoi (tmp
.in ()));
178 length_host
= cp_pos
- ior
;
181 length_host
= okd
- ior
;
183 CORBA::String_var tmp
= CORBA::string_alloc (length_host
);
185 // Skip the trailing '/'
186 ACE_OS::strncpy (tmp
.inout (), ior
, length_host
);
187 tmp
[length_host
] = '\0';
189 this->endpoint_
.host_
= tmp
._retn ();
191 if (ACE_OS::strcmp (this->endpoint_
.host_
.in (), "") == 0)
193 ACE_INET_Addr host_addr
;
195 char tmp_host
[MAXHOSTNAMELEN
+ 1];
197 // If no host is specified: assign the default host, i.e. the
199 if (host_addr
.get_host_name (tmp_host
,
200 sizeof (tmp_host
)) != 0)
202 // Can't get the IP address since the INET_Addr wasn't
203 // initialized. Just throw an exception.
205 if (TAO_debug_level
> 0)
206 TAOLIB_DEBUG ((LM_DEBUG
,
207 ACE_TEXT ("\n\nTAO (%P|%t) ")
208 ACE_TEXT ("SCIOP_Profile::parse_string ")
209 ACE_TEXT ("- %p\n\n"),
210 ACE_TEXT ("cannot determine hostname")));
212 // @@ What's the right exception to throw here?
213 throw ::CORBA::INV_OBJREF (
214 CORBA::SystemException::_tao_minor_code (
217 CORBA::COMPLETED_NO
);
220 this->endpoint_
.host_
= CORBA::string_dup (tmp_host
);
221 this->endpoint_
.preferred_interfaces (this->orb_core ());
226 TAO::ObjectKey::decode_string_to_sequence (ok
,
229 (void) this->orb_core ()->object_key_table ().bind (ok
,
230 this->ref_object_key_
);
234 TAO_SCIOP_Profile::do_is_equivalent (const TAO_Profile
*other_profile
)
236 const TAO_SCIOP_Profile
*op
=
237 dynamic_cast<const TAO_SCIOP_Profile
*> (other_profile
);
242 // Check endpoints equivalence.
243 const TAO_SCIOP_Endpoint
*other_endp
= &op
->endpoint_
;
244 for (TAO_SCIOP_Endpoint
*endp
= &this->endpoint_
;
248 if (endp
->is_equivalent (other_endp
))
249 other_endp
= other_endp
->next_
;
258 TAO_SCIOP_Profile::hash (CORBA::ULong max
)
260 // Get the hash value for all endpoints.
261 CORBA::ULong hashval
= 0;
262 for (TAO_SCIOP_Endpoint
*endp
= &this->endpoint_
;
266 hashval
+= endp
->hash ();
269 hashval
+= this->version_
.minor
;
270 hashval
+= this->tag ();
272 const TAO::ObjectKey
&ok
=
273 this->ref_object_key_
->object_key ();
275 if (ok
.length () >= 4)
281 hashval
+= this->hash_service_i (max
);
283 return hashval
% max
;
287 TAO_SCIOP_Profile::endpoint ()
289 return &this->endpoint_
;
293 TAO_SCIOP_Profile::endpoint_count () const
299 TAO_SCIOP_Profile::add_endpoint (TAO_SCIOP_Endpoint
*endp
)
301 endp
->next_
= this->endpoint_
.next_
;
302 this->endpoint_
.next_
= endp
;
308 TAO_SCIOP_Profile::to_string () const
310 CORBA::String_var key
;
311 TAO::ObjectKey::encode_sequence_to_string (key
.inout(),
312 this->ref_object_key_
->object_key());
314 size_t buflen
= (8 /* "corbaloc" */ +
315 1 /* colon separator */ +
316 ACE_OS::strlen (::prefix_
) +
317 1 /* colon separator */ +
318 1 /* major version */ +
319 1 /* decimal point */ +
320 1 /* minor version */ +
321 1 /* `@' character */ +
322 ACE_OS::strlen (this->endpoint_
.host ()) +
323 1 /* colon separator */ +
324 5 /* port number */ +
325 1 /* object key separator */ +
326 ACE_OS::strlen (key
.in ()));
328 char * buf
= CORBA::string_alloc (static_cast<CORBA::ULong
> (buflen
));
330 static const char digits
[] = "0123456789";
332 ACE_OS::sprintf (buf
,
333 "corbaloc:%s:%c.%c@%s:%d%c%s",
335 digits
[this->version_
.major
],
336 digits
[this->version_
.minor
],
337 this->endpoint_
.host (),
338 this->endpoint_
.port (),
339 this->object_key_delimiter_
,
346 TAO_SCIOP_Profile::prefix ()
352 TAO_SCIOP_Profile::create_profile_body (TAO_OutputCDR
&encap
) const
354 encap
.write_octet (TAO_ENCAP_BYTE_ORDER
);
357 encap
.write_octet (this->version_
.major
);
358 encap
.write_octet (this->version_
.minor
);
360 // STRING hostname from profile
361 // encap.write_string (this->endpoint_.host ());
363 CORBA::StringSeq strseq
;
364 strseq
.length(this->count_
);
366 const TAO_SCIOP_Endpoint
*endpoint
= &this->endpoint_
;
367 for (CORBA::ULong i
= 0;
371 strseq
[i
] = endpoint
->host();
372 endpoint
= endpoint
->next_
;
375 // strseq[0] = this->endpoint_.host();
378 // UNSIGNED SHORT port number
379 encap
.write_ushort (this->endpoint_
.port ());
381 // UNSIGNED SHORT max_streams
382 encap
.write_ushort (1);
384 // OCTET SEQUENCE for object key
385 if (this->ref_object_key_
)
386 encap
<< this->ref_object_key_
->object_key ();
389 TAOLIB_ERROR ((LM_ERROR
,
390 "(%P|%t) TAO - IIOP_Profile::create_profile_body "
391 "no object key marshalled\n"));
395 this->tagged_components ().encode (encap
);
399 TAO_SCIOP_Profile::encode_endpoints ()
401 CORBA::ULong actual_count
= 0;
403 const TAO_SCIOP_Endpoint
*endpoint
= &this->endpoint_
;
405 // Count the number of endpoints that needs to be encoded
406 for (CORBA::ULong c
= 0;
410 if (endpoint
->is_encodable_
)
413 endpoint
= endpoint
->next_
;
416 // Create a data structure and fill it with endpoint info for wire
418 // We include information for the head of the list
419 // together with other endpoints because even though its addressing
420 // info is transmitted using standard ProfileBody components, its
423 TAO_SCIOPEndpointSequence endpoints
;
424 endpoints
.length (actual_count
);
426 endpoint
= &this->endpoint_
;
428 for (CORBA::ULong i
= 0;
432 if (endpoint
->is_encodable_
)
434 endpoints
[i
].host
= endpoint
->host ();
435 endpoints
[i
].port
= endpoint
->port ();
436 endpoints
[i
].priority
= endpoint
->priority ();
439 endpoint
= endpoint
->next_
;
442 // Encode the data structure.
443 TAO_OutputCDR out_cdr
;
444 if ((out_cdr
<< ACE_OutputCDR::from_boolean (TAO_ENCAP_BYTE_ORDER
)
446 || (out_cdr
<< endpoints
) == 0)
449 this->set_tagged_components (out_cdr
);
455 TAO_SCIOP_Profile::decode_endpoints ()
457 IOP::TaggedComponent tagged_component
;
458 tagged_component
.tag
= TAO_TAG_ENDPOINTS
;
460 if (this->tagged_components_
.get_component (tagged_component
))
462 const CORBA::Octet
*buf
=
463 tagged_component
.component_data
.get_buffer ();
465 TAO_InputCDR
in_cdr (reinterpret_cast<const char*> (buf
),
466 tagged_component
.component_data
.length ());
468 // Extract the Byte Order.
469 CORBA::Boolean byte_order
;
470 if ((in_cdr
>> ACE_InputCDR::to_boolean (byte_order
)) == 0)
472 in_cdr
.reset_byte_order (static_cast<int> (byte_order
));
474 // Extract endpoints sequence.
475 TAO_SCIOPEndpointSequence endpoints
;
477 if ((in_cdr
>> endpoints
) == 0)
480 // Get the priority of the first endpoint (head of the list.
481 // It's other data is extracted as part of the standard profile
483 this->endpoint_
.priority (endpoints
[0].priority
);
485 // Use information extracted from the tagged component to
486 // populate the profile. Skip the first endpoint, since it is
487 // always extracted through standard profile body. Also, begin
488 // from the end of the sequence to preserve endpoint order,
489 // since <add_endpoint> method reverses the order of endpoints
491 for (CORBA::ULong i
= endpoints
.length () - 1;
495 TAO_SCIOP_Endpoint
*endpoint
= 0;
496 ACE_NEW_RETURN (endpoint
,
497 TAO_SCIOP_Endpoint (endpoints
[i
].host
,
499 endpoints
[i
].priority
),
502 this->add_endpoint (endpoint
);
509 TAO_END_VERSIONED_NAMESPACE_DECL
511 #endif /* TAO_HAS_SCIOP == 1 */