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 79727 2007-09-26 18:12:47Z 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 = mcast_name_cstring.find (':', 0);
00358
00359 #if defined (ACE_HAS_IPV6)
00360
00361 bool ipv6_in_host = false;
00362
00363
00364
00365 if (mcast_name_cstring[0] == '[')
00366 {
00367
00368
00369 ACE_CString::size_type const cp_pos = mcast_name_cstring.find (']', 0);
00370 if (cp_pos == 0)
00371 {
00372
00373 if (TAO_debug_level > 0)
00374 {
00375 ACE_ERROR ((LM_ERROR,
00376 ACE_TEXT ("\nTAO (%P|%t) MCAST_Parser: ")
00377 ACE_TEXT ("Invalid IPv6 decimal address specified.\n")));
00378 }
00379
00380 return;
00381 }
00382 else
00383 {
00384 if (mcast_name_cstring[cp_pos + 1] == ':')
00385 pos_colon1 = cp_pos + 1;
00386 else
00387 pos_colon1 = cp_pos;
00388 ipv6_in_host = true;
00389 }
00390 }
00391 #endif
00392
00393 if (pos_colon1 == 0)
00394 {
00395 #if defined (ACE_HAS_IPV6)
00396 const char default_addr[] = ACE_DEFAULT_MULTICASTV6_ADDR;
00397 #else
00398 const char default_addr[] = ACE_DEFAULT_MULTICAST_ADDR;
00399 #endif
00400 this->mcast_address_ = default_addr;
00401 }
00402 else
00403 {
00404 #if defined (ACE_HAS_IPV6)
00405 if (ipv6_in_host)
00406 this->mcast_address_ =
00407 mcast_name_cstring.substring (1,
00408 pos_colon1 - 2).c_str ();
00409 else
00410 #endif
00411 this->mcast_address_ =
00412 mcast_name_cstring.substring (0,
00413 pos_colon1).c_str ();
00414 }
00415 mcast_name_cstring =
00416 mcast_name_cstring.substring (pos_colon1 + 1,
00417 mcast_name_cstring.length() -
00418 pos_colon1);
00419
00420 ACE_CString::size_type const pos_colon2 = mcast_name_cstring.find (':', 0);
00421
00422 if (pos_colon2 == 0)
00423 {
00424 if (mcast_name_cstring.find ("InterfaceRepository") != ACE_CString::npos)
00425 {
00426 this->mcast_port_ =
00427 TAO_DEFAULT_INTERFACEREPO_SERVER_REQUEST_PORT;
00428 }
00429 else if (mcast_name_cstring.find ("ImplRepoService") != ACE_CString::npos)
00430 {
00431 this->mcast_port_ =
00432 TAO_DEFAULT_IMPLREPO_SERVER_REQUEST_PORT;
00433 }
00434 else if (mcast_name_cstring.find ("TradingService") != ACE_CString::npos)
00435 {
00436 this->mcast_port_ = TAO_DEFAULT_TRADING_SERVER_REQUEST_PORT;
00437 }
00438 }
00439 else
00440 {
00441 int const the_port =
00442 ACE_OS::atoi (mcast_name_cstring.substring (0, pos_colon2).c_str ());
00443
00444 if (the_port > 0 && the_port < 0xffffL)
00445 this->mcast_port_ = the_port;
00446 }
00447
00448 mcast_name_cstring =
00449 mcast_name_cstring.substring (pos_colon2 + 1,
00450 mcast_name_cstring.length() - pos_colon2);
00451
00452
00453 ACE_CString::size_type const pos_colon3 = mcast_name_cstring.find (':', 0);
00454
00455 this->mcast_nic_ = mcast_name_cstring.substring (0, pos_colon3).c_str ();
00456
00457 mcast_name_cstring =
00458 mcast_name_cstring.substring (pos_colon3 + 1,
00459 mcast_name_cstring.length() - pos_colon3);
00460
00461 ACE_CString::size_type const pos_colon4 = mcast_name_cstring.find ('/', 0);
00462
00463 if (pos_colon4 != 0)
00464 {
00465
00466 int const the_ttl =
00467 ACE_OS::atoi (mcast_name_cstring.substring (0, pos_colon4).c_str ());
00468
00469 if (the_ttl > 0 && the_ttl <= 255)
00470 this->mcast_ttl_ = the_ttl;
00471 }
00472
00473 mcast_name_cstring =
00474 mcast_name_cstring.substring (pos_colon4,
00475 mcast_name_cstring.length() - pos_colon4);
00476
00477 this->service_name_ =
00478 mcast_name_cstring.substring (1, mcast_name_cstring.length() - 1).c_str ();
00479 }
00480
00481 TAO_END_VERSIONED_NAMESPACE_DECL
00482
00483 ACE_STATIC_SVC_DEFINE (TAO_MCAST_Parser,
00484 ACE_TEXT ("MCAST_Parser"),
00485 ACE_SVC_OBJ_T,
00486 &ACE_SVC_NAME (TAO_MCAST_Parser),
00487 ACE_Service_Type::DELETE_THIS |
00488 ACE_Service_Type::DELETE_OBJ,
00489 0)
00490
00491 ACE_FACTORY_DEFINE (TAO, TAO_MCAST_Parser)
00492
00493 #endif