00001 #include "tao/MCAST_Parser.h"
00002 #include "tao/default_ports.h"
00003 #include "tao/ORB_Core.h"
00004 #include "tao/ORB.h"
00005 #include "tao/Environment.h"
00006 #include "tao/debug.h"
00007
00008 #include "ace/SOCK_Acceptor.h"
00009 #include "ace/SOCK_Dgram.h"
00010 #include "ace/OS_NS_strings.h"
00011 #include "ace/OS_NS_string.h"
00012
00013 #if !defined(__ACE_INLINE__)
00014 #include "tao/MCAST_Parser.i"
00015 #endif
00016
00017
00018 ACE_RCSID (tao,
00019 MCAST_Parser,
00020 "MCAST_Parser.cpp,v 1.32 2006/04/19 09:02:55 jwillemsen Exp")
00021
00022
00023 static const char mcast_prefix[] = "mcast:";
00024
00025
00026 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00027
00028 TAO_MCAST_Parser::~TAO_MCAST_Parser (void)
00029 {
00030 }
00031
00032 int
00033 TAO_MCAST_Parser::match_prefix (const char *ior_string) const
00034 {
00035 return (ACE_OS::strncmp (ior_string,
00036 ::mcast_prefix,
00037 sizeof (::mcast_prefix) - 1) == 0);
00038 }
00039
00040 CORBA::Object_ptr
00041 TAO_MCAST_Parser::parse_string (const char *ior,
00042 CORBA::ORB_ptr orb
00043 ACE_ENV_ARG_DECL)
00044 ACE_THROW_SPEC ((CORBA::SystemException))
00045 {
00046 const char *mcast_name =
00047 ior + sizeof (::mcast_prefix) + 1;
00048
00049 assign_to_variables (mcast_name);
00050
00051
00052
00053
00054
00055 CORBA::Object_ptr object = CORBA::Object::_nil ();
00056
00057 CORBA::UShort const port =
00058 (CORBA::UShort) ACE_OS::atoi (this->mcast_port_.in ());
00059
00060 ACE_Time_Value *timeout = orb->get_timeout ();
00061
00062 object = multicast_to_service (service_name_.in (),
00063 port,
00064 this->mcast_address_.in (),
00065 this->mcast_ttl_.in (),
00066 this->mcast_nic_.in (),
00067 orb,
00068 timeout
00069 ACE_ENV_ARG_PARAMETER);
00070 ACE_CHECK_RETURN (CORBA::Object::_nil ());
00071
00072 return object;
00073 }
00074
00075 CORBA::Object_ptr
00076 TAO_MCAST_Parser::multicast_to_service (const char *service_name,
00077 u_short port,
00078 const char *mcast_address,
00079 const char *mcast_ttl,
00080 const char *mcast_nic,
00081 CORBA::ORB_ptr orb,
00082 ACE_Time_Value *timeout
00083 ACE_ENV_ARG_DECL)
00084 {
00085 char buf[2048];
00086 char *ior = buf;
00087
00088 CORBA::String_var cleaner;
00089
00090 CORBA::Object_var return_value =
00091 CORBA::Object::_nil ();
00092
00093
00094 int const result = this->multicast_query (ior,
00095 service_name,
00096 port,
00097 mcast_address,
00098 mcast_ttl,
00099 mcast_nic,
00100 timeout,
00101 orb);
00102
00103
00104
00105 if (ior != buf)
00106 cleaner = ior;
00107
00108 if (result == 0)
00109 {
00110
00111 return_value =
00112 orb->string_to_object (ior
00113 ACE_ENV_ARG_PARAMETER);
00114 ACE_CHECK_RETURN (CORBA::Object::_nil ());
00115 }
00116
00117
00118 return return_value._retn ();
00119 }
00120
00121 int
00122 TAO_MCAST_Parser::multicast_query (char *&buf,
00123 const char *service_name,
00124 u_short port,
00125 const char *mcast_address,
00126 const char *mcast_ttl,
00127 const char *mcast_nic,
00128 ACE_Time_Value *timeout,
00129 CORBA::ORB_ptr orb)
00130 {
00131 ACE_INET_Addr my_addr;
00132 ACE_SOCK_Acceptor acceptor;
00133 ACE_SOCK_Stream stream;
00134 ACE_SOCK_Dgram dgram;
00135
00136 ssize_t result = 0;
00137
00138
00139 #if defined (ACE_HAS_IPV6)
00140 if (acceptor.open (ACE_Addr::sap_any, 0, AF_INET6) == -1
00141 #else
00142 if (acceptor.open (ACE_Addr::sap_any) == -1
00143 #endif
00144 || acceptor.get_local_addr (my_addr) == -1)
00145 {
00146 ACE_ERROR ((LM_ERROR,
00147 ACE_TEXT ("acceptor.open () || ")
00148 ACE_TEXT ("acceptor.get_local_addr () failed\n")));
00149 result = -1;
00150 }
00151 else
00152 {
00153 if (TAO_debug_level > 0)
00154 {
00155 ACE_TCHAR addr[64];
00156 my_addr.addr_to_string (addr, sizeof(addr));
00157 ACE_DEBUG ((LM_DEBUG,
00158 "(%P|%t) TAO_MCAST_Parser: acceptor local address %s.\n",
00159 addr));
00160 }
00161
00162 ACE_INET_Addr multicast_addr (port,
00163 mcast_address);
00164
00165
00166
00167 ACE_CString mde (orb->orb_core ()->orb_params ()
00168 ->mcast_discovery_endpoint ());
00169
00170 if (ACE_OS::strcasecmp (service_name,
00171 "NameService") == 0
00172 && mde.length () != 0)
00173 if (multicast_addr.set (mde.c_str()) == -1)
00174 {
00175 ACE_ERROR ((LM_ERROR,
00176 ACE_TEXT("ORB.cpp: Multicast address setting failed\n")));
00177 stream.close ();
00178 dgram.close ();
00179 acceptor.close ();
00180 return -1;
00181 }
00182
00183
00184 if (dgram.open (ACE_Addr::sap_any) == -1)
00185 {
00186 ACE_ERROR ((LM_ERROR,
00187 ACE_TEXT ("Unable to open the Datagram!\n")));
00188 result = -1;
00189 }
00190 else
00191 {
00192
00193 dgram.set_nic (ACE_TEXT_CHAR_TO_TCHAR (mcast_nic),
00194 multicast_addr.get_type ());
00195
00196
00197 int mcast_ttl_optval = ACE_OS::atoi (mcast_ttl);
00198
00199 #if defined (ACE_HAS_IPV6)
00200 if (multicast_addr.get_type () == AF_INET6)
00201 {
00202 if (dgram.set_option (
00203 IPPROTO_IPV6,
00204 IPV6_MULTICAST_HOPS,
00205 &mcast_ttl_optval,
00206 sizeof (mcast_ttl_optval)) != 0)
00207 return -1;
00208 }
00209 else
00210 #endif
00211 if (dgram.set_option (
00212 IPPROTO_IP,
00213 IP_MULTICAST_TTL,
00214 &mcast_ttl_optval,
00215 sizeof (mcast_ttl_optval)) != 0)
00216 result = -1;
00217
00218
00219 ACE_UINT16 response_port =
00220 (ACE_UINT16) ACE_HTONS (my_addr.get_port_number ());
00221
00222
00223 CORBA::Short data_len =
00224 (CORBA::Short) ACE_HTONS (ACE_OS::strlen (service_name) + 1);
00225
00226
00227
00228
00229 const int iovcnt = 3;
00230 iovec iovp[iovcnt];
00231
00232
00233 iovp[0].iov_base = (char *) &data_len;
00234 iovp[0].iov_len = sizeof (CORBA::Short);
00235
00236
00237 iovp[1].iov_base = (char *) &response_port;
00238 iovp[1].iov_len = sizeof (ACE_UINT16);
00239
00240
00241 iovp[2].iov_base = (char *) service_name;
00242 iovp[2].iov_len =
00243 static_cast<u_long> (ACE_OS::strlen (service_name) + 1);
00244
00245
00246 result = dgram.send (iovp,
00247 iovcnt,
00248 multicast_addr);
00249
00250 if (TAO_debug_level > 0)
00251 ACE_DEBUG ((LM_DEBUG,
00252 ACE_TEXT ("\nsent multicast request.")));
00253
00254
00255 if (result == -1)
00256 ACE_ERROR ((LM_ERROR,
00257 ACE_TEXT ("%p\n"),
00258 ACE_TEXT ("error sending IIOP multicast")));
00259 else
00260 {
00261 if (TAO_debug_level > 0)
00262 ACE_DEBUG ((LM_DEBUG,
00263 ACE_TEXT ("\n%N; Sent multicast.")
00264 ACE_TEXT ("# of bytes sent is %d.\n"),
00265 result));
00266
00267 ACE_Time_Value tv (
00268 timeout == 0
00269 ? ACE_Time_Value (TAO_DEFAULT_SERVICE_RESOLUTION_TIMEOUT)
00270 : *timeout);
00271
00272
00273 if (acceptor.accept (stream,
00274 0,
00275 &tv) == -1)
00276 {
00277 ACE_ERROR ((LM_ERROR,
00278 ACE_TEXT ("%p\n"),
00279 ACE_TEXT ("multicast_query: unable to accept")));
00280 result = -1;
00281 }
00282 else
00283 {
00284
00285
00286
00287 CORBA::Short ior_len;
00288 result = stream.recv_n (&ior_len,
00289 sizeof ior_len,
00290 0,
00291 &tv);
00292 if (result != sizeof (ior_len))
00293 {
00294 ACE_ERROR ((LM_ERROR,
00295 ACE_TEXT ("%p\n"),
00296 ACE_TEXT ("multicast_query: unable to receive ")
00297 ACE_TEXT ("ior length")));
00298 result = -1;
00299 }
00300 else
00301 {
00302
00303
00304 ior_len = (CORBA::Short) ACE_NTOHS (ior_len);
00305 if (ior_len > TAO_DEFAULT_IOR_SIZE)
00306 {
00307 buf = CORBA::string_alloc (ior_len);
00308 if (buf == 0)
00309 {
00310 ACE_ERROR ((LM_ERROR,
00311 ACE_TEXT ("%p\n"),
00312 ACE_TEXT ("multicast_query: unable to ")
00313 ACE_TEXT ("allocate memory")));
00314 result = -1;
00315 }
00316 }
00317
00318 if (result != -1)
00319 {
00320
00321 result = stream.recv_n (buf,
00322 ior_len,
00323 0,
00324 &tv);
00325 if (result == -1)
00326 ACE_ERROR ((LM_ERROR,
00327 ACE_TEXT ( "%p\n"),
00328 ACE_TEXT ("error reading ior")));
00329 else if (TAO_debug_level > 0)
00330 ACE_DEBUG ((LM_DEBUG,
00331 ACE_TEXT ("%N: service resolved to IOR <%s>\n"),
00332 ACE_TEXT_CHAR_TO_TCHAR (buf)));
00333 }
00334 }
00335 }
00336 }
00337 }
00338 if (result == -1)
00339 {
00340 ACE_ERROR ((LM_ERROR,
00341 ACE_TEXT("\nmulticast discovery of %s failed.\n"),
00342 ACE_TEXT_CHAR_TO_TCHAR (service_name)));
00343
00344 if (ACE_OS::strcasecmp (service_name,
00345 "NameService") == 0)
00346 {
00347 ACE_ERROR ((LM_ERROR,
00348 ACE_TEXT("Specify -m 1 when starting Naming_Service,\n")
00349 ACE_TEXT("or see http://www.theaceorb.com/faq/#115\n")
00350 ACE_TEXT("for using NameService without multicast.\n\n")));
00351 }
00352 }
00353 }
00354
00355
00356 stream.close ();
00357 dgram.close ();
00358 acceptor.close ();
00359
00360 return result == -1 ? -1 : 0;
00361 }
00362
00363 void
00364 TAO_MCAST_Parser::assign_to_variables (const char * &mcast_name)
00365 {
00366
00367
00368
00369 ACE_CString mcast_name_cstring (mcast_name);
00370
00371 ssize_t pos_colon1 = mcast_name_cstring.find (':', 0);
00372 #if defined (ACE_HAS_IPV6)
00373
00374 bool ipv6_in_host = false;
00375
00376
00377
00378 if (mcast_name_cstring[0] == '[')
00379 {
00380
00381
00382 int cp_pos = mcast_name_cstring.find (']', 0);
00383 if (cp_pos == 0)
00384 {
00385
00386 if (TAO_debug_level > 0)
00387 {
00388 ACE_DEBUG ((LM_ERROR,
00389 ACE_TEXT ("\nTAO (%P|%t) MCAST_Parser: ")
00390 ACE_TEXT ("Invalid IPv6 decimal address specified.\n")));
00391 }
00392
00393 return;
00394 }
00395 else
00396 {
00397 if (mcast_name_cstring[cp_pos + 1] == ':')
00398 pos_colon1 = cp_pos + 1;
00399 else
00400 pos_colon1 = cp_pos;
00401 ipv6_in_host = true;
00402 }
00403 }
00404 #endif
00405
00406 if (pos_colon1 == 0)
00407 {
00408 #if defined (ACE_HAS_IPV6)
00409 const char *default_addr = ACE_DEFAULT_MULTICASTV6_ADDR;
00410 #else
00411 const char *default_addr = ACE_DEFAULT_MULTICAST_ADDR;
00412 #endif
00413 this->mcast_address_ = default_addr;
00414 }
00415 else
00416 {
00417 #if defined (ACE_HAS_IPV6)
00418 if (ipv6_in_host)
00419 this->mcast_address_ =
00420 mcast_name_cstring.substring (1,
00421 pos_colon1 - 2).c_str ();
00422 else
00423 #endif
00424 this->mcast_address_ =
00425 mcast_name_cstring.substring (0,
00426 pos_colon1).c_str ();
00427 }
00428 mcast_name_cstring =
00429 mcast_name_cstring.substring (pos_colon1 + 1,
00430 mcast_name_cstring.length() -
00431 pos_colon1);
00432
00433 ssize_t pos_colon2 = mcast_name_cstring.find (':', 0);
00434
00435 if (pos_colon2 == 0)
00436 {
00437
00438
00439
00440
00441
00442
00443 char default_port[33];
00444
00445 int trial_port = TAO_DEFAULT_NAME_SERVER_REQUEST_PORT;
00446
00447 if (mcast_name_cstring.find ("InterfaceRepository") !=
00448 ACE_CString::npos)
00449 {
00450 trial_port = TAO_DEFAULT_INTERFACEREPO_SERVER_REQUEST_PORT;
00451 }
00452 else if (mcast_name_cstring.find ("ImplRepoService") !=
00453 ACE_CString::npos)
00454 {
00455 trial_port = TAO_DEFAULT_IMPLREPO_SERVER_REQUEST_PORT;
00456 }
00457 else if (mcast_name_cstring.find ("TradingService") !=
00458 ACE_CString::npos)
00459 {
00460 trial_port = TAO_DEFAULT_TRADING_SERVER_REQUEST_PORT;
00461 }
00462
00463
00464 ACE_OS::itoa (trial_port, default_port, 10);
00465
00466 this->mcast_port_ = (const char *) default_port;
00467 }
00468 else
00469 {
00470 this->mcast_port_ = mcast_name_cstring.substring (0,
00471 pos_colon2).c_str ();
00472 }
00473
00474 mcast_name_cstring =
00475 mcast_name_cstring.substring (pos_colon2 + 1,
00476 mcast_name_cstring.length() - pos_colon2);
00477
00478
00479 ssize_t pos_colon3 = mcast_name_cstring.find (':', 0);
00480
00481 this->mcast_nic_ =
00482 mcast_name_cstring.substring (0,
00483 pos_colon3).c_str ();
00484
00485 mcast_name_cstring =
00486 mcast_name_cstring.substring (pos_colon3 + 1,
00487 mcast_name_cstring.length() - pos_colon3);
00488
00489 ssize_t pos_colon4 = mcast_name_cstring.find ('/', 0);
00490
00491 if (pos_colon4 == 0)
00492 {
00493
00494 const char *default_ttl = "1";
00495 this->mcast_ttl_ = default_ttl;
00496 }
00497 else
00498 {
00499 this->mcast_ttl_ =
00500 mcast_name_cstring.substring (0,
00501 pos_colon4).c_str ();
00502 }
00503 mcast_name_cstring =
00504 mcast_name_cstring.substring (pos_colon4,
00505 mcast_name_cstring.length() - pos_colon4);
00506
00507 this->service_name_ =
00508 mcast_name_cstring.substring (1,
00509 mcast_name_cstring.length()
00510 -1).c_str ();
00511 }
00512
00513 TAO_END_VERSIONED_NAMESPACE_DECL
00514
00515 ACE_STATIC_SVC_DEFINE (TAO_MCAST_Parser,
00516 ACE_TEXT ("MCAST_Parser"),
00517 ACE_SVC_OBJ_T,
00518 &ACE_SVC_NAME (TAO_MCAST_Parser),
00519 ACE_Service_Type::DELETE_THIS |
00520 ACE_Service_Type::DELETE_OBJ,
00521 0)
00522
00523 ACE_FACTORY_DEFINE (TAO, TAO_MCAST_Parser)
00524