00001 #include "tao/IIOP_Connector.h"
00002
00003 #if defined (TAO_HAS_IIOP) && (TAO_HAS_IIOP != 0)
00004
00005 #include "tao/IIOP_Profile.h"
00006 #include "tao/debug.h"
00007 #include "tao/ORB_Core.h"
00008 #include "tao/Environment.h"
00009 #include "tao/Protocols_Hooks.h"
00010 #include "tao/Connect_Strategy.h"
00011 #include "tao/Thread_Lane_Resources.h"
00012 #include "tao/Profile_Transport_Resolver.h"
00013 #include "tao/Base_Transport_Property.h"
00014 #include "tao/Transport.h"
00015 #include "tao/Wait_Strategy.h"
00016 #include "tao/SystemException.h"
00017 #include "tao/LF_Multi_Event.h"
00018 #include "ace/OS_NS_strings.h"
00019 #include "ace/OS_NS_string.h"
00020 #include "ace/OS_NS_time.h"
00021
00022 ACE_RCSID (tao,
00023 IIOP_Connector,
00024 "IIOP_Connector.cpp,v 1.152 2006/05/16 06:10:47 mesnier_p Exp")
00025
00026 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 class TAO_IIOP_Connection_Handler_Array_Guard
00043 {
00044 public:
00045 TAO_IIOP_Connection_Handler_Array_Guard (TAO_IIOP_Connection_Handler **p, unsigned count);
00046 ~TAO_IIOP_Connection_Handler_Array_Guard (void);
00047
00048 private:
00049
00050 TAO_IIOP_Connection_Handler **ptr_;
00051 unsigned count_;
00052 };
00053
00054 TAO_IIOP_Connection_Handler_Array_Guard::TAO_IIOP_Connection_Handler_Array_Guard (TAO_IIOP_Connection_Handler **p,
00055 unsigned count)
00056 : ptr_ (p),
00057 count_ (count)
00058 {
00059 }
00060
00061 TAO_IIOP_Connection_Handler_Array_Guard::~TAO_IIOP_Connection_Handler_Array_Guard (void)
00062 {
00063 if (this->ptr_ != 0)
00064 {
00065 for (unsigned i = 0; i < this->count_; i++)
00066 this->ptr_[i]->remove_reference ();
00067 }
00068 }
00069
00070
00071
00072
00073 TAO_IIOP_Connector::~TAO_IIOP_Connector (void)
00074 {
00075 }
00076
00077
00078 TAO_IIOP_Connector::TAO_IIOP_Connector (CORBA::Boolean flag)
00079 : TAO_Connector (IOP::TAG_INTERNET_IOP)
00080 , lite_flag_ (flag)
00081 , connect_strategy_ ()
00082 , base_connector_ ()
00083 {
00084 }
00085
00086 int
00087 TAO_IIOP_Connector::open (TAO_ORB_Core *orb_core)
00088 {
00089
00090
00091
00092
00093
00094 this->orb_core (orb_core);
00095
00096
00097 if (this->create_connect_strategy () == -1)
00098 return -1;
00099
00100
00101 TAO_IIOP_CONNECT_CREATION_STRATEGY *connect_creation_strategy = 0;
00102
00103 ACE_NEW_RETURN (connect_creation_strategy,
00104 TAO_IIOP_CONNECT_CREATION_STRATEGY
00105 (orb_core->thr_mgr (),
00106 orb_core,
00107 this->lite_flag_),
00108 -1);
00109
00110
00111 TAO_IIOP_CONNECT_CONCURRENCY_STRATEGY *concurrency_strategy = 0;
00112
00113 ACE_NEW_RETURN (concurrency_strategy,
00114 TAO_IIOP_CONNECT_CONCURRENCY_STRATEGY (orb_core),
00115 -1);
00116
00117 return this->base_connector_.open (this->orb_core ()->reactor (),
00118 connect_creation_strategy,
00119 &this->connect_strategy_,
00120 concurrency_strategy);
00121 }
00122
00123 int
00124 TAO_IIOP_Connector::close (void)
00125 {
00126 delete this->base_connector_.concurrency_strategy ();
00127 delete this->base_connector_.creation_strategy ();
00128 return this->base_connector_.close ();
00129 }
00130
00131 int
00132 TAO_IIOP_Connector::supports_parallel_connects(void) const
00133 {
00134 return 1;
00135 }
00136
00137 int
00138 TAO_IIOP_Connector::set_validate_endpoint (TAO_Endpoint *endpoint)
00139 {
00140 TAO_IIOP_Endpoint *iiop_endpoint =
00141 this->remote_endpoint (endpoint);
00142
00143 if (iiop_endpoint == 0)
00144 return -1;
00145
00146 const ACE_INET_Addr &remote_address =
00147 iiop_endpoint->object_addr ();
00148
00149
00150
00151
00152 #if defined (ACE_HAS_IPV6)
00153 if (remote_address.get_type () != AF_INET &&
00154 remote_address.get_type () != AF_INET6)
00155 #else
00156 if (remote_address.get_type () != AF_INET)
00157 #endif
00158 {
00159 if (TAO_debug_level > 0)
00160 {
00161 ACE_DEBUG ((LM_DEBUG,
00162 ACE_TEXT ("(%P|%t) IIOP connection failed.\n")
00163 ACE_TEXT (" This is most likely ")
00164 ACE_TEXT ("due to a hostname lookup ")
00165 ACE_TEXT ("failure.\n")));
00166 }
00167
00168 return -1;
00169 }
00170
00171 return 0;
00172 }
00173
00174 TAO_Transport *
00175 TAO_IIOP_Connector::make_connection (TAO::Profile_Transport_Resolver *r,
00176 TAO_Transport_Descriptor_Interface &desc,
00177 ACE_Time_Value *timeout)
00178 {
00179 TAO_IIOP_Connection_Handler *svc_handler = 0;
00180 TAO_IIOP_Endpoint *iiop_endpoint =
00181 this->remote_endpoint (desc.endpoint());
00182 int result = -1;
00183 if (iiop_endpoint == 0)
00184 return 0;
00185
00186 result = this->begin_connection (svc_handler, r, iiop_endpoint, timeout);
00187
00188 if (result == -1 && errno != EWOULDBLOCK)
00189 {
00190
00191 svc_handler->remove_reference();
00192
00193 if (TAO_debug_level > 1)
00194 {
00195 ACE_DEBUG ((LM_ERROR,
00196 ACE_TEXT ("(%P|%t) IIOP_Connector::make_connection, ")
00197 ACE_TEXT("connection to <%s:%d> failed (%p)\n"),
00198 ACE_TEXT_CHAR_TO_TCHAR (iiop_endpoint->host ()),
00199 iiop_endpoint->port (),
00200 ACE_TEXT("errno")));
00201 }
00202 return 0;
00203 }
00204 TAO_IIOP_Connection_Handler **sh_ptr = &svc_handler;
00205 TAO_IIOP_Endpoint **ep_ptr = &iiop_endpoint;
00206 TAO_LF_Multi_Event mev;
00207 mev.add_event(svc_handler);
00208 return this->complete_connection (result, desc,
00209 sh_ptr, ep_ptr,
00210 1U, r, &mev, timeout);
00211 }
00212
00213 TAO_Transport *
00214 TAO_IIOP_Connector::make_parallel_connection (TAO::Profile_Transport_Resolver *r,
00215 TAO_Transport_Descriptor_Interface &desc,
00216 ACE_Time_Value *timeout)
00217 {
00218 TAO_Endpoint *root_ep = desc.endpoint();
00219 unsigned max_count = 1;
00220 unsigned long ns_stagger =
00221 this->orb_core()->orb_params()->parallel_connect_delay();
00222 unsigned long sec_stagger = ns_stagger/1000;
00223 ns_stagger = (ns_stagger % 1000) * 1000000;
00224 for (TAO_Endpoint *ep = root_ep->next_filtered (this->orb_core(),0);
00225 ep != 0;
00226 ep = ep->next_filtered(this->orb_core(),root_ep))
00227 max_count++;
00228
00229 if (TAO_debug_level > 2)
00230 ACE_DEBUG ((LM_DEBUG,
00231 ACE_TEXT ("TAO (%P|%t) - IIOP_Connector::")
00232 ACE_TEXT ("make_parallel_connection, ")
00233 ACE_TEXT ("to %d endpoints\n"), max_count));
00234 TAO_IIOP_Endpoint **eplist = 0;
00235 TAO_IIOP_Connection_Handler **shlist = 0;
00236 ACE_NEW_RETURN (shlist, TAO_IIOP_Connection_Handler *[max_count], 0);
00237 ACE_NEW_RETURN (eplist, TAO_IIOP_Endpoint *[max_count], 0);
00238
00239 TAO_LF_Multi_Event mev;
00240 int result = 0;
00241 unsigned count = 0;
00242 for (TAO_Endpoint *ep = root_ep->next_filtered (this->orb_core(),0);
00243 ep != 0;
00244 ep = ep->next_filtered(this->orb_core(),root_ep))
00245 {
00246 eplist[count] = this->remote_endpoint (ep);
00247 shlist[count] = 0;
00248 result = this->begin_connection (shlist[count],
00249 r,
00250 eplist[count],
00251 timeout);
00252
00253
00254
00255
00256
00257 if (result == -1)
00258 {
00259 if (errno == EWOULDBLOCK)
00260 {
00261 mev.add_event(shlist[count++]);
00262 if (ep->next() != 0)
00263 {
00264 struct timespec nsleep = {sec_stagger, ns_stagger};
00265 ACE_OS::nanosleep (&nsleep);
00266 result = this->active_connect_strategy_->poll (&mev);
00267 if (result != -1)
00268 break;
00269 }
00270 }
00271 else
00272 {
00273 shlist[count]->remove_reference();
00274 }
00275 continue;
00276 }
00277
00278 if (result != -1)
00279 {
00280 count++;
00281 break;
00282 }
00283 }
00284
00285 TAO_Transport *winner = 0;
00286 if (count > 0)
00287 winner = this->complete_connection (result,desc,
00288 shlist,eplist,count,r,&mev,timeout);
00289 delete [] shlist;
00290 delete [] eplist;
00291 return winner;
00292 }
00293
00294 int
00295 TAO_IIOP_Connector::begin_connection (TAO_IIOP_Connection_Handler *&svc_handler,
00296 TAO::Profile_Transport_Resolver *r,
00297 TAO_IIOP_Endpoint *iiop_endpoint,
00298 ACE_Time_Value *timeout)
00299 {
00300 const ACE_INET_Addr &remote_address =
00301 iiop_endpoint->object_addr ();
00302
00303 u_short port = 0;
00304 const ACE_UINT32 ia_any = INADDR_ANY;
00305 ACE_INET_Addr local_addr(port, ia_any);
00306
00307 if (iiop_endpoint->is_preferred_network ())
00308 local_addr.set (port,
00309 iiop_endpoint->preferred_network ());
00310 #if defined (ACE_HAS_IPV6)
00311 else if (remote_address.get_type () == AF_INET6)
00312 local_addr.set (port,
00313 ACE_IPV6_ANY);
00314 #endif
00315
00316 if (TAO_debug_level > 2)
00317 ACE_DEBUG ((LM_DEBUG,
00318 ACE_TEXT ("TAO (%P|%t) - IIOP_Connector::begin_connection, ")
00319 ACE_TEXT ("to <%s:%d> which should %s\n"),
00320 ACE_TEXT_CHAR_TO_TCHAR(iiop_endpoint->host()),
00321 iiop_endpoint->port(),
00322 r->blocked_connect () ? ACE_TEXT("block") : ACE_TEXT("nonblock")));
00323
00324
00325 ACE_Synch_Options synch_options;
00326
00327 this->active_connect_strategy_->synch_options (timeout,
00328 synch_options);
00329
00330
00331
00332 ACE_Time_Value tmp_zero (ACE_Time_Value::zero);
00333 if (!r->blocked_connect ())
00334 {
00335 synch_options.timeout (ACE_Time_Value::zero);
00336 timeout = &tmp_zero;
00337 }
00338
00339 svc_handler = 0;
00340
00341 int result =
00342 this->base_connector_.connect (svc_handler,
00343 remote_address,
00344 synch_options,
00345 local_addr);
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365 return result;
00366 }
00367
00368 TAO_Transport *
00369 TAO_IIOP_Connector::complete_connection (int result,
00370 TAO_Transport_Descriptor_Interface &desc,
00371 TAO_IIOP_Connection_Handler **&sh_list,
00372 TAO_IIOP_Endpoint **ep_list,
00373 unsigned count,
00374 TAO::Profile_Transport_Resolver *r,
00375 TAO_LF_Multi_Event *mev,
00376 ACE_Time_Value *timeout)
00377 {
00378
00379
00380 TAO_IIOP_Connection_Handler_Array_Guard svc_handler_auto_ptr (sh_list,count);
00381 TAO_Transport *transport = 0;
00382 TAO_Transport **tlist = 0;
00383 ACE_NEW_RETURN (tlist,TAO_Transport*[count],0);
00384
00385
00386 for (unsigned i = 0; i < count; i++)
00387 tlist[i] = sh_list[i]->transport();
00388
00389 if (result != -1)
00390 {
00391
00392
00393
00394 transport = tlist[count-1];
00395 }
00396 else
00397 {
00398 if (count == 1)
00399 {
00400 transport = tlist[0];
00401 if (!this->wait_for_connection_completion (r,
00402 transport,
00403 timeout))
00404 {
00405 if (TAO_debug_level > 2)
00406 ACE_ERROR ((LM_ERROR,
00407 ACE_TEXT ("TAO (%P|%t) - IIOP_Connector::")
00408 ACE_TEXT ("complete_connection, wait for completion ")
00409 ACE_TEXT ("failed for 1 pending connect\n")));
00410 }
00411 }
00412 else
00413 {
00414 if (!this->wait_for_connection_completion (r,
00415 transport,
00416 tlist,
00417 count,
00418 mev,
00419 timeout))
00420 {
00421 if (TAO_debug_level > 2)
00422 ACE_ERROR ((LM_ERROR,
00423 ACE_TEXT ("TAO (%P|%t) - IIOP_Connector::")
00424 ACE_TEXT ("complete_connection, wait for completion ")
00425 ACE_TEXT ("failed for %d pending connects\n"),
00426 count));
00427 }
00428 }
00429 }
00430
00431
00432 TAO_IIOP_Connection_Handler *svc_handler = 0;
00433 TAO_IIOP_Endpoint *iiop_endpoint = 0;
00434
00435 if (transport != 0)
00436 {
00437 for (unsigned i = 0; i < count; i++)
00438 {
00439 if (transport == tlist[i])
00440 {
00441 svc_handler = sh_list[i];
00442 if (transport->connection_handler()->keep_waiting())
00443 {
00444 svc_handler->add_reference();
00445 }
00446 iiop_endpoint = ep_list[i];
00447 break;
00448 }
00449 }
00450 }
00451
00452
00453
00454
00455 delete [] tlist;
00456
00457
00458 if (transport == 0)
00459 {
00460
00461 if (TAO_debug_level > 3)
00462 {
00463 for (unsigned i = 0; i < count; i++)
00464 ACE_DEBUG ((LM_ERROR,
00465 ACE_TEXT ("(%P|%t) IIOP_Connector::make_connection, ")
00466 ACE_TEXT("connection to <%s:%d> failed (%p)\n"),
00467 ACE_TEXT_CHAR_TO_TCHAR (ep_list[i]->host ()),
00468 ep_list[i]->port (),
00469 ACE_TEXT("errno")));
00470 }
00471
00472 return 0;
00473 }
00474
00475
00476 if (TAO_debug_level > 2)
00477 {
00478 ACE_DEBUG ((LM_DEBUG,
00479 ACE_TEXT ("TAO (%P|%t) - IIOP_Connector::make_connection, ")
00480 ACE_TEXT ("new %s connection to <%s:%d> on Transport[%d]\n"),
00481 transport->is_connected() ?
00482 ACE_TEXT("connected") : ACE_TEXT("not connected"),
00483 ACE_TEXT_CHAR_TO_TCHAR (iiop_endpoint->host ()),
00484 iiop_endpoint->port (),
00485 svc_handler->peer ().get_handle ()));
00486 }
00487
00488
00489 int retval = -1;
00490 if (count == 1U || desc.reset_endpoint(iiop_endpoint))
00491 {
00492 retval = this->orb_core ()->
00493 lane_resources ().transport_cache ().cache_transport (&desc,
00494 transport);
00495 }
00496
00497
00498 if (retval != 0)
00499 {
00500
00501 svc_handler->close ();
00502
00503 if (TAO_debug_level > 0)
00504 {
00505 ACE_ERROR ((LM_ERROR,
00506 ACE_TEXT ("(%P|%t) IIOP_Connector::make_connection, ")
00507 ACE_TEXT ("could not add new connection to cache\n")));
00508 }
00509
00510 return 0;
00511 }
00512
00513 if (transport->is_connected () &&
00514 transport->wait_strategy ()->register_handler () != 0)
00515 {
00516
00517
00518
00519
00520 (void) transport->purge_entry ();
00521
00522
00523 (void) transport->close_connection ();
00524
00525 if (TAO_debug_level > 0)
00526 ACE_ERROR ((LM_ERROR,
00527 ACE_TEXT ("(%P|%t) IIOP_Connector [%d]::make_connection, ")
00528 ACE_TEXT ("could not register the transport ")
00529 ACE_TEXT ("in the reactor.\n"),
00530 transport->id ()));
00531
00532 return 0;
00533 }
00534
00535 return transport;
00536 }
00537
00538 TAO_Profile *
00539 TAO_IIOP_Connector::create_profile (TAO_InputCDR& cdr)
00540 {
00541 TAO_Profile *pfile = 0;
00542 ACE_NEW_RETURN (pfile,
00543 TAO_IIOP_Profile (this->orb_core ()),
00544 0);
00545
00546 const int r = pfile->decode (cdr);
00547 if (r == -1)
00548 {
00549 pfile->_decr_refcnt ();
00550 pfile = 0;
00551 }
00552
00553 return pfile;
00554 }
00555
00556 TAO_Profile *
00557 TAO_IIOP_Connector::make_profile (ACE_ENV_SINGLE_ARG_DECL)
00558 {
00559
00560
00561
00562
00563
00564 TAO_Profile *profile = 0;
00565 ACE_NEW_THROW_EX (profile,
00566 TAO_IIOP_Profile (this->orb_core ()),
00567 CORBA::NO_MEMORY (
00568 CORBA::SystemException::_tao_minor_code (
00569 0,
00570 ENOMEM),
00571 CORBA::COMPLETED_NO));
00572 ACE_CHECK_RETURN (0);
00573
00574 return profile;
00575 }
00576
00577 int
00578 TAO_IIOP_Connector::check_prefix (const char *endpoint)
00579 {
00580
00581 if (!endpoint || !*endpoint)
00582 return -1;
00583
00584 static const char *protocol[] = { "iiop", "iioploc" };
00585
00586 const size_t slot = ACE_OS::strchr (endpoint, ':') - endpoint;
00587 if (slot == 0)
00588 return 0;
00589
00590 const size_t len0 = ACE_OS::strlen (protocol[0]);
00591 const size_t len1 = ACE_OS::strlen (protocol[1]);
00592
00593
00594
00595 if (slot == len0
00596 && ACE_OS::strncasecmp (endpoint, protocol[0], len0) == 0)
00597 return 0;
00598 else if (slot == len1
00599 && ACE_OS::strncasecmp (endpoint, protocol[1], len1) == 0)
00600 return 0;
00601
00602 return -1;
00603
00604
00605 }
00606
00607 char
00608 TAO_IIOP_Connector::object_key_delimiter (void) const
00609 {
00610 return TAO_IIOP_Profile::object_key_delimiter_;
00611 }
00612
00613 TAO_IIOP_Endpoint *
00614 TAO_IIOP_Connector::remote_endpoint (TAO_Endpoint *endpoint)
00615 {
00616 if (endpoint->tag () != IOP::TAG_INTERNET_IOP)
00617 return 0;
00618
00619 TAO_IIOP_Endpoint *iiop_endpoint =
00620 dynamic_cast<TAO_IIOP_Endpoint *> (endpoint );
00621
00622 if (iiop_endpoint == 0)
00623 return 0;
00624
00625 return iiop_endpoint;
00626 }
00627
00628 int
00629 TAO_IIOP_Connector::cancel_svc_handler (
00630 TAO_Connection_Handler * svc_handler)
00631 {
00632 TAO_IIOP_Connection_Handler* handler=
00633 dynamic_cast<TAO_IIOP_Connection_Handler*>(svc_handler);
00634
00635
00636 if (handler)
00637 {
00638 handler->abort();
00639 return this->base_connector_.cancel (handler);
00640 }
00641
00642 return -1;
00643 }
00644
00645
00646
00647
00648 TAO_END_VERSIONED_NAMESPACE_DECL
00649
00650 #endif