2 #include "tao/CORBALOC_Parser.h"
4 #if (TAO_HAS_CORBALOC_PARSER == 1)
6 #include "tao/ORB_Core.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__ */
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
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
,
46 TAO_CORBALOC_Parser::make_stub_from_mprofile (CORBA::ORB_ptr orb
,
47 TAO_MProfile
&mprofile
)
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
60 (void) safe_data
.release ();
62 /// Return the object reference to the application.
66 /// Shouldnt come here: if so, return nil reference.
67 return CORBA::Object::_nil ();
71 TAO_CORBALOC_Parser::parse_string_rir_helper (const char * ior
,
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
81 CORBA::Object_var rir_obj
=
82 orb
->resolve_initial_references (*objkey
== '\0' ? "NameService" : objkey
);
84 return rir_obj
._retn ();
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
95 // Separate out the key, delimited by '/'
96 // Split out the various parts of our corbaloc string, comma-delimited
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 (...);
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
,',');
123 comma
= std::strchr (comma
+1,','))
124 ++max_endpoint_count
;
126 ACE_Array
<parsed_endpoint
> endpoints(max_endpoint_count
);
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.
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;
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_
);
157 if (endpoints
[ndx
].profile_
== nullptr)
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"),
164 throw ::CORBA::BAD_PARAM (CORBA::OMGVMCID
| 10, CORBA::COMPLETED_NO
);
166 if (*ior
== ',') // more endpoints follow
172 if (*ior
== endpoints
[ndx
].obj_key_sep_
) // found key separator
178 if (*ior
== '\0') // no key separator appended, use default key
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.
188 // anything else is a violation.
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"),
194 throw ::CORBA::BAD_PARAM (CORBA::OMGVMCID
| 10, CORBA::COMPLETED_NO
);
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_
+
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;
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.
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"),
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
);
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);
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;
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")));
286 if (cp_pos
[1] == ':') // Look for a port
287 separator
= cp_pos
+ 1;
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);
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
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
);
334 canonical_endpoint
+= tmp_host
;
339 canonical_endpoint
+= raw_host
;
342 canonical_endpoint
+= raw_port
;
345 ACE_STATIC_SVC_DEFINE (TAO_CORBALOC_Parser
,
346 ACE_TEXT ("CORBALOC_Parser"),
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 */