Revert "Use a variable on the stack to not have a temporary in the call"
[ACE_TAO.git] / TAO / tao / CORBALOC_Parser.cpp
blob2ab88c2c38a79b904cf4874d202b5136167f0f1b
1 // -*- C++ -*-
2 #include "tao/CORBALOC_Parser.h"
4 #if (TAO_HAS_CORBALOC_PARSER == 1)
6 #include "tao/ORB_Core.h"
7 #include "tao/Stub.h"
8 #include "tao/MProfile.h"
9 #include "tao/Connector_Registry.h"
10 #include "tao/Transport_Connector.h"
11 #include "tao/Protocol_Factory.h"
12 #include "tao/debug.h"
13 #include "tao/SystemException.h"
14 #include "ace/Vector_T.h"
15 #include "ace/INET_Addr.h"
16 #include "ace/OS_NS_string.h"
17 #include "ace/Truncate.h"
19 #include "ace/os_include/os_netdb.h"
21 #if !defined(__ACE_INLINE__)
22 #include "tao/CORBALOC_Parser.inl"
23 #endif /* __ACE_INLINE__ */
25 #include <cstring>
27 static const char prefix[] = "corbaloc:";
28 static const size_t prefix_len = sizeof prefix - 1;
29 static const char rir_token[] = "rir:";
30 static const size_t rir_token_len = sizeof rir_token - 1;
31 static const char iiop_token[] = "iiop:";
32 static const char iiop_token_len = sizeof iiop_token - 1;
34 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
36 bool
37 TAO_CORBALOC_Parser::match_prefix (const char *ior_string) const
39 // Check if the prefix is 'corbaloc:' and return the result.
40 return (ACE_OS::strncmp (ior_string,
41 prefix,
42 prefix_len) == 0);
45 CORBA::Object_ptr
46 TAO_CORBALOC_Parser::make_stub_from_mprofile (CORBA::ORB_ptr orb,
47 TAO_MProfile &mprofile)
49 // Create a TAO_Stub.
50 TAO_Stub *data = orb->orb_core ()->create_stub ((const char *) nullptr, mprofile);
52 TAO_Stub_Auto_Ptr safe_data (data);
54 CORBA::Object_var obj = orb->orb_core ()->create_object (data);
56 if (!CORBA::is_nil (obj.in ()))
58 /// All is well, so release the stub object from its
59 /// auto_ptr.
60 (void) safe_data.release ();
62 /// Return the object reference to the application.
63 return obj._retn ();
66 /// Shouldnt come here: if so, return nil reference.
67 return CORBA::Object::_nil ();
70 CORBA::Object_ptr
71 TAO_CORBALOC_Parser::parse_string_rir_helper (const char * ior,
72 CORBA::ORB_ptr orb)
74 // Pass the key string as an argument to resolve_initial_references.
75 // NameService is the default if an empty key string is supplied.
76 const char *objkey = ior + rir_token_len;
77 if (*objkey == '/') // there is an explicit object key, which may
78 // validly be null.
79 objkey++;
81 CORBA::Object_var rir_obj =
82 orb->resolve_initial_references (*objkey == '\0' ? "NameService" : objkey);
84 return rir_obj._retn ();
87 CORBA::Object_ptr
88 TAO_CORBALOC_Parser::parse_string (const char * ior, CORBA::ORB_ptr orb)
90 // The decomposition of a corbaloc string is in Section 13.6.10.
92 // following the "corbaloc:"
93 // a comma separated list of <prot_addr> strings
94 // for each,
95 // Separate out the key, delimited by '/'
96 // Split out the various parts of our corbaloc string, comma-delimited
97 // For each part
98 // Determine the protocol
99 // If rir, defer to another function and return the object
100 // If iiop, make the profile with <endpoint>:<port>/<key>
101 // If another protocol, use <remainder>/<key>
102 // Search through the collection of protocols for the correct one
103 // If not found, throw exception
104 // If found, make our_connector from it.
105 // our_connector->make_mprofile_unchecked (...);
106 // object = this->make_stub_from_mprofile (...);
107 // Return the object
109 // Skip the prefix. We know it is there because this method is only
110 // called if match_prefix() returns 1.
111 ior += std::strlen(prefix);
113 // First check for rir
114 if (ACE_OS::strncmp (ior,rir_token,rir_token_len) == 0)
115 return this->parse_string_rir_helper (ior,orb);
117 // set up space for parsed endpoints. there will be at least 1, and
118 // most likely commas will separate endpoints, although they could be
119 // part of an endpoint address for some protocols.
120 size_t max_endpoint_count = 1;
121 for (const char *comma = std::strchr (ior,',');
122 comma;
123 comma = std::strchr (comma+1,','))
124 ++max_endpoint_count;
126 ACE_Array<parsed_endpoint> endpoints(max_endpoint_count);
127 endpoints.size (0);
129 // Get the Connector Registry from the ORB.
130 TAO_Connector_Registry *conn_reg =
131 orb->orb_core ()->connector_registry();
133 while (1) { // will loop on comma only.
134 size_t len = 0;
135 size_t ndx = endpoints.size();
136 endpoints.size(ndx+1);
137 bool uiop_compatible = false;
138 TAO_ConnectorSetIterator conn_iter = nullptr;
139 for (conn_iter = conn_reg->begin();
140 conn_iter != conn_reg->end() &&
141 endpoints[ndx].profile_ == nullptr;
142 conn_iter ++)
144 endpoints[ndx].profile_ =
145 (*conn_iter)->corbaloc_scan(ior,len);
147 if (endpoints[ndx].profile_)
149 endpoints[ndx].obj_key_sep_ = (*conn_iter)->object_key_delimiter();
150 uiop_compatible = (endpoints[ndx].obj_key_sep_ == '|');
151 this->make_canonical (ior,len,endpoints[ndx].prot_addr_);
152 ior += len;
153 break;
157 if (endpoints[ndx].profile_ == nullptr)
159 if (TAO_debug_level)
160 TAOLIB_ERROR ((LM_ERROR,
161 ACE_TEXT("TAO (%P|%t) - TAO_CORBALOC_Parser::parse_string ")
162 ACE_TEXT("could not parse from %C\n"),
163 ior));
164 throw ::CORBA::BAD_PARAM (CORBA::OMGVMCID | 10, CORBA::COMPLETED_NO);
166 if (*ior == ',') // more endpoints follow
168 ++ior;
169 continue;
172 if (*ior == endpoints[ndx].obj_key_sep_) // found key separator
174 ++ior;
175 break;
178 if (*ior == '\0') // no key separator appended, use default key
180 break;
183 if (uiop_compatible && *(ior - 1) == '|')
184 // Assume this is an old uiop style corbaloc. No need to warn here,
185 // the UIOP_Connector::corbaloc_scan already did.
186 break;
188 // anything else is a violation.
189 if (TAO_debug_level)
190 TAOLIB_ERROR ((LM_ERROR,
191 ACE_TEXT("TAO (%P|%t) - TAO_CORBALOC_Parser::parse_string ")
192 ACE_TEXT("could not parse from <%C>\n"),
193 ior));
194 throw ::CORBA::BAD_PARAM (CORBA::OMGVMCID | 10, CORBA::COMPLETED_NO);
195 } // end of while
197 // At this point, ior points at the start of the object key
198 ACE_CString obj_key (*ior ? ior : (const char *)"NameService");
200 // now take the collection of endpoints along with the decoded key and
201 // mix them together to get the mprofile.
202 TAO_MProfile mprofile (ACE_Utils::truncate_cast<CORBA::ULong> (endpoints.size()));
204 for (size_t i = 0; i < endpoints.size(); i++)
206 ACE_CString full_ep = endpoints[i].prot_addr_ +
207 endpoints[i].obj_key_sep_ +
208 obj_key;
209 const char * str = full_ep.c_str();
210 endpoints[i].profile_->parse_string (str);
211 int const share = orb->orb_core()->orb_params()->shared_profile();
212 if (mprofile.give_profile(endpoints[i].profile_, share) != -1)
213 endpoints[i].profile_ = nullptr;
214 else
216 // Although this ought never happen, we want to make some
217 // indication back to the caller, more as an audit trail than
218 // anything else. The only failure possible is that there was
219 // insufficient heap to allocate the mprofile, hence the
220 // mprofile's size is 0, and give_profile fails.
221 if (TAO_debug_level)
222 TAOLIB_ERROR ((LM_ERROR,
223 ACE_TEXT("TAO (%P|%t) - TAO_CORBALOC_Parser::parse_string ")
224 ACE_TEXT("mprofile.give_profile failed for i = %d\n"),
225 i));
226 throw ::CORBA::BAD_PARAM (CORBA::OMGVMCID | 10, CORBA::COMPLETED_NO);
230 // Get an object stub out.
231 return this->make_stub_from_mprofile (orb, mprofile);
234 void
235 TAO_CORBALOC_Parser::make_canonical (const char *ior,
236 size_t prot_addr_len,
237 ACE_CString &canonical_endpoint)
239 const char *separator = std::strchr (ior, ':');
241 // A special case for handling iiop
242 if (ior[0] != ':' && ACE_OS::strncmp (ior,iiop_token,iiop_token_len) != 0)
244 canonical_endpoint.set (separator+1,
245 prot_addr_len - (separator - ior) - 1,1);
246 return;
249 const char *addr_base = separator+1;
250 const char *addr_tail = ior + prot_addr_len;
251 // skip past version, if any
252 separator = std::strchr (addr_base,'@');
253 if (separator != nullptr && separator < addr_tail)
255 canonical_endpoint.set (addr_base,(separator - addr_base)+1,1);
256 addr_base = separator + 1;
258 else
259 canonical_endpoint.clear ();
261 ACE_CString raw_host;
262 ACE_CString raw_port;
263 separator = std::strchr (addr_base,':');
264 #if defined (ACE_HAS_IPV6)
265 // IPv6 numeric address in host string?
267 // Check if this is an address containing a decimal IPv6 address representation.
268 if (addr_base < addr_tail && addr_base[0] == '[')
270 // In this case we have to find the end of the numeric address and
271 // start looking for the port separator from there.
272 const char *cp_pos = std::strchr(addr_base, ']');
273 if (cp_pos == 0 || cp_pos >= addr_tail)
275 // No valid IPv6 address specified but that will come out later.
276 if (TAO_debug_level > 0)
278 TAOLIB_ERROR ((LM_ERROR,
279 ACE_TEXT ("TAO (%P|%t) - TAO_CORBALOC_Parser: ")
280 ACE_TEXT ("Invalid IPv6 decimal address specified.\n")));
282 separator = 0;
284 else
286 if (cp_pos[1] == ':') // Look for a port
287 separator = cp_pos + 1;
288 else
289 separator = 0;
292 #endif /* ACE_HAS_IPV6 */
294 if (separator != nullptr && separator < addr_tail)
296 // we have a port number
297 raw_host.set (addr_base, (separator - addr_base), 1);
298 raw_port.set (separator, (addr_tail - separator), 1);
300 else
302 // we must default port #
303 if (addr_base < addr_tail)
304 raw_host.set (addr_base, (addr_tail - addr_base),1);
305 raw_port.set (":2809");
308 if (raw_host.length() == 0)
310 ACE_INET_Addr host_addr;
312 char tmp_host [MAXHOSTNAMELEN + 1];
314 // If no host is specified: assign the default host, i.e. the
315 // local host.
316 if (host_addr.get_host_name (tmp_host,
317 sizeof (tmp_host)) != 0)
319 // Can't get the IP address since the INET_Addr wasn't
320 // initialized. Just throw an exception.
322 if (TAO_debug_level > 0)
323 TAOLIB_DEBUG ((LM_DEBUG,
324 ACE_TEXT ("TAO (%P|%t) - ")
325 ACE_TEXT ("Cannot determine hostname.\n")));
327 throw ::CORBA::INV_OBJREF
328 (CORBA::SystemException::_tao_minor_code
329 (TAO::VMCID, EINVAL),
330 CORBA::COMPLETED_NO);
332 else
334 canonical_endpoint += tmp_host;
337 else
339 canonical_endpoint += raw_host;
342 canonical_endpoint += raw_port;
345 ACE_STATIC_SVC_DEFINE (TAO_CORBALOC_Parser,
346 ACE_TEXT ("CORBALOC_Parser"),
347 ACE_SVC_OBJ_T,
348 &ACE_SVC_NAME (TAO_CORBALOC_Parser),
349 ACE_Service_Type::DELETE_THIS |
350 ACE_Service_Type::DELETE_OBJ,
353 ACE_FACTORY_DEFINE (TAO, TAO_CORBALOC_Parser)
355 TAO_END_VERSIONED_NAMESPACE_DECL
357 #endif /* TAO_HAS_CORBALOC_PARSER == 1 */