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 80199 2007-12-05 14:49:58Z johnnyw $")
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 int result = -1;
00192 if (iiop_endpoint == 0)
00193 return 0;
00194
00195 result = this->begin_connection (svc_handler, r, iiop_endpoint, timeout);
00196
00197 if (result == -1 && errno != EWOULDBLOCK)
00198 {
00199
00200 svc_handler->remove_reference();
00201
00202 if (TAO_debug_level > 1)
00203 {
00204 ACE_ERROR ((LM_ERROR,
00205 ACE_TEXT ("TAO (%P|%t) IIOP_Connector::make_connection, ")
00206 ACE_TEXT("connection to <%s:%d> failed (%p)\n"),
00207 ACE_TEXT_CHAR_TO_TCHAR (iiop_endpoint->host ()),
00208 iiop_endpoint->port (),
00209 ACE_TEXT("errno")));
00210 }
00211 return 0;
00212 }
00213 TAO_IIOP_Connection_Handler **sh_ptr = &svc_handler;
00214 TAO_IIOP_Endpoint **ep_ptr = &iiop_endpoint;
00215 TAO_LF_Multi_Event mev;
00216 mev.add_event (svc_handler);
00217
00218 return this->complete_connection (result,
00219 desc,
00220 sh_ptr,
00221 ep_ptr,
00222 1U,
00223 r,
00224 &mev,
00225 timeout);
00226 }
00227
00228 TAO_Transport *
00229 TAO_IIOP_Connector::make_parallel_connection (
00230 TAO::Profile_Transport_Resolver * r,
00231 TAO_Transport_Descriptor_Interface & desc,
00232 ACE_Time_Value * timeout)
00233 {
00234 TAO_Endpoint *root_ep = desc.endpoint();
00235 unsigned max_count = 1;
00236 unsigned long ns_stagger =
00237 this->orb_core ()->orb_params ()->parallel_connect_delay ();
00238 unsigned long sec_stagger = ns_stagger/1000;
00239 ns_stagger = (ns_stagger % 1000) * 1000000;
00240 for (TAO_Endpoint *ep = root_ep->next_filtered (this->orb_core(), 0);
00241 ep != 0;
00242 ep = ep->next_filtered (this->orb_core(), root_ep))
00243 ++max_count;
00244
00245 if (TAO_debug_level > 2)
00246 ACE_DEBUG ((LM_DEBUG,
00247 ACE_TEXT ("TAO (%P|%t) - IIOP_Connector::")
00248 ACE_TEXT ("make_parallel_connection, ")
00249 ACE_TEXT ("to %d endpoints\n"), max_count));
00250 TAO_IIOP_Endpoint **eplist = 0;
00251 TAO_IIOP_Connection_Handler **shlist = 0;
00252 ACE_NEW_RETURN (shlist, TAO_IIOP_Connection_Handler *[max_count], 0);
00253 ACE_NEW_RETURN (eplist, TAO_IIOP_Endpoint *[max_count], 0);
00254
00255 TAO_LF_Multi_Event mev;
00256 int result = 0;
00257 unsigned count = 0;
00258 for (TAO_Endpoint *ep = root_ep->next_filtered (this->orb_core(),0);
00259 ep != 0;
00260 ep = ep->next_filtered(this->orb_core(),root_ep))
00261 {
00262 eplist[count] = this->remote_endpoint (ep);
00263 shlist[count] = 0;
00264 result = this->begin_connection (shlist[count],
00265 r,
00266 eplist[count],
00267 timeout);
00268
00269
00270
00271
00272
00273 if (result == -1)
00274 {
00275 if (errno == EWOULDBLOCK)
00276 {
00277 mev.add_event(shlist[count++]);
00278 if (ep->next() != 0)
00279 {
00280 struct timespec nsleep = {sec_stagger, ns_stagger};
00281 ACE_OS::nanosleep (&nsleep);
00282 result = this->active_connect_strategy_->poll (&mev);
00283 if (result != -1)
00284 break;
00285 }
00286 }
00287 else
00288 {
00289 shlist[count]->remove_reference();
00290 }
00291 continue;
00292 }
00293
00294 if (result != -1)
00295 {
00296 count++;
00297 break;
00298 }
00299 }
00300
00301 TAO_Transport *winner = 0;
00302 if (count > 0)
00303 winner = this->complete_connection (result,
00304 desc,
00305 shlist,
00306 eplist,
00307 count,r,
00308 &mev,
00309 timeout);
00310
00311 delete [] shlist;
00312 delete [] eplist;
00313 return winner;
00314 }
00315
00316 int
00317 TAO_IIOP_Connector::begin_connection (TAO_IIOP_Connection_Handler *&svc_handler,
00318 TAO::Profile_Transport_Resolver *r,
00319 TAO_IIOP_Endpoint *iiop_endpoint,
00320 ACE_Time_Value *timeout)
00321 {
00322 const ACE_INET_Addr &remote_address =
00323 iiop_endpoint->object_addr ();
00324
00325 u_short port = 0;
00326 const ACE_UINT32 ia_any = INADDR_ANY;
00327 ACE_INET_Addr local_addr(port, ia_any);
00328
00329 if (iiop_endpoint->is_preferred_network ())
00330 local_addr.set (port,
00331 iiop_endpoint->preferred_network ());
00332 #if defined (ACE_HAS_IPV6)
00333 else if (remote_address.get_type () == AF_INET6)
00334 local_addr.set (port,
00335 ACE_IPV6_ANY);
00336 #endif
00337
00338 if (TAO_debug_level > 2)
00339 ACE_DEBUG ((LM_DEBUG,
00340 ACE_TEXT ("TAO (%P|%t) - IIOP_Connector::begin_connection, ")
00341 ACE_TEXT ("to <%s:%d> which should %s\n"),
00342 ACE_TEXT_CHAR_TO_TCHAR(iiop_endpoint->host()),
00343 iiop_endpoint->port(),
00344 r->blocked_connect () ? ACE_TEXT("block") : ACE_TEXT("nonblock")));
00345
00346
00347 ACE_Synch_Options synch_options;
00348
00349 this->active_connect_strategy_->synch_options (timeout,
00350 synch_options);
00351
00352
00353
00354
00355
00356 svc_handler = 0;
00357
00358 int result =
00359 this->base_connector_.connect (svc_handler,
00360 remote_address,
00361 synch_options,
00362 local_addr);
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382 return result;
00383 }
00384
00385 TAO_Transport *
00386 TAO_IIOP_Connector::complete_connection (int result,
00387 TAO_Transport_Descriptor_Interface &desc,
00388 TAO_IIOP_Connection_Handler **&sh_list,
00389 TAO_IIOP_Endpoint **ep_list,
00390 unsigned count,
00391 TAO::Profile_Transport_Resolver *r,
00392 TAO_LF_Multi_Event *mev,
00393 ACE_Time_Value *timeout)
00394 {
00395
00396
00397 TAO_IIOP_Connection_Handler_Array_Guard svc_handler_auto_ptr (sh_list,count);
00398 TAO_Transport *transport = 0;
00399 TAO_Transport **tlist = 0;
00400 ACE_NEW_RETURN (tlist,TAO_Transport*[count],0);
00401
00402
00403 for (unsigned i = 0; i < count; i++)
00404 tlist[i] = sh_list[i]->transport();
00405
00406 if (result != -1)
00407 {
00408
00409
00410
00411 transport = tlist[count-1];
00412 }
00413 else
00414 {
00415 if (count == 1)
00416 {
00417 transport = tlist[0];
00418 if (!this->wait_for_connection_completion (r,
00419 transport,
00420 timeout))
00421 {
00422 if (TAO_debug_level > 2)
00423 ACE_ERROR ((LM_ERROR,
00424 ACE_TEXT ("TAO (%P|%t) - IIOP_Connector::")
00425 ACE_TEXT ("complete_connection, wait for completion ")
00426 ACE_TEXT ("failed for 1 pending connect\n")));
00427 }
00428 }
00429 else
00430 {
00431 if (!this->wait_for_connection_completion (r,
00432 transport,
00433 tlist,
00434 count,
00435 mev,
00436 timeout))
00437 {
00438 if (TAO_debug_level > 2)
00439 ACE_ERROR ((LM_ERROR,
00440 ACE_TEXT ("TAO (%P|%t) - IIOP_Connector::")
00441 ACE_TEXT ("complete_connection, wait for completion ")
00442 ACE_TEXT ("failed for %d pending connects\n"),
00443 count));
00444 }
00445 }
00446 }
00447
00448 #if defined (INDUCE_BUG_2654_A)
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459 ACE_Time_Value udelay(0,600);
00460 struct timespec ts = udelay;
00461 ACE_OS::nanosleep (&ts);
00462 #endif // INDUCE_BUG_2654_A
00463
00464 int retval = -1;
00465
00466
00467
00468 TAO_IIOP_Connection_Handler *svc_handler = 0;
00469 TAO_IIOP_Endpoint *iiop_endpoint = 0;
00470
00471 if (transport != 0)
00472 {
00473 if (count == 1)
00474 {
00475 svc_handler = sh_list[0];
00476 iiop_endpoint = ep_list[0];
00477 }
00478 else
00479 {
00480 for (unsigned i = 0; i < count; i++)
00481 {
00482 if (transport == tlist[i])
00483 {
00484 svc_handler = sh_list[i];
00485 iiop_endpoint = ep_list[i];
00486 break;
00487 }
00488 }
00489 }
00490 }
00491
00492
00493
00494
00495 delete [] tlist;
00496
00497
00498 if (transport == 0)
00499 {
00500
00501 if (TAO_debug_level > 3)
00502 {
00503 for (unsigned i = 0; i < count; i++)
00504 {
00505 ACE_ERROR ((LM_ERROR,
00506 ACE_TEXT ("TAO (%P|%t) - IIOP_Connector::complete_connection,")
00507 ACE_TEXT (" connection to <%s:%d> failed (%p)\n"),
00508 ACE_TEXT_CHAR_TO_TCHAR (ep_list[i]->host ()),
00509 ep_list[i]->port (),
00510 ACE_TEXT("errno")));
00511 }
00512 }
00513 return 0;
00514 }
00515
00516 if (svc_handler->keep_waiting())
00517 {
00518 svc_handler->connection_pending();
00519 }
00520
00521 #if defined (INDUCE_BUG_2654_B)
00522
00523
00524
00525
00526 ACE_Time_Value udelay(0,600);
00527 struct timespec ts = udelay;
00528 ACE_OS::nanosleep (&ts);
00529 #endif // INDUCE_BUG_2654_B
00530
00531
00532 if (transport->connection_handler()->error_detected())
00533 {
00534 if (TAO_debug_level > 0)
00535 ACE_DEBUG((LM_DEBUG,
00536 ACE_TEXT("TAO (%P|%t) - IIOP_Connector::make_connection, ")
00537 ACE_TEXT("transport in error before cache! \n")));
00538 transport->connection_handler()->cancel_pending_connection();
00539 return 0;
00540 }
00541
00542 if (TAO_debug_level > 2)
00543 {
00544 ACE_DEBUG ((LM_DEBUG,
00545 ACE_TEXT ("TAO (%P|%t) - IIOP_Connector::make_connection, ")
00546 ACE_TEXT ("new %s connection to <%s:%d> on Transport[%d]\n"),
00547 transport->is_connected() ?
00548 ACE_TEXT("connected") : ACE_TEXT("not connected"),
00549 ACE_TEXT_CHAR_TO_TCHAR (iiop_endpoint->host ()),
00550 iiop_endpoint->port (),
00551 svc_handler->peer ().get_handle ()));
00552 }
00553
00554 #if defined (INDUCE_BUG_2654_C)
00555
00556
00557
00558 ACE_Time_Value udelay(0,600);
00559 struct timespec ts = udelay;
00560 ACE_OS::nanosleep (&ts);
00561 #endif // INDUCE_BUG_2654_C
00562
00563
00564
00565 if (count == 1 || desc.reset_endpoint(iiop_endpoint))
00566 {
00567 retval = this->orb_core ()->
00568 lane_resources ().transport_cache ().cache_transport (&desc,
00569 transport);
00570 }
00571
00572
00573 if (retval != 0)
00574 {
00575
00576 svc_handler->close ();
00577
00578 if (TAO_debug_level > 0)
00579 {
00580 ACE_ERROR ((LM_ERROR,
00581 ACE_TEXT ("TAO (%P|%t) IIOP_Connector::make_connection, ")
00582 ACE_TEXT ("could not add new connection to cache\n")));
00583 }
00584
00585 return 0;
00586 }
00587
00588
00589
00590
00591
00592
00593 if (svc_handler->error_detected())
00594 {
00595 if (TAO_debug_level > 0)
00596 ACE_DEBUG((LM_DEBUG,
00597 ACE_TEXT("TAO (%P|%t) - IIOP_Connector::make_connection, ")
00598 ACE_TEXT("transport in error after cache! \n")));
00599 svc_handler->cancel_pending_connection();
00600 transport->purge_entry();
00601 return 0;
00602 }
00603
00604
00605 #if defined (INDUCE_BUG_2654_D)
00606
00607
00608 ACE_Time_Value udelay(0,600);
00609 struct timespec ts = udelay;
00610 ACE_OS::nanosleep (&ts);
00611 #endif // INDUCE_BUG_2654_D
00612
00613 if (transport->is_connected () &&
00614 transport->wait_strategy ()->register_handler () != 0)
00615 {
00616
00617
00618
00619
00620 (void) transport->purge_entry ();
00621
00622
00623 (void) transport->close_connection ();
00624
00625 if (TAO_debug_level > 0)
00626 ACE_ERROR ((LM_ERROR,
00627 ACE_TEXT ("TAO (%P|%t) IIOP_Connector [%d]::make_connection, ")
00628 ACE_TEXT ("could not register the transport ")
00629 ACE_TEXT ("in the reactor.\n"),
00630 transport->id ()));
00631
00632 return 0;
00633 }
00634
00635 return transport;
00636 }
00637
00638 TAO_Profile *
00639 TAO_IIOP_Connector::create_profile (TAO_InputCDR& cdr)
00640 {
00641 TAO_Profile *pfile = 0;
00642 ACE_NEW_RETURN (pfile,
00643 TAO_IIOP_Profile (this->orb_core ()),
00644 0);
00645
00646 const int r = pfile->decode (cdr);
00647 if (r == -1)
00648 {
00649 pfile->_decr_refcnt ();
00650 pfile = 0;
00651 }
00652
00653 return pfile;
00654 }
00655
00656 TAO_Profile *
00657 TAO_IIOP_Connector::make_profile (void)
00658 {
00659
00660
00661
00662
00663
00664 TAO_Profile *profile = 0;
00665 ACE_NEW_THROW_EX (profile,
00666 TAO_IIOP_Profile (this->orb_core ()),
00667 CORBA::NO_MEMORY (
00668 CORBA::SystemException::_tao_minor_code (
00669 0,
00670 ENOMEM),
00671 CORBA::COMPLETED_NO));
00672
00673 return profile;
00674 }
00675
00676 int
00677 TAO_IIOP_Connector::check_prefix (const char *endpoint)
00678 {
00679
00680 if (!endpoint || !*endpoint)
00681 return -1;
00682
00683 static const char *protocol[] = { "iiop", "iioploc" };
00684
00685 size_t const slot = ACE_OS::strchr (endpoint, ':') - endpoint;
00686 if (slot == 0)
00687 return 0;
00688
00689 size_t const len0 = ACE_OS::strlen (protocol[0]);
00690 size_t const len1 = ACE_OS::strlen (protocol[1]);
00691
00692
00693
00694 if (slot == len0 && ACE_OS::strncasecmp (endpoint, protocol[0], len0) == 0)
00695 return 0;
00696 else if (slot == len1 && ACE_OS::strncasecmp (endpoint, protocol[1], len1) == 0)
00697 return 0;
00698
00699 return -1;
00700
00701
00702 }
00703
00704 char
00705 TAO_IIOP_Connector::object_key_delimiter (void) const
00706 {
00707 return TAO_IIOP_Profile::object_key_delimiter_;
00708 }
00709
00710 TAO_IIOP_Endpoint *
00711 TAO_IIOP_Connector::remote_endpoint (TAO_Endpoint *endpoint)
00712 {
00713 if (endpoint->tag () != IOP::TAG_INTERNET_IOP)
00714 return 0;
00715
00716 TAO_IIOP_Endpoint *iiop_endpoint =
00717 dynamic_cast<TAO_IIOP_Endpoint *> (endpoint );
00718
00719 if (iiop_endpoint == 0)
00720 return 0;
00721
00722 return iiop_endpoint;
00723 }
00724
00725 int
00726 TAO_IIOP_Connector::cancel_svc_handler (
00727 TAO_Connection_Handler * svc_handler)
00728 {
00729 TAO_IIOP_Connection_Handler* handler=
00730 dynamic_cast<TAO_IIOP_Connection_Handler*>(svc_handler);
00731
00732
00733 if (handler)
00734 {
00735 handler->abort();
00736 return this->base_connector_.cancel (handler);
00737 }
00738
00739 return -1;
00740 }
00741
00742
00743
00744
00745 TAO_END_VERSIONED_NAMESPACE_DECL
00746
00747 #endif