1 #include "tao/MCAST_Parser.h"
3 #if (TAO_HAS_MCAST_PARSER == 1)
5 #include "tao/default_ports.h"
6 #include "tao/ORB_Core.h"
10 #include "ace/SOCK_Acceptor.h"
11 #include "ace/SOCK_Dgram.h"
12 #include "ace/OS_NS_strings.h"
13 #include "ace/OS_NS_string.h"
14 #include "ace/Truncate.h"
17 #if !defined(__ACE_INLINE__)
18 #include "tao/MCAST_Parser.inl"
19 #endif /* __ACE_INLINE__ */
21 static const char mcast_prefix
[] = "mcast:";
23 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
25 TAO_MCAST_Parser::~TAO_MCAST_Parser ()
30 TAO_MCAST_Parser::match_prefix (const char *ior_string
) const
32 return (ACE_OS::strncmp (ior_string
,
34 sizeof (::mcast_prefix
) - 1) == 0);
38 TAO_MCAST_Parser::parse_string (const char *ior
, CORBA::ORB_ptr orb
)
40 char const * const mcast_name
=
41 ior
+ sizeof (::mcast_prefix
) + 1;
43 this->assign_to_variables (mcast_name
);
46 * Now that we got the global variables.
47 * we can invoke multicast_to_service and multicast_query
49 ACE_Time_Value
*timeout
= orb
->get_timeout ();
52 this->multicast_to_service (service_name_
.in (),
54 this->mcast_address_
.in (),
56 this->mcast_nic_
.in (),
62 TAO_MCAST_Parser::multicast_to_service (const char *service_name
,
64 const char *mcast_address
,
66 const char *mcast_nic
,
68 ACE_Time_Value
*timeout
)
70 char buf
[TAO_DEFAULT_IOR_SIZE
];
73 // Use UDP multicast to locate the service.
74 int const result
= this->multicast_query (ior
,
83 CORBA::Object_var return_value
;
87 CORBA::String_var cleaner
;
88 // If the IOR didn't fit into <buf>, memory for it was dynamically
89 // allocated - make sure it gets deallocated.
93 // Convert IOR to an object reference.
95 orb
->string_to_object (ior
);
98 // Return object reference.
99 return return_value
._retn ();
103 TAO_MCAST_Parser::multicast_query (char* & buf
,
104 const char *service_name
,
106 const char *mcast_address
,
108 const char *mcast_nic
,
109 ACE_Time_Value
*timeout
,
112 ACE_INET_Addr my_addr
;
113 ACE_SOCK_Acceptor acceptor
;
114 ACE_SOCK_Stream stream
;
115 ACE_SOCK_Dgram dgram
;
119 // Bind listener to any port and then find out what the port was.
120 #if defined (ACE_HAS_IPV6)
121 if (acceptor
.open (ACE_Addr::sap_any
, 0, AF_INET6
) == -1
122 #else /* ACE_HAS_IPV6 */
123 if (acceptor
.open (ACE_Addr::sap_any
) == -1
124 #endif /* !ACE_HAS_IPV6 */
125 || acceptor
.get_local_addr (my_addr
) == -1)
127 TAOLIB_ERROR ((LM_ERROR
,
128 ACE_TEXT ("acceptor.open () || ")
129 ACE_TEXT ("acceptor.get_local_addr () failed\n")));
134 if (TAO_debug_level
> 0)
137 my_addr
.addr_to_string (addr
, sizeof(addr
));
138 TAOLIB_DEBUG ((LM_DEBUG
,
139 ACE_TEXT("TAO (%P|%t) - MCAST_Parser: acceptor local address %s.\n"),
143 ACE_INET_Addr
multicast_addr (port
,
146 // Set the address if multicast_discovery_endpoint option
147 // is specified for the Naming Service.
148 ACE_CString
mde (orb
->orb_core ()->orb_params ()
149 ->mcast_discovery_endpoint ());
151 if (ACE_OS::strcasecmp (service_name
,
153 && mde
.length () != 0)
154 if (multicast_addr
.set (mde
.c_str()) == -1)
156 TAOLIB_ERROR ((LM_ERROR
,
157 ACE_TEXT("ORB.cpp: Multicast address setting failed\n")));
164 // Open the datagram.
165 if (dgram
.open (ACE_Addr::sap_any
, multicast_addr
.get_type ()) == -1)
167 TAOLIB_ERROR ((LM_ERROR
,
168 ACE_TEXT ("Unable to open the Datagram!\n")));
174 dgram
.set_nic (ACE_TEXT_CHAR_TO_TCHAR (mcast_nic
),
175 multicast_addr
.get_type ());
178 int mcast_ttl_optval
= mcast_ttl
;
180 #if defined (ACE_HAS_IPV6)
181 if (multicast_addr
.get_type () == AF_INET6
)
183 if (dgram
.set_option (
187 sizeof (mcast_ttl_optval
)) != 0)
191 #endif /* ACE_HAS_IPV6 */
192 if (dgram
.set_option (
196 sizeof (mcast_ttl_optval
)) != 0)
199 // Convert the acceptor port into network byte order.
200 ACE_UINT16 response_port
=
201 (ACE_UINT16
) ACE_HTONS (my_addr
.get_port_number ());
203 // Length of service name we will send.
204 CORBA::Short data_len
=
205 (CORBA::Short
) ACE_HTONS (
206 ACE_Utils::truncate_cast
<ACE_UINT16
> (
207 std::strlen (service_name
) + 1));
209 // Vector we will send. It contains: 1) length of service
210 // name string, 2)port on which we are listening for
211 // replies, and 3) name of service we are looking for.
212 const int iovcnt
= 3;
215 // The length of service name string.
216 iovp
[0].iov_base
= (char *) &data_len
;
217 iovp
[0].iov_len
= sizeof (CORBA::Short
);
219 // The port at which we are listening.
220 iovp
[1].iov_base
= (char *) &response_port
;
221 iovp
[1].iov_len
= sizeof (ACE_UINT16
);
223 // The service name string.
224 iovp
[2].iov_base
= (char *) service_name
;
226 static_cast<u_long
> (std::strlen (service_name
) + 1);
228 // Send the multicast.
229 result
= dgram
.send (iovp
,
233 if (TAO_debug_level
> 0)
234 TAOLIB_DEBUG ((LM_DEBUG
,
235 ACE_TEXT ("\nsent multicast request.")));
239 TAOLIB_ERROR ((LM_ERROR
,
241 ACE_TEXT ("error sending IIOP multicast")));
244 if (TAO_debug_level
> 0)
245 TAOLIB_DEBUG ((LM_DEBUG
,
246 ACE_TEXT ("\n%N; Sent multicast.")
247 ACE_TEXT ("# of bytes sent is %d.\n"),
249 // Wait for response until timeout.
252 ? ACE_Time_Value (TAO_DEFAULT_SERVICE_RESOLUTION_TIMEOUT
)
255 // Accept reply connection from server.
256 if (acceptor
.accept (stream
,
260 if (TAO_debug_level
> 0)
262 TAOLIB_ERROR ((LM_ERROR
,
264 ACE_TEXT ("multicast_query: unable to accept")));
273 CORBA::Short ior_len
;
274 result
= stream
.recv_n (&ior_len
,
278 if (result
!= (ssize_t
)sizeof (ior_len
))
280 if (TAO_debug_level
> 0)
282 TAOLIB_ERROR ((LM_ERROR
,
284 ACE_TEXT ("multicast_query: unable to receive ")
285 ACE_TEXT ("ior length")));
291 // Allocate more space for the ior if we don't
293 ior_len
= (CORBA::Short
) ACE_NTOHS (ior_len
);
294 if (ior_len
>= TAO_DEFAULT_IOR_SIZE
)
296 buf
= CORBA::string_alloc (ior_len
);
299 if (TAO_debug_level
> 0)
301 TAOLIB_ERROR ((LM_ERROR
,
303 ACE_TEXT ("multicast_query: unable to ")
304 ACE_TEXT ("allocate memory")));
313 result
= stream
.recv_n (buf
,
318 TAOLIB_ERROR ((LM_ERROR
,
320 ACE_TEXT ("error reading ior")));
321 else if (TAO_debug_level
> 0)
322 TAOLIB_DEBUG ((LM_DEBUG
,
323 ACE_TEXT ("%N: service resolved to IOR <%C>\n"),
332 TAOLIB_ERROR ((LM_ERROR
,
333 ACE_TEXT("\nmulticast discovery of %C failed.\n"),
336 if (ACE_OS::strcasecmp (service_name
,
339 TAOLIB_ERROR ((LM_ERROR
,
340 ACE_TEXT("Specify -m 1 when starting Naming_Service,\n")
341 ACE_TEXT("or see http://www.theaceorb.com/faq/#115\n")
342 ACE_TEXT("for using NameService without multicast.\n\n")));
352 return result
== -1 ? -1 : 0;
356 TAO_MCAST_Parser::assign_to_variables (char const * mcast_name
)
359 * The format now is "multicast_address:port:nicaddress:ttl/object_key"
361 ACE_CString
mcast_name_cstring (mcast_name
);
363 ACE_CString::size_type pos_colon1
= mcast_name_cstring
.find (':', 0);
365 #if defined (ACE_HAS_IPV6)
366 // IPv6 numeric address in host string?
367 bool ipv6_in_host
= false;
369 // Check if this is an mcast address containing a
370 // decimal IPv6 address representation.
371 if (mcast_name_cstring
[0] == '[')
373 // In this case we have to find the end of the numeric address and
374 // start looking for the port separator from there.
375 ACE_CString::size_type
const cp_pos
= mcast_name_cstring
.find (']', 0);
378 // No valid IPv6 address specified.
379 if (TAO_debug_level
> 0)
381 TAOLIB_ERROR ((LM_ERROR
,
382 ACE_TEXT ("\nTAO (%P|%t) MCAST_Parser: ")
383 ACE_TEXT ("Invalid IPv6 decimal address specified.\n")));
390 if (mcast_name_cstring
[cp_pos
+ 1] == ':') // Look for a port
391 pos_colon1
= cp_pos
+ 1;
394 ipv6_in_host
= true; // host string contains full IPv6 numeric address
397 #endif /* ACE_HAS_IPV6 */
401 #if defined (ACE_HAS_IPV6)
402 const char default_addr
[] = ACE_DEFAULT_MULTICASTV6_ADDR
;
403 #else /* ACE_HAS_IPV6 */
404 const char default_addr
[] = ACE_DEFAULT_MULTICAST_ADDR
;
405 #endif /* !ACE_HAS_IPV6 */
406 this->mcast_address_
= default_addr
;
410 #if defined (ACE_HAS_IPV6)
412 this->mcast_address_
=
413 mcast_name_cstring
.substring (1,
414 pos_colon1
- 2).c_str ();
416 #endif /* ACE_HAS_IPV6 */
417 this->mcast_address_
=
418 mcast_name_cstring
.substring (0,
419 pos_colon1
).c_str ();
422 mcast_name_cstring
.substring (pos_colon1
+ 1,
423 mcast_name_cstring
.length() -
426 ACE_CString::size_type
const pos_colon2
= mcast_name_cstring
.find (':', 0);
430 if (mcast_name_cstring
.find ("InterfaceRepository") != ACE_CString::npos
)
433 TAO_DEFAULT_INTERFACEREPO_SERVER_REQUEST_PORT
;
435 else if (mcast_name_cstring
.find ("ImplRepoService") != ACE_CString::npos
)
438 TAO_DEFAULT_IMPLREPO_SERVER_REQUEST_PORT
;
440 else if (mcast_name_cstring
.find ("TradingService") != ACE_CString::npos
)
442 this->mcast_port_
= TAO_DEFAULT_TRADING_SERVER_REQUEST_PORT
;
448 ACE_OS::atoi (mcast_name_cstring
.substring (0, pos_colon2
).c_str ());
450 if (the_port
>= 0 && the_port
<= ACE_MAX_DEFAULT_PORT
)
451 this->mcast_port_
= the_port
;
455 mcast_name_cstring
.substring (pos_colon2
+ 1,
456 mcast_name_cstring
.length() - pos_colon2
);
459 ACE_CString::size_type
const pos_colon3
= mcast_name_cstring
.find (':', 0);
461 this->mcast_nic_
= mcast_name_cstring
.substring (0, pos_colon3
).c_str ();
464 mcast_name_cstring
.substring (pos_colon3
+ 1,
465 mcast_name_cstring
.length() - pos_colon3
);
467 ACE_CString::size_type
const pos_colon4
= mcast_name_cstring
.find ('/', 0);
471 // Change TTL to non-default value.
473 ACE_OS::atoi (mcast_name_cstring
.substring (0, pos_colon4
).c_str ());
475 if (the_ttl
> 0 && the_ttl
<= 255) // Valid TTLs: (0, 255]
476 this->mcast_ttl_
= the_ttl
;
480 mcast_name_cstring
.substring (pos_colon4
,
481 mcast_name_cstring
.length() - pos_colon4
);
483 this->service_name_
=
484 mcast_name_cstring
.substring (1, mcast_name_cstring
.length() - 1).c_str ();
487 ACE_STATIC_SVC_DEFINE (TAO_MCAST_Parser
,
488 ACE_TEXT ("MCAST_Parser"),
490 &ACE_SVC_NAME (TAO_MCAST_Parser
),
491 ACE_Service_Type::DELETE_THIS
|
492 ACE_Service_Type::DELETE_OBJ
,
495 ACE_FACTORY_DEFINE (TAO
, TAO_MCAST_Parser
)
497 TAO_END_VERSIONED_NAMESPACE_DECL
500 #endif /* TAO_HAS_MCAST_PARSER == 1 */