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