=default for generated implementation copy ctor
[ACE_TAO.git] / TAO / tao / Strategies / SCIOP_Profile.cpp
blobc82ac53436066c226bec7de9866c403bb5f13594
1 #include "tao/Strategies/SCIOP_Profile.h"
3 #if TAO_HAS_SCIOP == 1
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/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
20 char
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,
31 orb_core,
32 object_key,
33 version),
34 endpoint_ (addr,
35 orb_core->orb_params ()->use_dotted_decimal_addresses ()),
36 count_ (1)
40 TAO_SCIOP_Profile::TAO_SCIOP_Profile (const char* host,
41 CORBA::UShort port,
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,
47 orb_core,
48 object_key,
49 version),
50 endpoint_ (host, port, addr),
51 count_ (1)
55 TAO_SCIOP_Profile::TAO_SCIOP_Profile (TAO_ORB_Core *orb_core)
56 : TAO_Profile (TAO_TAG_SCIOP_PROFILE,
57 orb_core,
58 TAO_GIOP_Message_Version (TAO_DEF_SCIOP_MAJOR, TAO_DEF_SCIOP_MINOR)),
59 endpoint_ (),
60 count_ (1)
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 ();
71 next != 0;
72 next = tmp)
74 tmp = next->next ();
75 delete next;
79 int
80 TAO_SCIOP_Profile::decode_profile (TAO_InputCDR& cdr)
82 // Decode multiple endpoints, starting with the primary (endpoint_)
83 CORBA::StringSeq endpointSeq;
84 cdr >> 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")));
94 return -1;
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()),
106 -1);
108 this->count_ +=
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) {
119 return -1;
122 if (cdr.good_bit ())
124 // Invalidate the object_addr_ until first access.
125 this->endpoint_.object_addr_.set_type (-1);
127 return 1;
130 return -1;
133 void
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 (
146 TAO::VMCID,
147 EINVAL),
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
156 if (cp_pos == ior)
158 // No hostname specified! It is required by the spec.
159 throw ::CORBA::INV_OBJREF (
160 CORBA::SystemException::_tao_minor_code (
161 TAO::VMCID,
162 EINVAL),
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;
180 else
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
198 // local host.
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 (
215 TAO::VMCID,
216 EINVAL),
217 CORBA::COMPLETED_NO);
220 this->endpoint_.host_ = CORBA::string_dup (tmp_host);
221 this->endpoint_.preferred_interfaces (this->orb_core ());
224 TAO::ObjectKey ok;
226 TAO::ObjectKey::decode_string_to_sequence (ok,
227 okd + 1);
229 (void) this->orb_core ()->object_key_table ().bind (ok,
230 this->ref_object_key_);
233 CORBA::Boolean
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);
239 if (op == 0)
240 return false;
242 // Check endpoints equivalence.
243 const TAO_SCIOP_Endpoint *other_endp = &op->endpoint_;
244 for (TAO_SCIOP_Endpoint *endp = &this->endpoint_;
245 endp != 0;
246 endp = endp->next_)
248 if (endp->is_equivalent (other_endp))
249 other_endp = other_endp->next_;
250 else
251 return false;
254 return true;
257 CORBA::ULong
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_;
263 endp != 0;
264 endp = endp->next_)
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)
277 hashval += ok[1];
278 hashval += ok[3];
281 hashval += this->hash_service_i (max);
283 return hashval % max;
286 TAO_Endpoint*
287 TAO_SCIOP_Profile::endpoint ()
289 return &this->endpoint_;
292 CORBA::ULong
293 TAO_SCIOP_Profile::endpoint_count () const
295 return this->count_;
298 void
299 TAO_SCIOP_Profile::add_endpoint (TAO_SCIOP_Endpoint *endp)
301 endp->next_ = this->endpoint_.next_;
302 this->endpoint_.next_ = endp;
304 this->count_++;
307 char *
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",
334 ::prefix_,
335 digits [this->version_.major],
336 digits [this->version_.minor],
337 this->endpoint_.host (),
338 this->endpoint_.port (),
339 this->object_key_delimiter_,
340 key.in ());
342 return buf;
345 const char *
346 TAO_SCIOP_Profile::prefix ()
348 return ::prefix_;
351 void
352 TAO_SCIOP_Profile::create_profile_body (TAO_OutputCDR &encap) const
354 encap.write_octet (TAO_ENCAP_BYTE_ORDER);
356 // The SCIOP version
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;
368 i < this->count_;
369 ++i)
371 strseq[i] = endpoint->host();
372 endpoint = endpoint->next_;
375 // strseq[0] = this->endpoint_.host();
376 encap << strseq;
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 ();
387 else
389 TAOLIB_ERROR ((LM_ERROR,
390 "(%P|%t) TAO - IIOP_Profile::create_profile_body "
391 "no object key marshalled\n"));
394 // Tagged Components
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;
407 c != this->count_;
408 ++c)
410 if (endpoint->is_encodable_)
411 ++actual_count;
413 endpoint = endpoint->next_;
416 // Create a data structure and fill it with endpoint info for wire
417 // transfer.
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
421 // priority is not!
423 TAO_SCIOPEndpointSequence endpoints;
424 endpoints.length (actual_count);
426 endpoint = &this->endpoint_;
428 for (CORBA::ULong i = 0;
429 i < this->count_;
430 ++i)
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)
445 == 0)
446 || (out_cdr << endpoints) == 0)
447 return -1;
449 this->set_tagged_components (out_cdr);
451 return 0;
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)
471 return -1;
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)
478 return -1;
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
482 // decoding.
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
490 // in the list.
491 for (CORBA::ULong i = endpoints.length () - 1;
492 i > 0;
493 --i)
495 TAO_SCIOP_Endpoint *endpoint = 0;
496 ACE_NEW_RETURN (endpoint,
497 TAO_SCIOP_Endpoint (endpoints[i].host,
498 endpoints[i].port,
499 endpoints[i].priority),
500 -1);
502 this->add_endpoint (endpoint);
506 return 0;
509 TAO_END_VERSIONED_NAMESPACE_DECL
511 #endif /* TAO_HAS_SCIOP == 1 */