PageRenderTime 49ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/dep/acelite/ace/Connector.cpp

https://github.com/chucho/FaceCore
C++ | 1005 lines | 746 code | 156 blank | 103 comment | 123 complexity | f95fadff44b737912dfb8d2526dbc4bd MD5 | raw file
  1. // $Id: Connector.cpp 91527 2010-08-27 15:03:31Z shuston $
  2. #ifndef ACE_CONNECTOR_CPP
  3. #define ACE_CONNECTOR_CPP
  4. #include "ace/Connector.h"
  5. #include "ace/ACE.h"
  6. #include "ace/OS_NS_stdio.h"
  7. #include "ace/OS_NS_string.h"
  8. #include "ace/os_include/os_fcntl.h" /* Has ACE_NONBLOCK */
  9. #if !defined (ACE_LACKS_PRAGMA_ONCE)
  10. # pragma once
  11. #endif /* ACE_LACKS_PRAGMA_ONCE */
  12. ACE_BEGIN_VERSIONED_NAMESPACE_DECL
  13. ACE_ALLOC_HOOK_DEFINE(ACE_Connector)
  14. template <class SVC_HANDLER>
  15. ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::ACE_NonBlocking_Connect_Handler
  16. (ACE_Connector_Base<SVC_HANDLER> &connector,
  17. SVC_HANDLER *sh,
  18. long id)
  19. : connector_ (connector)
  20. , svc_handler_ (sh)
  21. , cleanup_svc_handler_ (0)
  22. , timer_id_ (id)
  23. {
  24. ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::ACE_NonBlocking_Connect_Handler");
  25. this->reference_counting_policy ().value
  26. (ACE_Event_Handler::Reference_Counting_Policy::ENABLED);
  27. if (this->svc_handler_ != 0 &&
  28. this->svc_handler_->reference_counting_policy ().value () ==
  29. ACE_Event_Handler::Reference_Counting_Policy::ENABLED)
  30. {
  31. // If SVC_HANDLER is reference counted then NBCH holds a reference
  32. // in cleanup_svc_handle_ which is both a pointer to SVC_HANDLER
  33. // and a flag that triggers remove_reference in NBCH destructor.
  34. this->cleanup_svc_handler_ = sh;
  35. this->cleanup_svc_handler_->add_reference ();
  36. }
  37. }
  38. template <class SVC_HANDLER>
  39. ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::~ACE_NonBlocking_Connect_Handler (void)
  40. {
  41. if (this->cleanup_svc_handler_)
  42. {
  43. this->cleanup_svc_handler_->remove_reference ();
  44. }
  45. }
  46. template <class SVC_HANDLER> SVC_HANDLER *
  47. ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::svc_handler (void)
  48. {
  49. ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::svc_handler");
  50. return this->svc_handler_;
  51. }
  52. template <class SVC_HANDLER> long
  53. ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::timer_id (void)
  54. {
  55. ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::timer_id");
  56. return this->timer_id_;
  57. }
  58. template <class SVC_HANDLER> void
  59. ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::timer_id (long id)
  60. {
  61. ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::timer_id");
  62. this->timer_id_ = id;
  63. }
  64. template <class SVC_HANDLER> void
  65. ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::dump (void) const
  66. {
  67. #if defined (ACE_HAS_DUMP)
  68. ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::dump");
  69. ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
  70. ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("svc_handler_ = %x"), this->svc_handler_));
  71. ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ntimer_id_ = %d"), this->timer_id_));
  72. ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
  73. #endif /* ACE_HAS_DUMP */
  74. }
  75. template <class SVC_HANDLER> bool
  76. ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::close (SVC_HANDLER *&sh)
  77. {
  78. // Make sure that we haven't already initialized the Svc_Handler.
  79. if (!this->svc_handler_)
  80. return false;
  81. {
  82. // Exclusive access to the Reactor.
  83. ACE_GUARD_RETURN (ACE_Lock,
  84. ace_mon,
  85. this->reactor ()->lock (),
  86. 0);
  87. // Double check.
  88. if (!this->svc_handler_)
  89. return false;
  90. // Remember the Svc_Handler.
  91. sh = this->svc_handler_;
  92. ACE_HANDLE h = sh->get_handle ();
  93. this->svc_handler_ = 0;
  94. // Remove this handle from the set of non-blocking handles
  95. // in the Connector.
  96. this->connector_.non_blocking_handles ().remove (h);
  97. // Cancel timer.
  98. if (this->reactor ()->cancel_timer (this->timer_id (),
  99. 0,
  100. 0) == -1)
  101. return false;
  102. // Remove from Reactor.
  103. if (-1 == this->reactor ()->remove_handler (
  104. h,
  105. ACE_Event_Handler::ALL_EVENTS_MASK | ACE_Event_Handler::DONT_CALL))
  106. return false;
  107. }
  108. return true;
  109. }
  110. template <class SVC_HANDLER> int
  111. ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_timeout
  112. (const ACE_Time_Value &tv,
  113. const void *arg)
  114. {
  115. // This method is called if a connection times out before completing.
  116. ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_timeout");
  117. SVC_HANDLER *svc_handler = 0;
  118. int const retval = this->close (svc_handler) ? 0 : -1;
  119. // Forward to the SVC_HANDLER the <arg> that was passed in as a
  120. // magic cookie during ACE_Connector::connect(). This gives the
  121. // SVC_HANDLER an opportunity to take corrective action (e.g., wait
  122. // a few milliseconds and try to reconnect again.
  123. if (svc_handler != 0 && svc_handler->handle_timeout (tv, arg) == -1)
  124. svc_handler->handle_close (svc_handler->get_handle (),
  125. ACE_Event_Handler::TIMER_MASK);
  126. return retval;
  127. }
  128. template <class SVC_HANDLER> int
  129. ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_input (ACE_HANDLE)
  130. {
  131. // Called when a failure occurs during asynchronous connection
  132. // establishment.
  133. ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_input");
  134. SVC_HANDLER *svc_handler = 0;
  135. int const retval = this->close (svc_handler) ? 0 : -1;
  136. // Close Svc_Handler.
  137. if (svc_handler != 0)
  138. {
  139. svc_handler->close (NORMAL_CLOSE_OPERATION);
  140. }
  141. return retval;
  142. }
  143. template <class SVC_HANDLER> int
  144. ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_close (ACE_HANDLE handle,
  145. ACE_Reactor_Mask m)
  146. {
  147. // epoll on Linux will, at least sometimes, return EPOLLERR when a connect
  148. // fails, triggering a total removal from the reactor. This is different from
  149. // select()-based systems which select the fd for read on a connect failure.
  150. // So just call handle_input() to rejoin common handling for a failed
  151. // connect.
  152. if (m == ACE_Event_Handler::ALL_EVENTS_MASK)
  153. return this->handle_input (handle);
  154. return -1;
  155. }
  156. template <class SVC_HANDLER> int
  157. ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_output (ACE_HANDLE handle)
  158. {
  159. // Called when a connection is establishment asynchronous.
  160. ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_output");
  161. // Grab the connector ref before smashing ourselves in close().
  162. ACE_Connector_Base<SVC_HANDLER> &connector = this->connector_;
  163. SVC_HANDLER *svc_handler = 0;
  164. int const retval = this->close (svc_handler) ? 0 : -1;
  165. if (svc_handler != 0)
  166. {
  167. connector.initialize_svc_handler (handle, svc_handler);
  168. }
  169. return retval;
  170. }
  171. template <class SVC_HANDLER> int
  172. ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_exception (ACE_HANDLE h)
  173. {
  174. // On Win32, the except mask must also be set for asynchronous
  175. // connects.
  176. ACE_TRACE ("ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::handle_exception");
  177. return this->handle_output (h);
  178. }
  179. template <class SVC_HANDLER> int
  180. ACE_NonBlocking_Connect_Handler<SVC_HANDLER>::resume_handler (void)
  181. {
  182. return ACE_Event_Handler::ACE_EVENT_HANDLER_NOT_RESUMED;
  183. }
  184. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> void
  185. ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::dump (void) const
  186. {
  187. #if defined (ACE_HAS_DUMP)
  188. ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::dump");
  189. ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
  190. ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nflags_ = %d"), this->flags_));
  191. ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
  192. #endif /* ACE_HAS_DUMP */
  193. }
  194. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
  195. ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::make_svc_handler (SVC_HANDLER *&sh)
  196. {
  197. ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::make_svc_handler");
  198. if (sh == 0)
  199. ACE_NEW_RETURN (sh,
  200. SVC_HANDLER,
  201. -1);
  202. // Set the reactor of the newly created <SVC_HANDLER> to the same
  203. // reactor that this <Connector> is using.
  204. sh->reactor (this->reactor ());
  205. return 0;
  206. }
  207. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
  208. ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::activate_svc_handler (SVC_HANDLER *svc_handler)
  209. {
  210. ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::activate_svc_handler");
  211. // No errors initially
  212. int error = 0;
  213. // See if we should enable non-blocking I/O on the <svc_handler>'s
  214. // peer.
  215. if (ACE_BIT_ENABLED (this->flags_, ACE_NONBLOCK) != 0)
  216. {
  217. if (svc_handler->peer ().enable (ACE_NONBLOCK) == -1)
  218. error = 1;
  219. }
  220. // Otherwise, make sure it's disabled by default.
  221. else if (svc_handler->peer ().disable (ACE_NONBLOCK) == -1)
  222. error = 1;
  223. // We are connected now, so try to open things up.
  224. if (error || svc_handler->open ((void *) this) == -1)
  225. {
  226. // Make sure to close down the <svc_handler> to avoid descriptor
  227. // leaks.
  228. // The connection was already made; so this close is a "normal"
  229. // close operation.
  230. svc_handler->close (NORMAL_CLOSE_OPERATION);
  231. return -1;
  232. }
  233. else
  234. return 0;
  235. }
  236. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> ACE_PEER_CONNECTOR &
  237. ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connector (void) const
  238. {
  239. return const_cast<ACE_PEER_CONNECTOR &> (this->connector_);
  240. }
  241. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
  242. ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_svc_handler
  243. (SVC_HANDLER *&svc_handler,
  244. const ACE_PEER_CONNECTOR_ADDR &remote_addr,
  245. ACE_Time_Value *timeout,
  246. const ACE_PEER_CONNECTOR_ADDR &local_addr,
  247. int reuse_addr,
  248. int flags,
  249. int perms)
  250. {
  251. ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_svc_handler");
  252. return this->connector_.connect (svc_handler->peer (),
  253. remote_addr,
  254. timeout,
  255. local_addr,
  256. reuse_addr,
  257. flags,
  258. perms);
  259. }
  260. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
  261. ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_svc_handler
  262. (SVC_HANDLER *&svc_handler,
  263. SVC_HANDLER *&sh_copy,
  264. const ACE_PEER_CONNECTOR_ADDR &remote_addr,
  265. ACE_Time_Value *timeout,
  266. const ACE_PEER_CONNECTOR_ADDR &local_addr,
  267. int reuse_addr,
  268. int flags,
  269. int perms)
  270. {
  271. ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_svc_handler");
  272. sh_copy = svc_handler;
  273. return this->connector_.connect (svc_handler->peer (),
  274. remote_addr,
  275. timeout,
  276. local_addr,
  277. reuse_addr,
  278. flags,
  279. perms);
  280. }
  281. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
  282. ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::open (ACE_Reactor *r, int flags)
  283. {
  284. ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::open");
  285. this->reactor (r);
  286. this->flags_ = flags;
  287. return 0;
  288. }
  289. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1>
  290. ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::ACE_Connector (ACE_Reactor *r,
  291. int flags)
  292. {
  293. ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::ACE_Connector");
  294. (void) this->open (r, flags);
  295. }
  296. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
  297. ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect
  298. (SVC_HANDLER *&sh,
  299. const ACE_PEER_CONNECTOR_ADDR &remote_addr,
  300. const ACE_Synch_Options &synch_options,
  301. const ACE_PEER_CONNECTOR_ADDR &local_addr,
  302. int reuse_addr,
  303. int flags,
  304. int perms)
  305. {
  306. // Initiate connection to peer.
  307. return this->connect_i (sh,
  308. 0,
  309. remote_addr,
  310. synch_options,
  311. local_addr,
  312. reuse_addr,
  313. flags,
  314. perms);
  315. }
  316. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
  317. ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect
  318. (SVC_HANDLER *&sh,
  319. SVC_HANDLER *&sh_copy,
  320. const ACE_PEER_CONNECTOR_ADDR &remote_addr,
  321. const ACE_Synch_Options &synch_options,
  322. const ACE_PEER_CONNECTOR_ADDR &local_addr,
  323. int reuse_addr,
  324. int flags,
  325. int perms)
  326. {
  327. // Initiate connection to peer.
  328. return this->connect_i (sh,
  329. &sh_copy,
  330. remote_addr,
  331. synch_options,
  332. local_addr,
  333. reuse_addr,
  334. flags,
  335. perms);
  336. }
  337. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
  338. ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_i
  339. (SVC_HANDLER *&sh,
  340. SVC_HANDLER **sh_copy,
  341. const ACE_PEER_CONNECTOR_ADDR &remote_addr,
  342. const ACE_Synch_Options &synch_options,
  343. const ACE_PEER_CONNECTOR_ADDR &local_addr,
  344. int reuse_addr,
  345. int flags,
  346. int perms)
  347. {
  348. ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_i");
  349. // If the user hasn't supplied us with a <SVC_HANDLER> we'll use the
  350. // factory method to create one. Otherwise, things will remain as
  351. // they are...
  352. if (this->make_svc_handler (sh) == -1)
  353. return -1;
  354. ACE_Time_Value *timeout = 0;
  355. int const use_reactor = synch_options[ACE_Synch_Options::USE_REACTOR];
  356. if (use_reactor)
  357. timeout = const_cast<ACE_Time_Value *> (&ACE_Time_Value::zero);
  358. else
  359. timeout = const_cast<ACE_Time_Value *> (synch_options.time_value ());
  360. int result;
  361. if (sh_copy == 0)
  362. result = this->connect_svc_handler (sh,
  363. remote_addr,
  364. timeout,
  365. local_addr,
  366. reuse_addr,
  367. flags,
  368. perms);
  369. else
  370. result = this->connect_svc_handler (sh,
  371. *sh_copy,
  372. remote_addr,
  373. timeout,
  374. local_addr,
  375. reuse_addr,
  376. flags,
  377. perms);
  378. // Activate immediately if we are connected.
  379. if (result != -1)
  380. return this->activate_svc_handler (sh);
  381. // Delegate to connection strategy.
  382. if (use_reactor && ACE_OS::last_error () == EWOULDBLOCK)
  383. {
  384. // If the connection hasn't completed and we are using
  385. // non-blocking semantics then register
  386. // ACE_NonBlocking_Connect_Handler with the ACE_Reactor so that
  387. // it will call us back when the connection is complete or we
  388. // timeout, whichever comes first...
  389. int result;
  390. if (sh_copy == 0)
  391. result = this->nonblocking_connect (sh, synch_options);
  392. else
  393. result = this->nonblocking_connect (*sh_copy, synch_options);
  394. // If for some reason the <nonblocking_connect> call failed, then <errno>
  395. // will be set to the new error. If the call succeeds, however,
  396. // we need to make sure that <errno> remains set to
  397. // <EWOULDBLOCK>.
  398. if (result == 0)
  399. errno = EWOULDBLOCK;
  400. }
  401. else
  402. {
  403. // Save/restore errno.
  404. ACE_Errno_Guard error (errno);
  405. // Make sure to close down the service handler to avoid handle
  406. // leaks.
  407. if (sh_copy == 0)
  408. {
  409. if (sh)
  410. sh->close (CLOSE_DURING_NEW_CONNECTION);
  411. }
  412. else if (*sh_copy)
  413. (*sh_copy)->close (CLOSE_DURING_NEW_CONNECTION);
  414. }
  415. return -1;
  416. }
  417. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
  418. ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_n
  419. (size_t n,
  420. SVC_HANDLER *sh[],
  421. ACE_PEER_CONNECTOR_ADDR remote_addrs[],
  422. ACE_TCHAR *failed_svc_handlers,
  423. const ACE_Synch_Options &synch_options)
  424. {
  425. int result = 0;
  426. for (size_t i = 0; i < n; i++)
  427. {
  428. if (this->connect (sh[i], remote_addrs[i], synch_options) == -1
  429. && !(synch_options[ACE_Synch_Options::USE_REACTOR]
  430. && errno == EWOULDBLOCK))
  431. {
  432. result = -1;
  433. if (failed_svc_handlers != 0)
  434. // Mark this entry as having failed.
  435. failed_svc_handlers[i] = 1;
  436. }
  437. else if (failed_svc_handlers != 0)
  438. // Mark this entry as having succeeded.
  439. failed_svc_handlers[i] = 0;
  440. }
  441. return result;
  442. }
  443. // Cancel a <svc_handler> that was started asynchronously.
  444. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
  445. ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::cancel (SVC_HANDLER *sh)
  446. {
  447. ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::cancel");
  448. ACE_Event_Handler *handler =
  449. this->reactor ()->find_handler (sh->get_handle ());
  450. if (handler == 0)
  451. return -1;
  452. // find_handler() increments handler's refcount; ensure we decrement it.
  453. ACE_Event_Handler_var safe_handler (handler);
  454. NBCH *nbch =
  455. dynamic_cast<NBCH *> (handler);
  456. if (nbch == 0)
  457. return -1;
  458. SVC_HANDLER *tmp_sh = 0;
  459. if (nbch->close (tmp_sh) == false)
  460. return -1;
  461. return 0;
  462. }
  463. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
  464. ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::nonblocking_connect
  465. (SVC_HANDLER *sh,
  466. const ACE_Synch_Options &synch_options)
  467. {
  468. ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::nonblocking_connect");
  469. // Must have a valid Reactor for non-blocking connects to work.
  470. if (this->reactor () == 0)
  471. return -1;
  472. // Register the pending SVC_HANDLER so that it can be activated
  473. // later on when the connection completes.
  474. ACE_HANDLE handle = sh->get_handle ();
  475. long timer_id = -1;
  476. ACE_Time_Value *tv = 0;
  477. NBCH *nbch = 0;
  478. ACE_NEW_RETURN (nbch,
  479. NBCH (*this,
  480. sh,
  481. -1),
  482. -1);
  483. ACE_Event_Handler_var safe_nbch (nbch);
  484. // Exclusive access to the Reactor.
  485. ACE_GUARD_RETURN (ACE_Lock, ace_mon, this->reactor ()->lock (), -1);
  486. // Register handle with the reactor for connection events.
  487. ACE_Reactor_Mask mask = ACE_Event_Handler::CONNECT_MASK;
  488. if (this->reactor ()->register_handler (handle,
  489. nbch,
  490. mask) == -1)
  491. goto reactor_registration_failure;
  492. // Add handle to non-blocking handle set.
  493. this->non_blocking_handles ().insert (handle);
  494. // If we're starting connection under timer control then we need to
  495. // schedule a timeout with the ACE_Reactor.
  496. tv = const_cast<ACE_Time_Value *> (synch_options.time_value ());
  497. if (tv != 0)
  498. {
  499. timer_id =
  500. this->reactor ()->schedule_timer (nbch,
  501. synch_options.arg (),
  502. *tv);
  503. if (timer_id == -1)
  504. goto timer_registration_failure;
  505. // Remember timer id.
  506. nbch->timer_id (timer_id);
  507. }
  508. return 0;
  509. // Undo previous actions using the ol' "goto label and fallthru"
  510. // trick...
  511. timer_registration_failure:
  512. // Remove from Reactor.
  513. this->reactor ()->remove_handler (handle, mask);
  514. // Remove handle from the set of non-blocking handles.
  515. this->non_blocking_handles ().remove (handle);
  516. /* FALLTHRU */
  517. reactor_registration_failure:
  518. // Close the svc_handler
  519. sh->close (CLOSE_DURING_NEW_CONNECTION);
  520. return -1;
  521. }
  522. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1>
  523. ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::~ACE_Connector (void)
  524. {
  525. ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::~ACE_Connector");
  526. this->close ();
  527. }
  528. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> void
  529. ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::initialize_svc_handler
  530. (ACE_HANDLE handle,
  531. SVC_HANDLER *svc_handler)
  532. {
  533. // Try to find out if the reactor uses event associations for the
  534. // handles it waits on. If so we need to reset it.
  535. bool reset_new_handle =
  536. this->reactor ()->uses_event_associations ();
  537. if (reset_new_handle)
  538. this->connector_.reset_new_handle (handle);
  539. // Transfer ownership of the ACE_HANDLE to the SVC_HANDLER.
  540. svc_handler->set_handle (handle);
  541. ACE_PEER_CONNECTOR_ADDR raddr;
  542. // Check to see if we're connected.
  543. if (svc_handler->peer ().get_remote_addr (raddr) != -1)
  544. this->activate_svc_handler (svc_handler);
  545. else // Somethings gone wrong, so close down...
  546. {
  547. #if defined (ACE_WIN32)
  548. // Win32 (at least prior to Windows 2000) has a timing problem.
  549. // If you check to see if the connection has completed too fast,
  550. // it will fail - so wait 35 milliseconds to let it catch up.
  551. ACE_Time_Value tv (0, ACE_NON_BLOCKING_BUG_DELAY);
  552. ACE_OS::sleep (tv);
  553. if (svc_handler->peer ().get_remote_addr (raddr) != -1)
  554. this->activate_svc_handler (svc_handler);
  555. else // do the svc handler close below...
  556. #endif /* ACE_WIN32 */
  557. svc_handler->close (NORMAL_CLOSE_OPERATION);
  558. }
  559. }
  560. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> void
  561. ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::reactor (ACE_Reactor *reactor)
  562. {
  563. this->reactor_ = reactor;
  564. }
  565. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> ACE_Reactor *
  566. ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::reactor (void) const
  567. {
  568. return this->reactor_;
  569. }
  570. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> ACE_Unbounded_Set<ACE_HANDLE> &
  571. ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::non_blocking_handles (void)
  572. {
  573. return this->non_blocking_handles_;
  574. }
  575. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
  576. ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::close (void)
  577. {
  578. // If there are no non-blocking handle pending, return immediately.
  579. if (this->non_blocking_handles ().size () == 0)
  580. return 0;
  581. // Exclusive access to the Reactor.
  582. ACE_GUARD_RETURN (ACE_Lock, ace_mon, this->reactor ()->lock (), -1);
  583. // Go through all the non-blocking handles. It is necessary to
  584. // create a new iterator each time because we remove from the handle
  585. // set when we cancel the Svc_Handler.
  586. ACE_HANDLE *handle = 0;
  587. while (1)
  588. {
  589. ACE_Unbounded_Set_Iterator<ACE_HANDLE>
  590. iterator (this->non_blocking_handles ());
  591. if (!iterator.next (handle))
  592. break;
  593. ACE_Event_Handler *handler =
  594. this->reactor ()->find_handler (*handle);
  595. if (handler == 0)
  596. {
  597. ACE_ERROR ((LM_ERROR,
  598. ACE_TEXT ("%t: Connector::close h %d, no handler\n"),
  599. *handle));
  600. // Remove handle from the set of non-blocking handles.
  601. this->non_blocking_handles ().remove (*handle);
  602. continue;
  603. }
  604. // find_handler() incremented handler's refcount; ensure it's decremented
  605. ACE_Event_Handler_var safe_handler (handler);
  606. NBCH *nbch = dynamic_cast<NBCH *> (handler);
  607. if (nbch == 0)
  608. {
  609. ACE_ERROR ((LM_ERROR,
  610. ACE_TEXT ("%t: Connector::close h %d handler %@ ")
  611. ACE_TEXT ("not a legit handler\n"),
  612. *handle,
  613. handler));
  614. // Remove handle from the set of non-blocking handles.
  615. this->non_blocking_handles ().remove (*handle);
  616. continue;
  617. }
  618. SVC_HANDLER *svc_handler = nbch->svc_handler ();
  619. // Cancel the non-blocking connection.
  620. this->cancel (svc_handler);
  621. // Close the associated Svc_Handler.
  622. svc_handler->close (NORMAL_CLOSE_OPERATION);
  623. }
  624. return 0;
  625. }
  626. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
  627. ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::fini (void)
  628. {
  629. ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::fini");
  630. return this->close ();
  631. }
  632. // Hook called by the explicit dynamic linking facility.
  633. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
  634. ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::init (int, ACE_TCHAR *[])
  635. {
  636. ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::init");
  637. return -1;
  638. }
  639. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
  640. ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::suspend (void)
  641. {
  642. ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::suspend");
  643. return -1;
  644. }
  645. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
  646. ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::resume (void)
  647. {
  648. ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::resume");
  649. return -1;
  650. }
  651. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
  652. ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::info (ACE_TCHAR **strp, size_t length) const
  653. {
  654. ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::info");
  655. ACE_TCHAR buf[BUFSIZ];
  656. ACE_OS::sprintf (buf,
  657. ACE_TEXT ("%s\t %s"),
  658. ACE_TEXT ("ACE_Connector"),
  659. ACE_TEXT ("# connector factory\n"));
  660. if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0)
  661. return -1;
  662. else
  663. ACE_OS::strsncpy (*strp, buf, length);
  664. return static_cast<int> (ACE_OS::strlen (buf));
  665. }
  666. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
  667. ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::open (ACE_Reactor *r,
  668. int flags)
  669. {
  670. ACE_TRACE ("ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::open");
  671. return this->open (r, 0, 0, 0, flags);
  672. }
  673. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
  674. ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::open
  675. (ACE_Reactor *r,
  676. ACE_Creation_Strategy<SVC_HANDLER> *cre_s,
  677. ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2> *conn_s,
  678. ACE_Concurrency_Strategy<SVC_HANDLER> *con_s,
  679. int flags)
  680. {
  681. ACE_TRACE ("ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::open");
  682. this->reactor (r);
  683. // @@ Not implemented yet.
  684. // this->flags_ = flags;
  685. ACE_UNUSED_ARG (flags);
  686. // Initialize the creation strategy.
  687. // First we decide if we need to clean up.
  688. if (this->creation_strategy_ != 0 &&
  689. this->delete_creation_strategy_ &&
  690. cre_s != 0)
  691. {
  692. delete this->creation_strategy_;
  693. this->creation_strategy_ = 0;
  694. this->delete_creation_strategy_ = false;
  695. }
  696. if (cre_s != 0)
  697. this->creation_strategy_ = cre_s;
  698. else if (this->creation_strategy_ == 0)
  699. {
  700. ACE_NEW_RETURN (this->creation_strategy_,
  701. CREATION_STRATEGY,
  702. -1);
  703. this->delete_creation_strategy_ = true;
  704. }
  705. // Initialize the accept strategy.
  706. if (this->connect_strategy_ != 0 &&
  707. this->delete_connect_strategy_ &&
  708. conn_s != 0)
  709. {
  710. delete this->connect_strategy_;
  711. this->connect_strategy_ = 0;
  712. this->delete_connect_strategy_ = false;
  713. }
  714. if (conn_s != 0)
  715. this->connect_strategy_ = conn_s;
  716. else if (this->connect_strategy_ == 0)
  717. {
  718. ACE_NEW_RETURN (this->connect_strategy_,
  719. CONNECT_STRATEGY,
  720. -1);
  721. this->delete_connect_strategy_ = true;
  722. }
  723. // Initialize the concurrency strategy.
  724. if (this->concurrency_strategy_ != 0 &&
  725. this->delete_concurrency_strategy_ &&
  726. con_s != 0)
  727. {
  728. delete this->concurrency_strategy_;
  729. this->concurrency_strategy_ = 0;
  730. this->delete_concurrency_strategy_ = false;
  731. }
  732. if (con_s != 0)
  733. this->concurrency_strategy_ = con_s;
  734. else if (this->concurrency_strategy_ == 0)
  735. {
  736. ACE_NEW_RETURN (this->concurrency_strategy_,
  737. CONCURRENCY_STRATEGY,
  738. -1);
  739. this->delete_concurrency_strategy_ = true;
  740. }
  741. return 0;
  742. }
  743. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1>
  744. ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::ACE_Strategy_Connector
  745. (ACE_Reactor *reactor,
  746. ACE_Creation_Strategy<SVC_HANDLER> *cre_s,
  747. ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2> *conn_s,
  748. ACE_Concurrency_Strategy<SVC_HANDLER> *con_s,
  749. int flags)
  750. : creation_strategy_ (0),
  751. delete_creation_strategy_ (false),
  752. connect_strategy_ (0),
  753. delete_connect_strategy_ (false),
  754. concurrency_strategy_ (0),
  755. delete_concurrency_strategy_ (false)
  756. {
  757. ACE_TRACE ("ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::ACE_Strategy_Connector");
  758. if (this->open (reactor, cre_s, conn_s, con_s, flags) == -1)
  759. ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("ACE_Strategy_Connector::ACE_Strategy_Connector")));
  760. }
  761. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1>
  762. ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::~ACE_Strategy_Connector (void)
  763. {
  764. ACE_TRACE ("ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::~ACE_Strategy_Connector");
  765. // Close down
  766. this->close ();
  767. }
  768. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
  769. ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::close (void)
  770. {
  771. if (this->delete_creation_strategy_)
  772. delete this->creation_strategy_;
  773. this->delete_creation_strategy_ = false;
  774. this->creation_strategy_ = 0;
  775. if (this->delete_connect_strategy_)
  776. delete this->connect_strategy_;
  777. this->delete_connect_strategy_ = false;
  778. this->connect_strategy_ = 0;
  779. if (this->delete_concurrency_strategy_)
  780. delete this->concurrency_strategy_;
  781. this->delete_concurrency_strategy_ = false;
  782. this->concurrency_strategy_ = 0;
  783. return SUPER::close ();
  784. }
  785. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
  786. ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::make_svc_handler (SVC_HANDLER *&sh)
  787. {
  788. return this->creation_strategy_->make_svc_handler (sh);
  789. }
  790. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
  791. ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_svc_handler
  792. (SVC_HANDLER *&sh,
  793. const ACE_PEER_CONNECTOR_ADDR &remote_addr,
  794. ACE_Time_Value *timeout,
  795. const ACE_PEER_CONNECTOR_ADDR &local_addr,
  796. int reuse_addr,
  797. int flags,
  798. int perms)
  799. {
  800. return this->connect_strategy_->connect_svc_handler (sh,
  801. remote_addr,
  802. timeout,
  803. local_addr,
  804. reuse_addr,
  805. flags,
  806. perms);
  807. }
  808. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
  809. ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_svc_handler
  810. (SVC_HANDLER *&sh,
  811. SVC_HANDLER *&sh_copy,
  812. const ACE_PEER_CONNECTOR_ADDR &remote_addr,
  813. ACE_Time_Value *timeout,
  814. const ACE_PEER_CONNECTOR_ADDR &local_addr,
  815. int reuse_addr,
  816. int flags,
  817. int perms)
  818. {
  819. return this->connect_strategy_->connect_svc_handler (sh,
  820. sh_copy,
  821. remote_addr,
  822. timeout,
  823. local_addr,
  824. reuse_addr,
  825. flags,
  826. perms);
  827. }
  828. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> int
  829. ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::activate_svc_handler (SVC_HANDLER *svc_handler)
  830. {
  831. return this->concurrency_strategy_->activate_svc_handler (svc_handler, this);
  832. }
  833. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> ACE_Creation_Strategy<SVC_HANDLER> *
  834. ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::creation_strategy (void) const
  835. {
  836. return this->creation_strategy_;
  837. }
  838. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2> *
  839. ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::connect_strategy (void) const
  840. {
  841. return this->connect_strategy_;
  842. }
  843. template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1> ACE_Concurrency_Strategy<SVC_HANDLER> *
  844. ACE_Strategy_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>::concurrency_strategy (void) const
  845. {
  846. return this->concurrency_strategy_;
  847. }
  848. ACE_END_VERSIONED_NAMESPACE_DECL
  849. #endif /* ACE_CONNECTOR_C */