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